Add support to the HLSL translator for arrays of named interface blocks.
TRAC #22930
Signed-off-by: Nicolas Capens
Signed-off-by: Geoff Lang
Author: Jamie Madill
git-svn-id: https://angleproject.googlecode.com/svn/branches/es3proto@2347 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/OutputHLSL.cpp b/src/compiler/OutputHLSL.cpp
index 6057e6b..89bb72d 100644
--- a/src/compiler/OutputHLSL.cpp
+++ b/src/compiler/OutputHLSL.cpp
@@ -168,6 +168,81 @@
}
}
+TString OutputHLSL::decoratePrivate(const TString &privateText)
+{
+ return "dx_" + privateText;
+}
+
+TString OutputHLSL::interfaceBlockStructName(const TType &interfaceBlockType)
+{
+ return decoratePrivate(interfaceBlockType.getTypeName()) + "_type";
+}
+
+TString OutputHLSL::interfaceBlockInstanceString(const TType& interfaceBlockType, unsigned int arrayIndex)
+{
+ if (!interfaceBlockType.hasInstanceName())
+ {
+ return "";
+ }
+ else if (interfaceBlockType.isArray())
+ {
+ return decoratePrivate(interfaceBlockType.getInstanceName()) + "_" + str(arrayIndex);
+ }
+ else
+ {
+ return decorate(interfaceBlockType.getInstanceName());
+ }
+}
+
+TString OutputHLSL::interfaceBlockMemberString(const TTypeList &typeList)
+{
+ TString hlsl;
+
+ // TODO: padding for standard layout
+
+ for (unsigned int typeIndex = 0; typeIndex < typeList.size(); typeIndex++)
+ {
+ const TType &memberType = *typeList[typeIndex].type;
+ hlsl += " " + typeString(memberType) + " " + decorate(memberType.getFieldName()) + arrayString(memberType) + ";\n";
+ }
+
+ return hlsl;
+}
+
+TString OutputHLSL::interfaceBlockStructString(const TType &interfaceBlockType)
+{
+ const TTypeList &typeList = *interfaceBlockType.getStruct();
+
+ return "struct " + interfaceBlockStructName(interfaceBlockType) + "\n"
+ "{\n" +
+ interfaceBlockMemberString(typeList) +
+ "};\n\n";
+}
+
+TString OutputHLSL::interfaceBlockString(const TType &interfaceBlockType, unsigned int registerIndex, unsigned int arrayIndex)
+{
+ const TString &arrayIndexString = (arrayIndex != GL_INVALID_INDEX ? decorate(str(arrayIndex)) : "");
+ const TString &blockName = interfaceBlockType.getTypeName() + arrayIndexString;
+ TString hlsl;
+
+ hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) + ")\n"
+ "{\n";
+
+ if (interfaceBlockType.hasInstanceName())
+ {
+ hlsl += " " + interfaceBlockStructName(interfaceBlockType) + " " + interfaceBlockInstanceString(interfaceBlockType, arrayIndex) + ";\n";
+ }
+ else
+ {
+ const TTypeList &typeList = *interfaceBlockType.getStruct();
+ hlsl += interfaceBlockMemberString(typeList);
+ }
+
+ hlsl += "};\n\n";
+
+ return hlsl;
+}
+
void OutputHLSL::header()
{
ShShaderType shaderType = mContext.shaderType;
@@ -185,6 +260,7 @@
TString uniforms;
TString interfaceBlocks;
+ TString interfaceBlockInit;
TString varyings;
TString attributes;
@@ -217,7 +293,8 @@
const TString &blockName = interfaceBlockType.getTypeName();
const TTypeList &typeList = *interfaceBlockType.getStruct();
- sh::InterfaceBlock interfaceBlock(blockName.c_str(), 0, mInterfaceBlockRegister++);
+ const unsigned int arraySize = interfaceBlockType.isArray() ? interfaceBlockType.getArraySize() : 0;
+ sh::InterfaceBlock interfaceBlock(blockName.c_str(), arraySize, mInterfaceBlockRegister);
for (unsigned int typeIndex = 0; typeIndex < typeList.size(); typeIndex++)
{
const TType &memberType = *typeList[typeIndex].type;
@@ -225,31 +302,43 @@
declareUniformToList(memberType, fullUniformName, typeIndex, interfaceBlock.activeUniforms);
}
+ mInterfaceBlockRegister += std::max(1u, interfaceBlock.arraySize);
+
// TODO: handle other block layouts
interfaceBlock.setPackedBlockLayout();
mActiveInterfaceBlocks.push_back(interfaceBlock);
- interfaceBlocks += "cbuffer " + blockName + " : register(b" + str(interfaceBlock.registerIndex) + ")\n"
- "{\n";
-
if (interfaceBlockType.hasInstanceName())
{
- interfaceBlocks += " struct {\n";
+ interfaceBlocks += interfaceBlockStructString(interfaceBlockType);
}
- for (unsigned int typeIndex = 0; typeIndex < typeList.size(); typeIndex++)
+ if (arraySize > 0)
{
- // TODO: padding for standard layout
- const TType &memberType = *typeList[typeIndex].type;
- interfaceBlocks += " " + typeString(memberType) + " " + decorate(memberType.getFieldName()) + arrayString(memberType) + ";\n";
- }
+ interfaceBlocks += "static " + interfaceBlockStructName(interfaceBlockType) + " " + decorate(interfaceBlockType.getInstanceName()) +
+ arrayString(interfaceBlockType) + ";\n\n";
- if (interfaceBlockType.hasInstanceName())
+ for (unsigned int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
+ {
+ interfaceBlocks += interfaceBlockString(interfaceBlockType, interfaceBlock.registerIndex + arrayIndex, arrayIndex);
+
+ const TString &instanceName = interfaceBlockType.getInstanceName();
+ interfaceBlockInit += " " + decorate(instanceName) + "[" + str(arrayIndex) + "] = " +
+ interfaceBlockInstanceString(interfaceBlockType, arrayIndex) + ";\n";
+ }
+ }
+ else
{
- interfaceBlocks += " } " + decorate(interfaceBlockType.getInstanceName()) + ";\n";
+ interfaceBlocks += interfaceBlockString(interfaceBlockType, interfaceBlock.registerIndex, GL_INVALID_INDEX);
}
+ }
- interfaceBlocks += "};\n\n";
+ if (!interfaceBlockInit.empty())
+ {
+ interfaceBlocks += "void dx_initConstantBuffers()\n"
+ "{\n" +
+ interfaceBlockInit +
+ "}\n\n";
}
for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin(); varying != mReferencedVaryings.end(); varying++)
diff --git a/src/compiler/OutputHLSL.h b/src/compiler/OutputHLSL.h
index 20660ae..09c3856 100644
--- a/src/compiler/OutputHLSL.h
+++ b/src/compiler/OutputHLSL.h
@@ -175,6 +175,12 @@
void declareUniform(const TType &type, const TString &name, int index);
TString interfaceBlockUniformName(const TType &interfaceBlockType, const TType &uniformType);
+ TString decoratePrivate(const TString &privateText);
+ TString interfaceBlockStructName(const TType &interfaceBlockType);
+ TString interfaceBlockInstanceString(const TType& interfaceBlockType, unsigned int arrayIndex);
+ TString interfaceBlockMemberString(const TTypeList &typeList);
+ TString interfaceBlockStructString(const TType &interfaceBlockType);
+ TString interfaceBlockString(const TType &interfaceBlockType, unsigned int registerIndex, unsigned int arrayIndex);
static GLenum glVariableType(const TType &type);
static GLenum glVariablePrecision(const TType &type);
diff --git a/src/compiler/ParseHelper.cpp b/src/compiler/ParseHelper.cpp
index 455097b..9295e0b 100644
--- a/src/compiler/ParseHelper.cpp
+++ b/src/compiler/ParseHelper.cpp
@@ -1686,6 +1686,11 @@
error(location, "", "[", "array must be redeclared with a size before being indexed with a variable");
recover();
}
+ else if (baseExpression->getBasicType() == EbtInterfaceBlock)
+ {
+ error(location, "", "[", "array indexes for interface blocks arrays must be constant integeral expressions");
+ recover();
+ }
indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
}
@@ -1700,7 +1705,9 @@
{
if (baseExpression->getType().getStruct())
{
- indexedExpression->setType(TType(baseExpression->getType().getStruct(), baseExpression->getType().getTypeName()));
+ TType copyOfType(baseExpression->getType().getStruct(), baseExpression->getType().getTypeName());
+ copyOfType.setBasicType(baseExpression->getType().getBasicType()); // necessary to preserve interface block basic type
+ indexedExpression->setType(copyOfType);
}
else
{
diff --git a/src/compiler/VariableInfo.cpp b/src/compiler/VariableInfo.cpp
index eb6bea9..bf7a13e 100644
--- a/src/compiler/VariableInfo.cpp
+++ b/src/compiler/VariableInfo.cpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2013 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.
//
@@ -208,7 +208,7 @@
const TIntermSymbol* variable = (*i)->getAsSymbolNode();
// The only case in which the sequence will not contain a
// TIntermSymbol node is initialization. It will contain a
- // TInterBinary node in that case. Since attributes and unifroms
+ // TIntermBinary node in that case. Since attributes and uniforms
// cannot be initialized in a shader, we must have only
// TIntermSymbol nodes in the sequence.
ASSERT(variable != NULL);
diff --git a/src/libGLESv2/ProgramBinary.cpp b/src/libGLESv2/ProgramBinary.cpp
index ca92742..64efe44 100644
--- a/src/libGLESv2/ProgramBinary.cpp
+++ b/src/libGLESv2/ProgramBinary.cpp
@@ -1178,6 +1178,12 @@
vertexHLSL += "(input." + decorateAttribute(attribute->name) + ");\n";
}
+ if (vertexHLSL.find("dx_initConstantBuffers") != std::string::npos)
+ {
+ vertexHLSL += "\n"
+ " dx_initConstantBuffers();\n";
+ }
+
if (shaderModel >= 4)
{
vertexHLSL += "\n"
@@ -1421,6 +1427,12 @@
else UNREACHABLE();
}
+ if (pixelHLSL.find("dx_initConstantBuffers") != std::string::npos)
+ {
+ pixelHLSL += "\n"
+ " dx_initConstantBuffers();\n";
+ }
+
pixelHLSL += "\n"
" gl_main();\n"
"\n"