Use the proper register count for structs in HLSL uniforms and varyings.
We must respect HLSL packing rules when uploading structs to D3D.
TRAC #23748
Signed-off-by: Geoff Lang
Signed-off-by: Nicolas Capens
diff --git a/src/compiler/HLSLLayoutEncoder.cpp b/src/compiler/HLSLLayoutEncoder.cpp
index f3501a6..2c1832a 100644
--- a/src/compiler/HLSLLayoutEncoder.cpp
+++ b/src/compiler/HLSLLayoutEncoder.cpp
@@ -85,31 +85,45 @@
}
template <class ShaderVarType>
-unsigned int HLSLRegisterCount(const ShaderVarType &variable)
+void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder)
{
if (variable.isStruct())
{
- unsigned int totalCount = 0;
- for (size_t fieldIndex = 0; fieldIndex < variable.fields.size(); fieldIndex++)
+ for (size_t arrayElement = 0; arrayElement < variable.elementCount(); arrayElement++)
{
- totalCount += HLSLVariableRegisterCount(variable.fields[fieldIndex]);
+ encoder->enterAggregateType();
+
+ for (size_t fieldIndex = 0; fieldIndex < variable.fields.size(); fieldIndex++)
+ {
+ HLSLVariableRegisterCount(variable.fields[fieldIndex], encoder);
+ }
+
+ encoder->exitAggregateType();
}
- return totalCount * variable.elementCount();
}
else
{
- return gl::VariableRowCount(variable.type) * variable.elementCount();
+ // We operate only on varyings and uniforms, which do not have matrix layout qualifiers
+ encoder->encodeType(variable.type, variable.arraySize, false);
}
}
unsigned int HLSLVariableRegisterCount(const Varying &variable)
{
- return HLSLRegisterCount(variable);
+ HLSLBlockEncoder encoder(NULL);
+ HLSLVariableRegisterCount(variable, &encoder);
+
+ const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
+ return rx::roundUp(encoder.getBlockSize(), registerBytes) / registerBytes;
}
unsigned int HLSLVariableRegisterCount(const Uniform &variable)
{
- return HLSLRegisterCount(variable);
+ HLSLBlockEncoder encoder(NULL);
+ HLSLVariableRegisterCount(variable, &encoder);
+
+ const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
+ return rx::roundUp(encoder.getBlockSize(), registerBytes) / registerBytes;
}
}