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);