Commit 574d9dd0 by Jamie Madill Committed by Shannon Woods

Add support for std140 uniform block layout for basic types.

This support does not include structures. TRAC #23083 Signed-off-by: Nicolas Capens Signed-off-by: Shannon Woods Authored-by: Jamie Madill
parent 919b066a
...@@ -124,6 +124,7 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc ...@@ -124,6 +124,7 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc
mSamplerRegister = 0; mSamplerRegister = 0;
mInterfaceBlockRegister = 2; // Reserve registers for the default uniform block and driver constants mInterfaceBlockRegister = 2; // Reserve registers for the default uniform block and driver constants
mPaddingCounter = 0;
} }
OutputHLSL::~OutputHLSL() OutputHLSL::~OutputHLSL()
...@@ -235,17 +236,113 @@ TString OutputHLSL::interfaceBlockMemberTypeString(const TType &memberType) ...@@ -235,17 +236,113 @@ TString OutputHLSL::interfaceBlockMemberTypeString(const TType &memberType)
} }
} }
TString OutputHLSL::interfaceBlockMemberString(const TTypeList &typeList) TString OutputHLSL::std140PrePaddingString(const TType &type, int *elementIndex)
{
if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray())
{
// no padding needed, HLSL will align the field to a new register
*elementIndex = 0;
return "";
}
const GLenum glType = glVariableType(type);
const int numComponents = gl::UniformComponentCount(glType);
if (numComponents >= 4)
{
// no padding needed, HLSL will align the field to a new register
*elementIndex = 0;
return "";
}
if (*elementIndex + numComponents > 4)
{
// no padding needed, HLSL will align the field to a new register
*elementIndex = numComponents;
return "";
}
TString padding;
const int alignment = numComponents == 3 ? 4 : numComponents;
const int paddingOffset = (*elementIndex % alignment);
if (paddingOffset != 0)
{
// padding is neccessary
for (int paddingIndex = paddingOffset; paddingIndex < alignment; paddingIndex++)
{
padding += " float pad_" + str(mPaddingCounter++) + ";\n";
}
*elementIndex += (alignment - paddingOffset);
}
*elementIndex += numComponents;
*elementIndex %= 4;
return padding;
}
TString OutputHLSL::std140PostPaddingString(const TType &type)
{
if (!type.isMatrix() && !type.isArray())
{
return "";
}
const GLenum glType = glVariableType(type);
int numComponents = 0;
if (type.isMatrix())
{
const bool isRowMajorMatrix = (type.getLayoutQualifier().matrixPacking == EmpRowMajor);
numComponents = gl::MatrixComponentCount(glType, isRowMajorMatrix);
}
else
{
numComponents = gl::UniformComponentCount(glType);
}
TString padding;
for (int paddingOffset = numComponents; paddingOffset < 4; paddingOffset++)
{
padding += " float pad_" + str(mPaddingCounter++) + ";\n";
}
return padding;
}
TString OutputHLSL::interfaceBlockMemberString(const TTypeList &typeList, TLayoutBlockStorage blockStorage)
{ {
TString hlsl; TString hlsl;
// TODO: padding for standard layout int elementIndex = 0;
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;
if (blockStorage == EbsStd140)
{
if (memberType.getBasicType() == EbtStruct)
{
UNIMPLEMENTED();
}
else
{
// 2 and 3 component vector types in some cases need pre-padding
hlsl += std140PrePaddingString(memberType, &elementIndex);
}
}
hlsl += " " + interfaceBlockMemberTypeString(memberType) + hlsl += " " + interfaceBlockMemberTypeString(memberType) +
" " + decorate(memberType.getFieldName()) + arrayString(memberType) + ";\n"; " " + decorate(memberType.getFieldName()) + arrayString(memberType) + ";\n";
// must pad out after matrices and arrays, where HLSL usually allows itself room to pack stuff
if (blockStorage == EbsStd140)
{
hlsl += std140PostPaddingString(memberType);
}
} }
return hlsl; return hlsl;
...@@ -254,10 +351,11 @@ TString OutputHLSL::interfaceBlockMemberString(const TTypeList &typeList) ...@@ -254,10 +351,11 @@ TString OutputHLSL::interfaceBlockMemberString(const TTypeList &typeList)
TString OutputHLSL::interfaceBlockStructString(const TType &interfaceBlockType) TString OutputHLSL::interfaceBlockStructString(const TType &interfaceBlockType)
{ {
const TTypeList &typeList = *interfaceBlockType.getStruct(); const TTypeList &typeList = *interfaceBlockType.getStruct();
const TLayoutBlockStorage blockStorage = interfaceBlockType.getLayoutQualifier().blockStorage;
return "struct " + interfaceBlockStructName(interfaceBlockType) + "\n" return "struct " + interfaceBlockStructName(interfaceBlockType) + "\n"
"{\n" + "{\n" +
interfaceBlockMemberString(typeList) + interfaceBlockMemberString(typeList, blockStorage) +
"};\n\n"; "};\n\n";
} }
...@@ -277,7 +375,8 @@ TString OutputHLSL::interfaceBlockString(const TType &interfaceBlockType, unsign ...@@ -277,7 +375,8 @@ TString OutputHLSL::interfaceBlockString(const TType &interfaceBlockType, unsign
else else
{ {
const TTypeList &typeList = *interfaceBlockType.getStruct(); const TTypeList &typeList = *interfaceBlockType.getStruct();
hlsl += interfaceBlockMemberString(typeList); const TLayoutBlockStorage blockStorage = interfaceBlockType.getLayoutQualifier().blockStorage;
hlsl += interfaceBlockMemberString(typeList, blockStorage);
} }
hlsl += "};\n\n"; hlsl += "};\n\n";
...@@ -316,6 +415,17 @@ void setBlockLayout(InterfaceBlock *interfaceBlock, BlockLayoutType newLayout) ...@@ -316,6 +415,17 @@ void setBlockLayout(InterfaceBlock *interfaceBlock, BlockLayoutType newLayout)
} }
} }
BlockLayoutType convertBlockLayoutType(TLayoutBlockStorage blockStorage)
{
switch (blockStorage)
{
case EbsPacked: return BLOCKLAYOUT_PACKED;
case EbsShared: return BLOCKLAYOUT_SHARED;
case EbsStd140: return BLOCKLAYOUT_STANDARD;
default: UNREACHABLE(); return BLOCKLAYOUT_SHARED;
}
}
void OutputHLSL::header() void OutputHLSL::header()
{ {
ShShaderType shaderType = mContext.shaderType; ShShaderType shaderType = mContext.shaderType;
...@@ -366,8 +476,8 @@ void OutputHLSL::header() ...@@ -366,8 +476,8 @@ void OutputHLSL::header()
mInterfaceBlockRegister += std::max(1u, interfaceBlock.arraySize); mInterfaceBlockRegister += std::max(1u, interfaceBlock.arraySize);
// TODO: handle other block layouts BlockLayoutType blockLayoutType = convertBlockLayoutType(interfaceBlockType.getLayoutQualifier().blockStorage);
setBlockLayout(&interfaceBlock, BLOCKLAYOUT_SHARED); setBlockLayout(&interfaceBlock, blockLayoutType);
mActiveInterfaceBlocks.push_back(interfaceBlock); mActiveInterfaceBlocks.push_back(interfaceBlock);
if (interfaceBlockType.hasInstanceName()) if (interfaceBlockType.hasInstanceName())
......
...@@ -173,6 +173,7 @@ class OutputHLSL : public TIntermTraverser ...@@ -173,6 +173,7 @@ class OutputHLSL : public TIntermTraverser
int mUniformRegister; int mUniformRegister;
int mInterfaceBlockRegister; int mInterfaceBlockRegister;
int mSamplerRegister; int mSamplerRegister;
int mPaddingCounter;
TString registerString(TIntermSymbol *operand); TString registerString(TIntermSymbol *operand);
int samplerRegister(TIntermSymbol *sampler); int samplerRegister(TIntermSymbol *sampler);
...@@ -185,9 +186,11 @@ class OutputHLSL : public TIntermTraverser ...@@ -185,9 +186,11 @@ class OutputHLSL : public TIntermTraverser
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 interfaceBlockMemberTypeString(const TType &memberType);
TString interfaceBlockMemberString(const TTypeList &typeList); TString interfaceBlockMemberString(const TTypeList &typeList, TLayoutBlockStorage blockStorage);
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);
TString std140PrePaddingString(const TType &type, int *elementIndex);
TString std140PostPaddingString(const TType &type);
static GLenum glVariableType(const TType &type); static GLenum glVariableType(const TType &type);
static GLenum glVariablePrecision(const TType &type); static GLenum glVariablePrecision(const TType &type);
......
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