Add support for structs in uniform blocks with standard layout.
TRAC #23327
Signed-off-by: Geoff Lang
Signed-off-by: Shannon Woods
Authored-by: Jamie Madill
diff --git a/src/compiler/OutputHLSL.cpp b/src/compiler/OutputHLSL.cpp
index 22a4e4f..4737400 100644
--- a/src/compiler/OutputHLSL.cpp
+++ b/src/compiler/OutputHLSL.cpp
@@ -253,7 +253,7 @@
}
}
-TString OutputHLSL::interfaceBlockMemberTypeString(const TType &memberType)
+TString OutputHLSL::interfaceBlockMemberTypeString(const TType &memberType, TLayoutBlockStorage blockStorage)
{
const TLayoutMatrixPacking matrixPacking = memberType.getLayoutQualifier().matrixPacking;
ASSERT(matrixPacking != EmpUnspecified);
@@ -267,7 +267,7 @@
else if (memberType.getBasicType() == EbtStruct)
{
// Use HLSL row-major packing for GLSL column-major matrices
- return structureTypeName(memberType, matrixPacking == EmpColumnMajor);
+ return structureTypeName(memberType, matrixPacking == EmpColumnMajor, blockStorage == EbsStd140);
}
else
{
@@ -325,21 +325,26 @@
TString OutputHLSL::std140PostPaddingString(const TType &type)
{
- if (!type.isMatrix() && !type.isArray())
+ if (!type.isMatrix() && !type.isArray() && type.getBasicType() != EbtStruct)
{
return "";
}
- const GLenum glType = glVariableType(type);
int numComponents = 0;
if (type.isMatrix())
{
const bool isRowMajorMatrix = (type.getLayoutQualifier().matrixPacking == EmpRowMajor);
+ const GLenum glType = glVariableType(type);
numComponents = gl::MatrixComponentCount(glType, isRowMajorMatrix);
}
+ else if (type.getBasicType() == EbtStruct)
+ {
+ // TODO
+ }
else
{
+ const GLenum glType = glVariableType(type);
numComponents = gl::UniformComponentCount(glType);
}
@@ -363,18 +368,11 @@
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);
- }
+ // 2 and 3 component vector types in some cases need pre-padding
+ hlsl += std140PrePaddingString(memberType, &elementIndex);
}
- hlsl += " " + interfaceBlockMemberTypeString(memberType) +
+ hlsl += " " + interfaceBlockMemberTypeString(memberType, blockStorage) +
" " + decorate(memberType.getFieldName()) + arrayString(memberType) + ";\n";
// must pad out after matrices and arrays, where HLSL usually allows itself room to pack stuff
@@ -2782,7 +2780,7 @@
}
else // Nameless structure, define in place
{
- return structureString(type, false);
+ return structureString(type, false, false);
}
}
else if (type.isMatrix())
@@ -2900,13 +2898,13 @@
return "{" + string + "}";
}
-TString OutputHLSL::structureString(const TType &structType, bool useHLSLRowMajorPacking)
+TString OutputHLSL::structureString(const TType &structType, bool useHLSLRowMajorPacking, bool useStd140Packing)
{
ASSERT(structType.getStruct());
const TTypeList &fields = *structType.getStruct();
const bool isNameless = (structType.getTypeName() == "");
- const TString &structName = structureTypeName(structType, useHLSLRowMajorPacking);
+ const TString &structName = structureTypeName(structType, useHLSLRowMajorPacking, useStd140Packing);
const TString declareString = (isNameless ? "struct" : "struct " + structName);
@@ -2914,12 +2912,24 @@
structure += declareString + "\n"
"{\n";
+ int elementIndex = 0;
+
for (unsigned int i = 0; i < fields.size(); i++)
{
const TType &field = *fields[i].type;
- structure += " " + structureTypeName(field, useHLSLRowMajorPacking) + " " +
+ if (useStd140Packing)
+ {
+ structure += std140PrePaddingString(field, &elementIndex);
+ }
+
+ structure += " " + structureTypeName(field, useHLSLRowMajorPacking, useStd140Packing) + " " +
decorateField(field.getFieldName(), structType) + arrayString(field) + ";\n";
+
+ if (useStd140Packing)
+ {
+ structure += std140PostPaddingString(field);
+ }
}
// Nameless structs do not finish with a semicolon and newline, to leave room for an instance variable
@@ -2928,7 +2938,7 @@
return structure;
}
-TString OutputHLSL::structureTypeName(const TType &structType, bool useHLSLRowMajorPacking)
+TString OutputHLSL::structureTypeName(const TType &structType, bool useHLSLRowMajorPacking, bool useStd140Packing)
{
if (structType.getBasicType() != EbtStruct)
{
@@ -2944,8 +2954,15 @@
// Structs packed with row-major matrices in HLSL are prefixed with "rm"
// GLSL column-major maps to HLSL row-major, and the converse is true
+
+ if (useStd140Packing)
+ {
+ prefix += "std";
+ }
+
if (useHLSLRowMajorPacking)
{
+ if (prefix != "") prefix += "_";
prefix += "rm";
}
@@ -2978,17 +2995,27 @@
{
mStructNames.insert(decorate(name));
- const TString &structure = structureString(type, false);
+ const TString &structure = structureString(type, false, false);
if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structure) == mStructDeclarations.end())
{
// Add row-major packed struct for interface blocks
TString rowMajorString = "#pragma pack_matrix(row_major)\n" +
- structureString(type, true) +
+ structureString(type, true, false) +
"#pragma pack_matrix(column_major)\n";
+ const TString &std140Prefix = "std";
+ TString std140String = structureString(type, false, true);
+
+ const TString &std140RowMajorPrefix = "std_rm";
+ TString std140RowMajorString = "#pragma pack_matrix(row_major)\n" +
+ structureString(type, true, true) +
+ "#pragma pack_matrix(column_major)\n";
+
mStructDeclarations.push_back(structure);
mStructDeclarations.push_back(rowMajorString);
+ mStructDeclarations.push_back(std140String);
+ mStructDeclarations.push_back(std140RowMajorString);
}
const TTypeList &fields = *type.getStruct();
diff --git a/src/compiler/OutputHLSL.h b/src/compiler/OutputHLSL.h
index fd32811..baa4675 100644
--- a/src/compiler/OutputHLSL.h
+++ b/src/compiler/OutputHLSL.h
@@ -40,8 +40,8 @@
TString typeString(const TType &type);
TString textureString(const TType &type);
TString interpolationString(TQualifier qualifier);
- TString structureString(const TType &structType, bool useHLSLRowMajorPacking);
- TString structureTypeName(const TType &structType, bool useHLSLRowMajorPacking);
+ TString structureString(const TType &structType, bool useHLSLRowMajorPacking, bool useStd140Packing);
+ TString structureTypeName(const TType &structType, bool useHLSLRowMajorPacking, bool useStd140Packing);
static TString qualifierString(TQualifier qualifier);
static TString arrayString(const TType &type);
static TString initializer(const TType &type);
@@ -193,7 +193,7 @@
TString decoratePrivate(const TString &privateText);
TString interfaceBlockStructName(const TType &interfaceBlockType);
TString interfaceBlockInstanceString(const TType& interfaceBlockType, unsigned int arrayIndex);
- TString interfaceBlockMemberTypeString(const TType &memberType);
+ TString interfaceBlockMemberTypeString(const TType &memberType, TLayoutBlockStorage blockStorage);
TString interfaceBlockMemberString(const TTypeList &typeList, TLayoutBlockStorage blockStorage);
TString interfaceBlockStructString(const TType &interfaceBlockType);
TString interfaceBlockString(const TType &interfaceBlockType, unsigned int registerIndex, unsigned int arrayIndex);