Commit 5609378d by Jamie Madill

Add full support for uniform structs.

TRAC #23750 Signed-off-by: Geoff Lang Signed-off-by: Nicolas Capens
parent 5b085dc3
......@@ -84,6 +84,39 @@ void HLSLBlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool i
}
}
void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, Uniform *variable, HLSLBlockEncoder *encoder, const std::vector<BlockMemberInfo> &blockInfo)
{
// because this method computes offsets (element indexes) instead of any total sizes,
// we can ignore the array size of the variable
if (variable->isStruct())
{
encoder->enterAggregateType();
for (size_t fieldIndex = 0; fieldIndex < variable->fields.size(); fieldIndex++)
{
HLSLVariableGetRegisterInfo(baseRegisterIndex, &variable->fields[fieldIndex], encoder, blockInfo);
}
encoder->exitAggregateType();
}
else
{
encoder->encodeType(variable->type, variable->arraySize, false);
const size_t registerBytes = (encoder->BytesPerComponent * encoder->ComponentsPerRegister);
variable->registerIndex = baseRegisterIndex + (blockInfo.back().offset / registerBytes);
variable->elementIndex = (blockInfo.back().offset % registerBytes) / sizeof(float);
}
}
void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, Uniform *variable)
{
std::vector<BlockMemberInfo> blockInfo;
HLSLBlockEncoder encoder(&blockInfo);
HLSLVariableGetRegisterInfo(baseRegisterIndex, variable, &encoder, blockInfo);
}
template <class ShaderVarType>
void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder)
{
......
......@@ -31,6 +31,10 @@ class HLSLBlockEncoder : public BlockLayoutEncoder
virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride);
};
// This method assigns values to the variable's "registerIndex" and "elementIndex" fields.
// "elementIndex" is only used for structures.
void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, Uniform *variable);
// This method returns the number of used registers for a ShaderVariable. It is dependent on the HLSLBlockEncoder
// class to count the number of used registers in a struct (which are individually packed according to the same rules).
unsigned int HLSLVariableRegisterCount(const Varying &variable);
......
......@@ -3596,16 +3596,16 @@ Uniform OutputHLSL::declareUniformToList(const TType &type, const TString &name,
{
const bool isRowMajorMatrix = (type.isMatrix() && type.getLayoutQualifier().matrixPacking == EmpRowMajor);
Uniform uniform(glVariableType(type), glVariablePrecision(type), name.c_str(),
(unsigned int)type.getArraySize(), (unsigned int)registerIndex);
(unsigned int)type.getArraySize(), (unsigned int)registerIndex, 0);
output.push_back(uniform);
return uniform;
}
else
{
Uniform structUniform(GL_STRUCT_ANGLEX, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), (unsigned int)registerIndex);
Uniform structUniform(GL_STRUCT_ANGLEX, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(),
(unsigned int)registerIndex, GL_INVALID_INDEX);
int fieldRegister = registerIndex;
const TFieldList &fields = structure->fields();
for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
......@@ -3613,10 +3613,12 @@ Uniform OutputHLSL::declareUniformToList(const TType &type, const TString &name,
TField *field = fields[fieldIndex];
TType *fieldType = field->type();
const Uniform &fieldVariable = declareUniformToList(*fieldType, field->name(), fieldRegister, structUniform.fields);
fieldRegister += HLSLVariableRegisterCount(fieldVariable);
declareUniformToList(*fieldType, field->name(), GL_INVALID_INDEX, structUniform.fields);
}
// assign register offset information -- this will override the information in any sub-structures.
HLSLVariableGetRegisterInfo(registerIndex, &structUniform);
output.push_back(structUniform);
return structUniform;
......
......@@ -17,9 +17,10 @@ ShaderVariable::ShaderVariable(GLenum typeIn, GLenum precisionIn, const char *na
{
}
Uniform::Uniform(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn, unsigned int registerIndexIn)
Uniform::Uniform(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn, unsigned int registerIndexIn, unsigned int elementIndexIn)
: ShaderVariable(typeIn, precisionIn, nameIn, arraySizeIn),
registerIndex(registerIndexIn)
registerIndex(registerIndexIn),
elementIndex(elementIndexIn)
{
}
......
......@@ -39,9 +39,11 @@ struct ShaderVariable
struct Uniform : public ShaderVariable
{
unsigned int registerIndex;
unsigned int elementIndex; // For struct varyings
std::vector<Uniform> fields;
Uniform(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn, unsigned int registerIndexIn);
Uniform(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn,
unsigned int registerIndexIn, unsigned int elementIndexIn);
bool isStruct() const { return !fields.empty(); }
};
......
......@@ -2385,7 +2385,8 @@ bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, In
{
const sh::Uniform &field = constant.fields[fieldIndex];
const std::string &uniformName = constant.name + arrayString(elementIndex) + "." + field.name;
const sh::Uniform fieldUniform(field.type, field.precision, uniformName.c_str(), field.arraySize, elementRegisterIndex);
const sh::Uniform fieldUniform(field.type, field.precision, uniformName.c_str(), field.arraySize,
elementRegisterIndex, field.elementIndex);
if (!defineUniform(shader, fieldUniform, infoLog))
{
return false;
......@@ -2396,21 +2397,20 @@ bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, In
}
else
{
unsigned int fieldRegisterIndex = constant.registerIndex;
for (size_t fieldIndex = 0; fieldIndex < constant.fields.size(); fieldIndex++)
{
const sh::Uniform &field = constant.fields[fieldIndex];
const std::string &uniformName = constant.name + "." + field.name;
sh::Uniform fieldUniform(field.type, field.precision, uniformName.c_str(), field.arraySize, fieldRegisterIndex);
sh::Uniform fieldUniform(field.type, field.precision, uniformName.c_str(), field.arraySize,
field.registerIndex, field.elementIndex);
fieldUniform.fields = field.fields;
if (!defineUniform(shader, fieldUniform, infoLog))
{
return false;
}
fieldRegisterIndex += sh::HLSLVariableRegisterCount(field);
}
}
......@@ -2470,6 +2470,7 @@ bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, In
else
{
uniform = new Uniform(constant.type, constant.precision, constant.name, constant.arraySize, -1, sh::BlockMemberInfo::defaultBlockInfo);
uniform->registerElement = constant.elementIndex;
}
if (!uniform)
......
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