Use ImmutableString for HLSL texture references
This also adds ImmutableStringBuilder class, which can be used to
build ImmutableStrings in place without extra allocations if the
maximum length is known in advance.
BUG=angleproject:2267
TEST=angle_unittests
Change-Id: I4dfb78adeb0cffcfad0d25753fb8063466012c92
Reviewed-on: https://chromium-review.googlesource.com/886362
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/ImmutableString.cpp b/src/compiler/translator/ImmutableString.cpp
new file mode 100644
index 0000000..93dad1b
--- /dev/null
+++ b/src/compiler/translator/ImmutableString.cpp
@@ -0,0 +1,15 @@
+//
+// Copyright (c) 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ImmutableString.cpp: Wrapper for static or pool allocated char arrays, that are guaranteed to be
+// valid and unchanged for the duration of the compilation.
+//
+
+#include "compiler/translator/ImmutableString.h"
+
+std::ostream &operator<<(std::ostream &os, const sh::ImmutableString &str)
+{
+ return os.write(str.data(), str.length());
+}
diff --git a/src/compiler/translator/ImmutableString.h b/src/compiler/translator/ImmutableString.h
index 2957944..a33fec9 100644
--- a/src/compiler/translator/ImmutableString.h
+++ b/src/compiler/translator/ImmutableString.h
@@ -45,10 +45,13 @@
{
}
+ constexpr ImmutableString(const char *data, size_t length) : mData(data), mLength(length) {}
+
ImmutableString(const ImmutableString &) = default;
ImmutableString &operator=(const ImmutableString &) = default;
const char *data() const { return mData ? mData : ""; }
+ size_t length() const { return mLength; }
bool operator<(const ImmutableString &b) const
{
@@ -64,10 +67,12 @@
}
private:
- const char *const mData;
- const size_t mLength;
+ const char *mData;
+ size_t mLength;
};
} // namespace sh
+std::ostream &operator<<(std::ostream &os, const sh::ImmutableString &str);
+
#endif // COMPILER_TRANSLATOR_IMMUTABLESTRING_H_
diff --git a/src/compiler/translator/ImmutableStringBuilder.cpp b/src/compiler/translator/ImmutableStringBuilder.cpp
new file mode 100644
index 0000000..00a8261
--- /dev/null
+++ b/src/compiler/translator/ImmutableStringBuilder.cpp
@@ -0,0 +1,53 @@
+//
+// Copyright (c) 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ImmutableStringBuilder.cpp: Stringstream-like utility for building pool allocated strings where
+// the maximum length is known in advance.
+//
+
+#include "compiler/translator/ImmutableStringBuilder.h"
+
+namespace sh
+{
+
+ImmutableStringBuilder &ImmutableStringBuilder::operator<<(const ImmutableString &str)
+{
+ ASSERT(mData != nullptr);
+ ASSERT(mPos + str.length() <= mMaxLength);
+ memcpy(mData + mPos, str.data(), str.length());
+ mPos += str.length();
+ return *this;
+}
+
+ImmutableStringBuilder &ImmutableStringBuilder::operator<<(const char *str)
+{
+ ASSERT(mData != nullptr);
+ size_t len = strlen(str);
+ ASSERT(mPos + len <= mMaxLength);
+ memcpy(mData + mPos, str, len);
+ mPos += len;
+ return *this;
+}
+
+ImmutableStringBuilder &ImmutableStringBuilder::operator<<(const char &c)
+{
+ ASSERT(mData != nullptr);
+ ASSERT(mPos + 1 <= mMaxLength);
+ mData[mPos++] = c;
+ return *this;
+}
+
+ImmutableStringBuilder::operator ImmutableString()
+{
+ mData[mPos] = '\0';
+ ImmutableString str(static_cast<const char *>(mData), mPos);
+#if defined(ANGLE_ENABLE_ASSERTS)
+ // Make sure that nothing is added to the string after it is finalized.
+ mData = nullptr;
+#endif
+ return str;
+}
+
+} // namespace sh
diff --git a/src/compiler/translator/ImmutableStringBuilder.h b/src/compiler/translator/ImmutableStringBuilder.h
new file mode 100644
index 0000000..94dcc3b
--- /dev/null
+++ b/src/compiler/translator/ImmutableStringBuilder.h
@@ -0,0 +1,49 @@
+//
+// Copyright (c) 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ImmutableStringBuilder.h: Stringstream-like utility for building pool allocated strings where the
+// maximum length is known in advance.
+//
+
+#ifndef COMPILER_TRANSLATOR_IMMUTABLESTRINGBUILDER_H_
+#define COMPILER_TRANSLATOR_IMMUTABLESTRINGBUILDER_H_
+
+#include "compiler/translator/ImmutableString.h"
+
+namespace sh
+{
+
+class ImmutableStringBuilder
+{
+ public:
+ ImmutableStringBuilder(size_t maxLength)
+ : mPos(0u), mMaxLength(maxLength), mData(AllocateEmptyPoolCharArray(maxLength))
+ {
+ }
+
+ ImmutableStringBuilder &operator<<(const ImmutableString &str);
+
+ ImmutableStringBuilder &operator<<(const char *str);
+
+ ImmutableStringBuilder &operator<<(const char &c);
+
+ // This invalidates the ImmutableStringBuilder, so it should only be called once.
+ operator ImmutableString();
+
+ private:
+ inline static char *AllocateEmptyPoolCharArray(size_t strLength)
+ {
+ size_t requiredSize = strLength + 1u;
+ return reinterpret_cast<char *>(GetGlobalPoolAllocator()->allocate(requiredSize));
+ }
+
+ size_t mPos;
+ size_t mMaxLength;
+ char *mData;
+};
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_IMMUTABLESTRINGBUILDER_H_
diff --git a/src/compiler/translator/TextureFunctionHLSL.cpp b/src/compiler/translator/TextureFunctionHLSL.cpp
index d2b65a6..36898ff 100644
--- a/src/compiler/translator/TextureFunctionHLSL.cpp
+++ b/src/compiler/translator/TextureFunctionHLSL.cpp
@@ -11,6 +11,7 @@
#include "compiler/translator/TextureFunctionHLSL.h"
+#include "compiler/translator/ImmutableStringBuilder.h"
#include "compiler/translator/UtilsHLSL.h"
namespace sh
@@ -104,8 +105,8 @@
void OutputHLSL4SampleFunctionPrefix(TInfoSinkBase &out,
const TextureFunctionHLSL::TextureFunction &textureFunction,
- const TString &textureReference,
- const TString &samplerReference)
+ const ImmutableString &textureReference,
+ const ImmutableString &samplerReference)
{
out << textureReference;
if (IsIntegerSampler(textureFunction.sampler) ||
@@ -450,37 +451,56 @@
void GetTextureReference(TInfoSinkBase &out,
const TextureFunctionHLSL::TextureFunction &textureFunction,
const ShShaderOutput outputType,
- TString *textureReference,
- TString *samplerReference)
+ ImmutableString *textureReference,
+ ImmutableString *samplerReference)
{
if (outputType == SH_HLSL_4_1_OUTPUT)
{
- TString suffix = TextureGroupSuffix(textureFunction.sampler);
+ static const ImmutableString kTexturesStr("textures");
+ static const ImmutableString kSamplersStr("samplers");
+ static const ImmutableString kSamplerIndexStr("[samplerIndex]");
+ static const ImmutableString kTextureIndexStr("[textureIndex]");
+ static const ImmutableString kSamplerArrayIndexStr("[samplerArrayIndex]");
+ ImmutableString suffix(TextureGroupSuffix(textureFunction.sampler));
+
if (TextureGroup(textureFunction.sampler) == HLSL_TEXTURE_2D)
{
- *textureReference = TString("textures") + suffix + "[samplerIndex]";
- *samplerReference = TString("samplers") + suffix + "[samplerIndex]";
+ ImmutableStringBuilder textureRefBuilder(kTexturesStr.length() + suffix.length() +
+ kSamplerIndexStr.length());
+ textureRefBuilder << kTexturesStr << suffix << kSamplerIndexStr;
+ *textureReference = textureRefBuilder;
+ ImmutableStringBuilder samplerRefBuilder(kSamplersStr.length() + suffix.length() +
+ kSamplerIndexStr.length());
+ samplerRefBuilder << kSamplersStr << suffix << kSamplerIndexStr;
+ *samplerReference = samplerRefBuilder;
}
else
{
- out << " const uint textureIndex = samplerIndex - textureIndexOffset" << suffix
- << ";\n";
- *textureReference = TString("textures") + suffix + "[textureIndex]";
- out << " const uint samplerArrayIndex = samplerIndex - samplerIndexOffset" << suffix
- << ";\n";
- *samplerReference = TString("samplers") + suffix + "[samplerArrayIndex]";
+ out << " const uint textureIndex = samplerIndex - textureIndexOffset"
+ << suffix.data() << ";\n";
+ ImmutableStringBuilder textureRefBuilder(kTexturesStr.length() + suffix.length() +
+ kTextureIndexStr.length());
+ textureRefBuilder << kTexturesStr << suffix << kTextureIndexStr;
+ *textureReference = textureRefBuilder;
+
+ out << " const uint samplerArrayIndex = samplerIndex - samplerIndexOffset"
+ << suffix.data() << ";\n";
+ ImmutableStringBuilder samplerRefBuilder(kSamplersStr.length() + suffix.length() +
+ kSamplerArrayIndexStr.length());
+ samplerRefBuilder << kSamplersStr << suffix << kSamplerArrayIndexStr;
+ *samplerReference = samplerRefBuilder;
}
}
else
{
- *textureReference = "x";
- *samplerReference = "s";
+ *textureReference = ImmutableString("x");
+ *samplerReference = ImmutableString("s");
}
}
void OutputTextureSizeFunctionBody(TInfoSinkBase &out,
const TextureFunctionHLSL::TextureFunction &textureFunction,
- const TString &textureReference,
+ const ImmutableString &textureReference,
bool getDimensionsIgnoresBaseLevel)
{
if (IsSampler2DMS(textureFunction.sampler))
@@ -565,7 +585,7 @@
TInfoSinkBase &out,
const TextureFunctionHLSL::TextureFunction &textureFunction,
const ShShaderOutput outputType,
- const TString &textureReference,
+ const ImmutableString &textureReference,
TString *texCoordX,
TString *texCoordY,
TString *texCoordZ)
@@ -811,8 +831,8 @@
TInfoSinkBase &out,
const TextureFunctionHLSL::TextureFunction &textureFunction,
const ShShaderOutput outputType,
- const TString &textureReference,
- const TString &samplerReference,
+ const ImmutableString &textureReference,
+ const ImmutableString &samplerReference,
const TString &texCoordX,
const TString &texCoordY,
const TString &texCoordZ)
@@ -1291,8 +1311,8 @@
// sampling we need to call the function directly on references to the texture and sampler
// arrays. The bug was found using dEQP-GLES3.functional.shaders.discard*loop_texture*
// tests.
- TString textureReference;
- TString samplerReference;
+ ImmutableString textureReference("");
+ ImmutableString samplerReference("");
GetTextureReference(out, textureFunction, outputType, &textureReference, &samplerReference);
if (textureFunction.method == TextureFunction::SIZE)
diff --git a/src/compiler/translator/UtilsHLSL.cpp b/src/compiler/translator/UtilsHLSL.cpp
index 2b8c688..14ba353 100644
--- a/src/compiler/translator/UtilsHLSL.cpp
+++ b/src/compiler/translator/UtilsHLSL.cpp
@@ -218,7 +218,7 @@
return HLSL_TEXTURE_UNKNOWN;
}
-TString TextureString(const HLSLTextureGroup textureGroup)
+const char *TextureString(const HLSLTextureGroup textureGroup)
{
switch (textureGroup)
{
@@ -277,12 +277,12 @@
return "<unknown read texture type>";
}
-TString TextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
+const char *TextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
{
return TextureString(TextureGroup(type, imageInternalFormat));
}
-TString TextureGroupSuffix(const HLSLTextureGroup type)
+const char *TextureGroupSuffix(const HLSLTextureGroup type)
{
switch (type)
{
@@ -341,7 +341,8 @@
return "<unknown texture type>";
}
-TString TextureGroupSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
+const char *TextureGroupSuffix(const TBasicType type,
+ TLayoutImageInternalFormat imageInternalFormat)
{
return TextureGroupSuffix(TextureGroup(type, imageInternalFormat));
}
diff --git a/src/compiler/translator/UtilsHLSL.h b/src/compiler/translator/UtilsHLSL.h
index fd7715a..a6af60e 100644
--- a/src/compiler/translator/UtilsHLSL.h
+++ b/src/compiler/translator/UtilsHLSL.h
@@ -87,12 +87,12 @@
HLSLTextureGroup TextureGroup(const TBasicType type,
TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified);
-TString TextureString(const HLSLTextureGroup textureGroup);
-TString TextureString(const TBasicType type,
- TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified);
-TString TextureGroupSuffix(const HLSLTextureGroup type);
-TString TextureGroupSuffix(const TBasicType type,
- TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified);
+const char *TextureString(const HLSLTextureGroup textureGroup);
+const char *TextureString(const TBasicType type,
+ TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified);
+const char *TextureGroupSuffix(const HLSLTextureGroup type);
+const char *TextureGroupSuffix(const TBasicType type,
+ TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified);
TString TextureTypeSuffix(const TBasicType type,
TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified);
HLSLRWTextureGroup RWTextureGroup(const TBasicType type,