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
}
}
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 hlsl;
......@@ -203,7 +221,8 @@ TString OutputHLSL::interfaceBlockMemberString(const TTypeList &typeList)
for (unsigned int typeIndex = 0; typeIndex < typeList.size(); typeIndex++)
{
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;
......@@ -305,7 +324,7 @@ void OutputHLSL::header()
mInterfaceBlockRegister += std::max(1u, interfaceBlock.arraySize);
// TODO: handle other block layouts
interfaceBlock.setPackedBlockLayout();
interfaceBlock.setBlockLayout(BLOCKLAYOUT_SHARED);
mActiveInterfaceBlocks.push_back(interfaceBlock);
if (interfaceBlockType.hasInstanceName())
......@@ -2920,8 +2939,7 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI
mStructNames.insert(decorate(name));
TString structure;
structure += "struct " + decorate(name) + "\n"
"{\n";
structure += "{\n";
const TTypeList &fields = *type.getStruct();
......@@ -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())
{
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++)
......
......@@ -178,6 +178,7 @@ class OutputHLSL : public TIntermTraverser
TString decoratePrivate(const TString &privateText);
TString interfaceBlockStructName(const TType &interfaceBlockType);
TString interfaceBlockInstanceString(const TType& interfaceBlockType, unsigned int arrayIndex);
TString interfaceBlockMemberTypeString(const TType &memberType);
TString interfaceBlockMemberString(const TTypeList &typeList);
TString interfaceBlockStructString(const TType &interfaceBlockType);
TString interfaceBlockString(const TType &interfaceBlockType, unsigned int registerIndex, unsigned int arrayIndex);
......
......@@ -45,6 +45,15 @@ struct BlockMemberInfo
static const BlockMemberInfo defaultBlockInfo;
};
typedef std::vector<BlockMemberInfo> BlockMemberInfoArray;
enum BlockLayoutType
{
BLOCKLAYOUT_STANDARD,
BLOCKLAYOUT_PACKED,
BLOCKLAYOUT_SHARED
};
struct InterfaceBlock
{
InterfaceBlock(const char *name, unsigned int arraySize, unsigned int registerIndex);
......@@ -54,12 +63,17 @@ struct InterfaceBlock
ActiveUniforms activeUniforms;
size_t dataSize;
std::vector<BlockMemberInfo> blockInfo;
BlockLayoutType layout;
unsigned int registerIndex;
void setSharedBlockLayout();
void setPackedBlockLayout();
void setStandardBlockLayout();
void setBlockLayout(BlockLayoutType newLayout);
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;
......
......@@ -2362,6 +2362,30 @@ bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const sh::ActiveInterfac
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)
{
// create uniform block entries if they do not exist
......@@ -2371,16 +2395,8 @@ bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, GLenum shader, const sh
const unsigned int blockIndex = mUniformBlocks.size();
// define member uniforms
for (unsigned int activeUniformIndex = 0; activeUniformIndex < interfaceBlock.activeUniforms.size(); activeUniformIndex++)
{
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);
}
BlockInfoItr blockInfoItr = interfaceBlock.blockInfo.cbegin();
defineUniformBlockMembers(interfaceBlock.activeUniforms, "", blockIndex, &blockInfoItr, &blockUniformIndexes);
// create all the uniform blocks
if (interfaceBlock.arraySize > 0)
......
......@@ -154,11 +154,14 @@ class ProgramBinary : public RefCountObject
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 linkUniforms(InfoLog &infoLog, const sh::ActiveUniforms &vertexUniforms, const sh::ActiveUniforms &fragmentUniforms);
bool defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog);
bool areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock);
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 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