Add support for structures in interface and uniform blocks.

Also redesigns the uniform block layout computation to be more general. TRAC #23018 Signed-off-by: Geoff Lang Signed-off-by: Nicolas Capens Author: Jamie Madill git-svn-id: https://angleproject.googlecode.com/svn/branches/es3proto@2387 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 27125346
...@@ -194,6 +194,24 @@ TString OutputHLSL::interfaceBlockInstanceString(const TType& interfaceBlockType ...@@ -194,6 +194,24 @@ TString OutputHLSL::interfaceBlockInstanceString(const TType& interfaceBlockType
} }
} }
TString OutputHLSL::interfaceBlockMemberTypeString(const TType &memberType)
{
// TODO: layout support
if (memberType.isMatrix())
{
return " row_major " + typeString(memberType);
}
else if (memberType.getBasicType() == EbtStruct)
{
return "rm" + typeString(memberType);
}
else
{
return typeString(memberType);
}
}
TString OutputHLSL::interfaceBlockMemberString(const TTypeList &typeList) TString OutputHLSL::interfaceBlockMemberString(const TTypeList &typeList)
{ {
TString hlsl; TString hlsl;
...@@ -203,7 +221,8 @@ TString OutputHLSL::interfaceBlockMemberString(const TTypeList &typeList) ...@@ -203,7 +221,8 @@ TString OutputHLSL::interfaceBlockMemberString(const TTypeList &typeList)
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;
hlsl += " " + typeString(memberType) + " " + decorate(memberType.getFieldName()) + arrayString(memberType) + ";\n"; hlsl += " " + interfaceBlockMemberTypeString(memberType) +
" " + decorate(memberType.getFieldName()) + arrayString(memberType) + ";\n";
} }
return hlsl; return hlsl;
...@@ -305,7 +324,7 @@ void OutputHLSL::header() ...@@ -305,7 +324,7 @@ void OutputHLSL::header()
mInterfaceBlockRegister += std::max(1u, interfaceBlock.arraySize); mInterfaceBlockRegister += std::max(1u, interfaceBlock.arraySize);
// TODO: handle other block layouts // TODO: handle other block layouts
interfaceBlock.setPackedBlockLayout(); interfaceBlock.setBlockLayout(BLOCKLAYOUT_SHARED);
mActiveInterfaceBlocks.push_back(interfaceBlock); mActiveInterfaceBlocks.push_back(interfaceBlock);
if (interfaceBlockType.hasInstanceName()) if (interfaceBlockType.hasInstanceName())
...@@ -2920,8 +2939,7 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI ...@@ -2920,8 +2939,7 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI
mStructNames.insert(decorate(name)); mStructNames.insert(decorate(name));
TString structure; TString structure;
structure += "struct " + decorate(name) + "\n" structure += "{\n";
"{\n";
const TTypeList &fields = *type.getStruct(); const TTypeList &fields = *type.getStruct();
...@@ -2936,7 +2954,14 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI ...@@ -2936,7 +2954,14 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI
if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structure) == mStructDeclarations.end()) if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structure) == mStructDeclarations.end())
{ {
mStructDeclarations.push_back(structure); TString columnMajorString = "struct " + decorate(name) + "\n" + structure;
TString rowMajorString = "#pragma pack_matrix(row_major)\n"
"struct rm" + decorate(name) + "\n" +
structure +
"#pragma pack_matrix(column_major)\n";
mStructDeclarations.push_back(columnMajorString);
mStructDeclarations.push_back(rowMajorString);
} }
for (unsigned int i = 0; i < fields.size(); i++) for (unsigned int i = 0; i < fields.size(); i++)
......
...@@ -178,6 +178,7 @@ class OutputHLSL : public TIntermTraverser ...@@ -178,6 +178,7 @@ class OutputHLSL : public TIntermTraverser
TString decoratePrivate(const TString &privateText); TString decoratePrivate(const TString &privateText);
TString interfaceBlockStructName(const TType &interfaceBlockType); TString interfaceBlockStructName(const TType &interfaceBlockType);
TString interfaceBlockInstanceString(const TType& interfaceBlockType, unsigned int arrayIndex); TString interfaceBlockInstanceString(const TType& interfaceBlockType, unsigned int arrayIndex);
TString interfaceBlockMemberTypeString(const TType &memberType);
TString interfaceBlockMemberString(const TTypeList &typeList); TString interfaceBlockMemberString(const TTypeList &typeList);
TString interfaceBlockStructString(const TType &interfaceBlockType); TString interfaceBlockStructString(const TType &interfaceBlockType);
TString interfaceBlockString(const TType &interfaceBlockType, unsigned int registerIndex, unsigned int arrayIndex); TString interfaceBlockString(const TType &interfaceBlockType, unsigned int registerIndex, unsigned int arrayIndex);
......
...@@ -45,6 +45,15 @@ struct BlockMemberInfo ...@@ -45,6 +45,15 @@ struct BlockMemberInfo
static const BlockMemberInfo defaultBlockInfo; static const BlockMemberInfo defaultBlockInfo;
}; };
typedef std::vector<BlockMemberInfo> BlockMemberInfoArray;
enum BlockLayoutType
{
BLOCKLAYOUT_STANDARD,
BLOCKLAYOUT_PACKED,
BLOCKLAYOUT_SHARED
};
struct InterfaceBlock struct InterfaceBlock
{ {
InterfaceBlock(const char *name, unsigned int arraySize, unsigned int registerIndex); InterfaceBlock(const char *name, unsigned int arraySize, unsigned int registerIndex);
...@@ -54,12 +63,17 @@ struct InterfaceBlock ...@@ -54,12 +63,17 @@ struct InterfaceBlock
ActiveUniforms activeUniforms; ActiveUniforms activeUniforms;
size_t dataSize; size_t dataSize;
std::vector<BlockMemberInfo> blockInfo; std::vector<BlockMemberInfo> blockInfo;
BlockLayoutType layout;
unsigned int registerIndex; unsigned int registerIndex;
void setSharedBlockLayout(); void setBlockLayout(BlockLayoutType newLayout);
void setPackedBlockLayout();
void setStandardBlockLayout(); private:
void getBlockLayoutInfo(const sh::ActiveUniforms &fields, unsigned int *currentOffset);
bool getBlockLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut);
void getD3DLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut);
void getStandardLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut);
}; };
typedef std::vector<InterfaceBlock> ActiveInterfaceBlocks; typedef std::vector<InterfaceBlock> ActiveInterfaceBlocks;
......
...@@ -2362,6 +2362,30 @@ bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const sh::ActiveInterfac ...@@ -2362,6 +2362,30 @@ bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const sh::ActiveInterfac
return true; return true;
} }
void ProgramBinary::defineUniformBlockMembers(const sh::ActiveUniforms &uniforms, const std::string &prefix, int blockIndex, BlockInfoItr *blockInfoItr, std::vector<unsigned int> *blockUniformIndexes)
{
for (unsigned int uniformIndex = 0; uniformIndex < uniforms.size(); uniformIndex++)
{
const sh::Uniform &uniform = uniforms[uniformIndex];
if (!uniform.fields.empty())
{
defineUniformBlockMembers(uniform.fields, uniform.name, blockIndex, blockInfoItr, blockUniformIndexes);
}
else
{
const std::string &uniformName = (prefix.empty() ? uniform.name : prefix + "." + uniform.name);
Uniform *newUniform = new Uniform(uniform.type, uniform.precision, uniformName, uniform.arraySize,
blockIndex, **blockInfoItr);
// add to uniform list, but not index, since uniform block uniforms have no location
blockUniformIndexes->push_back(mUniforms.size());
mUniforms.push_back(newUniform);
(*blockInfoItr)++;
}
}
}
bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, GLenum shader, const sh::InterfaceBlock &interfaceBlock) bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, GLenum shader, const sh::InterfaceBlock &interfaceBlock)
{ {
// create uniform block entries if they do not exist // create uniform block entries if they do not exist
...@@ -2371,16 +2395,8 @@ bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, GLenum shader, const sh ...@@ -2371,16 +2395,8 @@ bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, GLenum shader, const sh
const unsigned int blockIndex = mUniformBlocks.size(); const unsigned int blockIndex = mUniformBlocks.size();
// define member uniforms // define member uniforms
for (unsigned int activeUniformIndex = 0; activeUniformIndex < interfaceBlock.activeUniforms.size(); activeUniformIndex++) BlockInfoItr blockInfoItr = interfaceBlock.blockInfo.cbegin();
{ defineUniformBlockMembers(interfaceBlock.activeUniforms, "", blockIndex, &blockInfoItr, &blockUniformIndexes);
const sh::Uniform &constant = interfaceBlock.activeUniforms[activeUniformIndex];
Uniform *uniform = new Uniform(constant.type, constant.precision, constant.name, constant.arraySize,
blockIndex, interfaceBlock.blockInfo[activeUniformIndex]);
// add to uniform list, but not index, since uniform block uniforms have no location
blockUniformIndexes.push_back(mUniforms.size());
mUniforms.push_back(uniform);
}
// create all the uniform blocks // create all the uniform blocks
if (interfaceBlock.arraySize > 0) if (interfaceBlock.arraySize > 0)
......
...@@ -154,11 +154,14 @@ class ProgramBinary : public RefCountObject ...@@ -154,11 +154,14 @@ class ProgramBinary : public RefCountObject
bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader); bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader);
typedef sh::BlockMemberInfoArray::const_iterator BlockInfoItr;
bool areMatchingUniforms(InfoLog &infoLog, const std::string& uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform); bool areMatchingUniforms(InfoLog &infoLog, const std::string& uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform);
bool linkUniforms(InfoLog &infoLog, const sh::ActiveUniforms &vertexUniforms, const sh::ActiveUniforms &fragmentUniforms); bool linkUniforms(InfoLog &infoLog, const sh::ActiveUniforms &vertexUniforms, const sh::ActiveUniforms &fragmentUniforms);
bool defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog); bool defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog);
bool areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock); bool areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock);
bool linkUniformBlocks(InfoLog &infoLog, const sh::ActiveInterfaceBlocks &vertexUniformBlocks, const sh::ActiveInterfaceBlocks &fragmentUniformBlocks); bool linkUniformBlocks(InfoLog &infoLog, const sh::ActiveInterfaceBlocks &vertexUniformBlocks, const sh::ActiveInterfaceBlocks &fragmentUniformBlocks);
void defineUniformBlockMembers(const sh::ActiveUniforms &uniforms, const std::string &prefix, int blockIndex, BlockInfoItr *blockInfoItr, std::vector<unsigned int> *blockUniformIndexes);
bool defineUniformBlock(InfoLog &infoLog, GLenum shader, const sh::InterfaceBlock &interfaceBlock); bool defineUniformBlock(InfoLog &infoLog, GLenum shader, const sh::InterfaceBlock &interfaceBlock);
bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex); bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex);
......
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