diff --git a/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp b/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp index 16bd91604..64bbf27e0 100644 --- a/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp +++ b/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp @@ -1699,6 +1699,25 @@ bool D3D11DebugAPIWrapper::CalculateMathIntrinsic(DXBCBytecode::OpcodeType opcod return true; } +void AddCBuffersToDebugTrace(const DXBCBytecode::Program &program, D3D11DebugManager &debugManager, + ShaderDebugTrace &trace, const D3D11RenderState::Shader &shader, + const ShaderReflection &refl, const ShaderBindpointMapping &mapping) +{ + bytebuf cbufData; + for(int i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++) + { + if(shader.ConstantBuffers[i]) + { + ShaderDebug::BindingSlot slot(i, 0); + cbufData.clear(); + debugManager.GetBufferData(shader.ConstantBuffers[i], shader.CBOffsets[i] * sizeof(Vec4f), + shader.CBCounts[i] * sizeof(Vec4f), cbufData); + + AddCBufferToDebugTrace(program, trace, refl, mapping, slot, cbufData); + } + } +} + ShaderDebugTrace D3D11Replay::DebugVertex(uint32_t eventId, uint32_t vertid, uint32_t instid, uint32_t idx, uint32_t instOffset, uint32_t vertOffset) { @@ -1793,19 +1812,15 @@ ShaderDebugTrace D3D11Replay::DebugVertex(uint32_t eventId, uint32_t vertid, uin } } - bytebuf cbufData[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; - - for(int i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++) - if(rs->VS.ConstantBuffers[i]) - GetDebugManager()->GetBufferData(rs->VS.ConstantBuffers[i], - rs->VS.CBOffsets[i] * sizeof(Vec4f), 0, cbufData[i]); - ShaderDebugTrace ret; GlobalState global; global.PopulateGroupshared(dxbc->GetDXBCByteCode()); State initialState; - CreateShaderDebugStateAndTrace(initialState, ret, -1, dxbc, refl, cbufData); + CreateShaderDebugStateAndTrace(initialState, ret, -1, dxbc, refl); + + AddCBuffersToDebugTrace(*dxbc->GetDXBCByteCode(), *GetDebugManager(), ret, rs->VS, refl, + vs->GetMapping()); for(size_t i = 0; i < ret.inputs.size(); i++) { @@ -2640,13 +2655,6 @@ void ExtractInputsPS(PSInput IN, float4 debug_pixelPos : SV_Position, uint prim // get the index of our desired pixel int destIdx = (x - xTL) + 2 * (y - yTL); - bytebuf cbufData[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; - - for(int i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++) - if(rs->PS.ConstantBuffers[i]) - GetDebugManager()->GetBufferData(rs->PS.ConstantBuffers[i], - rs->PS.CBOffsets[i] * sizeof(Vec4f), 0, cbufData[i]); - D3D11_COMPARISON_FUNC depthFunc = D3D11_COMPARISON_LESS; if(rs->OM.DepthStencilState) @@ -2719,15 +2727,17 @@ void ExtractInputsPS(PSInput IN, float4 debug_pixelPos : SV_Position, uint prim GlobalState global; global.PopulateGroupshared(dxbc->GetDXBCByteCode()); - global.sampleEvalRegisterMask = sampleEvalRegisterMask; + State initialState; + CreateShaderDebugStateAndTrace(initialState, traces[destIdx], destIdx, dxbc, refl); + + AddCBuffersToDebugTrace(*dxbc->GetDXBCByteCode(), *GetDebugManager(), traces[destIdx], rs->PS, + refl, ps->GetMapping()); + { DebugHit *hit = winner; - State initialState; - CreateShaderDebugStateAndTrace(initialState, traces[destIdx], destIdx, dxbc, refl, cbufData); - rdcarray &ins = traces[destIdx].inputs; if(!ins.empty() && ins.back().name == "vCoverage") ins.back().value.u.x = hit->coverage; @@ -3015,19 +3025,15 @@ ShaderDebugTrace D3D11Replay::DebugThread(uint32_t eventId, const uint32_t group D3D11RenderState *rs = m_pImmediateContext->GetCurrentPipelineState(); - bytebuf cbufData[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; - - for(int i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++) - if(rs->CS.ConstantBuffers[i]) - GetDebugManager()->GetBufferData(rs->CS.ConstantBuffers[i], - rs->CS.CBOffsets[i] * sizeof(Vec4f), 0, cbufData[i]); - ShaderDebugTrace ret; GlobalState global; global.PopulateGroupshared(dxbc->GetDXBCByteCode()); State initialState; - CreateShaderDebugStateAndTrace(initialState, ret, -1, dxbc, refl, cbufData); + CreateShaderDebugStateAndTrace(initialState, ret, -1, dxbc, refl); + + AddCBuffersToDebugTrace(*dxbc->GetDXBCByteCode(), *GetDebugManager(), ret, rs->CS, refl, + cs->GetMapping()); for(int i = 0; i < 3; i++) { diff --git a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp index 4bbcb8d7f..8bfd1ebb2 100644 --- a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp +++ b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp @@ -1035,9 +1035,10 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( return true; } -void GatherConstantBuffers(WrappedID3D12Device *pDevice, DXBC::ShaderType shaderType, +void GatherConstantBuffers(WrappedID3D12Device *pDevice, const DXBCBytecode::Program &program, const D3D12RenderState::RootSignature &rootsig, - bytebuf cbufData[D3D12_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]) + const ShaderReflection &refl, const ShaderBindpointMapping &mapping, + ShaderDebugTrace &debugTrace) { WrappedID3D12RootSignature *pD3D12RootSig = pDevice->GetResourceManager()->GetCurrentAs(rootsig.rootsig); @@ -1047,21 +1048,26 @@ void GatherConstantBuffers(WrappedID3D12Device *pDevice, DXBC::ShaderType shader { const D3D12RootSignatureParameter &rootSigParam = pD3D12RootSig->sig.Parameters[i]; const D3D12RenderState::SignatureElement &element = rootsig.sigelems[i]; - if(IsShaderParameterVisible(shaderType, rootSigParam.ShaderVisibility)) + if(IsShaderParameterVisible(program.GetShaderType(), rootSigParam.ShaderVisibility)) { if(rootSigParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS && element.type == eRootConst) { - UINT cbufIndex = rootSigParam.Constants.ShaderRegister; + ShaderDebug::BindingSlot slot(rootSigParam.Constants.ShaderRegister, + rootSigParam.Constants.RegisterSpace); UINT sizeBytes = sizeof(uint32_t) * RDCMIN(rootSigParam.Constants.Num32BitValues, (UINT)element.constants.size()); - cbufData[cbufIndex].assign((const byte *)element.constants.data(), sizeBytes); + bytebuf cbufData((const byte *)element.constants.data(), sizeBytes); + AddCBufferToDebugTrace(program, debugTrace, refl, mapping, slot, cbufData); } else if(rootSigParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV && element.type == eRootCBV) { - UINT cbufIndex = rootSigParam.Descriptor.ShaderRegister; + ShaderDebug::BindingSlot slot(rootSigParam.Descriptor.ShaderRegister, + rootSigParam.Descriptor.RegisterSpace); ID3D12Resource *cbv = pDevice->GetResourceManager()->GetCurrentAs(element.id); - pDevice->GetDebugManager()->GetBufferData(cbv, element.offset, 0, cbufData[cbufIndex]); + bytebuf cbufData; + pDevice->GetDebugManager()->GetBufferData(cbv, element.offset, 0, cbufData); + AddCBufferToDebugTrace(program, debugTrace, refl, mapping, slot, cbufData); } else if(rootSigParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && element.type == eRootTable) @@ -1073,10 +1079,10 @@ void GatherConstantBuffers(WrappedID3D12Device *pDevice, DXBC::ShaderType shader size_t numRanges = rootSigParam.ranges.size(); for(size_t r = 0; r < numRanges; r++) { - // For this traversal we only care about CBV descriptor ranges + // For this traversal we only care about CBV descriptor ranges, but we still need to + // calculate the table offsets in case a descriptor table has a combination of + // different range types const D3D12_DESCRIPTOR_RANGE1 &range = rootSigParam.ranges[r]; - if(range.RangeType != D3D12_DESCRIPTOR_RANGE_TYPE_CBV) - continue; UINT offset = range.OffsetInDescriptorsFromTableStart; if(range.OffsetInDescriptorsFromTableStart == D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) @@ -1098,9 +1104,13 @@ void GatherConstantBuffers(WrappedID3D12Device *pDevice, DXBC::ShaderType shader prevTableOffset = offset + numDescriptors; - UINT cbufIndex = range.BaseShaderRegister; + if(range.RangeType != D3D12_DESCRIPTOR_RANGE_TYPE_CBV) + continue; - for(UINT n = 0; n < numDescriptors; ++n, ++cbufIndex) + ShaderDebug::BindingSlot slot(range.BaseShaderRegister, range.RegisterSpace); + + bytebuf cbufData; + for(UINT n = 0; n < numDescriptors; ++n, ++slot.shaderRegister) { if(desc) { @@ -1110,8 +1120,9 @@ void GatherConstantBuffers(WrappedID3D12Device *pDevice, DXBC::ShaderType shader WrappedID3D12Resource1::GetResIDFromAddr(cbv.BufferLocation, resId, byteOffset); ID3D12Resource *pCbvResource = pDevice->GetResourceManager()->GetCurrentAs(resId); - pDevice->GetDebugManager()->GetBufferData(pCbvResource, element.offset, 0, - cbufData[cbufIndex]); + cbufData.clear(); + pDevice->GetDebugManager()->GetBufferData(pCbvResource, element.offset, 0, cbufData); + AddCBufferToDebugTrace(program, debugTrace, refl, mapping, slot, cbufData); } } } @@ -1509,10 +1520,6 @@ void ExtractInputsPS(PSInput IN, float4 debug_pixelPos : SV_Position, uint prim // get the index of our desired pixel int destIdx = (x - xTL) + 2 * (y - yTL); - // Fetch constant buffer data from root signature - bytebuf cbufData[D3D12_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; - GatherConstantBuffers(m_pDevice, dxbc->m_Type, rs.graphics, cbufData); - // Get depth func and determine "winner" pixel D3D12_COMPARISON_FUNC depthFunc = pipeDesc.DepthStencilState.DepthFunc; DebugHit *pWinnerHit = NULL; @@ -1571,10 +1578,15 @@ void ExtractInputsPS(PSInput IN, float4 debug_pixelPos : SV_Position, uint prim GlobalState global; global.PopulateGroupshared(dxbc->GetDXBCByteCode()); + State initialState; + CreateShaderDebugStateAndTrace(initialState, traces[destIdx], destIdx, dxbc, refl); + + // Fetch constant buffer data from root signature + GatherConstantBuffers(m_pDevice, *dxbc->GetDXBCByteCode(), rs.graphics, refl, + origPSO->PS()->GetMapping(), traces[destIdx]); + { DebugHit *pHit = pWinnerHit; - State initialState; - CreateShaderDebugStateAndTrace(initialState, traces[destIdx], destIdx, dxbc, refl, cbufData); rdcarray &ins = traces[destIdx].inputs; if(!ins.empty() && ins.back().name == "vCoverage") @@ -1849,15 +1861,17 @@ ShaderDebugTrace D3D12Replay::DebugThread(uint32_t eventId, const uint32_t group D3D12RenderState &rs = m_pDevice->GetQueue()->GetCommandData()->m_RenderState; - bytebuf cbufData[D3D12_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; - GatherConstantBuffers(m_pDevice, dxbc->m_Type, rs.compute, cbufData); - ShaderDebugTrace ret; GlobalState global; global.PopulateGroupshared(dxbc->GetDXBCByteCode()); State initialState; - CreateShaderDebugStateAndTrace(initialState, ret, -1, dxbc, refl, cbufData); + CreateShaderDebugStateAndTrace(initialState, ret, -1, dxbc, refl); + + WrappedID3D12PipelineState *pso = + m_pDevice->GetResourceManager()->GetCurrentAs(rs.pipe); + GatherConstantBuffers(m_pDevice, *dxbc->GetDXBCByteCode(), rs.compute, refl, + pso->CS()->GetMapping(), ret); for(int i = 0; i < 3; i++) { diff --git a/renderdoc/driver/shaders/dxbc/dxbc_bytecode.cpp b/renderdoc/driver/shaders/dxbc/dxbc_bytecode.cpp index 07e36d7d4..57816e02e 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_bytecode.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_bytecode.cpp @@ -329,13 +329,19 @@ DXBC::Reflection *Program::GuessReflection() RDCASSERT(dcl.operand.indices.size() == 2 || dcl.operand.indices.size() == 3); RDCASSERT(dcl.operand.indices[0].absolute && dcl.operand.indices[1].absolute); + // Constant buffer declarations differ between SM5 and SM5.1. For SM5.1, the indices are + // logical identifier, start shader register, and end shader register. Register space and + // buffer size are stored elsewhere in the declaration. For SM5 and earlier, the indices + // are the shader register and buffer size (measured in float4's) + bool isShaderModel51 = IsShaderModel51(); uint32_t idx = (uint32_t)dcl.operand.indices[0].index; - uint32_t numVecs = (uint32_t)dcl.operand.indices[1].index; + uint32_t reg = isShaderModel51 ? (uint32_t)dcl.operand.indices[1].index : idx; + uint32_t numVecs = isShaderModel51 ? dcl.float4size : (uint32_t)dcl.operand.indices[1].index; desc.name = StringFormat::Fmt("cbuffer%u", idx); desc.type = DXBC::ShaderInputBind::TYPE_CBUFFER; desc.space = dcl.space; - desc.reg = idx; + desc.reg = reg; desc.bindCount = 1; desc.flags = 1; desc.retType = DXBC::RETURN_TYPE_UNKNOWN; @@ -353,8 +359,12 @@ DXBC::Reflection *Program::GuessReflection() cb.name = desc.name; + // In addition to the register, store the identifier that we'll use to lookup during + // debugging. For SM5.1, this is the logical identifier that correlates to the CB order in + // the bytecode. For SM5 and earlier, it's the CB register. + cb.identifier = idx; cb.space = dcl.space; - cb.reg = idx; + cb.reg = reg; cb.bindCount = desc.bindCount; cb.descriptor.name = cb.name; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_bytecode.h b/renderdoc/driver/shaders/dxbc/dxbc_bytecode.h index f72ce396d..c5723eaae 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_bytecode.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_bytecode.h @@ -754,6 +754,7 @@ struct Declaration resType[0] = resType[1] = resType[2] = resType[3] = DXBC::NUM_RETURN_TYPES; dim = RESOURCE_DIMENSION_UNKNOWN; sampleCount = 0; + float4size = 0; interpolation = INTERPOLATION_UNDEFINED; systemValue = DXBC::SVNAME_UNDEFINED; maxOut = 0; @@ -828,6 +829,9 @@ struct Declaration ResourceDimension dim; uint32_t sampleCount; + // OPCODE_DCL_CONSTANT_BUFFER + uint32_t float4size; + // OPCODE_DCL_INPUT_PS InterpolationMode interpolation; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_common.h b/renderdoc/driver/shaders/dxbc/dxbc_common.h index a58c192fc..70945e8e5 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_common.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_common.h @@ -319,6 +319,7 @@ struct CBuffer { rdcstr name; + uint32_t identifier; uint32_t space; uint32_t reg; uint32_t bindCount; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_container.cpp b/renderdoc/driver/shaders/dxbc/dxbc_container.cpp index 8788377ae..60c4c9a04 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_container.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_container.cpp @@ -880,6 +880,10 @@ DXBCContainer::DXBCContainer(const void *ByteCode, size_t ByteCodeLength) cbuffernames.insert(cname); + // In addition to the register, store the identifier that we'll use to lookup during + // debugging. For SM5.1, this is the logical identifier that correlates to the CB order in + // the bytecode. For SM5 and earlier, it's the CB register. + cb.identifier = (h->targetVersion < 0x501) ? cbufferbinds[cname].reg : i; cb.space = cbufferbinds[cname].space; cb.reg = cbufferbinds[cname].reg; cb.bindCount = cbufferbinds[cname].bindCount; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp index 289e5c7f0..9bc5beed4 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp @@ -1564,9 +1564,14 @@ ShaderVariable State::GetSrc(const Operand &oper, const Operation &op, bool allo { int cb = -1; + // For this operand, index 0 is always the logical identifier that we can use to + // lookup the correct cbuffer. The location of the access entry differs for SM5.1, + // as index 1 stores the shader register. + uint32_t cbIdentifier = indices[0]; + uint32_t cbLookup = program->IsShaderModel51() ? indices[2] : indices[1]; for(size_t i = 0; i < reflection->CBuffers.size(); i++) { - if(reflection->CBuffers[i].reg == indices[0]) + if(reflection->CBuffers[i].identifier == cbIdentifier) { cb = (int)i; break; @@ -1579,11 +1584,11 @@ ShaderVariable State::GetSrc(const Operand &oper, const Operation &op, bool allo if(cb >= 0 && cb < trace->constantBlocks.count()) { RDCASSERTMSG("Out of bounds cbuffer lookup", - indices[1] < (uint32_t)trace->constantBlocks[cb].members.count(), indices[1], + cbLookup < (uint32_t)trace->constantBlocks[cb].members.count(), cbLookup, trace->constantBlocks[cb].members.count()); - if(indices[1] < (uint32_t)trace->constantBlocks[cb].members.count()) - v = s = trace->constantBlocks[cb].members[indices[1]]; + if(cbLookup < (uint32_t)trace->constantBlocks[cb].members.count()) + v = s = trace->constantBlocks[cb].members[cbLookup]; else v = s = ShaderVariable("", 0U, 0U, 0U, 0U); } @@ -4128,7 +4133,7 @@ void GlobalState::PopulateGroupshared(const DXBCBytecode::Program *pBytecode) void CreateShaderDebugStateAndTrace(ShaderDebug::State &initialState, ShaderDebugTrace &trace, int quadIdx, DXBC::DXBCContainer *dxbc, - const ShaderReflection &refl, bytebuf *cbufData) + const ShaderReflection &refl) { initialState = ShaderDebug::State(quadIdx, &trace, dxbc->GetReflection(), dxbc->GetDXBCByteCode()); @@ -4268,28 +4273,43 @@ void CreateShaderDebugStateAndTrace(ShaderDebug::State &initialState, ShaderDebu } } - // Fill constant buffers and add them to the trace + // Set the number of constant buffers in the trace, but assignment happens later size_t numCBuffers = dxbc->GetReflection()->CBuffers.size(); trace.constantBlocks.resize(numCBuffers); - for(size_t i = 0; i < numCBuffers; i++) + + initialState.Init(); +} + +void AddCBufferToDebugTrace(const DXBCBytecode::Program &program, ShaderDebugTrace &trace, + const ShaderReflection &refl, const ShaderBindpointMapping &mapping, + const ShaderDebug::BindingSlot &slot, bytebuf &cbufData) +{ + // Find the identifier + size_t numCBs = mapping.constantBlocks.size(); + for(size_t i = 0; i < numCBs; ++i) { - rdcarray vars; - - // Fetch cbuffers into vars, which will be 'natural': structs with members, non merged vectors - StandardFillCBufferVariables(refl.resourceId, refl.constantBlocks[i].variables, vars, - cbufData[dxbc->GetReflection()->CBuffers[i].reg]); - - FlattenVariables(refl.constantBlocks[i].variables, vars, trace.constantBlocks[i].members); - - for(size_t c = 0; c < trace.constantBlocks[i].members.size(); c++) + if((uint32_t)mapping.constantBlocks[i].bindset == slot.registerSpace && + (uint32_t)mapping.constantBlocks[i].bind == slot.shaderRegister) { - trace.constantBlocks[i].members[c].name = - StringFormat::Fmt("cb%u[%u] (%s)", dxbc->GetReflection()->CBuffers[i].reg, (uint32_t)c, - trace.constantBlocks[i].members[c].name.c_str()); + RDCASSERTMSG("Reassigning previously filled cbuffer", trace.constantBlocks[i].members.empty()); + + rdcarray vars; + StandardFillCBufferVariables(refl.resourceId, refl.constantBlocks[i].variables, vars, cbufData); + FlattenVariables(refl.constantBlocks[i].variables, vars, trace.constantBlocks[i].members); + + const char *format = program.IsShaderModel51() ? "CB%u[%u] (%s)" : "cb%u[%u] (%s)"; + uint32_t regSlot = program.IsShaderModel51() ? (uint32_t)i : slot.shaderRegister; + for(size_t c = 0; c < trace.constantBlocks[i].members.size(); c++) + { + trace.constantBlocks[i].members[c].name = StringFormat::Fmt( + format, regSlot, (uint32_t)c, trace.constantBlocks[i].members[c].name.c_str()); + } + return; } } - initialState.Init(); + RDCERR("Cannot find cbuffer (b%u, space%u) in shader mapping", slot.shaderRegister, + slot.registerSpace); } bool PromptDebugTimeout(uint32_t cycleCounter) diff --git a/renderdoc/driver/shaders/dxbc/dxbc_debug.h b/renderdoc/driver/shaders/dxbc/dxbc_debug.h index 22ec6f8c9..609df83ba 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_debug.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_debug.h @@ -365,6 +365,9 @@ private: void CreateShaderDebugStateAndTrace(ShaderDebug::State &initialState, ShaderDebugTrace &trace, int quadIdx, DXBC::DXBCContainer *dxbc, - const ShaderReflection &refl, bytebuf *cbufData); + const ShaderReflection &refl); +void AddCBufferToDebugTrace(const DXBCBytecode::Program &program, ShaderDebugTrace &trace, + const ShaderReflection &refl, const ShaderBindpointMapping &mapping, + const ShaderDebug::BindingSlot &slot, bytebuf &cbufData); }; // namespace ShaderDebug diff --git a/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp b/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp index 77193b65d..890385de3 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp @@ -1447,10 +1447,12 @@ bool Program::ExtractDecl(uint32_t *&tokenStream, Declaration &retDecl, bool fri retDecl.str += retDecl.operand.toString(m_Reflection, flags); if(sm51) { - uint32_t float4size = tokenStream[0]; + // Store the size provided. If there's no reflection data, this will be + // necessary to guess the buffer size properly + retDecl.float4size = tokenStream[0]; tokenStream++; - retDecl.str += StringFormat::Fmt("[%u]", float4size); + retDecl.str += StringFormat::Fmt("[%u]", retDecl.float4size); } retDecl.str += ", ";