summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp')
-rw-r--r--src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp448
1 files changed, 269 insertions, 179 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp
index fd1a29c1cd..61a9431ceb 100644
--- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp
@@ -4,7 +4,7 @@
// found in the LICENSE file.
//
// StructureHLSL.cpp:
-// Definitions of methods for HLSL translation of GLSL structures.
+// HLSL translation of GLSL constructors and structures.
//
#include "compiler/translator/StructureHLSL.h"
@@ -17,23 +17,94 @@
namespace sh
{
+namespace
+{
+
+TString Define(const TStructure &structure,
+ bool useHLSLRowMajorPacking,
+ bool useStd140Packing,
+ Std140PaddingHelper *padHelper)
+{
+ const TFieldList &fields = structure.fields();
+ const bool isNameless = (structure.name() == "");
+ const TString &structName =
+ QualifiedStructNameString(structure, useHLSLRowMajorPacking, useStd140Packing);
+ const TString declareString = (isNameless ? "struct" : "struct " + structName);
+
+ TString string;
+ string += declareString +
+ "\n"
+ "{\n";
+
+ for (const TField *field : fields)
+ {
+ const TType &fieldType = *field->type();
+ if (!IsSampler(fieldType.getBasicType()))
+ {
+ const TStructure *fieldStruct = fieldType.getStruct();
+ const TString &fieldTypeString =
+ fieldStruct ? QualifiedStructNameString(*fieldStruct, useHLSLRowMajorPacking,
+ useStd140Packing)
+ : TypeString(fieldType);
+
+ if (padHelper)
+ {
+ string += padHelper->prePaddingString(fieldType);
+ }
+
+ string += " " + fieldTypeString + " " + DecorateField(field->name(), structure) +
+ ArrayString(fieldType) + ";\n";
+
+ if (padHelper)
+ {
+ string += padHelper->postPaddingString(fieldType, useHLSLRowMajorPacking);
+ }
+ }
+ }
+
+ // Nameless structs do not finish with a semicolon and newline, to leave room for an instance
+ // variable
+ string += (isNameless ? "} " : "};\n");
+
+ return string;
+}
+
+TString WriteParameterList(const std::vector<TType> &parameters)
+{
+ TString parameterList;
+ for (size_t parameter = 0u; parameter < parameters.size(); parameter++)
+ {
+ const TType &paramType = parameters[parameter];
+
+ parameterList += TypeString(paramType) + " x" + str(parameter) + ArrayString(paramType);
+
+ if (parameter < parameters.size() - 1u)
+ {
+ parameterList += ", ";
+ }
+ }
+ return parameterList;
+}
+
+} // anonymous namespace
+
Std140PaddingHelper::Std140PaddingHelper(const std::map<TString, int> &structElementIndexes,
unsigned *uniqueCounter)
- : mPaddingCounter(uniqueCounter),
- mElementIndex(0),
- mStructElementIndexes(&structElementIndexes)
-{}
+ : mPaddingCounter(uniqueCounter), mElementIndex(0), mStructElementIndexes(&structElementIndexes)
+{
+}
Std140PaddingHelper::Std140PaddingHelper(const Std140PaddingHelper &other)
: mPaddingCounter(other.mPaddingCounter),
mElementIndex(other.mElementIndex),
mStructElementIndexes(other.mStructElementIndexes)
-{}
+{
+}
Std140PaddingHelper &Std140PaddingHelper::operator=(const Std140PaddingHelper &other)
{
- mPaddingCounter = other.mPaddingCounter;
- mElementIndex = other.mElementIndex;
+ mPaddingCounter = other.mPaddingCounter;
+ mElementIndex = other.mElementIndex;
mStructElementIndexes = other.mStructElementIndexes;
return *this;
}
@@ -53,7 +124,7 @@ int Std140PaddingHelper::prePadding(const TType &type)
return 0;
}
- const GLenum glType = GLVariableType(type);
+ const GLenum glType = GLVariableType(type);
const int numComponents = gl::VariableComponentCount(glType);
if (numComponents >= 4)
@@ -70,9 +141,9 @@ int Std140PaddingHelper::prePadding(const TType &type)
return 0;
}
- const int alignment = numComponents == 3 ? 4 : numComponents;
+ const int alignment = numComponents == 3 ? 4 : numComponents;
const int paddingOffset = (mElementIndex % alignment);
- const int paddingCount = (paddingOffset != 0 ? (alignment - paddingOffset) : 0);
+ const int paddingCount = (paddingOffset != 0 ? (alignment - paddingOffset) : 0);
mElementIndex += paddingCount;
mElementIndex += numComponents;
@@ -102,25 +173,26 @@ TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRo
return "";
}
- int numComponents = 0;
- TStructure *structure = type.getStruct();
+ int numComponents = 0;
+ const TStructure *structure = type.getStruct();
if (type.isMatrix())
{
- // This method can also be called from structureString, which does not use layout qualifiers.
+ // This method can also be called from structureString, which does not use layout
+ // qualifiers.
// Thus, use the method parameter for determining the matrix packing.
//
// Note HLSL row major packing corresponds to GL API column-major, and vice-versa, since we
// wish to always transpose GL matrices to play well with HLSL's matrix array indexing.
//
const bool isRowMajorMatrix = !useHLSLRowMajorPacking;
- const GLenum glType = GLVariableType(type);
- numComponents = gl::MatrixComponentCount(glType, isRowMajorMatrix);
+ const GLenum glType = GLVariableType(type);
+ numComponents = gl::MatrixComponentCount(glType, isRowMajorMatrix);
}
else if (structure)
{
- const TString &structName = QualifiedStructNameString(*structure,
- useHLSLRowMajorPacking, true);
+ const TString &structName =
+ QualifiedStructNameString(*structure, useHLSLRowMajorPacking, true);
numComponents = mStructElementIndexes->find(structName)->second;
if (numComponents == 0)
@@ -131,7 +203,7 @@ TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRo
else
{
const GLenum glType = GLVariableType(type);
- numComponents = gl::VariableComponentCount(glType);
+ numComponents = gl::VariableComponentCount(glType);
}
TString padding;
@@ -142,178 +214,183 @@ TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRo
return padding;
}
-StructureHLSL::StructureHLSL()
- : mUniquePaddingCounter(0)
-{}
+StructureHLSL::StructureHLSL() : mUniquePaddingCounter(0)
+{
+}
Std140PaddingHelper StructureHLSL::getPaddingHelper()
{
return Std140PaddingHelper(mStd140StructElementIndexes, &mUniquePaddingCounter);
}
-TString StructureHLSL::defineQualified(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing)
+TString StructureHLSL::defineQualified(const TStructure &structure,
+ bool useHLSLRowMajorPacking,
+ bool useStd140Packing)
{
if (useStd140Packing)
{
Std140PaddingHelper padHelper = getPaddingHelper();
- return define(structure, useHLSLRowMajorPacking, useStd140Packing, &padHelper);
+ return Define(structure, useHLSLRowMajorPacking, useStd140Packing, &padHelper);
}
else
{
- return define(structure, useHLSLRowMajorPacking, useStd140Packing, NULL);
+ return Define(structure, useHLSLRowMajorPacking, useStd140Packing, nullptr);
}
}
TString StructureHLSL::defineNameless(const TStructure &structure)
{
- return define(structure, false, false, NULL);
+ return Define(structure, false, false, nullptr);
}
-TString StructureHLSL::define(const TStructure &structure, bool useHLSLRowMajorPacking,
- bool useStd140Packing, Std140PaddingHelper *padHelper)
+StructureHLSL::DefinedStructs::iterator StructureHLSL::defineVariants(const TStructure &structure,
+ const TString &name)
{
- const TFieldList &fields = structure.fields();
- const bool isNameless = (structure.name() == "");
- const TString &structName = QualifiedStructNameString(structure, useHLSLRowMajorPacking,
- useStd140Packing);
- const TString declareString = (isNameless ? "struct" : "struct " + structName);
+ ASSERT(mDefinedStructs.find(name) == mDefinedStructs.end());
- TString string;
- string += declareString + "\n"
- "{\n";
-
- for (unsigned int i = 0; i < fields.size(); i++)
+ for (const TField *field : structure.fields())
{
- const TField &field = *fields[i];
- const TType &fieldType = *field.type();
- const TStructure *fieldStruct = fieldType.getStruct();
- const TString &fieldTypeString = fieldStruct ?
- QualifiedStructNameString(*fieldStruct, useHLSLRowMajorPacking,
- useStd140Packing) :
- TypeString(fieldType);
-
- if (padHelper)
+ const TType *fieldType = field->type();
+ if (fieldType->getBasicType() == EbtStruct)
{
- string += padHelper->prePaddingString(fieldType);
- }
-
- string += " " + fieldTypeString + " " + DecorateField(field.name(), structure) + ArrayString(fieldType) + ";\n";
-
- if (padHelper)
- {
- string += padHelper->postPaddingString(fieldType, useHLSLRowMajorPacking);
+ ensureStructDefined(*fieldType->getStruct());
}
}
- // Nameless structs do not finish with a semicolon and newline, to leave room for an instance variable
- string += (isNameless ? "} " : "};\n");
-
- return string;
+ DefinedStructs::iterator addedStruct =
+ mDefinedStructs.insert(std::make_pair(name, new TStructProperties())).first;
+ // Add element index
+ storeStd140ElementIndex(structure, false);
+ storeStd140ElementIndex(structure, true);
+
+ const TString &structString = defineQualified(structure, false, false);
+
+ ASSERT(std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structString) ==
+ mStructDeclarations.end());
+ // Add row-major packed struct for interface blocks
+ TString rowMajorString = "#pragma pack_matrix(row_major)\n" +
+ defineQualified(structure, true, false) +
+ "#pragma pack_matrix(column_major)\n";
+
+ TString std140String = defineQualified(structure, false, true);
+ TString std140RowMajorString = "#pragma pack_matrix(row_major)\n" +
+ defineQualified(structure, true, true) +
+ "#pragma pack_matrix(column_major)\n";
+
+ mStructDeclarations.push_back(structString);
+ mStructDeclarations.push_back(rowMajorString);
+ mStructDeclarations.push_back(std140String);
+ mStructDeclarations.push_back(std140RowMajorString);
+ return addedStruct;
}
-void StructureHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters)
+void StructureHLSL::ensureStructDefined(const TStructure &structure)
{
+ const TString name = StructNameString(structure);
if (name == "")
{
- return; // Nameless structures don't have constructors
+ return; // Nameless structures are not defined
}
-
- if (type.getStruct() && mStructNames.find(name) != mStructNames.end())
+ if (mDefinedStructs.find(name) == mDefinedStructs.end())
{
- return; // Already added
+ defineVariants(structure, name);
}
+}
- TType ctorType = type;
- ctorType.clearArrayness();
- ctorType.setPrecision(EbpHigh);
- ctorType.setQualifier(EvqTemporary);
-
- typedef std::vector<TType> ParameterArray;
- ParameterArray ctorParameters;
-
- const TStructure* structure = type.getStruct();
- if (structure)
- {
- mStructNames.insert(name);
-
- // Add element index
- storeStd140ElementIndex(*structure, false);
- storeStd140ElementIndex(*structure, true);
-
- const TString &structString = defineQualified(*structure, false, false);
-
- if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structString) == mStructDeclarations.end())
- {
- // Add row-major packed struct for interface blocks
- TString rowMajorString = "#pragma pack_matrix(row_major)\n" +
- defineQualified(*structure, true, false) +
- "#pragma pack_matrix(column_major)\n";
-
- TString std140String = defineQualified(*structure, false, true);
- TString std140RowMajorString = "#pragma pack_matrix(row_major)\n" +
- defineQualified(*structure, true, true) +
- "#pragma pack_matrix(column_major)\n";
-
- mStructDeclarations.push_back(structString);
- mStructDeclarations.push_back(rowMajorString);
- mStructDeclarations.push_back(std140String);
- mStructDeclarations.push_back(std140RowMajorString);
- }
+TString StructureHLSL::addStructConstructor(const TStructure &structure)
+{
+ const TString name = StructNameString(structure);
- const TFieldList &fields = structure->fields();
- for (unsigned int i = 0; i < fields.size(); i++)
- {
- ctorParameters.push_back(*fields[i]->type());
- }
- }
- else if (parameters)
+ if (name == "")
{
- for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++)
- {
- ctorParameters.push_back((*parameter)->getAsTyped()->getType());
- }
+ return TString(); // Nameless structures don't have constructors
}
- else UNREACHABLE();
-
- TString constructor;
- if (ctorType.getStruct())
+ auto definedStruct = mDefinedStructs.find(name);
+ if (definedStruct == mDefinedStructs.end())
{
- constructor += name + " " + name + "_ctor(";
+ definedStruct = defineVariants(structure, name);
}
- else // Built-in type
+ const TString constructorFunctionName = TString(name) + "_ctor";
+ TString *constructor = &definedStruct->second->constructor;
+ if (!constructor->empty())
{
- constructor += TypeString(ctorType) + " " + name + "(";
+ return constructorFunctionName; // Already added
}
+ *constructor += name + " " + constructorFunctionName + "(";
- for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++)
+ std::vector<TType> ctorParameters;
+ const TFieldList &fields = structure.fields();
+ for (const TField *field : fields)
{
- const TType &paramType = ctorParameters[parameter];
-
- constructor += TypeString(paramType) + " x" + str(parameter) + ArrayString(paramType);
-
- if (parameter < ctorParameters.size() - 1)
+ const TType *fieldType = field->type();
+ if (!IsSampler(fieldType->getBasicType()))
{
- constructor += ", ";
+ ctorParameters.push_back(*fieldType);
}
}
+ // Structs that have sampler members should not have constructor calls, and otherwise structs
+ // are guaranteed to be non-empty by the grammar. Structs can't contain empty declarations
+ // either.
+ ASSERT(!ctorParameters.empty());
+
+ *constructor += WriteParameterList(ctorParameters);
- constructor += ")\n"
- "{\n";
+ *constructor +=
+ ")\n"
+ "{\n"
+ " " +
+ name + " structure = { ";
- if (ctorType.getStruct())
+ for (size_t parameterIndex = 0u; parameterIndex < ctorParameters.size(); ++parameterIndex)
{
- constructor += " " + name + " structure = {";
+ *constructor += "x" + str(parameterIndex);
+ if (parameterIndex < ctorParameters.size() - 1u)
+ {
+ *constructor += ", ";
+ }
}
- else
+ *constructor +=
+ "};\n"
+ " return structure;\n"
+ "}\n";
+
+ return constructorFunctionName;
+}
+
+TString StructureHLSL::addBuiltInConstructor(const TType &type, const TIntermSequence *parameters)
+{
+ ASSERT(!type.isArray());
+ ASSERT(type.getStruct() == nullptr);
+ ASSERT(parameters);
+
+ TType ctorType = type;
+ ctorType.setPrecision(EbpHigh);
+ ctorType.setQualifier(EvqTemporary);
+
+ const TString constructorFunctionName =
+ TString(type.getBuiltInTypeNameString()) + "_ctor" + DisambiguateFunctionName(parameters);
+ TString constructor = TypeString(ctorType) + " " + constructorFunctionName + "(";
+
+ std::vector<TType> ctorParameters;
+ for (auto parameter : *parameters)
{
- constructor += " return " + TypeString(ctorType) + "(";
+ const TType &paramType = parameter->getAsTyped()->getType();
+ ASSERT(!paramType.isArray());
+ ctorParameters.push_back(paramType);
}
+ constructor += WriteParameterList(ctorParameters);
+
+ constructor +=
+ ")\n"
+ "{\n"
+ " return " +
+ TypeString(ctorType) + "(";
if (ctorType.isMatrix() && ctorParameters.size() == 1)
{
- int rows = ctorType.getRows();
- int cols = ctorType.getCols();
+ int rows = ctorType.getRows();
+ int cols = ctorType.getCols();
const TType &parameter = ctorParameters[0];
if (parameter.isScalar())
@@ -355,7 +432,8 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const
}
else
{
- ASSERT(rows == 2 && cols == 2 && parameter.isVector() && parameter.getNominalSize() == 4);
+ ASSERT(rows == 2 && cols == 2 && parameter.isVector() &&
+ parameter.getNominalSize() == 4);
constructor += "x0";
}
@@ -367,20 +445,13 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const
while (remainingComponents > 0)
{
- const TType &parameter = ctorParameters[parameterIndex];
+ const TType &parameter = ctorParameters[parameterIndex];
const size_t parameterSize = parameter.getObjectSize();
- bool moreParameters = parameterIndex + 1 < ctorParameters.size();
+ bool moreParameters = parameterIndex + 1 < ctorParameters.size();
constructor += "x" + str(parameterIndex);
- if (ctorType.getStruct())
- {
- ASSERT(remainingComponents == parameterSize || moreParameters);
- ASSERT(parameterSize <= remainingComponents);
-
- remainingComponents -= parameterSize;
- }
- else if (parameter.isScalar())
+ if (parameter.isScalar())
{
remainingComponents -= parameter.getObjectSize();
}
@@ -395,16 +466,26 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const
{
switch (remainingComponents)
{
- case 1: constructor += ".x"; break;
- case 2: constructor += ".xy"; break;
- case 3: constructor += ".xyz"; break;
- case 4: constructor += ".xyzw"; break;
- default: UNREACHABLE();
+ case 1:
+ constructor += ".x";
+ break;
+ case 2:
+ constructor += ".xy";
+ break;
+ case 3:
+ constructor += ".xyz";
+ break;
+ case 4:
+ constructor += ".xyzw";
+ break;
+ default:
+ UNREACHABLE();
}
remainingComponents = 0;
}
- else UNREACHABLE();
+ else
+ UNREACHABLE();
}
else if (parameter.isMatrix())
{
@@ -417,10 +498,17 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const
{
switch (remainingComponents)
{
- case 1: constructor += ".x"; break;
- case 2: constructor += ".xy"; break;
- case 3: constructor += ".xyz"; break;
- default: UNREACHABLE();
+ case 1:
+ constructor += ".x";
+ break;
+ case 2:
+ constructor += ".xy";
+ break;
+ case 3:
+ constructor += ".xyz";
+ break;
+ default:
+ UNREACHABLE();
}
remainingComponents = 0;
@@ -438,7 +526,10 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const
column++;
}
}
- else UNREACHABLE();
+ else
+ {
+ UNREACHABLE();
+ }
if (moreParameters)
{
@@ -452,53 +543,52 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const
}
}
- if (ctorType.getStruct())
- {
- constructor += "};\n"
- " return structure;\n"
- "}\n";
- }
- else
- {
- constructor += ");\n"
- "}\n";
- }
+ constructor +=
+ ");\n"
+ "}\n";
- mConstructors.insert(constructor);
+ mBuiltInConstructors.insert(constructor);
+
+ return constructorFunctionName;
}
std::string StructureHLSL::structsHeader() const
{
TInfoSinkBase out;
- for (size_t structIndex = 0; structIndex < mStructDeclarations.size(); structIndex++)
+ for (auto &declaration : mStructDeclarations)
+ {
+ out << declaration;
+ }
+
+ for (auto &structure : mDefinedStructs)
{
- out << mStructDeclarations[structIndex];
+ out << structure.second->constructor;
}
- for (Constructors::const_iterator constructor = mConstructors.begin();
- constructor != mConstructors.end();
- constructor++)
+ for (auto &constructor : mBuiltInConstructors)
{
- out << *constructor;
+ out << constructor;
}
return out.str();
}
-void StructureHLSL::storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking)
+void StructureHLSL::storeStd140ElementIndex(const TStructure &structure,
+ bool useHLSLRowMajorPacking)
{
Std140PaddingHelper padHelper = getPaddingHelper();
- const TFieldList &fields = structure.fields();
+ const TFieldList &fields = structure.fields();
- for (unsigned int i = 0; i < fields.size(); i++)
+ for (const TField *field : fields)
{
- padHelper.prePadding(*fields[i]->type());
+ padHelper.prePadding(*field->type());
}
- // Add remaining element index to the global map, for use with nested structs in standard layouts
+ // Add remaining element index to the global map, for use with nested structs in standard
+ // layouts
const TString &structName = QualifiedStructNameString(structure, useHLSLRowMajorPacking, true);
mStd140StructElementIndexes[structName] = padHelper.elementIndex();
}
-}
+} // namespace sh