Split OutputHLSL uniform code into new module.
Refactoring patch only, should have no externally visible changes.
BUG=angle:466
Change-Id: I01088a3b2979b96702d0a3c424d26928eb72b5b2
Reviewed-on: https://chromium-review.googlesource.com/203731
Reviewed-by: Nicolas Capens <nicolascapens@chromium.org>
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index 220898e..4783e59 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/UniformHLSL.h"
#include "compiler/translator/StructureHLSL.h"
#include <algorithm>
@@ -72,18 +73,6 @@
return name + "(";
}
-const char *RegisterPrefix(const TType &type)
-{
- if (IsSampler(type.getBasicType()))
- {
- return "s";
- }
- else
- {
- return "c";
- }
-}
-
bool OutputHLSL::TextureFunction::operator<(const TextureFunction &rhs) const
{
if (sampler < rhs.sampler) return true;
@@ -149,31 +138,31 @@
mExcessiveLoopIndex = NULL;
mStructureHLSL = new StructureHLSL;
+ mUniformHLSL = new UniformHLSL(mStructureHLSL, mOutputType);
if (mOutputType == SH_HLSL9_OUTPUT)
{
if (mContext.shaderType == SH_FRAGMENT_SHADER)
{
- mUniformRegister = 3; // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront
+ // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront
+ mUniformHLSL->reserveUniformRegisters(3);
}
else
{
- mUniformRegister = 2; // Reserve registers for dx_DepthRange and dx_ViewAdjust
+ // Reserve registers for dx_DepthRange and dx_ViewAdjust
+ mUniformHLSL->reserveUniformRegisters(2);
}
}
- else
- {
- mUniformRegister = 0;
- }
- mSamplerRegister = 0;
- mInterfaceBlockRegister = 2; // Reserve registers for the default uniform block and driver constants
+ // Reserve registers for the default uniform block and driver constants
+ mUniformHLSL->reserveInterfaceBlockRegisters(2);
}
OutputHLSL::~OutputHLSL()
{
SafeDelete(mUnfoldShortCircuit);
SafeDelete(mStructureHLSL);
+ SafeDelete(mUniformHLSL);
}
void OutputHLSL::output()
@@ -225,12 +214,12 @@
const std::vector<gl::Uniform> &OutputHLSL::getUniforms()
{
- return mActiveUniforms;
+ return mUniformHLSL->getUniforms();
}
const std::vector<gl::InterfaceBlock> &OutputHLSL::getInterfaceBlocks() const
{
- return mActiveInterfaceBlocks;
+ return mUniformHLSL->getInterfaceBlocks();
}
const std::vector<gl::Attribute> &OutputHLSL::getOutputVariables() const
@@ -256,170 +245,6 @@
return elementSize * arraySize;
}
-TString OutputHLSL::interfaceBlockFieldString(const TInterfaceBlock &interfaceBlock, const TField &field)
-{
- if (interfaceBlock.hasInstanceName())
- {
- return interfaceBlock.name() + "." + field.name();
- }
- else
- {
- return field.name();
- }
-}
-
-TString OutputHLSL::interfaceBlockStructNameString(const TInterfaceBlock &interfaceBlock)
-{
- return DecoratePrivate(interfaceBlock.name()) + "_type";
-}
-
-TString OutputHLSL::interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex)
-{
- if (!interfaceBlock.hasInstanceName())
- {
- return "";
- }
- else if (interfaceBlock.isArray())
- {
- return DecoratePrivate(interfaceBlock.instanceName()) + "_" + str(arrayIndex);
- }
- else
- {
- return Decorate(interfaceBlock.instanceName());
- }
-}
-
-TString OutputHLSL::interfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage)
-{
- const TType &fieldType = *field.type();
- const TLayoutMatrixPacking matrixPacking = fieldType.getLayoutQualifier().matrixPacking;
- ASSERT(matrixPacking != EmpUnspecified);
-
- if (fieldType.isMatrix())
- {
- // Use HLSL row-major packing for GLSL column-major matrices
- const TString &matrixPackString = (matrixPacking == EmpRowMajor ? "column_major" : "row_major");
- return matrixPackString + " " + TypeString(fieldType);
- }
- else if (fieldType.getStruct())
- {
- // Use HLSL row-major packing for GLSL column-major matrices
- return QualifiedStructNameString(*fieldType.getStruct(), matrixPacking == EmpColumnMajor,
- blockStorage == EbsStd140);
- }
- else
- {
- return TypeString(fieldType);
- }
-}
-
-TString OutputHLSL::interfaceBlockFieldString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage)
-{
- TString hlsl;
-
- Std140PaddingHelper padHelper = mStructureHLSL->getPaddingHelper();
-
- for (unsigned int typeIndex = 0; typeIndex < interfaceBlock.fields().size(); typeIndex++)
- {
- const TField &field = *interfaceBlock.fields()[typeIndex];
- const TType &fieldType = *field.type();
-
- if (blockStorage == EbsStd140)
- {
- // 2 and 3 component vector types in some cases need pre-padding
- hlsl += padHelper.prePaddingString(fieldType);
- }
-
- hlsl += " " + interfaceBlockFieldTypeString(field, blockStorage) +
- " " + Decorate(field.name()) + ArrayString(fieldType) + ";\n";
-
- // must pad out after matrices and arrays, where HLSL usually allows itself room to pack stuff
- if (blockStorage == EbsStd140)
- {
- const bool useHLSLRowMajorPacking = (fieldType.getLayoutQualifier().matrixPacking == EmpColumnMajor);
- hlsl += padHelper.postPaddingString(fieldType, useHLSLRowMajorPacking);
- }
- }
-
- return hlsl;
-}
-
-TString OutputHLSL::interfaceBlockStructString(const TInterfaceBlock &interfaceBlock)
-{
- const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
-
- return "struct " + interfaceBlockStructNameString(interfaceBlock) + "\n"
- "{\n" +
- interfaceBlockFieldString(interfaceBlock, blockStorage) +
- "};\n\n";
-}
-
-TString OutputHLSL::interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex)
-{
- const TString &arrayIndexString = (arrayIndex != GL_INVALID_INDEX ? Decorate(str(arrayIndex)) : "");
- const TString &blockName = interfaceBlock.name() + arrayIndexString;
- TString hlsl;
-
- hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) + ")\n"
- "{\n";
-
- if (interfaceBlock.hasInstanceName())
- {
- hlsl += " " + interfaceBlockStructNameString(interfaceBlock) + " " + interfaceBlockInstanceString(interfaceBlock, arrayIndex) + ";\n";
- }
- else
- {
- const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
- hlsl += interfaceBlockFieldString(interfaceBlock, blockStorage);
- }
-
- hlsl += "};\n\n";
-
- return hlsl;
-}
-
-// Use the same layout for packed and shared
-void setBlockLayout(gl::InterfaceBlock *interfaceBlock, gl::BlockLayoutType newLayout)
-{
- interfaceBlock->layout = newLayout;
- interfaceBlock->blockInfo.clear();
-
- switch (newLayout)
- {
- case gl::BLOCKLAYOUT_SHARED:
- case gl::BLOCKLAYOUT_PACKED:
- {
- gl::HLSLBlockEncoder hlslEncoder(&interfaceBlock->blockInfo, gl::HLSLBlockEncoder::ENCODE_PACKED);
- hlslEncoder.encodeInterfaceBlockFields(interfaceBlock->fields);
- interfaceBlock->dataSize = hlslEncoder.getBlockSize();
- }
- break;
-
- case gl::BLOCKLAYOUT_STANDARD:
- {
- gl::Std140BlockEncoder stdEncoder(&interfaceBlock->blockInfo);
- stdEncoder.encodeInterfaceBlockFields(interfaceBlock->fields);
- interfaceBlock->dataSize = stdEncoder.getBlockSize();
- }
- break;
-
- default:
- UNREACHABLE();
- break;
- }
-}
-
-gl::BlockLayoutType convertBlockLayoutType(TLayoutBlockStorage blockStorage)
-{
- switch (blockStorage)
- {
- case EbsPacked: return gl::BLOCKLAYOUT_PACKED;
- case EbsShared: return gl::BLOCKLAYOUT_SHARED;
- case EbsStd140: return gl::BLOCKLAYOUT_STANDARD;
- default: UNREACHABLE(); return gl::BLOCKLAYOUT_SHARED;
- }
-}
-
TString OutputHLSL::structInitializerString(int indent, const TStructure &structure, const TString &rhsStructName)
{
TString init;
@@ -465,84 +290,10 @@
{
TInfoSinkBase &out = mHeader;
- TString uniforms;
- TString interfaceBlocks;
TString varyings;
TString attributes;
TString flaggedStructs;
- for (ReferencedSymbols::const_iterator uniformIt = mReferencedUniforms.begin(); uniformIt != mReferencedUniforms.end(); uniformIt++)
- {
- const TIntermSymbol &uniform = *uniformIt->second;
- const TType &type = uniform.getType();
- const TString &name = uniform.getSymbol();
-
- int registerIndex = declareUniformAndAssignRegister(type, name);
-
- if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) // Also declare the texture
- {
- uniforms += "uniform " + SamplerString(type) + " sampler_" + DecorateUniform(name, type) + ArrayString(type) +
- " : register(s" + str(registerIndex) + ");\n";
-
- uniforms += "uniform " + TextureString(type) + " texture_" + DecorateUniform(name, type) + ArrayString(type) +
- " : register(t" + str(registerIndex) + ");\n";
- }
- else
- {
- const TStructure *structure = type.getStruct();
- const TString &typeName = (structure ? QualifiedStructNameString(*structure, false, false) : TypeString(type));
-
- const TString ®isterString = TString("register(") + RegisterPrefix(type) + str(registerIndex) + ")";
-
- uniforms += "uniform " + typeName + " " + DecorateUniform(name, type) + ArrayString(type) + " : " + registerString + ";\n";
- }
- }
-
- for (ReferencedSymbols::const_iterator interfaceBlockIt = mReferencedInterfaceBlocks.begin(); interfaceBlockIt != mReferencedInterfaceBlocks.end(); interfaceBlockIt++)
- {
- const TType &nodeType = interfaceBlockIt->second->getType();
- const TInterfaceBlock &interfaceBlock = *nodeType.getInterfaceBlock();
- const TFieldList &fieldList = interfaceBlock.fields();
-
- unsigned int arraySize = static_cast<unsigned int>(interfaceBlock.arraySize());
- gl::InterfaceBlock activeBlock(interfaceBlock.name().c_str(), arraySize, mInterfaceBlockRegister);
- for (unsigned int typeIndex = 0; typeIndex < fieldList.size(); typeIndex++)
- {
- const TField &field = *fieldList[typeIndex];
- const TString &fullUniformName = interfaceBlockFieldString(interfaceBlock, field);
- declareInterfaceBlockField(*field.type(), fullUniformName, activeBlock.fields);
- }
-
- mInterfaceBlockRegister += std::max(1u, arraySize);
-
- gl::BlockLayoutType blockLayoutType = convertBlockLayoutType(interfaceBlock.blockStorage());
- setBlockLayout(&activeBlock, blockLayoutType);
-
- if (interfaceBlock.matrixPacking() == EmpRowMajor)
- {
- activeBlock.isRowMajorLayout = true;
- }
-
- mActiveInterfaceBlocks.push_back(activeBlock);
-
- if (interfaceBlock.hasInstanceName())
- {
- interfaceBlocks += interfaceBlockStructString(interfaceBlock);
- }
-
- if (arraySize > 0)
- {
- for (unsigned int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
- {
- interfaceBlocks += interfaceBlockString(interfaceBlock, activeBlock.registerIndex + arrayIndex, arrayIndex);
- }
- }
- else
- {
- interfaceBlocks += interfaceBlockString(interfaceBlock, activeBlock.registerIndex, GL_INVALID_INDEX);
- }
- }
-
for (std::map<TIntermTyped*, TString>::const_iterator flaggedStructIt = mFlaggedStructMappedNames.begin(); flaggedStructIt != mFlaggedStructMappedNames.end(); flaggedStructIt++)
{
TIntermTyped *structNode = flaggedStructIt->first;
@@ -581,6 +332,9 @@
out << mStructureHLSL->structsHeader();
+ out << mUniformHLSL->uniformsHeader(mOutputType, mReferencedUniforms);
+ out << mUniformHLSL->interfaceBlocksHeader(mReferencedInterfaceBlocks);
+
if (mUsesDiscardRewriting)
{
out << "#define ANGLE_USES_DISCARD_REWRITING" << "\n";
@@ -715,22 +469,13 @@
out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n"
"\n";
}
-
- out << uniforms;
- out << "\n";
- if (!interfaceBlocks.empty())
+ if (!flaggedStructs.empty())
{
- out << interfaceBlocks;
+ out << "// Std140 Structures accessed by value\n";
out << "\n";
-
- if (!flaggedStructs.empty())
- {
- out << "// Std140 Structures accessed by value\n";
- out << "\n";
- out << flaggedStructs;
- out << "\n";
- }
+ out << flaggedStructs;
+ out << "\n";
}
if (usingMRTExtension && mNumRenderTargets > 1)
@@ -754,7 +499,7 @@
out << attributes;
out << "\n"
"static float4 gl_Position = float4(0, 0, 0, 0);\n";
-
+
if (mUsesPointSize)
{
out << "static float gl_PointSize = float(1);\n";
@@ -804,21 +549,12 @@
"\n";
}
- out << uniforms;
- out << "\n";
-
- if (!interfaceBlocks.empty())
+ if (!flaggedStructs.empty())
{
- out << interfaceBlocks;
+ out << "// Std140 Structures accessed by value\n";
out << "\n";
-
- if (!flaggedStructs.empty())
- {
- out << "// Std140 Structures accessed by value\n";
- out << "\n";
- out << flaggedStructs;
- out << "\n";
- }
+ out << flaggedStructs;
+ out << "\n";
}
}
@@ -1288,7 +1024,7 @@
case 3: out << "int4("; break;
default: UNREACHABLE();
}
-
+
// Convert from normalized floating-point to integer
if (textureFunction->method != TextureFunction::FETCH)
{
@@ -1323,7 +1059,7 @@
}
TString proj = ""; // Only used for projected textures
-
+
if (textureFunction->proj)
{
switch(textureFunction->coords)
@@ -1507,7 +1243,7 @@
"}\n"
"\n";
}
-
+
if (mUsesMod3v)
{
out << "float3 mod(float3 x, float3 y)\n"
@@ -1811,7 +1547,7 @@
{
out << " = mul(";
node->getLeft()->traverse(this);
- out << ", transpose(";
+ out << ", transpose(";
}
else
{
@@ -1827,7 +1563,7 @@
{
out << " = mul(";
node->getLeft()->traverse(this);
- out << ", ";
+ out << ", ";
}
else
{
@@ -1844,10 +1580,8 @@
{
TInterfaceBlock* interfaceBlock = leftType.getInterfaceBlock();
const int arrayIndex = node->getRight()->getAsConstantUnion()->getIConst(0);
-
mReferencedInterfaceBlocks[interfaceBlock->instanceName()] = node->getLeft()->getAsSymbolNode();
- out << interfaceBlockInstanceString(*interfaceBlock, arrayIndex);
-
+ out << mUniformHLSL->interfaceBlockInstanceString(*interfaceBlock, arrayIndex);
return false;
}
}
@@ -2282,14 +2016,14 @@
out << ")\n"
"{\n";
-
+
if (sequence.size() > 1)
{
mInsideFunction = true;
sequence[1]->traverse(this);
mInsideFunction = false;
}
-
+
out << "}\n";
if (mContainsLoopDiscontinuity && !mOutputLod0Function)
@@ -2542,7 +2276,7 @@
case 4: mUsesFaceforward4 = true; break;
default: UNREACHABLE();
}
-
+
outputTriplet(visit, "faceforward(", ", ", ")");
}
break;
@@ -2572,7 +2306,7 @@
node->getCondition()->traverse(this);
out << ")\n";
-
+
outputLineDirective(node->getLine().first_line);
out << "{\n";
@@ -2655,7 +2389,7 @@
else
{
out << "{for(";
-
+
if (node->getInit())
{
node->getInit()->traverse(this);
@@ -2676,7 +2410,7 @@
}
out << ")\n";
-
+
outputLineDirective(node->getLine().first_line);
out << "{\n";
}
@@ -2851,7 +2585,7 @@
if (index != NULL && node->getCondition())
{
TIntermBinary *test = node->getCondition()->getAsBinaryNode();
-
+
if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId())
{
TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion();
@@ -2872,7 +2606,7 @@
{
TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode();
TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode();
-
+
if (binaryTerminal)
{
TOperator op = binaryTerminal->getOp();
@@ -2952,7 +2686,7 @@
{
mExcessiveLoopIndex = NULL; // Stops setting the Break flag
}
-
+
// for(int index = initial; index < clampedLimit; index += increment)
out << "for(";
@@ -2970,7 +2704,7 @@
out << " += ";
out << increment;
out << ")\n";
-
+
outputLineDirective(node->getLine().first_line);
out << "{\n";
@@ -2992,7 +2726,7 @@
initial += MAX_LOOP_ITERATIONS * increment;
iterations -= MAX_LOOP_ITERATIONS;
}
-
+
out << "}";
mExcessiveLoopIndex = restoreIndex;
@@ -3034,7 +2768,7 @@
{
mBody << " \"" << mContext.sourcePath << "\"";
}
-
+
mBody << "\n";
}
}
@@ -3057,7 +2791,7 @@
if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType()))
{
return QualifierString(qualifier) + " " + TextureString(type) + " texture_" + name + ArrayString(type) + ", " +
- QualifierString(qualifier) + " " + SamplerString(type) + " sampler_" + name + ArrayString(type);
+ QualifierString(qualifier) + " " + SamplerString(type) + " sampler_" + name + ArrayString(type);
}
return QualifierString(qualifier) + " " + TypeString(type) + " " + name + ArrayString(type);
@@ -3109,13 +2843,12 @@
if (structure)
{
out << StructNameString(*structure) + "_ctor(";
-
+
const TFieldList& fields = structure->fields();
for (size_t i = 0; i < fields.size(); i++)
{
const TType *fieldType = fields[i]->type();
-
constUnion = writeConstantUnion(*fieldType, constUnion);
if (i != fields.size() - 1)
@@ -3130,7 +2863,7 @@
{
size_t size = type.getObjectSize();
bool writeType = size > 1;
-
+
if (writeType)
{
out << TypeString(type) << "(";
@@ -3162,74 +2895,6 @@
return constUnion;
}
-void OutputHLSL::declareInterfaceBlockField(const TType &type, const TString &name, std::vector<gl::InterfaceBlockField>& output)
-{
- const TStructure *structure = type.getStruct();
-
- if (!structure)
- {
- const bool isRowMajorMatrix = (type.isMatrix() && type.getLayoutQualifier().matrixPacking == EmpRowMajor);
- gl::InterfaceBlockField field(GLVariableType(type), GLVariablePrecision(type), name.c_str(),
- (unsigned int)type.getArraySize(), isRowMajorMatrix);
- output.push_back(field);
- }
- else
- {
- gl::InterfaceBlockField structField(GL_STRUCT_ANGLEX, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), false);
-
- const TFieldList &fields = structure->fields();
-
- for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
- {
- TField *field = fields[fieldIndex];
- TType *fieldType = field->type();
-
- // make sure to copy matrix packing information
- fieldType->setLayoutQualifier(type.getLayoutQualifier());
-
- declareInterfaceBlockField(*fieldType, field->name(), structField.fields);
- }
-
- output.push_back(structField);
- }
-}
-
-gl::Uniform OutputHLSL::declareUniformToList(const TType &type, const TString &name, int registerIndex, std::vector<gl::Uniform>& output)
-{
- const TStructure *structure = type.getStruct();
-
- if (!structure)
- {
- gl::Uniform uniform(GLVariableType(type), GLVariablePrecision(type), name.c_str(),
- (unsigned int)type.getArraySize(), (unsigned int)registerIndex, 0);
- output.push_back(uniform);
-
- return uniform;
- }
- else
- {
- gl::Uniform structUniform(GL_STRUCT_ANGLEX, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(),
- (unsigned int)registerIndex, GL_INVALID_INDEX);
-
- const TFieldList &fields = structure->fields();
-
- for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
- {
- TField *field = fields[fieldIndex];
- TType *fieldType = field->type();
-
- declareUniformToList(*fieldType, field->name(), GL_INVALID_INDEX, structUniform.fields);
- }
-
- // assign register offset information -- this will override the information in any sub-structures.
- HLSLVariableGetRegisterInfo(registerIndex, &structUniform, mOutputType);
-
- output.push_back(structUniform);
-
- return structUniform;
- }
-}
-
void OutputHLSL::declareVaryingToList(const TType &type, TQualifier baseTypeQualifier, const TString &name, std::vector<gl::Varying>& fieldsOut)
{
const TStructure *structure = type.getStruct();
@@ -3257,22 +2922,4 @@
}
}
-int OutputHLSL::declareUniformAndAssignRegister(const TType &type, const TString &name)
-{
- int registerIndex = (IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister);
-
- const gl::Uniform &uniform = declareUniformToList(type, name, registerIndex, mActiveUniforms);
-
- if (IsSampler(type.getBasicType()))
- {
- mSamplerRegister += gl::HLSLVariableRegisterCount(uniform, mOutputType);
- }
- else
- {
- mUniformRegister += gl::HLSLVariableRegisterCount(uniform, mOutputType);
- }
-
- return registerIndex;
-}
-
}
diff --git a/src/compiler/translator/OutputHLSL.h b/src/compiler/translator/OutputHLSL.h
index 214ed42..78d02bd 100644
--- a/src/compiler/translator/OutputHLSL.h
+++ b/src/compiler/translator/OutputHLSL.h
@@ -22,6 +22,9 @@
{
class UnfoldShortCircuit;
class StructureHLSL;
+class UniformHLSL;
+
+typedef std::map<TString, TIntermSymbol*> ReferencedSymbols;
class OutputHLSL : public TIntermTraverser
{
@@ -74,7 +77,6 @@
TInfoSinkBase mBody;
TInfoSinkBase mFooter;
- typedef std::map<TString, TIntermSymbol*> ReferencedSymbols;
ReferencedSymbols mReferencedUniforms;
ReferencedSymbols mReferencedInterfaceBlocks;
ReferencedSymbols mReferencedAttributes;
@@ -82,6 +84,7 @@
ReferencedSymbols mReferencedOutputVariables;
StructureHLSL *mStructureHLSL;
+ UniformHLSL *mUniformHLSL;
struct TextureFunction
{
@@ -150,32 +153,10 @@
TIntermSymbol *mExcessiveLoopIndex;
- int mUniformRegister;
- int mInterfaceBlockRegister;
- int mSamplerRegister;
-
- TString registerString(TIntermSymbol *operand);
- int samplerRegister(TIntermSymbol *sampler);
- int uniformRegister(TIntermSymbol *uniform);
- void declareInterfaceBlockField(const TType &type, const TString &name, std::vector<gl::InterfaceBlockField>& output);
- gl::Uniform declareUniformToList(const TType &type, const TString &name, int registerIndex, std::vector<gl::Uniform>& output);
- void declareUniform(const TType &type, const TString &name, int index);
void declareVaryingToList(const TType &type, TQualifier baseTypeQualifier, const TString &name, std::vector<gl::Varying>& fieldsOut);
- // Returns the uniform's register index
- int declareUniformAndAssignRegister(const TType &type, const TString &name);
-
- TString interfaceBlockFieldString(const TInterfaceBlock &interfaceBlock, const TField &field);
- TString interfaceBlockStructNameString(const TInterfaceBlock &interfaceBlockType);
- TString interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex);
- TString interfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage);
- TString interfaceBlockFieldString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage);
- 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);
- std::vector<gl::Uniform> mActiveUniforms;
- std::vector<gl::InterfaceBlock> mActiveInterfaceBlocks;
std::vector<gl::Attribute> mActiveOutputVariables;
std::vector<gl::Attribute> mActiveAttributes;
std::vector<gl::Varying> mActiveVaryings;
diff --git a/src/compiler/translator/UniformHLSL.cpp b/src/compiler/translator/UniformHLSL.cpp
new file mode 100644
index 0000000..7f05259
--- /dev/null
+++ b/src/compiler/translator/UniformHLSL.cpp
@@ -0,0 +1,391 @@
+//
+// 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.
+//
+// UniformHLSL.cpp:
+// Methods for GLSL to HLSL translation for uniforms and interface blocks.
+//
+
+#include "OutputHLSL.h"
+#include "common/blocklayout.h"
+#include "common/utilities.h"
+#include "compiler/translator/UniformHLSL.h"
+#include "compiler/translator/StructureHLSL.h"
+#include "compiler/translator/util.h"
+#include "compiler/translator/UtilsHLSL.h"
+
+namespace sh
+{
+
+// Use the same layout for packed and shared
+static void SetBlockLayout(gl::InterfaceBlock *interfaceBlock, gl::BlockLayoutType newLayout)
+{
+ interfaceBlock->layout = newLayout;
+ interfaceBlock->blockInfo.clear();
+
+ switch (newLayout)
+ {
+ case gl::BLOCKLAYOUT_SHARED:
+ case gl::BLOCKLAYOUT_PACKED:
+ {
+ gl::HLSLBlockEncoder hlslEncoder(&interfaceBlock->blockInfo, gl::HLSLBlockEncoder::ENCODE_PACKED);
+ hlslEncoder.encodeInterfaceBlockFields(interfaceBlock->fields);
+ interfaceBlock->dataSize = hlslEncoder.getBlockSize();
+ }
+ break;
+
+ case gl::BLOCKLAYOUT_STANDARD:
+ {
+ gl::Std140BlockEncoder stdEncoder(&interfaceBlock->blockInfo);
+ stdEncoder.encodeInterfaceBlockFields(interfaceBlock->fields);
+ interfaceBlock->dataSize = stdEncoder.getBlockSize();
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+static gl::BlockLayoutType ConvertBlockLayoutType(TLayoutBlockStorage blockStorage)
+{
+ switch (blockStorage)
+ {
+ case EbsPacked: return gl::BLOCKLAYOUT_PACKED;
+ case EbsShared: return gl::BLOCKLAYOUT_SHARED;
+ case EbsStd140: return gl::BLOCKLAYOUT_STANDARD;
+ default: UNREACHABLE(); return gl::BLOCKLAYOUT_SHARED;
+ }
+}
+
+static const char *UniformRegisterPrefix(const TType &type)
+{
+ if (IsSampler(type.getBasicType()))
+ {
+ return "s";
+ }
+ else
+ {
+ return "c";
+ }
+}
+
+static TString InterfaceBlockFieldName(const TInterfaceBlock &interfaceBlock, const TField &field)
+{
+ if (interfaceBlock.hasInstanceName())
+ {
+ return interfaceBlock.name() + "." + field.name();
+ }
+ else
+ {
+ return field.name();
+ }
+}
+
+static TString InterfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage)
+{
+ const TType &fieldType = *field.type();
+ const TLayoutMatrixPacking matrixPacking = fieldType.getLayoutQualifier().matrixPacking;
+ ASSERT(matrixPacking != EmpUnspecified);
+ TStructure *structure = fieldType.getStruct();
+
+ if (fieldType.isMatrix())
+ {
+ // Use HLSL row-major packing for GLSL column-major matrices
+ const TString &matrixPackString = (matrixPacking == EmpRowMajor ? "column_major" : "row_major");
+ return matrixPackString + " " + TypeString(fieldType);
+ }
+ else if (structure)
+ {
+ // Use HLSL row-major packing for GLSL column-major matrices
+ return QualifiedStructNameString(*structure, matrixPacking == EmpColumnMajor,
+ blockStorage == EbsStd140);
+ }
+ else
+ {
+ return TypeString(fieldType);
+ }
+}
+
+static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock)
+{
+ return DecoratePrivate(interfaceBlock.name()) + "_type";
+}
+
+UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType)
+ : mUniformRegister(0),
+ mInterfaceBlockRegister(0),
+ mSamplerRegister(0),
+ mStructureHLSL(structureHLSL),
+ mOutputType(outputType)
+{}
+
+void UniformHLSL::reserveUniformRegisters(unsigned int registerCount)
+{
+ mUniformRegister = registerCount;
+}
+
+void UniformHLSL::reserveInterfaceBlockRegisters(unsigned int registerCount)
+{
+ mInterfaceBlockRegister = registerCount;
+}
+
+int UniformHLSL::declareUniformAndAssignRegister(const TType &type, const TString &name)
+{
+ int registerIndex = (IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister);
+
+ const gl::Uniform &uniform = declareUniformToList(type, name, registerIndex, &mActiveUniforms);
+
+ if (IsSampler(type.getBasicType()))
+ {
+ mSamplerRegister += gl::HLSLVariableRegisterCount(uniform, mOutputType);
+ }
+ else
+ {
+ mUniformRegister += gl::HLSLVariableRegisterCount(uniform, mOutputType);
+ }
+
+ return registerIndex;
+}
+
+gl::Uniform UniformHLSL::declareUniformToList(const TType &type, const TString &name, int registerIndex, std::vector<gl::Uniform> *output)
+{
+ const TStructure *structure = type.getStruct();
+
+ if (!structure)
+ {
+ gl::Uniform uniform(GLVariableType(type), GLVariablePrecision(type), name.c_str(),
+ (unsigned int)type.getArraySize(), (unsigned int)registerIndex, 0);
+ output->push_back(uniform);
+
+ return uniform;
+ }
+ else
+ {
+ gl::Uniform structUniform(GL_STRUCT_ANGLEX, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(),
+ (unsigned int)registerIndex, GL_INVALID_INDEX);
+
+ const TFieldList &fields = structure->fields();
+
+ for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
+ {
+ TField *field = fields[fieldIndex];
+ TType *fieldType = field->type();
+
+ declareUniformToList(*fieldType, field->name(), GL_INVALID_INDEX, &structUniform.fields);
+ }
+
+ // assign register offset information -- this will override the information in any sub-structures.
+ HLSLVariableGetRegisterInfo(registerIndex, &structUniform, mOutputType);
+
+ output->push_back(structUniform);
+
+ return structUniform;
+ }
+}
+
+TString UniformHLSL::uniformsHeader(ShShaderOutput outputType, const ReferencedSymbols &referencedUniforms)
+{
+ TString uniforms;
+
+ for (ReferencedSymbols::const_iterator uniformIt = referencedUniforms.begin();
+ uniformIt != referencedUniforms.end(); uniformIt++)
+ {
+ const TIntermSymbol &uniform = *uniformIt->second;
+ const TType &type = uniform.getType();
+ const TString &name = uniform.getSymbol();
+
+ int registerIndex = declareUniformAndAssignRegister(type, name);
+
+ if (outputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) // Also declare the texture
+ {
+ uniforms += "uniform " + SamplerString(type) + " sampler_" + DecorateUniform(name, type) + ArrayString(type) +
+ " : register(s" + str(registerIndex) + ");\n";
+
+ uniforms += "uniform " + TextureString(type) + " texture_" + DecorateUniform(name, type) + ArrayString(type) +
+ " : register(t" + str(registerIndex) + ");\n";
+ }
+ else
+ {
+ const TStructure *structure = type.getStruct();
+ const TString &typeName = (structure ? QualifiedStructNameString(*structure, false, false) : TypeString(type));
+
+ const TString ®isterString = TString("register(") + UniformRegisterPrefix(type) + str(registerIndex) + ")";
+
+ uniforms += "uniform " + typeName + " " + DecorateUniform(name, type) + ArrayString(type) + " : " + registerString + ";\n";
+ }
+ }
+
+ return (uniforms.empty() ? "" : ("// Uniforms\n\n" + uniforms));
+}
+
+TString UniformHLSL::interfaceBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks)
+{
+ TString interfaceBlocks;
+
+ for (ReferencedSymbols::const_iterator interfaceBlockIt = referencedInterfaceBlocks.begin();
+ interfaceBlockIt != referencedInterfaceBlocks.end(); interfaceBlockIt++)
+ {
+ const TType &nodeType = interfaceBlockIt->second->getType();
+ const TInterfaceBlock &interfaceBlock = *nodeType.getInterfaceBlock();
+ const TFieldList &fieldList = interfaceBlock.fields();
+
+ unsigned int arraySize = static_cast<unsigned int>(interfaceBlock.arraySize());
+ gl::InterfaceBlock activeBlock(interfaceBlock.name().c_str(), arraySize, mInterfaceBlockRegister);
+ for (unsigned int typeIndex = 0; typeIndex < fieldList.size(); typeIndex++)
+ {
+ const TField &field = *fieldList[typeIndex];
+ const TString &fullUniformName = InterfaceBlockFieldName(interfaceBlock, field);
+ declareInterfaceBlockField(*field.type(), fullUniformName, activeBlock.fields);
+ }
+
+ mInterfaceBlockRegister += std::max(1u, arraySize);
+
+ gl::BlockLayoutType blockLayoutType = ConvertBlockLayoutType(interfaceBlock.blockStorage());
+ SetBlockLayout(&activeBlock, blockLayoutType);
+
+ if (interfaceBlock.matrixPacking() == EmpRowMajor)
+ {
+ activeBlock.isRowMajorLayout = true;
+ }
+
+ mActiveInterfaceBlocks.push_back(activeBlock);
+
+ if (interfaceBlock.hasInstanceName())
+ {
+ interfaceBlocks += interfaceBlockStructString(interfaceBlock);
+ }
+
+ if (arraySize > 0)
+ {
+ for (unsigned int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
+ {
+ interfaceBlocks += interfaceBlockString(interfaceBlock, activeBlock.registerIndex + arrayIndex, arrayIndex);
+ }
+ }
+ else
+ {
+ interfaceBlocks += interfaceBlockString(interfaceBlock, activeBlock.registerIndex, GL_INVALID_INDEX);
+ }
+ }
+
+ return (interfaceBlocks.empty() ? "" : ("// Interface Blocks\n\n" + interfaceBlocks));
+}
+
+TString UniformHLSL::interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex)
+{
+ const TString &arrayIndexString = (arrayIndex != GL_INVALID_INDEX ? Decorate(str(arrayIndex)) : "");
+ const TString &blockName = interfaceBlock.name() + arrayIndexString;
+ TString hlsl;
+
+ hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) + ")\n"
+ "{\n";
+
+ if (interfaceBlock.hasInstanceName())
+ {
+ hlsl += " " + InterfaceBlockStructName(interfaceBlock) + " " +
+ interfaceBlockInstanceString(interfaceBlock, arrayIndex) + ";\n";
+ }
+ else
+ {
+ const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
+ hlsl += interfaceBlockMembersString(interfaceBlock, blockStorage);
+ }
+
+ hlsl += "};\n\n";
+
+ return hlsl;
+}
+
+TString UniformHLSL::interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex)
+{
+ if (!interfaceBlock.hasInstanceName())
+ {
+ return "";
+ }
+ else if (interfaceBlock.isArray())
+ {
+ return DecoratePrivate(interfaceBlock.instanceName()) + "_" + str(arrayIndex);
+ }
+ else
+ {
+ return Decorate(interfaceBlock.instanceName());
+ }
+}
+
+TString UniformHLSL::interfaceBlockMembersString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage)
+{
+ TString hlsl;
+
+ Std140PaddingHelper padHelper = mStructureHLSL->getPaddingHelper();
+
+ for (unsigned int typeIndex = 0; typeIndex < interfaceBlock.fields().size(); typeIndex++)
+ {
+ const TField &field = *interfaceBlock.fields()[typeIndex];
+ const TType &fieldType = *field.type();
+
+ if (blockStorage == EbsStd140)
+ {
+ // 2 and 3 component vector types in some cases need pre-padding
+ hlsl += padHelper.prePadding(fieldType);
+ }
+
+ hlsl += " " + InterfaceBlockFieldTypeString(field, blockStorage) +
+ " " + Decorate(field.name()) + ArrayString(fieldType) + ";\n";
+
+ // must pad out after matrices and arrays, where HLSL usually allows itself room to pack stuff
+ if (blockStorage == EbsStd140)
+ {
+ const bool useHLSLRowMajorPacking = (fieldType.getLayoutQualifier().matrixPacking == EmpColumnMajor);
+ hlsl += padHelper.postPaddingString(fieldType, useHLSLRowMajorPacking);
+ }
+ }
+
+ return hlsl;
+}
+
+TString UniformHLSL::interfaceBlockStructString(const TInterfaceBlock &interfaceBlock)
+{
+ const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
+
+ return "struct " + InterfaceBlockStructName(interfaceBlock) + "\n"
+ "{\n" +
+ interfaceBlockMembersString(interfaceBlock, blockStorage) +
+ "};\n\n";
+}
+
+void UniformHLSL::declareInterfaceBlockField(const TType &type, const TString &name, std::vector<gl::InterfaceBlockField>& output)
+{
+ const TStructure *structure = type.getStruct();
+
+ if (!structure)
+ {
+ const bool isRowMajorMatrix = (type.isMatrix() && type.getLayoutQualifier().matrixPacking == EmpRowMajor);
+ gl::InterfaceBlockField field(GLVariableType(type), GLVariablePrecision(type), name.c_str(),
+ (unsigned int)type.getArraySize(), isRowMajorMatrix);
+ output.push_back(field);
+ }
+ else
+ {
+ gl::InterfaceBlockField structField(GL_STRUCT_ANGLEX, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), false);
+
+ const TFieldList &fields = structure->fields();
+
+ for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
+ {
+ TField *field = fields[fieldIndex];
+ TType *fieldType = field->type();
+
+ // make sure to copy matrix packing information
+ fieldType->setLayoutQualifier(type.getLayoutQualifier());
+
+ declareInterfaceBlockField(*fieldType, field->name(), structField.fields);
+ }
+
+ output.push_back(structField);
+ }
+}
+
+}
diff --git a/src/compiler/translator/UniformHLSL.h b/src/compiler/translator/UniformHLSL.h
new file mode 100644
index 0000000..5822a8a
--- /dev/null
+++ b/src/compiler/translator/UniformHLSL.h
@@ -0,0 +1,58 @@
+//
+// 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.
+//
+// UniformHLSL.h:
+// Methods for GLSL to HLSL translation for uniforms and interface blocks.
+//
+
+#ifndef TRANSLATOR_UNIFORMHLSL_H_
+#define TRANSLATOR_UNIFORMHLSL_H_
+
+#include "common/shadervars.h"
+#include "compiler/translator/Types.h"
+
+namespace sh
+{
+class StructureHLSL;
+
+class UniformHLSL
+{
+ public:
+ UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType);
+
+ void reserveUniformRegisters(unsigned int registerCount);
+ void reserveInterfaceBlockRegisters(unsigned int registerCount);
+ TString uniformsHeader(ShShaderOutput outputType, const ReferencedSymbols &referencedUniforms);
+ TString interfaceBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks);
+
+ // Used for direct index references
+ static TString interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex);
+
+ const std::vector<gl::Uniform> &getUniforms() const { return mActiveUniforms; }
+ const std::vector<gl::InterfaceBlock> &getInterfaceBlocks() const { return mActiveInterfaceBlocks; }
+
+ private:
+ TString interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex);
+ TString interfaceBlockMembersString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage);
+ TString interfaceBlockStructString(const TInterfaceBlock &interfaceBlock);
+
+ // Returns the uniform's register index
+ int declareUniformAndAssignRegister(const TType &type, const TString &name);
+ void declareInterfaceBlockField(const TType &type, const TString &name, std::vector<gl::InterfaceBlockField>& output);
+ gl::Uniform declareUniformToList(const TType &type, const TString &name, int registerIndex, std::vector<gl::Uniform> *output);
+
+ unsigned int mUniformRegister;
+ unsigned int mInterfaceBlockRegister;
+ unsigned int mSamplerRegister;
+ StructureHLSL *mStructureHLSL;
+ ShShaderOutput mOutputType;
+
+ std::vector<gl::Uniform> mActiveUniforms;
+ std::vector<gl::InterfaceBlock> mActiveInterfaceBlocks;
+};
+
+}
+
+#endif // TRANSLATOR_UNIFORMHLSL_H_