diff options
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp')
-rw-r--r-- | src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp | 448 |
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> ¶meters) +{ + TString parameterList; + for (size_t parameter = 0u; parameter < parameters.size(); parameter++) + { + const TType ¶mType = 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 ¶mType = 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 ¶mType = 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 ¶meter = 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 ¶meter = ctorParameters[parameterIndex]; + const TType ¶meter = 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 |