diff --git a/renderdoc/driver/d3d12/d3d12_shader_feedback.cpp b/renderdoc/driver/d3d12/d3d12_shader_feedback.cpp index a68dd8311..8b6d48adf 100644 --- a/renderdoc/driver/d3d12/d3d12_shader_feedback.cpp +++ b/renderdoc/driver/d3d12/d3d12_shader_feedback.cpp @@ -114,7 +114,7 @@ static bool AnnotateDXBCShader(const DXBC::DXBCContainer *dxbc, uint32_t space, for(const Operand &operand : op.operands) { if(operand.type != TYPE_RESOURCE && operand.type != TYPE_UNORDERED_ACCESS_VIEW && - operand.type != TYPE_SAMPLER) + operand.type != TYPE_SAMPLER && operand.type != TYPE_CONSTANT_BUFFER) continue; const Declaration *decl = @@ -251,7 +251,7 @@ static bool AnnotateDXILShader(const DXBC::DXBCContainer *dxbc, uint32_t space, // register IDs of each SRV/UAV/Sampler with slots, and record the base slot in this array for // easy access later when annotating dx.op.createHandle calls. We also need to know the base // register because the index dxc provides is register-relative - rdcarray> srvBaseSlots, uavBaseSlots, sampBaseSlots; + rdcarray> srvBaseSlots, uavBaseSlots, cbvBaseSlots, sampBaseSlots; // declare the resource, this happens purely in metadata but we need to store the slot uint32_t regSlot = 0; @@ -271,6 +271,7 @@ static bool AnnotateDXILShader(const DXBC::DXBCContainer *dxbc, uint32_t space, Metadata *srvs = reslist->children[0]; Metadata *uavs = reslist->children[1]; + Metadata *cbvs = reslist->children[2]; Metadata *samps = reslist->children[3]; // if there isn't a UAV list, create an empty one so we can add our own if(!uavs) @@ -329,6 +330,56 @@ static bool AnnotateDXILShader(const DXBC::DXBCContainer *dxbc, uint32_t space, srvBaseSlots[id] = {feedbackSlot, key.bind}; } + key.type = DXBCBytecode::TYPE_CONSTANT_BUFFER; + + for(size_t i = 0; cbvs && i < cbvs->children.size(); i++) + { + // each Sampler child should have a fixed format + const Metadata *cbv = cbvs->children[i]; + const Constant *slot = cast(cbv->children[(size_t)ResField::ID]->value); + const Constant *cbvSpace = cast(cbv->children[(size_t)ResField::Space]->value); + const Constant *reg = cast(cbv->children[(size_t)ResField::RegBase]->value); + + if(!slot) + { + RDCWARN("Unexpected non-constant slot ID in constant buffer"); + continue; + } + + if(!cbvSpace) + { + RDCWARN("Unexpected non-constant register space in constant buffer"); + continue; + } + + if(!reg) + { + RDCWARN("Unexpected non-constant register base in constant buffer"); + continue; + } + + uint32_t id = slot->getU32(); + key.space = cbvSpace->getU32(); + key.bind = reg->getU32(); + + // ensure every valid ID has an index, even if it's 0 + cbvBaseSlots.resize_for_index(id); + + auto it = slots.find(key); + + // not annotated + if(it == slots.end()) + continue; + + uint32_t feedbackSlot = it->second.slot; + + // we assume all feedback slots are non-zero, so that a 0 base slot can be used as an + // identifier for 'this resource isn't annotated' + RDCASSERT(feedbackSlot > 0); + + cbvBaseSlots[id] = {feedbackSlot, key.bind}; + } + key.type = DXBCBytecode::TYPE_SAMPLER; for(size_t i = 0; samps && i < samps->children.size(); i++) @@ -668,6 +719,8 @@ static bool AnnotateDXILShader(const DXBC::DXBCContainer *dxbc, uint32_t space, slotInfo = uavBaseSlots[id]; else if(kind == HandleKind::Sampler && id < sampBaseSlots.size()) slotInfo = sampBaseSlots[id]; + else if(kind == HandleKind::CBuffer && id < cbvBaseSlots.size()) + slotInfo = cbvBaseSlots[id]; } else { @@ -716,6 +769,8 @@ static bool AnnotateDXILShader(const DXBC::DXBCContainer *dxbc, uint32_t space, key.type = DXBCBytecode::TYPE_UNORDERED_ACCESS_VIEW; else if(kind == HandleKind::Sampler) key.type = DXBCBytecode::TYPE_SAMPLER; + else if(kind == HandleKind::CBuffer) + key.type = DXBCBytecode::TYPE_CONSTANT_BUFFER; else continue; key.space = spaceArg->getU32(); @@ -972,6 +1027,32 @@ static bool AddArraySlots(WrappedID3D12PipelineState::ShaderEntry *shad, uint32_ const ShaderReflection &refl = shad->GetDetails(); + for(size_t i = 0; i < refl.constantBlocks.size(); i++) + { + const ConstantBlock &cb = refl.constantBlocks[i]; + if(cb.bindArraySize > 1) + { + D3D12FeedbackKey key; + key.stage = refl.stage; + key.type = DXBCBytecode::TYPE_CONSTANT_BUFFER; + key.space = cb.fixedBindSetOrSpace; + key.bind = cb.fixedBindNumber; + + DescriptorAccess access; + access.stage = refl.stage; + access.type = DescriptorType::ConstantBuffer; + access.index = i & 0xffff; + // descriptor storage side will be calculated later when finalising this with the root + // signature information. + + slots[key].numDescriptors = RDCMIN(maxDescriptors, cb.bindArraySize); + slots[key].access = access; + slots[key].slot = numSlots; + numSlots += slots[key].numDescriptors; + dynamicUsed = true; + } + } + for(size_t i = 0; i < refl.readOnlyResources.size(); i++) { const ShaderResource &ro = refl.readOnlyResources[i];