Check top-level stride of buffers to know if we need to pad. Refs #485

This commit is contained in:
baldurk
2017-01-11 14:49:12 +00:00
parent 34b4cee42c
commit b558cd4af4
+56
View File
@@ -757,6 +757,13 @@ void ReconstructVarTree(const GLHookSet &gl, GLenum query, GLuint sepProg, GLuin
else
var.type.descriptor.elements = 0;
GLint topLevelStride = 0;
if(query == eGL_BUFFER_VARIABLE)
{
GLenum propName = eGL_TOP_LEVEL_ARRAY_STRIDE;
gl.glGetProgramResourceiv(sepProg, query, varIdx, 1, &propName, 1, NULL, &topLevelStride);
}
vector<DynShaderConstant> *parentmembers = defaultBlock;
if(values[3] != -1 && values[3] < numParentBlocks)
@@ -833,6 +840,7 @@ void ReconstructVarTree(const GLHookSet &gl, GLenum query, GLuint sepProg, GLuin
parentVar.type.descriptor.rowMajorStorage = false;
parentVar.type.descriptor.type = var.type.descriptor.type;
parentVar.type.descriptor.elements = isarray ? RDCMAX(1U, uint32_t(arrayIdx + 1)) : 0;
parentVar.type.descriptor.arrayStride = topLevelStride;
bool found = false;
@@ -1534,6 +1542,54 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg,
for(size_t ssbo = 0; ssbo < ssbos.size(); ssbo++)
{
sort(members[ssbo]);
// account for padding for std430 layout, if we have a root array of
// structs, we need to pad the struct up to have the correct alignment
if(members[ssbo].size() == 1 && !members[ssbo][0].type.members.empty() &&
members[ssbo][0].type.descriptor.arrayStride != 0)
{
// now that we're sorted, see what the tightly packed stride would be by looking at the last
// member
uint32_t desiredStride = members[ssbo][0].type.descriptor.arrayStride;
DynShaderConstant *last = &members[ssbo][0].type.members.back();
while(!last->type.members.empty())
last = &last->type.members.back();
// start from the offset
uint32_t stride = last->reg.vec * 16 + last->reg.comp * 4;
// add its size
uint32_t size = last->type.descriptor.rows * last->type.descriptor.cols * 4;
if(last->type.descriptor.type == eVar_Double)
size *= 2;
stride += size;
if(stride < desiredStride)
{
uint32_t padding = desiredStride - stride;
RDCASSERT((padding % 4) == 0 && padding <= 16, padding);
padding /= 4;
DynShaderConstant paddingVar;
paddingVar.name = "__padding";
paddingVar.reg.vec = last->reg.vec + (size / 16);
paddingVar.reg.comp = (last->reg.comp + size / 4) % 16;
paddingVar.type.descriptor.type = eVar_UInt;
paddingVar.type.descriptor.rows = 1;
paddingVar.type.descriptor.cols = padding;
paddingVar.type.descriptor.elements = 1;
paddingVar.type.descriptor.rowMajorStorage = false;
paddingVar.type.descriptor.arrayStride = 0;
paddingVar.type.descriptor.name = StringFormat::Fmt("uint%u", padding);
members[ssbo][0].type.members.push_back(paddingVar);
}
}
copy(rwresources[ssbos[ssbo]].variableType.members, members[ssbo]);
}