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
parent 3f68bf0e
...@@ -168,6 +168,81 @@ TString OutputHLSL::interfaceBlockUniformName(const TType &interfaceBlockType, c ...@@ -168,6 +168,81 @@ TString OutputHLSL::interfaceBlockUniformName(const TType &interfaceBlockType, c
} }
} }
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() void OutputHLSL::header()
{ {
ShShaderType shaderType = mContext.shaderType; ShShaderType shaderType = mContext.shaderType;
...@@ -185,6 +260,7 @@ void OutputHLSL::header() ...@@ -185,6 +260,7 @@ void OutputHLSL::header()
TString uniforms; TString uniforms;
TString interfaceBlocks; TString interfaceBlocks;
TString interfaceBlockInit;
TString varyings; TString varyings;
TString attributes; TString attributes;
...@@ -217,7 +293,8 @@ void OutputHLSL::header() ...@@ -217,7 +293,8 @@ void OutputHLSL::header()
const TString &blockName = interfaceBlockType.getTypeName(); const TString &blockName = interfaceBlockType.getTypeName();
const TTypeList &typeList = *interfaceBlockType.getStruct(); 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++) for (unsigned int typeIndex = 0; typeIndex < typeList.size(); typeIndex++)
{ {
const TType &memberType = *typeList[typeIndex].type; const TType &memberType = *typeList[typeIndex].type;
...@@ -225,31 +302,43 @@ void OutputHLSL::header() ...@@ -225,31 +302,43 @@ void OutputHLSL::header()
declareUniformToList(memberType, fullUniformName, typeIndex, interfaceBlock.activeUniforms); declareUniformToList(memberType, fullUniformName, typeIndex, interfaceBlock.activeUniforms);
} }
mInterfaceBlockRegister += std::max(1u, interfaceBlock.arraySize);
// TODO: handle other block layouts // TODO: handle other block layouts
interfaceBlock.setPackedBlockLayout(); interfaceBlock.setPackedBlockLayout();
mActiveInterfaceBlocks.push_back(interfaceBlock); mActiveInterfaceBlocks.push_back(interfaceBlock);
interfaceBlocks += "cbuffer " + blockName + " : register(b" + str(interfaceBlock.registerIndex) + ")\n"
"{\n";
if (interfaceBlockType.hasInstanceName()) 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 interfaceBlocks += "static " + interfaceBlockStructName(interfaceBlockType) + " " + decorate(interfaceBlockType.getInstanceName()) +
const TType &memberType = *typeList[typeIndex].type; arrayString(interfaceBlockType) + ";\n\n";
interfaceBlocks += " " + typeString(memberType) + " " + decorate(memberType.getFieldName()) + arrayString(memberType) + ";\n";
}
if (interfaceBlockType.hasInstanceName()) for (unsigned int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
{ {
interfaceBlocks += " } " + decorate(interfaceBlockType.getInstanceName()) + ";\n"; interfaceBlocks += interfaceBlockString(interfaceBlockType, interfaceBlock.registerIndex + arrayIndex, arrayIndex);
const TString &instanceName = interfaceBlockType.getInstanceName();
interfaceBlockInit += " " + decorate(instanceName) + "[" + str(arrayIndex) + "] = " +
interfaceBlockInstanceString(interfaceBlockType, arrayIndex) + ";\n";
}
}
else
{
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++) for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin(); varying != mReferencedVaryings.end(); varying++)
......
...@@ -175,6 +175,12 @@ class OutputHLSL : public TIntermTraverser ...@@ -175,6 +175,12 @@ class OutputHLSL : public TIntermTraverser
void declareUniform(const TType &type, const TString &name, int index); void declareUniform(const TType &type, const TString &name, int index);
TString interfaceBlockUniformName(const TType &interfaceBlockType, const TType &uniformType); 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 glVariableType(const TType &type);
static GLenum glVariablePrecision(const TType &type); static GLenum glVariablePrecision(const TType &type);
......
...@@ -1686,6 +1686,11 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, TS ...@@ -1686,6 +1686,11 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, TS
error(location, "", "[", "array must be redeclared with a size before being indexed with a variable"); error(location, "", "[", "array must be redeclared with a size before being indexed with a variable");
recover(); 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); indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
} }
...@@ -1700,7 +1705,9 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, TS ...@@ -1700,7 +1705,9 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, TS
{ {
if (baseExpression->getType().getStruct()) 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 else
{ {
......
// //
// 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 // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
...@@ -208,7 +208,7 @@ bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node) ...@@ -208,7 +208,7 @@ bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node)
const TIntermSymbol* variable = (*i)->getAsSymbolNode(); const TIntermSymbol* variable = (*i)->getAsSymbolNode();
// The only case in which the sequence will not contain a // The only case in which the sequence will not contain a
// TIntermSymbol node is initialization. It will 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 // cannot be initialized in a shader, we must have only
// TIntermSymbol nodes in the sequence. // TIntermSymbol nodes in the sequence.
ASSERT(variable != NULL); ASSERT(variable != NULL);
......
...@@ -1178,6 +1178,12 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying ...@@ -1178,6 +1178,12 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
vertexHLSL += "(input." + decorateAttribute(attribute->name) + ");\n"; vertexHLSL += "(input." + decorateAttribute(attribute->name) + ");\n";
} }
if (vertexHLSL.find("dx_initConstantBuffers") != std::string::npos)
{
vertexHLSL += "\n"
" dx_initConstantBuffers();\n";
}
if (shaderModel >= 4) if (shaderModel >= 4)
{ {
vertexHLSL += "\n" vertexHLSL += "\n"
...@@ -1421,6 +1427,12 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying ...@@ -1421,6 +1427,12 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
else UNREACHABLE(); else UNREACHABLE();
} }
if (pixelHLSL.find("dx_initConstantBuffers") != std::string::npos)
{
pixelHLSL += "\n"
" dx_initConstantBuffers();\n";
}
pixelHLSL += "\n" pixelHLSL += "\n"
" gl_main();\n" " gl_main();\n"
"\n" "\n"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment