diff --git a/projects/src/translator_lib.vcxproj b/projects/src/translator_lib.vcxproj index 7d2cef98a..f46653133 100644 --- a/projects/src/translator_lib.vcxproj +++ b/projects/src/translator_lib.vcxproj @@ -159,6 +159,7 @@ + @@ -249,6 +250,7 @@ + diff --git a/projects/src/translator_lib.vcxproj.filters b/projects/src/translator_lib.vcxproj.filters index aa9b061a2..57f1a65d0 100644 --- a/projects/src/translator_lib.vcxproj.filters +++ b/projects/src/translator_lib.vcxproj.filters @@ -261,6 +261,9 @@ src\compiler\translator + + src\compiler\translator + src\compiler\translator @@ -390,6 +393,9 @@ src\compiler\translator + + src\compiler\translator + src\compiler\translator diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp index 2e88b52f5..220898ef1 100644 --- a/src/compiler/translator/OutputHLSL.cpp +++ b/src/compiler/translator/OutputHLSL.cpp @@ -19,6 +19,7 @@ #include "compiler/translator/RewriteElseBlocks.h" #include "compiler/translator/UtilsHLSL.h" #include "compiler/translator/util.h" +#include "compiler/translator/StructureHLSL.h" #include #include @@ -27,119 +28,6 @@ namespace sh { -class Std140PaddingHelper -{ - public: - explicit Std140PaddingHelper(const std::map &structElementIndexes) - : mPaddingCounter(0), - mElementIndex(0), - mStructElementIndexes(structElementIndexes) - {} - - int elementIndex() const { return mElementIndex; } - - int prePadding(const TType &type) - { - if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray()) - { - // no padding needed, HLSL will align the field to a new register - mElementIndex = 0; - return 0; - } - - const GLenum glType = GLVariableType(type); - const int numComponents = gl::UniformComponentCount(glType); - - if (numComponents >= 4) - { - // no padding needed, HLSL will align the field to a new register - mElementIndex = 0; - return 0; - } - - if (mElementIndex + numComponents > 4) - { - // no padding needed, HLSL will align the field to a new register - mElementIndex = numComponents; - return 0; - } - - const int alignment = numComponents == 3 ? 4 : numComponents; - const int paddingOffset = (mElementIndex % alignment); - const int paddingCount = (paddingOffset != 0 ? (alignment - paddingOffset) : 0); - - mElementIndex += paddingCount; - mElementIndex += numComponents; - mElementIndex %= 4; - - return paddingCount; - } - - TString prePaddingString(const TType &type) - { - int paddingCount = prePadding(type); - - TString padding; - - for (int paddingIndex = 0; paddingIndex < paddingCount; paddingIndex++) - { - padding += " float pad_" + str(mPaddingCounter++) + ";\n"; - } - - return padding; - } - - TString postPaddingString(const TType &type, bool useHLSLRowMajorPacking) - { - if (!type.isMatrix() && !type.isArray() && type.getBasicType() != EbtStruct) - { - return ""; - } - - int numComponents = 0; - - if (type.isMatrix()) - { - // 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); - } - else if (type.getStruct()) - { - const TString &structName = QualifiedStructNameString(*type.getStruct(), useHLSLRowMajorPacking, true); - numComponents = mStructElementIndexes.find(structName)->second; - - if (numComponents == 0) - { - return ""; - } - } - else - { - const GLenum glType = GLVariableType(type); - numComponents = gl::UniformComponentCount(glType); - } - - TString padding; - for (int paddingOffset = numComponents; paddingOffset < 4; paddingOffset++) - { - padding += " float pad_" + str(mPaddingCounter++) + ";\n"; - } - return padding; - } - - private: - int mPaddingCounter; - int mElementIndex; - const std::map &mStructElementIndexes; -}; - TString OutputHLSL::TextureFunction::name() const { TString name = "gl_texture"; @@ -260,6 +148,8 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc mExcessiveLoopIndex = NULL; + mStructureHLSL = new StructureHLSL; + if (mOutputType == SH_HLSL9_OUTPUT) { if (mContext.shaderType == SH_FRAGMENT_SHADER) @@ -282,7 +172,8 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc OutputHLSL::~OutputHLSL() { - delete mUnfoldShortCircuit; + SafeDelete(mUnfoldShortCircuit); + SafeDelete(mStructureHLSL); } void OutputHLSL::output() @@ -426,7 +317,7 @@ TString OutputHLSL::interfaceBlockFieldString(const TInterfaceBlock &interfaceBl { TString hlsl; - Std140PaddingHelper padHelper(mStd140StructElementIndexes); + Std140PaddingHelper padHelper = mStructureHLSL->getPaddingHelper(); for (unsigned int typeIndex = 0; typeIndex < interfaceBlock.fields().size(); typeIndex++) { @@ -688,15 +579,7 @@ void OutputHLSL::header() mActiveAttributes.push_back(attributeVar); } - for (StructDeclarations::iterator structDeclaration = mStructDeclarations.begin(); structDeclaration != mStructDeclarations.end(); structDeclaration++) - { - out << *structDeclaration; - } - - for (Constructors::iterator constructor = mConstructors.begin(); constructor != mConstructors.end(); constructor++) - { - out << *constructor; - } + out << mStructureHLSL->structsHeader(); if (mUsesDiscardRewriting) { @@ -2251,9 +2134,11 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) if (variable && (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal)) { - if (variable->getType().getStruct()) + TStructure *structure = variable->getType().getStruct(); + + if (structure) { - addConstructor(variable->getType(), StructNameString(*variable->getType().getStruct()), NULL); + mStructureHLSL->addConstructor(variable->getType(), StructNameString(*structure), NULL); } if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration @@ -2378,9 +2263,11 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) if (symbol) { - if (symbol->getType().getStruct()) + TStructure *structure = symbol->getType().getStruct(); + + if (structure) { - addConstructor(symbol->getType(), StructNameString(*symbol->getType().getStruct()), NULL); + mStructureHLSL->addConstructor(symbol->getType(), StructNameString(*structure), NULL); } out << argumentString(symbol); @@ -2593,7 +2480,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case EOpConstructStruct: { const TString &structName = StructNameString(*node->getType().getStruct()); - addConstructor(node->getType(), structName, &node->getSequence()); + mStructureHLSL->addConstructor(node->getType(), structName, &node->getSequence()); outputTriplet(visit, structName + "_ctor(", ", ", ")"); } break; @@ -3194,73 +3081,13 @@ TString OutputHLSL::initializer(const TType &type) return "{" + string + "}"; } -TString OutputHLSL::defineNamelessStruct(const TStructure &structure) -{ - return defineStruct(structure, false, false, NULL); -} - -TString OutputHLSL::defineQualifiedStruct(const TStructure &structure, bool useHLSLRowMajorPacking, - bool useStd140Packing) -{ - if (useStd140Packing) - { - Std140PaddingHelper padHelper(mStd140StructElementIndexes); - return defineStruct(structure, useHLSLRowMajorPacking, true, &padHelper); - } - else - { - return defineStruct(structure, useHLSLRowMajorPacking, false, NULL); - } -} - -TString OutputHLSL::defineStruct(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 (unsigned int i = 0; i < fields.size(); i++) - { - 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) - { - 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; -} - void OutputHLSL::outputConstructor(Visit visit, const TType &type, const TString &name, const TIntermSequence *parameters) { TInfoSinkBase &out = mBody; if (visit == PreVisit) { - addConstructor(type, name, parameters); + mStructureHLSL->addConstructor(type, name, parameters); out << name + "("; } @@ -3274,277 +3101,6 @@ void OutputHLSL::outputConstructor(Visit visit, const TType &type, const TString } } -void OutputHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters) -{ - if (name == "") - { - return; // Nameless structures don't have constructors - } - - if (type.getStruct() && mStructNames.find(name) != mStructNames.end()) - { - return; // Already added - } - - TType ctorType = type; - ctorType.clearArrayness(); - ctorType.setPrecision(EbpHigh); - ctorType.setQualifier(EvqTemporary); - - typedef std::vector 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 = defineQualifiedStruct(*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" + - defineQualifiedStruct(*structure, true, false) + - "#pragma pack_matrix(column_major)\n"; - - TString std140String = defineQualifiedStruct(*structure, false, true); - TString std140RowMajorString = "#pragma pack_matrix(row_major)\n" + - defineQualifiedStruct(*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); - } - - const TFieldList &fields = structure->fields(); - for (unsigned int i = 0; i < fields.size(); i++) - { - ctorParameters.push_back(*fields[i]->type()); - } - } - else if (parameters) - { - for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++) - { - ctorParameters.push_back((*parameter)->getAsTyped()->getType()); - } - } - else UNREACHABLE(); - - TString constructor; - - if (ctorType.getStruct()) - { - constructor += name + " " + name + "_ctor("; - } - else // Built-in type - { - constructor += TypeString(ctorType) + " " + name + "("; - } - - for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++) - { - const TType &type = ctorParameters[parameter]; - - constructor += TypeString(type) + " x" + str(parameter) + ArrayString(type); - - if (parameter < ctorParameters.size() - 1) - { - constructor += ", "; - } - } - - constructor += ")\n" - "{\n"; - - if (ctorType.getStruct()) - { - constructor += " " + name + " structure = {"; - } - else - { - constructor += " return " + TypeString(ctorType) + "("; - } - - if (ctorType.isMatrix() && ctorParameters.size() == 1) - { - int rows = ctorType.getRows(); - int cols = ctorType.getCols(); - const TType ¶meter = ctorParameters[0]; - - if (parameter.isScalar()) - { - for (int row = 0; row < rows; row++) - { - for (int col = 0; col < cols; col++) - { - constructor += TString((row == col) ? "x0" : "0.0"); - - if (row < rows - 1 || col < cols - 1) - { - constructor += ", "; - } - } - } - } - else if (parameter.isMatrix()) - { - for (int row = 0; row < rows; row++) - { - for (int col = 0; col < cols; col++) - { - if (row < parameter.getRows() && col < parameter.getCols()) - { - constructor += TString("x0") + "[" + str(row) + "][" + str(col) + "]"; - } - else - { - constructor += TString((row == col) ? "1.0" : "0.0"); - } - - if (row < rows - 1 || col < cols - 1) - { - constructor += ", "; - } - } - } - } - else - { - ASSERT(rows == 2 && cols == 2 && parameter.isVector() && parameter.getNominalSize() == 4); - - constructor += "x0"; - } - } - else - { - size_t remainingComponents = ctorType.getObjectSize(); - size_t parameterIndex = 0; - - while (remainingComponents > 0) - { - const TType ¶meter = ctorParameters[parameterIndex]; - const size_t parameterSize = parameter.getObjectSize(); - 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()) - { - remainingComponents -= parameter.getObjectSize(); - } - else if (parameter.isVector()) - { - if (remainingComponents == parameterSize || moreParameters) - { - ASSERT(parameterSize <= remainingComponents); - remainingComponents -= parameterSize; - } - else if (remainingComponents < static_cast(parameter.getNominalSize())) - { - switch (remainingComponents) - { - 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 if (parameter.isMatrix()) - { - int column = 0; - while (remainingComponents > 0 && column < parameter.getCols()) - { - constructor += "[" + str(column) + "]"; - - if (remainingComponents < static_cast(parameter.getRows())) - { - switch (remainingComponents) - { - case 1: constructor += ".x"; break; - case 2: constructor += ".xy"; break; - case 3: constructor += ".xyz"; break; - default: UNREACHABLE(); - } - - remainingComponents = 0; - } - else - { - remainingComponents -= parameter.getRows(); - - if (remainingComponents > 0) - { - constructor += ", x" + str(parameterIndex); - } - } - - column++; - } - } - else UNREACHABLE(); - - if (moreParameters) - { - parameterIndex++; - } - - if (remainingComponents) - { - constructor += ", "; - } - } - } - - if (ctorType.getStruct()) - { - constructor += "};\n" - " return structure;\n" - "}\n"; - } - else - { - constructor += ");\n" - "}\n"; - } - - mConstructors.insert(constructor); -} - -void OutputHLSL::storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking) -{ - Std140PaddingHelper padHelper(mStd140StructElementIndexes); - const TFieldList &fields = structure.fields(); - - for (unsigned int i = 0; i < fields.size(); i++) - { - padHelper.prePadding(*fields[i]->type()); - } - - // 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(); -} - const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion) { TInfoSinkBase &out = mBody; diff --git a/src/compiler/translator/OutputHLSL.h b/src/compiler/translator/OutputHLSL.h index 1daf643ac..214ed4283 100644 --- a/src/compiler/translator/OutputHLSL.h +++ b/src/compiler/translator/OutputHLSL.h @@ -21,7 +21,7 @@ namespace sh { class UnfoldShortCircuit; -class Std140PaddingHelper; +class StructureHLSL; class OutputHLSL : public TIntermTraverser { @@ -38,8 +38,6 @@ class OutputHLSL : public TIntermTraverser const std::vector &getAttributes() const; const std::vector &getVaryings() const; - static TString defineNamelessStruct(const TStructure &structure); - TString defineQualifiedStruct(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing); static TString initializer(const TType &type); protected: @@ -64,8 +62,6 @@ class OutputHLSL : public TIntermTraverser int vectorSize(const TType &type) const; void outputConstructor(Visit visit, const TType &type, const TString &name, const TIntermSequence *parameters); - void addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters); - void storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking); const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *constUnion); TParseContext &mContext; @@ -85,6 +81,8 @@ class OutputHLSL : public TIntermTraverser ReferencedSymbols mReferencedVaryings; ReferencedSymbols mReferencedOutputVariables; + StructureHLSL *mStructureHLSL; + struct TextureFunction { enum Method @@ -143,15 +141,6 @@ class OutputHLSL : public TIntermTraverser int mNumRenderTargets; - typedef std::set Constructors; - Constructors mConstructors; - - typedef std::set StructNames; - StructNames mStructNames; - - typedef std::list StructDeclarations; - StructDeclarations mStructDeclarations; - int mUniqueIndex; // For creating unique names bool mContainsLoopDiscontinuity; @@ -184,20 +173,18 @@ class OutputHLSL : public TIntermTraverser TString interfaceBlockStructString(const TInterfaceBlock &interfaceBlock); TString interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex); TString structInitializerString(int indent, const TStructure &structure, const TString &rhsStructName); - static TString defineStruct(const TStructure &structure, bool useHLSLRowMajorPacking, - bool useStd140Packing, Std140PaddingHelper *padHelper); std::vector mActiveUniforms; std::vector mActiveInterfaceBlocks; std::vector mActiveOutputVariables; std::vector mActiveAttributes; std::vector mActiveVaryings; - std::map mStd140StructElementIndexes; std::map mFlaggedStructMappedNames; std::map mFlaggedStructOriginalNames; void makeFlaggedStructMaps(const std::vector &flaggedStructs); }; + } #endif // COMPILER_OUTPUTHLSL_H_ diff --git a/src/compiler/translator/StructureHLSL.cpp b/src/compiler/translator/StructureHLSL.cpp new file mode 100644 index 000000000..e19058f23 --- /dev/null +++ b/src/compiler/translator/StructureHLSL.cpp @@ -0,0 +1,475 @@ +// +// Copyright (c) 2014 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. +// +// StructureHLSL.cpp: +// Definitions of methods for HLSL translation of GLSL structures. +// + +#include "compiler/translator/StructureHLSL.h" +#include "common/utilities.h" +#include "compiler/translator/OutputHLSL.h" +#include "compiler/translator/Types.h" +#include "compiler/translator/util.h" +#include "compiler/translator/UtilsHLSL.h" + +namespace sh +{ + +Std140PaddingHelper::Std140PaddingHelper(const std::map &structElementIndexes) + : mPaddingCounter(0), + mElementIndex(0), + mStructElementIndexes(structElementIndexes) +{} + +int Std140PaddingHelper::prePadding(const TType &type) +{ + if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray()) + { + // no padding needed, HLSL will align the field to a new register + mElementIndex = 0; + return 0; + } + + const GLenum glType = GLVariableType(type); + const int numComponents = gl::UniformComponentCount(glType); + + if (numComponents >= 4) + { + // no padding needed, HLSL will align the field to a new register + mElementIndex = 0; + return 0; + } + + if (mElementIndex + numComponents > 4) + { + // no padding needed, HLSL will align the field to a new register + mElementIndex = numComponents; + return 0; + } + + const int alignment = numComponents == 3 ? 4 : numComponents; + const int paddingOffset = (mElementIndex % alignment); + const int paddingCount = (paddingOffset != 0 ? (alignment - paddingOffset) : 0); + + mElementIndex += paddingCount; + mElementIndex += numComponents; + mElementIndex %= 4; + + return paddingCount; +} + +TString Std140PaddingHelper::prePaddingString(const TType &type) +{ + int paddingCount = prePadding(type); + + TString padding; + + for (int paddingIndex = 0; paddingIndex < paddingCount; paddingIndex++) + { + padding += " float pad_" + str(mPaddingCounter++) + ";\n"; + } + + return padding; +} + +TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRowMajorPacking) +{ + if (!type.isMatrix() && !type.isArray() && type.getBasicType() != EbtStruct) + { + return ""; + } + + int numComponents = 0; + TStructure *structure = type.getStruct(); + + if (type.isMatrix()) + { + // 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); + } + else if (structure) + { + const TString &structName = QualifiedStructNameString(*structure, + useHLSLRowMajorPacking, true); + numComponents = mStructElementIndexes.find(structName)->second; + + if (numComponents == 0) + { + return ""; + } + } + else + { + const GLenum glType = GLVariableType(type); + numComponents = gl::UniformComponentCount(glType); + } + + TString padding; + for (int paddingOffset = numComponents; paddingOffset < 4; paddingOffset++) + { + padding += " float pad_" + str(mPaddingCounter++) + ";\n"; + } + return padding; +} + +StructureHLSL::StructureHLSL() +{} + +TString StructureHLSL::defineQualified(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing) +{ + if (useStd140Packing) + { + Std140PaddingHelper padHelper(mStd140StructElementIndexes); + return define(structure, useHLSLRowMajorPacking, useStd140Packing, &padHelper); + } + else + { + return define(structure, useHLSLRowMajorPacking, useStd140Packing, NULL); + } +} + +TString StructureHLSL::defineNameless(const TStructure &structure) +{ + return define(structure, false, false, NULL); +} + +TString StructureHLSL::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 (unsigned int i = 0; i < fields.size(); i++) + { + 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) + { + 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; +} + +void StructureHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters) +{ + if (name == "") + { + return; // Nameless structures don't have constructors + } + + if (type.getStruct() && mStructNames.find(name) != mStructNames.end()) + { + return; // Already added + } + + TType ctorType = type; + ctorType.clearArrayness(); + ctorType.setPrecision(EbpHigh); + ctorType.setQualifier(EvqTemporary); + + typedef std::vector 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); + } + + const TFieldList &fields = structure->fields(); + for (unsigned int i = 0; i < fields.size(); i++) + { + ctorParameters.push_back(*fields[i]->type()); + } + } + else if (parameters) + { + for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++) + { + ctorParameters.push_back((*parameter)->getAsTyped()->getType()); + } + } + else UNREACHABLE(); + + TString constructor; + + if (ctorType.getStruct()) + { + constructor += name + " " + name + "_ctor("; + } + else // Built-in type + { + constructor += TypeString(ctorType) + " " + name + "("; + } + + for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++) + { + const TType &type = ctorParameters[parameter]; + + constructor += TypeString(type) + " x" + str(parameter) + ArrayString(type); + + if (parameter < ctorParameters.size() - 1) + { + constructor += ", "; + } + } + + constructor += ")\n" + "{\n"; + + if (ctorType.getStruct()) + { + constructor += " " + name + " structure = {"; + } + else + { + constructor += " return " + TypeString(ctorType) + "("; + } + + if (ctorType.isMatrix() && ctorParameters.size() == 1) + { + int rows = ctorType.getRows(); + int cols = ctorType.getCols(); + const TType ¶meter = ctorParameters[0]; + + if (parameter.isScalar()) + { + for (int row = 0; row < rows; row++) + { + for (int col = 0; col < cols; col++) + { + constructor += TString((row == col) ? "x0" : "0.0"); + + if (row < rows - 1 || col < cols - 1) + { + constructor += ", "; + } + } + } + } + else if (parameter.isMatrix()) + { + for (int row = 0; row < rows; row++) + { + for (int col = 0; col < cols; col++) + { + if (row < parameter.getRows() && col < parameter.getCols()) + { + constructor += TString("x0") + "[" + str(row) + "][" + str(col) + "]"; + } + else + { + constructor += TString((row == col) ? "1.0" : "0.0"); + } + + if (row < rows - 1 || col < cols - 1) + { + constructor += ", "; + } + } + } + } + else + { + ASSERT(rows == 2 && cols == 2 && parameter.isVector() && parameter.getNominalSize() == 4); + + constructor += "x0"; + } + } + else + { + size_t remainingComponents = ctorType.getObjectSize(); + size_t parameterIndex = 0; + + while (remainingComponents > 0) + { + const TType ¶meter = ctorParameters[parameterIndex]; + const size_t parameterSize = parameter.getObjectSize(); + 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()) + { + remainingComponents -= parameter.getObjectSize(); + } + else if (parameter.isVector()) + { + if (remainingComponents == parameterSize || moreParameters) + { + ASSERT(parameterSize <= remainingComponents); + remainingComponents -= parameterSize; + } + else if (remainingComponents < static_cast(parameter.getNominalSize())) + { + switch (remainingComponents) + { + 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 if (parameter.isMatrix()) + { + int column = 0; + while (remainingComponents > 0 && column < parameter.getCols()) + { + constructor += "[" + str(column) + "]"; + + if (remainingComponents < static_cast(parameter.getRows())) + { + switch (remainingComponents) + { + case 1: constructor += ".x"; break; + case 2: constructor += ".xy"; break; + case 3: constructor += ".xyz"; break; + default: UNREACHABLE(); + } + + remainingComponents = 0; + } + else + { + remainingComponents -= parameter.getRows(); + + if (remainingComponents > 0) + { + constructor += ", x" + str(parameterIndex); + } + } + + column++; + } + } + else UNREACHABLE(); + + if (moreParameters) + { + parameterIndex++; + } + + if (remainingComponents) + { + constructor += ", "; + } + } + } + + if (ctorType.getStruct()) + { + constructor += "};\n" + " return structure;\n" + "}\n"; + } + else + { + constructor += ");\n" + "}\n"; + } + + mConstructors.insert(constructor); +} + +std::string StructureHLSL::structsHeader() const +{ + TInfoSinkBase out; + + for (size_t structIndex = 0; structIndex < mStructDeclarations.size(); structIndex++) + { + out << mStructDeclarations[structIndex]; + } + + for (Constructors::iterator constructor = mConstructors.begin(); constructor != mConstructors.end(); constructor++) + { + out << *constructor; + } + + return out.str(); +} + +void StructureHLSL::storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking) +{ + Std140PaddingHelper padHelper(mStd140StructElementIndexes); + const TFieldList &fields = structure.fields(); + + for (unsigned int i = 0; i < fields.size(); i++) + { + padHelper.prePadding(*fields[i]->type()); + } + + // 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(); +} + +} \ No newline at end of file diff --git a/src/compiler/translator/StructureHLSL.h b/src/compiler/translator/StructureHLSL.h new file mode 100644 index 000000000..63fbaaaf8 --- /dev/null +++ b/src/compiler/translator/StructureHLSL.h @@ -0,0 +1,74 @@ +// +// Copyright (c) 2014 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. +// +// StructureHLSL.h: +// Interfaces of methods for HLSL translation of GLSL structures. +// + +#ifndef TRANSLATOR_STRUCTUREHLSL_H_ +#define TRANSLATOR_STRUCTUREHLSL_H_ + +#include "compiler/translator/Common.h" +#include "compiler/translator/intermediate.h" + +#include + +class TInfoSinkBase; +class TScopeBracket; + +namespace sh +{ + +// This helper class assists structure and interface block definitions in determining +// how to pack std140 structs within HLSL's packing rules. +class Std140PaddingHelper +{ + public: + explicit Std140PaddingHelper(const std::map &structElementIndexes); + + int elementIndex() const { return mElementIndex; } + int prePadding(const TType &type); + TString prePaddingString(const TType &type); + TString postPaddingString(const TType &type, bool useHLSLRowMajorPacking); + + private: + int mPaddingCounter; + int mElementIndex; + const std::map &mStructElementIndexes; +}; + +class StructureHLSL +{ + public: + StructureHLSL(); + + void addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters); + std::string structsHeader() const; + + TString defineQualified(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing); + static TString defineNameless(const TStructure &structure); + + Std140PaddingHelper getPaddingHelper() const { return Std140PaddingHelper(mStd140StructElementIndexes); } + + private: + std::map mStd140StructElementIndexes; + + typedef std::set StructNames; + StructNames mStructNames; + + typedef std::set Constructors; + Constructors mConstructors; + + typedef std::vector StructDeclarations; + StructDeclarations mStructDeclarations; + + void storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking); + static TString define(const TStructure &structure, bool useHLSLRowMajorPacking, + bool useStd140Packing, Std140PaddingHelper *padHelper); +}; + +} + +#endif // COMPILER_STRUCTUREHLSL_H_ diff --git a/src/compiler/translator/UtilsHLSL.cpp b/src/compiler/translator/UtilsHLSL.cpp index fa9b494e0..dbe35a50e 100644 --- a/src/compiler/translator/UtilsHLSL.cpp +++ b/src/compiler/translator/UtilsHLSL.cpp @@ -8,7 +8,7 @@ // #include "compiler/translator/UtilsHLSL.h" -#include "compiler/translator/OutputHLSL.h" +#include "compiler/translator/StructureHLSL.h" #include "compiler/translator/SymbolTable.h" namespace sh @@ -99,7 +99,7 @@ TString TypeString(const TType &type) } else // Nameless structure, define in place { - return OutputHLSL::defineNamelessStruct(*structure); + return StructureHLSL::defineNameless(*structure); } } else if (type.isMatrix()) @@ -175,7 +175,7 @@ TString StructNameString(const TStructure &structure) return ""; } - return "ss_" + str(structure.uniqueId()) + structure.name(); + return "ss" + str(structure.uniqueId()) + "_" + structure.name(); } TString QualifiedStructNameString(const TStructure &structure, bool useHLSLRowMajorPacking, @@ -193,13 +193,12 @@ TString QualifiedStructNameString(const TStructure &structure, bool useHLSLRowMa if (useStd140Packing) { - prefix += "std"; + prefix += "std_"; } if (useHLSLRowMajorPacking) { - if (prefix != "") prefix += "_"; - prefix += "rm"; + prefix += "rm_"; } return prefix + StructNameString(structure);