From b558cd4af4469253c3b7101b648ed00a58481ecf Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 11 Jan 2017 14:49:12 +0000 Subject: [PATCH] Check top-level stride of buffers to know if we need to pad. Refs #485 --- renderdoc/driver/gl/gl_shader_refl.cpp | 56 ++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/renderdoc/driver/gl/gl_shader_refl.cpp b/renderdoc/driver/gl/gl_shader_refl.cpp index 15ccd6928..8c3403690 100644 --- a/renderdoc/driver/gl/gl_shader_refl.cpp +++ b/renderdoc/driver/gl/gl_shader_refl.cpp @@ -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 *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]); }