diff --git a/renderdoc/api/replay/shader_types.h b/renderdoc/api/replay/shader_types.h index 9b1886c7a..f8acb3aa9 100644 --- a/renderdoc/api/replay/shader_types.h +++ b/renderdoc/api/replay/shader_types.h @@ -181,7 +181,7 @@ struct ShaderResource bool32 IsSampler; bool32 IsTexture; bool32 IsSRV; - bool32 IsUAV; + bool32 IsReadWrite; ShaderResourceType resType; diff --git a/renderdoc/core/replay_proxy.cpp b/renderdoc/core/replay_proxy.cpp index 5fe03dee8..43b20eace 100644 --- a/renderdoc/core/replay_proxy.cpp +++ b/renderdoc/core/replay_proxy.cpp @@ -397,7 +397,7 @@ void Serialiser::Serialise(const char *name, ShaderResource &el) Serialise("", el.IsSampler); Serialise("", el.IsTexture); Serialise("", el.IsSRV); - Serialise("", el.IsUAV); + Serialise("", el.IsReadWrite); Serialise("", el.name); Serialise("", el.variableType); Serialise("", el.bindPoint); diff --git a/renderdoc/driver/d3d11/d3d11_common.cpp b/renderdoc/driver/d3d11/d3d11_common.cpp index f8069e1fe..b52540f05 100644 --- a/renderdoc/driver/d3d11/d3d11_common.cpp +++ b/renderdoc/driver/d3d11/d3d11_common.cpp @@ -877,12 +877,12 @@ ShaderReflection *MakeShaderReflection(DXBC::DXBCFile *dxbc) r.type == DXBC::ShaderInputBind::TYPE_TEXTURE || r.type == DXBC::ShaderInputBind::TYPE_STRUCTURED || r.type == DXBC::ShaderInputBind::TYPE_BYTEADDRESS); - res.IsUAV = (r.type == DXBC::ShaderInputBind::TYPE_UAV_RWTYPED || - r.type == DXBC::ShaderInputBind::TYPE_UAV_RWSTRUCTURED || - r.type == DXBC::ShaderInputBind::TYPE_UAV_RWBYTEADDRESS || - r.type == DXBC::ShaderInputBind::TYPE_UAV_APPEND_STRUCTURED || - r.type == DXBC::ShaderInputBind::TYPE_UAV_CONSUME_STRUCTURED || - r.type == DXBC::ShaderInputBind::TYPE_UAV_RWSTRUCTURED_WITH_COUNTER); + res.IsReadWrite = (r.type == DXBC::ShaderInputBind::TYPE_UAV_RWTYPED || + r.type == DXBC::ShaderInputBind::TYPE_UAV_RWSTRUCTURED || + r.type == DXBC::ShaderInputBind::TYPE_UAV_RWBYTEADDRESS || + r.type == DXBC::ShaderInputBind::TYPE_UAV_APPEND_STRUCTURED || + r.type == DXBC::ShaderInputBind::TYPE_UAV_CONSUME_STRUCTURED || + r.type == DXBC::ShaderInputBind::TYPE_UAV_RWSTRUCTURED_WITH_COUNTER); switch(r.dimension) { diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index 6f27d22b3..2f6ca53ff 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -783,7 +783,7 @@ void GLReplay::GetMapping(WrappedOpenGL &gl, GLuint curProg, int shadIdx, Shader dummyReadback[i] = 0x6c7b8a9d; #endif - GLenum refEnum[] = { + const GLenum refEnum[] = { eGL_REFERENCED_BY_VERTEX_SHADER, eGL_REFERENCED_BY_TESS_CONTROL_SHADER, eGL_REFERENCED_BY_TESS_EVALUATION_SHADER, @@ -795,31 +795,98 @@ void GLReplay::GetMapping(WrappedOpenGL &gl, GLuint curProg, int shadIdx, Shader create_array_uninit(mapping.Resources, refl->Resources.count); for(int32_t i=0; i < refl->Resources.count; i++) { - if(refl->Resources.elems[i].IsSRV && refl->Resources.elems[i].IsTexture) + if(refl->Resources.elems[i].IsTexture) { + // normal sampler or image load/store + GLint loc = gl.glGetUniformLocation(curProg, refl->Resources.elems[i].name.elems); if(loc >= 0) { gl.glGetUniformiv(curProg, loc, dummyReadback); mapping.Resources[i].bind = dummyReadback[0]; } + + GLuint idx = 0; + idx = gl.glGetProgramResourceIndex(curProg, eGL_UNIFORM, refl->Resources.elems[i].name.elems); + + if(idx == GL_INVALID_INDEX) + { + mapping.Resources[i].used = false; + } + else + { + GLint used = 0; + gl.glGetProgramResourceiv(curProg, eGL_UNIFORM, idx, 1, &refEnum[shadIdx], 1, NULL, &used); + mapping.Resources[i].used = (used != 0); + } + } + else if(refl->Resources.elems[i].IsReadWrite && !refl->Resources.elems[i].IsTexture) + { + if(refl->Resources.elems[i].variableType.descriptor.cols == 1 && + refl->Resources.elems[i].variableType.descriptor.rows == 1 && + refl->Resources.elems[i].variableType.descriptor.type == eVar_UInt) + { + // atomic uint + GLuint idx = gl.glGetProgramResourceIndex(curProg, eGL_UNIFORM, refl->Resources.elems[i].name.elems); + + if(idx == GL_INVALID_INDEX) + { + mapping.Resources[i].bind = -1; + mapping.Resources[i].used = false; + } + else + { + GLenum prop = eGL_ATOMIC_COUNTER_BUFFER_INDEX; + GLuint atomicIndex; + gl.glGetProgramResourceiv(curProg, eGL_UNIFORM, idx, 1, &prop, 1, NULL, (GLint *)&atomicIndex); + + if(atomicIndex == GL_INVALID_INDEX) + { + mapping.Resources[i].bind = -1; + mapping.Resources[i].used = false; + } + else + { + const GLenum atomicRefEnum[] = { + eGL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER, + eGL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER, + eGL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER, + eGL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER, + eGL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER, + eGL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER, + }; + gl.glGetActiveAtomicCounterBufferiv(curProg, atomicIndex, eGL_ATOMIC_COUNTER_BUFFER_BINDING, &mapping.Resources[i].bind); + GLint used = 0; + gl.glGetActiveAtomicCounterBufferiv(curProg, atomicIndex, atomicRefEnum[shadIdx], &used); + mapping.Resources[i].used = (used != 0); + } + } + } + else + { + // shader storage buffer object + GLuint idx = gl.glGetProgramResourceIndex(curProg, eGL_SHADER_STORAGE_BLOCK, refl->Resources.elems[i].name.elems); + + if(idx == GL_INVALID_INDEX) + { + mapping.Resources[i].bind = -1; + mapping.Resources[i].used = false; + } + else + { + GLenum prop = eGL_BUFFER_BINDING; + gl.glGetProgramResourceiv(curProg, eGL_SHADER_STORAGE_BLOCK, idx, 1, &prop, 1, NULL, &mapping.Resources[i].bind); + GLint used = 0; + gl.glGetProgramResourceiv(curProg, eGL_SHADER_STORAGE_BLOCK, idx, 1, &refEnum[shadIdx], 1, NULL, &used); + mapping.Resources[i].used = (used != 0); + } + } } else { mapping.Resources[i].bind = -1; - } - - GLuint idx = gl.glGetProgramResourceIndex(curProg, eGL_UNIFORM, refl->Resources.elems[i].name.elems); - if(idx == GL_INVALID_INDEX) - { mapping.Resources[i].used = false; } - else - { - GLint used = 0; - gl.glGetProgramResourceiv(curProg, eGL_UNIFORM, idx, 1, &refEnum[shadIdx], 1, NULL, &used); - mapping.Resources[i].used = (used != 0); - } } create_array_uninit(mapping.ConstantBlocks, refl->ConstantBlocks.count); @@ -1226,6 +1293,8 @@ void GLReplay::SavePipelineState() for(int32_t r=0; r < refls[s]->Resources.count; r++) { + if(refls[s]->Resources[r].IsReadWrite) continue; + // bindPoint is the uniform value for this sampler if(mappings[s]->Resources[ refls[s]->Resources[r].bindPoint ].bind == unit) { diff --git a/renderdoc/driver/gl/gl_shader_refl.cpp b/renderdoc/driver/gl/gl_shader_refl.cpp index 864158a52..1a91a3128 100644 --- a/renderdoc/driver/gl/gl_shader_refl.cpp +++ b/renderdoc/driver/gl/gl_shader_refl.cpp @@ -220,6 +220,364 @@ GLuint MakeSeparableShaderProgram(const GLHookSet &gl, GLenum type, vector *parentBlocks, + vector *defaultBlock) +{ + const size_t numProps = 7; + + GLenum resProps[numProps] = { + eGL_TYPE, eGL_NAME_LENGTH, eGL_LOCATION, eGL_BLOCK_INDEX, eGL_ARRAY_SIZE, eGL_OFFSET, eGL_IS_ROW_MAJOR, + }; + + // GL_LOCATION not valid for buffer variables (it's only used if offset comes back -1, which will never + // happen for buffer variables) + if(query == eGL_BUFFER_VARIABLE) + resProps[2] = eGL_OFFSET; + + GLint values[numProps] = { -1, -1, -1, -1, -1, -1, -1 }; + gl.glGetProgramResourceiv(sepProg, query, varIdx, numProps, resProps, numProps, NULL, values); + + DynShaderConstant var; + + var.type.descriptor.elements = RDCMAX(1, values[4]); + + // set type (or bail if it's not a variable - sampler or such) + switch(values[0]) + { + case eGL_FLOAT_VEC4: + case eGL_FLOAT_VEC3: + case eGL_FLOAT_VEC2: + case eGL_FLOAT: + case eGL_FLOAT_MAT4: + case eGL_FLOAT_MAT3: + case eGL_FLOAT_MAT2: + case eGL_FLOAT_MAT4x2: + case eGL_FLOAT_MAT4x3: + case eGL_FLOAT_MAT3x4: + case eGL_FLOAT_MAT3x2: + case eGL_FLOAT_MAT2x4: + case eGL_FLOAT_MAT2x3: + var.type.descriptor.type = eVar_Float; + break; + case eGL_DOUBLE_VEC4: + case eGL_DOUBLE_VEC3: + case eGL_DOUBLE_VEC2: + case eGL_DOUBLE: + case eGL_DOUBLE_MAT4: + case eGL_DOUBLE_MAT3: + case eGL_DOUBLE_MAT2: + case eGL_DOUBLE_MAT4x2: + case eGL_DOUBLE_MAT4x3: + case eGL_DOUBLE_MAT3x4: + case eGL_DOUBLE_MAT3x2: + case eGL_DOUBLE_MAT2x4: + case eGL_DOUBLE_MAT2x3: + var.type.descriptor.type = eVar_Double; + break; + case eGL_UNSIGNED_INT_VEC4: + case eGL_UNSIGNED_INT_VEC3: + case eGL_UNSIGNED_INT_VEC2: + case eGL_UNSIGNED_INT: + case eGL_BOOL_VEC4: + case eGL_BOOL_VEC3: + case eGL_BOOL_VEC2: + case eGL_BOOL: + var.type.descriptor.type = eVar_UInt; + break; + case eGL_INT_VEC4: + case eGL_INT_VEC3: + case eGL_INT_VEC2: + case eGL_INT: + var.type.descriptor.type = eVar_Int; + break; + default: + // not a variable (sampler etc) + return; + } + + // set # rows if it's a matrix + var.type.descriptor.rows = 1; + + switch(values[0]) + { + case eGL_FLOAT_MAT4: + case eGL_DOUBLE_MAT4: + case eGL_FLOAT_MAT2x4: + case eGL_DOUBLE_MAT2x4: + case eGL_FLOAT_MAT3x4: + case eGL_DOUBLE_MAT3x4: + var.type.descriptor.rows = 4; + break; + case eGL_FLOAT_MAT3: + case eGL_DOUBLE_MAT3: + case eGL_FLOAT_MAT4x3: + case eGL_DOUBLE_MAT4x3: + case eGL_FLOAT_MAT2x3: + case eGL_DOUBLE_MAT2x3: + var.type.descriptor.rows = 3; + break; + case eGL_FLOAT_MAT2: + case eGL_DOUBLE_MAT2: + case eGL_FLOAT_MAT4x2: + case eGL_DOUBLE_MAT4x2: + case eGL_FLOAT_MAT3x2: + case eGL_DOUBLE_MAT3x2: + var.type.descriptor.rows = 2; + break; + default: + break; + } + + // set # columns + switch(values[0]) + { + case eGL_FLOAT_VEC4: + case eGL_FLOAT_MAT4: + case eGL_FLOAT_MAT4x2: + case eGL_FLOAT_MAT4x3: + case eGL_DOUBLE_VEC4: + case eGL_DOUBLE_MAT4: + case eGL_DOUBLE_MAT4x2: + case eGL_DOUBLE_MAT4x3: + case eGL_UNSIGNED_INT_VEC4: + case eGL_BOOL_VEC4: + case eGL_INT_VEC4: + var.type.descriptor.cols = 4; + break; + case eGL_FLOAT_VEC3: + case eGL_FLOAT_MAT3: + case eGL_FLOAT_MAT3x4: + case eGL_FLOAT_MAT3x2: + case eGL_DOUBLE_VEC3: + case eGL_DOUBLE_MAT3: + case eGL_DOUBLE_MAT3x4: + case eGL_DOUBLE_MAT3x2: + case eGL_UNSIGNED_INT_VEC3: + case eGL_BOOL_VEC3: + case eGL_INT_VEC3: + var.type.descriptor.cols = 3; + break; + case eGL_FLOAT_VEC2: + case eGL_FLOAT_MAT2: + case eGL_FLOAT_MAT2x4: + case eGL_FLOAT_MAT2x3: + case eGL_DOUBLE_VEC2: + case eGL_DOUBLE_MAT2: + case eGL_DOUBLE_MAT2x4: + case eGL_DOUBLE_MAT2x3: + case eGL_UNSIGNED_INT_VEC2: + case eGL_BOOL_VEC2: + case eGL_INT_VEC2: + var.type.descriptor.cols = 2; + break; + case eGL_FLOAT: + case eGL_DOUBLE: + case eGL_UNSIGNED_INT: + case eGL_INT: + case eGL_BOOL: + var.type.descriptor.cols = 1; + break; + default: + break; + } + + // set name + switch(values[0]) + { + case eGL_FLOAT_VEC4: var.type.descriptor.name = "vec4"; break; + case eGL_FLOAT_VEC3: var.type.descriptor.name = "vec3"; break; + case eGL_FLOAT_VEC2: var.type.descriptor.name = "vec2"; break; + case eGL_FLOAT: var.type.descriptor.name = "float"; break; + case eGL_FLOAT_MAT4: var.type.descriptor.name = "mat4"; break; + case eGL_FLOAT_MAT3: var.type.descriptor.name = "mat3"; break; + case eGL_FLOAT_MAT2: var.type.descriptor.name = "mat2"; break; + case eGL_FLOAT_MAT4x2: var.type.descriptor.name = "mat4x2"; break; + case eGL_FLOAT_MAT4x3: var.type.descriptor.name = "mat4x3"; break; + case eGL_FLOAT_MAT3x4: var.type.descriptor.name = "mat3x4"; break; + case eGL_FLOAT_MAT3x2: var.type.descriptor.name = "mat3x2"; break; + case eGL_FLOAT_MAT2x4: var.type.descriptor.name = "mat2x4"; break; + case eGL_FLOAT_MAT2x3: var.type.descriptor.name = "mat2x3"; break; + case eGL_DOUBLE_VEC4: var.type.descriptor.name = "dvec4"; break; + case eGL_DOUBLE_VEC3: var.type.descriptor.name = "dvec3"; break; + case eGL_DOUBLE_VEC2: var.type.descriptor.name = "dvec2"; break; + case eGL_DOUBLE: var.type.descriptor.name = "double"; break; + case eGL_DOUBLE_MAT4: var.type.descriptor.name = "dmat4"; break; + case eGL_DOUBLE_MAT3: var.type.descriptor.name = "dmat3"; break; + case eGL_DOUBLE_MAT2: var.type.descriptor.name = "dmat2"; break; + case eGL_DOUBLE_MAT4x2: var.type.descriptor.name = "dmat4x2"; break; + case eGL_DOUBLE_MAT4x3: var.type.descriptor.name = "dmat4x3"; break; + case eGL_DOUBLE_MAT3x4: var.type.descriptor.name = "dmat3x4"; break; + case eGL_DOUBLE_MAT3x2: var.type.descriptor.name = "dmat3x2"; break; + case eGL_DOUBLE_MAT2x4: var.type.descriptor.name = "dmat2x4"; break; + case eGL_DOUBLE_MAT2x3: var.type.descriptor.name = "dmat2x3"; break; + case eGL_UNSIGNED_INT_VEC4: var.type.descriptor.name = "uvec4"; break; + case eGL_UNSIGNED_INT_VEC3: var.type.descriptor.name = "uvec3"; break; + case eGL_UNSIGNED_INT_VEC2: var.type.descriptor.name = "uvec2"; break; + case eGL_UNSIGNED_INT: var.type.descriptor.name = "uint"; break; + case eGL_BOOL_VEC4: var.type.descriptor.name = "bvec4"; break; + case eGL_BOOL_VEC3: var.type.descriptor.name = "bvec3"; break; + case eGL_BOOL_VEC2: var.type.descriptor.name = "bvec2"; break; + case eGL_BOOL: var.type.descriptor.name = "bool"; break; + case eGL_INT_VEC4: var.type.descriptor.name = "ivec4"; break; + case eGL_INT_VEC3: var.type.descriptor.name = "ivec3"; break; + case eGL_INT_VEC2: var.type.descriptor.name = "ivec2"; break; + case eGL_INT: var.type.descriptor.name = "int"; break; + default: + break; + } + + if(values[5] == -1 && values[2] >= 0) + { + var.reg.vec = values[2]; + var.reg.comp = 0; + } + else if(values[5] >= 0) + { + var.reg.vec = values[5] / 16; + var.reg.comp = (values[5] / 4) % 4; + + RDCASSERT((values[5] % 4) == 0); + } + else + { + var.reg.vec = var.reg.comp = ~0U; + } + + var.type.descriptor.rowMajorStorage = (values[6] > 0); + + var.name.resize(values[1]-1); + gl.glGetProgramResourceName(sepProg, query, varIdx, values[1], NULL, &var.name[0]); + + int32_t c = values[1]-1; + + // trim off trailing [0] if it's an array + if(var.name[c-3] == '[' && var.name[c-2] == '0' && var.name[c-1] == ']') + var.name.resize(c-3); + else + var.type.descriptor.elements = 0; + + vector *parentmembers = defaultBlock; + + if(values[3] != -1 && values[3] < numParentBlocks) + { + parentmembers = &parentBlocks[ values[3] ]; + } + + if(parentmembers == NULL) + { + RDCWARN("Found variable '%s' without parent block index '%d'", var.name.c_str(), values[3]); + return; + } + + char *nm = &var.name[0]; + + // reverse figure out structures and structure arrays + while(strchr(nm, '.') || strchr(nm, '[')) + { + char *base = nm; + while(*nm != '.' && *nm != '[') nm++; + + // determine if we have an array index, and NULL out + // what's after the base variable name + bool isarray = (*nm == '['); + *nm = 0; nm++; + + int arrayIdx = 0; + + // if it's an array, get the index used + if(isarray) + { + // get array index, it's always a decimal number + while(*nm >= '0' && *nm <= '9') + { + arrayIdx *= 10; + arrayIdx += int(*nm) - int('0'); + nm++; + } + + RDCASSERT(*nm == ']'); + *nm = 0; nm++; + + // skip forward to the child name + if(*nm == '.') + { + *nm = 0; nm++; + } + else + { + // we strip any trailing [0] above (which is useful for non-structure variables), + // so we should not hit this path unless two variables exist like: + // structure.member[0] + // structure.member[1] + // The program introspection should only return the first for a basic type, + // and we should not hit this case + parentmembers = NULL; + RDCWARN("Unexpected naked array as member (expected only one [0], which should be trimmed"); + break; + } + } + + // construct a parent variable + DynShaderConstant parentVar; + parentVar.name = base; + parentVar.reg.vec = var.reg.vec; + parentVar.reg.comp = 0; + parentVar.type.descriptor.name = "struct"; + parentVar.type.descriptor.rows = 0; + parentVar.type.descriptor.cols = 0; + 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; + + bool found = false; + + // if we can find the base variable already, we recurse into its members + for(size_t i=0; i < parentmembers->size(); i++) + { + if((*parentmembers)[i].name == base) + { + // if we find the variable, update the # elements to account for this new array index + // and pick the minimum offset of all of our children as the parent offset. This is mostly + // just for sorting + (*parentmembers)[i].type.descriptor.elements = + RDCMAX((*parentmembers)[i].type.descriptor.elements, parentVar.type.descriptor.elements); + (*parentmembers)[i].reg.vec = RDCMIN((*parentmembers)[i].reg.vec, parentVar.reg.vec); + + parentmembers = &( (*parentmembers)[i].type.members ); + found = true; + + break; + } + } + + // if we didn't find the base variable, add it and recuse inside + if(!found) + { + parentmembers->push_back(parentVar); + parentmembers = &( parentmembers->back().type.members ); + } + + // the 0th element of each array fills out the actual members, when we + // encounter an index above that we only use it to increase the type.descriptor.elements + // member (which we've done by this point) and can stop recursing + if(arrayIdx > 0) + { + parentmembers = NULL; + break; + } + } + + if(parentmembers) + { + // nm points into var.name's storage, so copy out to a temporary + string n = nm; + var.name = n; + + parentmembers->push_back(var); + } +} + void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, ShaderReflection &refl) { refl.DebugInfo.entryFunc = "main"; @@ -247,7 +605,7 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, res.IsSampler = false; // no separate sampler objects in GL res.IsSRV = true; res.IsTexture = true; - res.IsUAV = false; + res.IsReadWrite = false; res.variableType.descriptor.rows = 1; res.variableType.descriptor.cols = 4; res.variableType.descriptor.elements = 0; @@ -361,136 +719,414 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, else if(values[0] == eGL_INT_SAMPLER_BUFFER) { res.resType = eResType_Buffer; - res.variableType.descriptor.name = "samplerBuffer"; + res.variableType.descriptor.name = "isamplerBuffer"; res.variableType.descriptor.type = eVar_Int; } else if(values[0] == eGL_INT_SAMPLER_1D) { res.resType = eResType_Texture1D; - res.variableType.descriptor.name = "sampler1D"; + res.variableType.descriptor.name = "isampler1D"; res.variableType.descriptor.type = eVar_Int; } else if(values[0] == eGL_INT_SAMPLER_1D_ARRAY) { res.resType = eResType_Texture1DArray; - res.variableType.descriptor.name = "sampler1DArray"; + res.variableType.descriptor.name = "isampler1DArray"; res.variableType.descriptor.type = eVar_Int; } else if(values[0] == eGL_INT_SAMPLER_2D) { res.resType = eResType_Texture2D; - res.variableType.descriptor.name = "sampler2D"; + res.variableType.descriptor.name = "isampler2D"; res.variableType.descriptor.type = eVar_Int; } else if(values[0] == eGL_INT_SAMPLER_2D_ARRAY) { res.resType = eResType_Texture2DArray; - res.variableType.descriptor.name = "sampler2DArray"; + res.variableType.descriptor.name = "isampler2DArray"; res.variableType.descriptor.type = eVar_Int; } else if(values[0] == eGL_INT_SAMPLER_2D_RECT) { res.resType = eResType_TextureRect; - res.variableType.descriptor.name = "sampler2DRect"; + res.variableType.descriptor.name = "isampler2DRect"; res.variableType.descriptor.type = eVar_Int; } else if(values[0] == eGL_INT_SAMPLER_3D) { res.resType = eResType_Texture3D; - res.variableType.descriptor.name = "sampler3D"; + res.variableType.descriptor.name = "isampler3D"; res.variableType.descriptor.type = eVar_Int; } else if(values[0] == eGL_INT_SAMPLER_CUBE) { res.resType = eResType_TextureCube; - res.variableType.descriptor.name = "samplerCube"; + res.variableType.descriptor.name = "isamplerCube"; res.variableType.descriptor.type = eVar_Int; } else if(values[0] == eGL_INT_SAMPLER_CUBE_MAP_ARRAY) { res.resType = eResType_TextureCubeArray; - res.variableType.descriptor.name = "samplerCubeArray"; + res.variableType.descriptor.name = "isamplerCubeArray"; res.variableType.descriptor.type = eVar_Int; } else if(values[0] == eGL_INT_SAMPLER_2D_MULTISAMPLE) { res.resType = eResType_Texture2DMS; - res.variableType.descriptor.name = "sampler2DMS"; + res.variableType.descriptor.name = "isampler2DMS"; res.variableType.descriptor.type = eVar_Int; } else if(values[0] == eGL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY) { res.resType = eResType_Texture2DMSArray; - res.variableType.descriptor.name = "sampler2DMSArray"; + res.variableType.descriptor.name = "isampler2DMSArray"; res.variableType.descriptor.type = eVar_Int; } // unsigned int samplers else if(values[0] == eGL_UNSIGNED_INT_SAMPLER_BUFFER) { res.resType = eResType_Buffer; - res.variableType.descriptor.name = "samplerBuffer"; + res.variableType.descriptor.name = "usamplerBuffer"; res.variableType.descriptor.type = eVar_UInt; } else if(values[0] == eGL_UNSIGNED_INT_SAMPLER_1D) { res.resType = eResType_Texture1D; - res.variableType.descriptor.name = "sampler1D"; + res.variableType.descriptor.name = "usampler1D"; res.variableType.descriptor.type = eVar_UInt; } else if(values[0] == eGL_UNSIGNED_INT_SAMPLER_1D_ARRAY) { res.resType = eResType_Texture1DArray; - res.variableType.descriptor.name = "sampler1DArray"; + res.variableType.descriptor.name = "usampler1DArray"; res.variableType.descriptor.type = eVar_UInt; } else if(values[0] == eGL_UNSIGNED_INT_SAMPLER_2D) { res.resType = eResType_Texture2D; - res.variableType.descriptor.name = "sampler2D"; + res.variableType.descriptor.name = "usampler2D"; res.variableType.descriptor.type = eVar_UInt; } else if(values[0] == eGL_UNSIGNED_INT_SAMPLER_2D_ARRAY) { res.resType = eResType_Texture2DArray; - res.variableType.descriptor.name = "sampler2DArray"; + res.variableType.descriptor.name = "usampler2DArray"; res.variableType.descriptor.type = eVar_UInt; } else if(values[0] == eGL_UNSIGNED_INT_SAMPLER_2D_RECT) { res.resType = eResType_TextureRect; - res.variableType.descriptor.name = "sampler2DRect"; + res.variableType.descriptor.name = "usampler2DRect"; res.variableType.descriptor.type = eVar_UInt; } else if(values[0] == eGL_UNSIGNED_INT_SAMPLER_3D) { res.resType = eResType_Texture3D; - res.variableType.descriptor.name = "sampler3D"; + res.variableType.descriptor.name = "usampler3D"; res.variableType.descriptor.type = eVar_UInt; } else if(values[0] == eGL_UNSIGNED_INT_SAMPLER_CUBE) { res.resType = eResType_TextureCube; - res.variableType.descriptor.name = "samplerCube"; + res.variableType.descriptor.name = "usamplerCube"; res.variableType.descriptor.type = eVar_UInt; } else if(values[0] == eGL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY) { res.resType = eResType_TextureCubeArray; - res.variableType.descriptor.name = "samplerCubeArray"; + res.variableType.descriptor.name = "usamplerCubeArray"; res.variableType.descriptor.type = eVar_UInt; } else if(values[0] == eGL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE) { res.resType = eResType_Texture2DMS; - res.variableType.descriptor.name = "sampler2DMS"; + res.variableType.descriptor.name = "usampler2DMS"; res.variableType.descriptor.type = eVar_UInt; } else if(values[0] == eGL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY) { res.resType = eResType_Texture2DMSArray; - res.variableType.descriptor.name = "sampler2DMSArray"; + res.variableType.descriptor.name = "usampler2DMSArray"; res.variableType.descriptor.type = eVar_UInt; } + // float images + if(values[0] == eGL_IMAGE_BUFFER) + { + res.resType = eResType_Buffer; + res.variableType.descriptor.name = "imageBuffer"; + res.variableType.descriptor.type = eVar_Float; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_IMAGE_1D) + { + res.resType = eResType_Texture1D; + res.variableType.descriptor.name = "image1D"; + res.variableType.descriptor.type = eVar_Float; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_IMAGE_1D_ARRAY) + { + res.resType = eResType_Texture1DArray; + res.variableType.descriptor.name = "image1DArray"; + res.variableType.descriptor.type = eVar_Float; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_IMAGE_2D) + { + res.resType = eResType_Texture2D; + res.variableType.descriptor.name = "image2D"; + res.variableType.descriptor.type = eVar_Float; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_IMAGE_2D_ARRAY) + { + res.resType = eResType_Texture2DArray; + res.variableType.descriptor.name = "image2DArray"; + res.variableType.descriptor.type = eVar_Float; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_IMAGE_2D_RECT) + { + res.resType = eResType_TextureRect; + res.variableType.descriptor.name = "image2DRect"; + res.variableType.descriptor.type = eVar_Float; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_IMAGE_3D) + { + res.resType = eResType_Texture3D; + res.variableType.descriptor.name = "image3D"; + res.variableType.descriptor.type = eVar_Float; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_IMAGE_CUBE) + { + res.resType = eResType_TextureCube; + res.variableType.descriptor.name = "imageCube"; + res.variableType.descriptor.type = eVar_Float; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_IMAGE_CUBE_MAP_ARRAY) + { + res.resType = eResType_TextureCubeArray; + res.variableType.descriptor.name = "imageCubeArray"; + res.variableType.descriptor.type = eVar_Float; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_IMAGE_2D_MULTISAMPLE) + { + res.resType = eResType_Texture2DMS; + res.variableType.descriptor.name = "image2DMS"; + res.variableType.descriptor.type = eVar_Float; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_IMAGE_2D_MULTISAMPLE_ARRAY) + { + res.resType = eResType_Texture2DMSArray; + res.variableType.descriptor.name = "image2DMSArray"; + res.variableType.descriptor.type = eVar_Float; + res.IsReadWrite = true; + res.IsSRV = false; + } + // int images + else if(values[0] == eGL_INT_IMAGE_BUFFER) + { + res.resType = eResType_Buffer; + res.variableType.descriptor.name = "iimageBuffer"; + res.variableType.descriptor.type = eVar_Int; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_INT_IMAGE_1D) + { + res.resType = eResType_Texture1D; + res.variableType.descriptor.name = "iimage1D"; + res.variableType.descriptor.type = eVar_Int; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_INT_IMAGE_1D_ARRAY) + { + res.resType = eResType_Texture1DArray; + res.variableType.descriptor.name = "iimage1DArray"; + res.variableType.descriptor.type = eVar_Int; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_INT_IMAGE_2D) + { + res.resType = eResType_Texture2D; + res.variableType.descriptor.name = "iimage2D"; + res.variableType.descriptor.type = eVar_Int; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_INT_IMAGE_2D_ARRAY) + { + res.resType = eResType_Texture2DArray; + res.variableType.descriptor.name = "iimage2DArray"; + res.variableType.descriptor.type = eVar_Int; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_INT_IMAGE_2D_RECT) + { + res.resType = eResType_TextureRect; + res.variableType.descriptor.name = "iimage2DRect"; + res.variableType.descriptor.type = eVar_Int; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_INT_IMAGE_3D) + { + res.resType = eResType_Texture3D; + res.variableType.descriptor.name = "iimage3D"; + res.variableType.descriptor.type = eVar_Int; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_INT_IMAGE_CUBE) + { + res.resType = eResType_TextureCube; + res.variableType.descriptor.name = "iimageCube"; + res.variableType.descriptor.type = eVar_Int; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_INT_IMAGE_CUBE_MAP_ARRAY) + { + res.resType = eResType_TextureCubeArray; + res.variableType.descriptor.name = "iimageCubeArray"; + res.variableType.descriptor.type = eVar_Int; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_INT_IMAGE_2D_MULTISAMPLE) + { + res.resType = eResType_Texture2DMS; + res.variableType.descriptor.name = "iimage2DMS"; + res.variableType.descriptor.type = eVar_Int; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_INT_IMAGE_2D_MULTISAMPLE_ARRAY) + { + res.resType = eResType_Texture2DMSArray; + res.variableType.descriptor.name = "iimage2DMSArray"; + res.variableType.descriptor.type = eVar_Int; + res.IsReadWrite = true; + res.IsSRV = false; + } + // unsigned int images + else if(values[0] == eGL_UNSIGNED_INT_IMAGE_BUFFER) + { + res.resType = eResType_Buffer; + res.variableType.descriptor.name = "uimageBuffer"; + res.variableType.descriptor.type = eVar_UInt; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_UNSIGNED_INT_IMAGE_1D) + { + res.resType = eResType_Texture1D; + res.variableType.descriptor.name = "uimage1D"; + res.variableType.descriptor.type = eVar_UInt; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_UNSIGNED_INT_IMAGE_1D_ARRAY) + { + res.resType = eResType_Texture1DArray; + res.variableType.descriptor.name = "uimage1DArray"; + res.variableType.descriptor.type = eVar_UInt; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_UNSIGNED_INT_IMAGE_2D) + { + res.resType = eResType_Texture2D; + res.variableType.descriptor.name = "uimage2D"; + res.variableType.descriptor.type = eVar_UInt; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_UNSIGNED_INT_IMAGE_2D_ARRAY) + { + res.resType = eResType_Texture2DArray; + res.variableType.descriptor.name = "uimage2DArray"; + res.variableType.descriptor.type = eVar_UInt; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_UNSIGNED_INT_IMAGE_2D_RECT) + { + res.resType = eResType_TextureRect; + res.variableType.descriptor.name = "uimage2DRect"; + res.variableType.descriptor.type = eVar_UInt; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_UNSIGNED_INT_IMAGE_3D) + { + res.resType = eResType_Texture3D; + res.variableType.descriptor.name = "uimage3D"; + res.variableType.descriptor.type = eVar_UInt; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_UNSIGNED_INT_IMAGE_CUBE) + { + res.resType = eResType_TextureCube; + res.variableType.descriptor.name = "uimageCube"; + res.variableType.descriptor.type = eVar_UInt; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY) + { + res.resType = eResType_TextureCubeArray; + res.variableType.descriptor.name = "uimageCubeArray"; + res.variableType.descriptor.type = eVar_UInt; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE) + { + res.resType = eResType_Texture2DMS; + res.variableType.descriptor.name = "uimage2DMS"; + res.variableType.descriptor.type = eVar_UInt; + res.IsReadWrite = true; + res.IsSRV = false; + } + else if(values[0] == eGL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY) + { + res.resType = eResType_Texture2DMSArray; + res.variableType.descriptor.name = "uimage2DMSArray"; + res.variableType.descriptor.type = eVar_UInt; + res.IsReadWrite = true; + res.IsSRV = false; + } + // atomic counter + else if(values[0] == eGL_UNSIGNED_INT_ATOMIC_COUNTER) + { + res.resType = eResType_Buffer; + res.variableType.descriptor.name = "atomic_uint"; + res.variableType.descriptor.type = eVar_UInt; + res.IsReadWrite = true; + res.IsSRV = false; + res.IsTexture = false; + res.variableType.descriptor.cols = 1; + } else { // not a sampler @@ -523,7 +1159,64 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, } } - refl.Resources = resources; + vector ssbos; + uint32_t ssboMembers = 0; + + GLint numSSBOs = 0; + { + gl.glGetProgramInterfaceiv(sepProg, eGL_SHADER_STORAGE_BLOCK, eGL_ACTIVE_RESOURCES, &numSSBOs); + + for(GLint u=0; u < numSSBOs; u++) + { + GLenum propName = eGL_NAME_LENGTH; + GLint len; + gl.glGetProgramResourceiv(sepProg, eGL_SHADER_STORAGE_BLOCK, u, 1, &propName, 1, NULL, &len); + + char *nm = new char[len+1]; + gl.glGetProgramResourceName(sepProg, eGL_SHADER_STORAGE_BLOCK, u, len+1, NULL, nm); + + ShaderResource res; + res.IsSampler = false; + res.IsSRV = false; + res.IsTexture = false; + res.IsReadWrite = true; + res.resType = eResType_Buffer; + res.variableType.descriptor.rows = 0; + res.variableType.descriptor.cols = 0; + res.variableType.descriptor.elements = len; + res.variableType.descriptor.rowMajorStorage = false; + res.variableType.descriptor.name = "buffer"; + res.variableType.descriptor.type = eVar_UInt; + res.bindPoint = (int32_t)resources.size(); + res.name = nm; + + propName = eGL_NUM_ACTIVE_VARIABLES; + gl.glGetProgramResourceiv(sepProg, eGL_SHADER_STORAGE_BLOCK, u, 1, &propName, 1, NULL, (GLint *)&res.variableType.descriptor.elements); + + resources.push_back(res); + ssbos.push_back(res.bindPoint); + ssboMembers += res.variableType.descriptor.elements; + + delete[] nm; + } + } + + { + vector *members = new vector[ssbos.size()]; + + for(uint32_t i=0; i < ssboMembers; i++) + { + ReconstructVarTree(gl, eGL_BUFFER_VARIABLE, sepProg, i, (GLint)ssbos.size(), members, NULL); + } + + for(size_t ssbo=0; ssbo < ssbos.size(); ssbo++) + { + sort(members[ssbo]); + copy(resources[ ssbos[ssbo] ].variableType.members, members[ssbo]); + } + + delete[] members; + } vector globalUniforms; @@ -552,342 +1245,7 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, for(GLint u=0; u < numUniforms; u++) { - GLint values[numProps]; - gl.glGetProgramResourceiv(sepProg, eGL_UNIFORM, u, numProps, resProps, numProps, NULL, values); - - DynShaderConstant var; - - var.type.descriptor.elements = RDCMAX(1, values[4]); - - // set type (or bail if it's not a variable - sampler or such) - switch(values[0]) - { - case eGL_FLOAT_VEC4: - case eGL_FLOAT_VEC3: - case eGL_FLOAT_VEC2: - case eGL_FLOAT: - case eGL_FLOAT_MAT4: - case eGL_FLOAT_MAT3: - case eGL_FLOAT_MAT2: - case eGL_FLOAT_MAT4x2: - case eGL_FLOAT_MAT4x3: - case eGL_FLOAT_MAT3x4: - case eGL_FLOAT_MAT3x2: - case eGL_FLOAT_MAT2x4: - case eGL_FLOAT_MAT2x3: - var.type.descriptor.type = eVar_Float; - break; - case eGL_DOUBLE_VEC4: - case eGL_DOUBLE_VEC3: - case eGL_DOUBLE_VEC2: - case eGL_DOUBLE: - case eGL_DOUBLE_MAT4: - case eGL_DOUBLE_MAT3: - case eGL_DOUBLE_MAT2: - case eGL_DOUBLE_MAT4x2: - case eGL_DOUBLE_MAT4x3: - case eGL_DOUBLE_MAT3x4: - case eGL_DOUBLE_MAT3x2: - case eGL_DOUBLE_MAT2x4: - case eGL_DOUBLE_MAT2x3: - var.type.descriptor.type = eVar_Double; - break; - case eGL_UNSIGNED_INT_VEC4: - case eGL_UNSIGNED_INT_VEC3: - case eGL_UNSIGNED_INT_VEC2: - case eGL_UNSIGNED_INT: - case eGL_BOOL_VEC4: - case eGL_BOOL_VEC3: - case eGL_BOOL_VEC2: - case eGL_BOOL: - var.type.descriptor.type = eVar_UInt; - break; - case eGL_INT_VEC4: - case eGL_INT_VEC3: - case eGL_INT_VEC2: - case eGL_INT: - var.type.descriptor.type = eVar_Int; - break; - default: - // not a variable (sampler etc) - continue; - } - - // set # rows if it's a matrix - var.type.descriptor.rows = 1; - - switch(values[0]) - { - case eGL_FLOAT_MAT4: - case eGL_DOUBLE_MAT4: - case eGL_FLOAT_MAT2x4: - case eGL_DOUBLE_MAT2x4: - case eGL_FLOAT_MAT3x4: - case eGL_DOUBLE_MAT3x4: - var.type.descriptor.rows = 4; - break; - case eGL_FLOAT_MAT3: - case eGL_DOUBLE_MAT3: - case eGL_FLOAT_MAT4x3: - case eGL_DOUBLE_MAT4x3: - case eGL_FLOAT_MAT2x3: - case eGL_DOUBLE_MAT2x3: - var.type.descriptor.rows = 3; - break; - case eGL_FLOAT_MAT2: - case eGL_DOUBLE_MAT2: - case eGL_FLOAT_MAT4x2: - case eGL_DOUBLE_MAT4x2: - case eGL_FLOAT_MAT3x2: - case eGL_DOUBLE_MAT3x2: - var.type.descriptor.rows = 2; - break; - default: - break; - } - - // set # columns - switch(values[0]) - { - case eGL_FLOAT_VEC4: - case eGL_FLOAT_MAT4: - case eGL_FLOAT_MAT4x2: - case eGL_FLOAT_MAT4x3: - case eGL_DOUBLE_VEC4: - case eGL_DOUBLE_MAT4: - case eGL_DOUBLE_MAT4x2: - case eGL_DOUBLE_MAT4x3: - case eGL_UNSIGNED_INT_VEC4: - case eGL_BOOL_VEC4: - case eGL_INT_VEC4: - var.type.descriptor.cols = 4; - break; - case eGL_FLOAT_VEC3: - case eGL_FLOAT_MAT3: - case eGL_FLOAT_MAT3x4: - case eGL_FLOAT_MAT3x2: - case eGL_DOUBLE_VEC3: - case eGL_DOUBLE_MAT3: - case eGL_DOUBLE_MAT3x4: - case eGL_DOUBLE_MAT3x2: - case eGL_UNSIGNED_INT_VEC3: - case eGL_BOOL_VEC3: - case eGL_INT_VEC3: - var.type.descriptor.cols = 3; - break; - case eGL_FLOAT_VEC2: - case eGL_FLOAT_MAT2: - case eGL_FLOAT_MAT2x4: - case eGL_FLOAT_MAT2x3: - case eGL_DOUBLE_VEC2: - case eGL_DOUBLE_MAT2: - case eGL_DOUBLE_MAT2x4: - case eGL_DOUBLE_MAT2x3: - case eGL_UNSIGNED_INT_VEC2: - case eGL_BOOL_VEC2: - case eGL_INT_VEC2: - var.type.descriptor.cols = 2; - break; - case eGL_FLOAT: - case eGL_DOUBLE: - case eGL_UNSIGNED_INT: - case eGL_INT: - case eGL_BOOL: - var.type.descriptor.cols = 1; - break; - default: - break; - } - - // set name - switch(values[0]) - { - case eGL_FLOAT_VEC4: var.type.descriptor.name = "vec4"; break; - case eGL_FLOAT_VEC3: var.type.descriptor.name = "vec3"; break; - case eGL_FLOAT_VEC2: var.type.descriptor.name = "vec2"; break; - case eGL_FLOAT: var.type.descriptor.name = "float"; break; - case eGL_FLOAT_MAT4: var.type.descriptor.name = "mat4"; break; - case eGL_FLOAT_MAT3: var.type.descriptor.name = "mat3"; break; - case eGL_FLOAT_MAT2: var.type.descriptor.name = "mat2"; break; - case eGL_FLOAT_MAT4x2: var.type.descriptor.name = "mat4x2"; break; - case eGL_FLOAT_MAT4x3: var.type.descriptor.name = "mat4x3"; break; - case eGL_FLOAT_MAT3x4: var.type.descriptor.name = "mat3x4"; break; - case eGL_FLOAT_MAT3x2: var.type.descriptor.name = "mat3x2"; break; - case eGL_FLOAT_MAT2x4: var.type.descriptor.name = "mat2x4"; break; - case eGL_FLOAT_MAT2x3: var.type.descriptor.name = "mat2x3"; break; - case eGL_DOUBLE_VEC4: var.type.descriptor.name = "dvec4"; break; - case eGL_DOUBLE_VEC3: var.type.descriptor.name = "dvec3"; break; - case eGL_DOUBLE_VEC2: var.type.descriptor.name = "dvec2"; break; - case eGL_DOUBLE: var.type.descriptor.name = "double"; break; - case eGL_DOUBLE_MAT4: var.type.descriptor.name = "dmat4"; break; - case eGL_DOUBLE_MAT3: var.type.descriptor.name = "dmat3"; break; - case eGL_DOUBLE_MAT2: var.type.descriptor.name = "dmat2"; break; - case eGL_DOUBLE_MAT4x2: var.type.descriptor.name = "dmat4x2"; break; - case eGL_DOUBLE_MAT4x3: var.type.descriptor.name = "dmat4x3"; break; - case eGL_DOUBLE_MAT3x4: var.type.descriptor.name = "dmat3x4"; break; - case eGL_DOUBLE_MAT3x2: var.type.descriptor.name = "dmat3x2"; break; - case eGL_DOUBLE_MAT2x4: var.type.descriptor.name = "dmat2x4"; break; - case eGL_DOUBLE_MAT2x3: var.type.descriptor.name = "dmat2x3"; break; - case eGL_UNSIGNED_INT_VEC4: var.type.descriptor.name = "uvec4"; break; - case eGL_UNSIGNED_INT_VEC3: var.type.descriptor.name = "uvec3"; break; - case eGL_UNSIGNED_INT_VEC2: var.type.descriptor.name = "uvec2"; break; - case eGL_UNSIGNED_INT: var.type.descriptor.name = "uint"; break; - case eGL_BOOL_VEC4: var.type.descriptor.name = "bvec4"; break; - case eGL_BOOL_VEC3: var.type.descriptor.name = "bvec3"; break; - case eGL_BOOL_VEC2: var.type.descriptor.name = "bvec2"; break; - case eGL_BOOL: var.type.descriptor.name = "bool"; break; - case eGL_INT_VEC4: var.type.descriptor.name = "ivec4"; break; - case eGL_INT_VEC3: var.type.descriptor.name = "ivec3"; break; - case eGL_INT_VEC2: var.type.descriptor.name = "ivec2"; break; - case eGL_INT: var.type.descriptor.name = "int"; break; - default: - break; - } - - if(values[5] == -1 && values[2] >= 0) - { - var.reg.vec = values[2]; - var.reg.comp = 0; - } - else if(values[5] >= 0) - { - var.reg.vec = values[5] / 16; - var.reg.comp = (values[5] / 4) % 4; - - RDCASSERT((values[5] % 4) == 0); - } - else - { - var.reg.vec = var.reg.comp = ~0U; - } - - var.type.descriptor.rowMajorStorage = (values[6] > 0); - - var.name.resize(values[1]-1); - gl.glGetProgramResourceName(sepProg, eGL_UNIFORM, u, values[1], NULL, &var.name[0]); - - int32_t c = values[1]-1; - - // trim off trailing [0] if it's an array - if(var.name[c-3] == '[' && var.name[c-2] == '0' && var.name[c-1] == ']') - var.name.resize(c-3); - else - var.type.descriptor.elements = 0; - - vector *parentmembers = &globalUniforms; - - if(values[3] != -1) - { - RDCASSERT(values[3] < numUBOs); - parentmembers = &ubos[ values[3] ]; - } - - char *nm = &var.name[0]; - - // reverse figure out structures and structure arrays - while(strchr(nm, '.') || strchr(nm, '[')) - { - char *base = nm; - while(*nm != '.' && *nm != '[') nm++; - - // determine if we have an array index, and NULL out - // what's after the base variable name - bool isarray = (*nm == '['); - *nm = 0; nm++; - - int arrayIdx = 0; - - // if it's an array, get the index used - if(isarray) - { - // get array index, it's always a decimal number - while(*nm >= '0' && *nm <= '9') - { - arrayIdx *= 10; - arrayIdx += int(*nm) - int('0'); - nm++; - } - - RDCASSERT(*nm == ']'); - *nm = 0; nm++; - - // skip forward to the child name - if(*nm == '.') - { - *nm = 0; nm++; - } - else - { - // we strip any trailing [0] above (which is useful for non-structure variables), - // so we should not hit this path unless two variables exist like: - // structure.member[0] - // structure.member[1] - // The program introspection should only return the first for a basic type, - // and we should not hit this case - parentmembers = NULL; - RDCWARN("Unexpected naked array as member (expected only one [0], which should be trimmed"); - break; - } - } - - // construct a parent variable - DynShaderConstant parentVar; - parentVar.name = base; - parentVar.reg.vec = var.reg.vec; - parentVar.reg.comp = 0; - parentVar.type.descriptor.name = "struct"; - parentVar.type.descriptor.rows = 0; - parentVar.type.descriptor.cols = 0; - 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; - - bool found = false; - - // if we can find the base variable already, we recurse into its members - for(size_t i=0; i < parentmembers->size(); i++) - { - if((*parentmembers)[i].name == base) - { - // if we find the variable, update the # elements to account for this new array index - // and pick the minimum offset of all of our children as the parent offset. This is mostly - // just for sorting - (*parentmembers)[i].type.descriptor.elements = - RDCMAX((*parentmembers)[i].type.descriptor.elements, parentVar.type.descriptor.elements); - (*parentmembers)[i].reg.vec = RDCMIN((*parentmembers)[i].reg.vec, parentVar.reg.vec); - - parentmembers = &( (*parentmembers)[i].type.members ); - found = true; - - break; - } - } - - // if we didn't find the base variable, add it and recuse inside - if(!found) - { - parentmembers->push_back(parentVar); - parentmembers = &( parentmembers->back().type.members ); - } - - // the 0th element of each array fills out the actual members, when we - // encounter an index above that we only use it to increase the type.descriptor.elements - // member (which we've done by this point) and can stop recursing - if(arrayIdx > 0) - { - parentmembers = NULL; - break; - } - } - - if(parentmembers) - { - // nm points into var.name's storage, so copy out to a temporary - string n = nm; - var.name = n; - - parentmembers->push_back(var); - } + ReconstructVarTree(gl, eGL_UNIFORM, sepProg, u, numUBOs, ubos, &globalUniforms); } vector cbuffers; @@ -1158,6 +1516,7 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, // TODO: fill in Interfaces with shader subroutines? + refl.Resources = resources; refl.ConstantBlocks = cbuffers; } diff --git a/renderdocui/Interop/Shader.cs b/renderdocui/Interop/Shader.cs index a83861c7a..b2c0e8444 100644 --- a/renderdocui/Interop/Shader.cs +++ b/renderdocui/Interop/Shader.cs @@ -344,7 +344,7 @@ namespace renderdoc public bool IsSampler; public bool IsTexture; public bool IsSRV; - public bool IsUAV; + public bool IsReadWrite; public ShaderResourceType resType; diff --git a/renderdocui/Windows/PipelineState/D3D11PipelineStateViewer.cs b/renderdocui/Windows/PipelineState/D3D11PipelineStateViewer.cs index 85705f51d..1e0c74f5b 100644 --- a/renderdocui/Windows/PipelineState/D3D11PipelineStateViewer.cs +++ b/renderdocui/Windows/PipelineState/D3D11PipelineStateViewer.cs @@ -848,7 +848,7 @@ namespace renderdocui.Windows.PipelineState { foreach (var bind in state.m_CS.ShaderDetails.Resources) { - if (bind.IsUAV && bind.bindPoint == i) + if (bind.IsReadWrite && bind.bindPoint == i) shaderInput = bind; } } @@ -1162,7 +1162,7 @@ namespace renderdocui.Windows.PipelineState { foreach (var bind in state.m_PS.ShaderDetails.Resources) { - if (bind.IsUAV && bind.bindPoint == i + state.m_OM.UAVStartSlot) + if (bind.IsReadWrite && bind.bindPoint == i + state.m_OM.UAVStartSlot) shaderInput = bind; } } @@ -1512,7 +1512,7 @@ namespace renderdocui.Windows.PipelineState if(r.IsTexture) continue; - if ( (r.IsSRV && !uav) || (r.IsUAV && uav) ) + if ((r.IsSRV && !uav) || (r.IsReadWrite && uav)) { if (r.bindPoint == bind) { @@ -1821,7 +1821,7 @@ namespace renderdocui.Windows.PipelineState { char regChar = 't'; - if (res.IsUAV) + if (res.IsReadWrite) { hlsl += "RW"; regChar = 'u'; @@ -2367,7 +2367,7 @@ namespace renderdocui.Windows.PipelineState { foreach (var bind in refl.Resources) { - if (bind.IsUAV && bind.bindPoint == i) + if (bind.IsReadWrite && bind.bindPoint == i) shaderInput = bind; } } diff --git a/renderdocui/Windows/ShaderViewer.cs b/renderdocui/Windows/ShaderViewer.cs index 34f36f68e..9f2ae70a2 100644 --- a/renderdocui/Windows/ShaderViewer.cs +++ b/renderdocui/Windows/ShaderViewer.cs @@ -346,7 +346,7 @@ namespace renderdocui.Windows Regex rgx = new Regex(needle); disasm = rgx.Replace(disasm, replacement); } - if (r.IsUAV) + if (r.IsReadWrite) { var needle = string.Format(", u{0}([^0-9])", r.bindPoint); var replacement = string.Format(", {0}$1", r.name); @@ -837,7 +837,7 @@ namespace renderdocui.Windows var res = m_Stage.SRVs[slot.bindPoint]; - if (slot.IsUAV) + if (slot.IsReadWrite) { if(m_Stage.stage == ShaderStageType.Pixel) res = pipestate.m_OM.UAVs[slot.bindPoint - pipestate.m_OM.UAVStartSlot]; diff --git a/renderdocui/Windows/TextureViewer.cs b/renderdocui/Windows/TextureViewer.cs index c35738623..c8bdbbd37 100644 --- a/renderdocui/Windows/TextureViewer.cs +++ b/renderdocui/Windows/TextureViewer.cs @@ -891,7 +891,7 @@ namespace renderdocui.Windows { foreach (var bind in details.Resources) { - if (mapping.Resources[bind.bindPoint].bind == i && bind.IsUAV) + if (mapping.Resources[bind.bindPoint].bind == i && bind.IsReadWrite) { bindName = "<" + bind.name + ">"; }