diff --git a/renderdoc/api/replay/shader_types.h b/renderdoc/api/replay/shader_types.h index aac7062ad..b742061fc 100644 --- a/renderdoc/api/replay/shader_types.h +++ b/renderdoc/api/replay/shader_types.h @@ -1143,6 +1143,7 @@ struct ConstantBlock bool operator==(const ConstantBlock &o) const { return name == o.name && variables == o.variables && bindPoint == o.bindPoint && + fixedBindSetOrSpace == o.fixedBindSetOrSpace && bufferBacked == o.bufferBacked && byteSize == o.byteSize && bufferBacked == o.bufferBacked && inlineDataBytes == o.inlineDataBytes && compileConstants == o.compileConstants; } @@ -1150,10 +1151,12 @@ struct ConstantBlock { if(!(name == o.name)) return name < o.name; - if(!(variables == o.variables)) - return variables < o.variables; if(!(bindPoint == o.bindPoint)) return bindPoint < o.bindPoint; + if(!(fixedBindNumber == o.fixedBindNumber)) + return fixedBindNumber < o.fixedBindNumber; + if(!(fixedBindSetOrSpace == o.fixedBindSetOrSpace)) + return fixedBindSetOrSpace < o.fixedBindSetOrSpace; if(!(byteSize == o.byteSize)) return byteSize < o.byteSize; if(!(bufferBacked == o.bufferBacked)) @@ -1162,6 +1165,8 @@ struct ConstantBlock return inlineDataBytes < o.inlineDataBytes; if(!(compileConstants == o.compileConstants)) return compileConstants < o.compileConstants; + if(!(variables == o.variables)) + return variables < o.variables; return false; } DOCUMENT("The name of this constant block, may be empty on some APIs."); @@ -1175,6 +1180,48 @@ struct ConstantBlock :data:`ShaderBindpointMapping.constantBlocks` list. )"); int32_t bindPoint = 0; + + DOCUMENT(R"(The fixed binding number for this binding. The interpretation of this is API-specific +and it is provided purely for informational purposes and has no bearing on how data is accessed or +described. Similarly some bindings don't have a fixed bind number and the value here should not be +relied on. + +For OpenGL only, this value is not used as bindings are dynamic and cannot be determined by the +shader reflection. Bindings must be determined only by the descriptor mapped to. + +Generally speaking sorting by this number will give a reasonable ordering by binding if it exists. + +.. note:: + Because this number is API-specific, there is no guarantee that it will be unique across all + resources, though generally it will be unique within all binds of the same type. It should be used + only within contexts that can interpret it API-specifically, or else for purely + informational/non-semantic purposes like sorting. + +:type: int +)"); + uint32_t fixedBindNumber = 0; + + DOCUMENT(R"(The fixed binding set or space for this binding. This is API-specific, on Vulkan this +gives the set and on D3D12 this gives the register space. +It is provided purely for informational purposes and has no bearing on how data is accessed or +described. + +Generally speaking sorting by this number before :data:`fixedBindNumber` will give a reasonable +ordering by binding if it exists. + +:type: int +)"); + uint32_t fixedBindSetOrSpace = 0; + + DOCUMENT(R"(If this binding is natively arrayed, how large is the array size. If not arrayed, this +will be set to 1. + +This value may be set to a very large number if the array is unbounded in the shader. + +:type: int +)"); + uint32_t bindArraySize = 1; + DOCUMENT("The total number of bytes consumed by all of the constants contained in this block."); uint32_t byteSize = 0; DOCUMENT(R"(``True`` if the contents are stored in a buffer of memory. If not then they are set by @@ -1222,6 +1269,47 @@ struct ShaderSampler :data:`ShaderBindpointMapping.samplers` list. )"); int32_t bindPoint; + + DOCUMENT(R"(The fixed binding number for this binding. The interpretation of this is API-specific +and it is provided purely for informational purposes and has no bearing on how data is accessed or +described. Similarly some bindings don't have a fixed bind number and the value here should not be +relied on. + +For OpenGL only, this value is not used as bindings are dynamic and cannot be determined by the +shader reflection. Bindings must be determined only by the descriptor mapped to. + +Generally speaking sorting by this number will give a reasonable ordering by binding if it exists. + +.. note:: + Because this number is API-specific, there is no guarantee that it will be unique across all + resources, though generally it will be unique within all binds of the same type. It should be used + only within contexts that can interpret it API-specifically, or else for purely + informational/non-semantic purposes like sorting. + +:type: int +)"); + uint32_t fixedBindNumber = 0; + + DOCUMENT(R"(The fixed binding set or space for this binding. This is API-specific, on Vulkan this +gives the set and on D3D12 this gives the register space. +It is provided purely for informational purposes and has no bearing on how data is accessed or +described. + +Generally speaking sorting by this number before :data:`fixedBindNumber` will give a reasonable +ordering by binding if it exists. + +:type: int +)"); + uint32_t fixedBindSetOrSpace = 0; + + DOCUMENT(R"(If this binding is natively arrayed, how large is the array size. If not arrayed, this +will be set to 1. + +This value may be set to a very large number if the array is unbounded in the shader. + +:type: int +)"); + uint32_t bindArraySize = 1; }; DECLARE_REFLECTION_STRUCT(ShaderSampler); @@ -1242,6 +1330,7 @@ struct ShaderResource bool operator==(const ShaderResource &o) const { return resType == o.resType && name == o.name && variableType == o.variableType && + fixedBindNumber == o.fixedBindNumber && fixedBindSetOrSpace == o.fixedBindSetOrSpace && bindPoint == o.bindPoint && isTexture == o.isTexture && hasSampler == o.hasSampler && isInputAttachment == o.isInputAttachment && isReadOnly == o.isReadOnly; } @@ -1253,8 +1342,8 @@ struct ShaderResource return name < o.name; if(!(variableType == o.variableType)) return variableType < o.variableType; - if(!(bindPoint == o.bindPoint)) - return bindPoint < o.bindPoint; + if(!(fixedBindSetOrSpace == o.fixedBindSetOrSpace)) + return fixedBindSetOrSpace < o.fixedBindSetOrSpace; if(!(isTexture == o.isTexture)) return isTexture < o.isTexture; if(!(hasSampler == o.hasSampler)) @@ -1283,6 +1372,47 @@ struct ShaderResource )"); int32_t bindPoint; + DOCUMENT(R"(The fixed binding number for this binding. The interpretation of this is API-specific +and it is provided purely for informational purposes and has no bearing on how data is accessed or +described. Similarly some bindings don't have a fixed bind number and the value here should not be +relied on. + +For OpenGL only, this value is not used as bindings are dynamic and cannot be determined by the +shader reflection. Bindings must be determined only by the descriptor mapped to. + +Generally speaking sorting by this number will give a reasonable ordering by binding if it exists. + +.. note:: + Because this number is API-specific, there is no guarantee that it will be unique across all + resources, though generally it will be unique within all binds of the same type. It should be used + only within contexts that can interpret it API-specifically, or else for purely + informational/non-semantic purposes like sorting. + +:type: int +)"); + uint32_t fixedBindNumber = 0; + + DOCUMENT(R"(The fixed binding set or space for this binding. This is API-specific, on Vulkan this +gives the set and on D3D12 this gives the register space. +It is provided purely for informational purposes and has no bearing on how data is accessed or +described. + +Generally speaking sorting by this number before :data:`fixedBindNumber` will give a reasonable +ordering by binding if it exists. + +:type: int +)"); + uint32_t fixedBindSetOrSpace = 0; + + DOCUMENT(R"(If this binding is natively arrayed, how large is the array size. If not arrayed, this +will be set to 1. + +This value may be set to a very large number if the array is unbounded in the shader. + +:type: int +)"); + uint32_t bindArraySize = 1; + DOCUMENT("``True`` if this resource is a texture, otherwise it is a buffer."); bool isTexture; DOCUMENT("``True`` if this texture resource has a sampler as well."); diff --git a/renderdoc/driver/shaders/dxbc/dxbc_reflect.cpp b/renderdoc/driver/shaders/dxbc/dxbc_reflect.cpp index f86afafd0..1869e05d9 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_reflect.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_reflect.cpp @@ -252,6 +252,10 @@ static void MakeResourceList(bool srv, DXBC::DXBCContainer *dxbc, res.bindPoint = (int32_t)i; + res.fixedBindNumber = r.reg; + res.fixedBindSetOrSpace = r.space; + res.bindArraySize = r.bindCount == 0 ? ~0U : r.bindCount; + Bindpoint map; map.arraySize = r.bindCount == 0 ? ~0U : r.bindCount; map.bindset = r.space; @@ -398,6 +402,10 @@ void MakeShaderReflection(DXBC::DXBCContainer *dxbc, ShaderReflection *refl, cb.byteSize = dxbcRefl->CBuffers[i].descriptor.byteSize; cb.bindPoint = (int32_t)i; + cb.fixedBindNumber = dxbcRefl->CBuffers[i].reg; + cb.fixedBindSetOrSpace = dxbcRefl->CBuffers[i].space; + cb.bindArraySize = dxbcRefl->CBuffers[i].bindCount; + Bindpoint map; map.arraySize = dxbcRefl->CBuffers[i].bindCount; map.bindset = dxbcRefl->CBuffers[i].space; @@ -424,6 +432,10 @@ void MakeShaderReflection(DXBC::DXBCContainer *dxbc, ShaderReflection *refl, s.name = dxbcRefl->Samplers[i].name; s.bindPoint = (int32_t)i; + s.fixedBindNumber = dxbcRefl->Samplers[i].reg; + s.fixedBindSetOrSpace = dxbcRefl->Samplers[i].space; + s.bindArraySize = dxbcRefl->Samplers[i].bindCount; + Bindpoint map; map.arraySize = 1; map.bindset = dxbcRefl->Samplers[i].space; diff --git a/renderdoc/driver/shaders/spirv/spirv_reflect.cpp b/renderdoc/driver/shaders/spirv/spirv_reflect.cpp index 3a2a86309..431ac2166 100644 --- a/renderdoc/driver/shaders/spirv/spirv_reflect.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_reflect.cpp @@ -1407,6 +1407,10 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st bindmap.bindset = 0; bindmap.bind = GetBinding(decorations[global.id].binding); + res.fixedBindSetOrSpace = 0; + res.fixedBindNumber = GetBinding(decorations[global.id].binding); + res.bindArraySize = isArray ? arraySize : 1; + rwresources.push_back(shaderrespair(bindmap, res)); } else if(varType->IsOpaqueType()) @@ -1424,6 +1428,10 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st if(res.name.empty()) res.name = StringFormat::Fmt("res%u", global.id.value()); + res.fixedBindSetOrSpace = bindmap.bindset; + res.fixedBindNumber = bindmap.bind; + res.bindArraySize = isArray ? arraySize : 1; + if(varType->type == DataType::SamplerType) { res.resType = TextureType::Unknown; @@ -1544,6 +1552,10 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st res.name = StringFormat::Fmt("ssbo%u", global.id.value()); res.resType = TextureType::Buffer; + res.fixedBindNumber = bindmap.bind; + res.fixedBindSetOrSpace = bindmap.bindset; + res.bindArraySize = isArray ? arraySize : 1; + res.variableType.columns = 0; res.variableType.rows = 0; res.variableType.baseType = VarType::Float; @@ -1564,6 +1576,10 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st cblock.bufferBacked = !pushConst; cblock.inlineDataBytes = pushConst; + cblock.fixedBindNumber = bindmap.bind; + cblock.fixedBindSetOrSpace = bindmap.bindset; + cblock.bindArraySize = isArray ? arraySize : 1; + MakeConstantBlockVariables(effectiveStorage, *varType, 0, 0, cblock.variables, pointerTypes, specInfo); @@ -1616,6 +1632,8 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st specblock.inlineDataBytes = true; specblock.compileConstants = true; specblock.byteSize = 0; + // set the binding number to some huge value to try to sort it to the end + specblock.fixedBindNumber = 0x8000000; Bindpoint bindmap; @@ -1636,6 +1654,8 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st globalsblock.inlineDataBytes = false; globalsblock.byteSize = (uint32_t)globalsblock.variables.size(); globalsblock.bindPoint = (int)cblocks.size(); + // set the binding number to some huge value to try to sort it to the end + globalsblock.fixedBindNumber = 0x8000001; Bindpoint bindmap; bindmap.bindset = 0; diff --git a/renderdoc/replay/renderdoc_serialise.inl b/renderdoc/replay/renderdoc_serialise.inl index 561932d52..fe9ec5520 100644 --- a/renderdoc/replay/renderdoc_serialise.inl +++ b/renderdoc/replay/renderdoc_serialise.inl @@ -198,11 +198,14 @@ void DoSerialise(SerialiserType &ser, ConstantBlock &el) SERIALISE_MEMBER(name); SERIALISE_MEMBER(variables); SERIALISE_MEMBER(bindPoint); + SERIALISE_MEMBER(fixedBindNumber); + SERIALISE_MEMBER(fixedBindSetOrSpace); + SERIALISE_MEMBER(bindArraySize); SERIALISE_MEMBER(byteSize); SERIALISE_MEMBER(bufferBacked); SERIALISE_MEMBER(compileConstants); - SIZE_CHECK(64); + SIZE_CHECK(72); } template @@ -210,8 +213,11 @@ void DoSerialise(SerialiserType &ser, ShaderSampler &el) { SERIALISE_MEMBER(name); SERIALISE_MEMBER(bindPoint); + SERIALISE_MEMBER(fixedBindNumber); + SERIALISE_MEMBER(fixedBindSetOrSpace); + SERIALISE_MEMBER(bindArraySize); - SIZE_CHECK(32); + SIZE_CHECK(40); } template @@ -221,12 +227,15 @@ void DoSerialise(SerialiserType &ser, ShaderResource &el) SERIALISE_MEMBER(name); SERIALISE_MEMBER(variableType); SERIALISE_MEMBER(bindPoint); + SERIALISE_MEMBER(fixedBindNumber); + SERIALISE_MEMBER(fixedBindSetOrSpace); + SERIALISE_MEMBER(bindArraySize); SERIALISE_MEMBER(isTexture); SERIALISE_MEMBER(hasSampler); SERIALISE_MEMBER(isInputAttachment); SERIALISE_MEMBER(isReadOnly); - SIZE_CHECK(112); + SIZE_CHECK(128); } template @@ -312,7 +321,7 @@ void DoSerialise(SerialiserType &ser, ShaderReflection &el) SERIALISE_MEMBER(taskPayload); - SIZE_CHECK(480); + SIZE_CHECK(488); } template