From 57a393f96cb815eab2349e01171a689276f9a049 Mon Sep 17 00:00:00 2001 From: Jake Turner Date: Mon, 11 May 2026 12:29:51 +0100 Subject: [PATCH] DXIL Debugger return 0,0,0,0 for out of bounds CB data access Use the constant buffer reflection data to determine the size of valid data instead of the size of the bound buffer --- renderdoc/driver/d3d12/d3d12_dxil_debug.cpp | 2 +- renderdoc/driver/d3d12/d3d12_dxil_debug.h | 4 ++-- renderdoc/driver/shaders/dxil/dxil_debug.cpp | 10 +++++----- renderdoc/driver/shaders/dxil/dxil_debug.h | 10 ++++++++-- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/renderdoc/driver/d3d12/d3d12_dxil_debug.cpp b/renderdoc/driver/d3d12/d3d12_dxil_debug.cpp index 45709b406..5f3eba460 100644 --- a/renderdoc/driver/d3d12/d3d12_dxil_debug.cpp +++ b/renderdoc/driver/d3d12/d3d12_dxil_debug.cpp @@ -995,7 +995,7 @@ void D3D12APIWrapper::AddCBufferToGlobalState(const BindingSlot &slot, bytebuf & RDCASSERTMSG("Reassigning previously filled cbuffer", targetVars.empty()); ConstantBlockReference constantBlockRef = {i, arrayIndex}; - m_ConstantBlocksDatas[constantBlockRef] = cbufData; + m_ConstantBlocksDatas[constantBlockRef] = {cbufData, cb.byteSize}; rdcstr resName = Debugger::GetResourceReferenceName(m_Program, ResourceClass::CBuffer, slot); m_ConstantBlocks[i].name = resName; diff --git a/renderdoc/driver/d3d12/d3d12_dxil_debug.h b/renderdoc/driver/d3d12/d3d12_dxil_debug.h index 773f2481f..9cae66f45 100644 --- a/renderdoc/driver/d3d12/d3d12_dxil_debug.h +++ b/renderdoc/driver/d3d12/d3d12_dxil_debug.h @@ -113,7 +113,7 @@ public: return m_WorkgroupProperties; } const rdcarray &GetConstantBlocks() const override { return m_ConstantBlocks; } - const std::map &GetConstantBlocksDatas() const override + const std::map &GetConstantBlocksDatas() const override { return m_ConstantBlocksDatas; } @@ -160,7 +160,7 @@ private: rdcarray> m_ThreadsBuiltins; rdcarray m_SourceVars; rdcarray m_ConstantBlocks; - std::map m_ConstantBlocksDatas; + std::map m_ConstantBlocksDatas; ShaderVariable m_InputPlaceholder; uint32_t m_SubgroupSize = 1; diff --git a/renderdoc/driver/shaders/dxil/dxil_debug.cpp b/renderdoc/driver/shaders/dxil/dxil_debug.cpp index 0a975d7ae..b092c92c5 100644 --- a/renderdoc/driver/shaders/dxil/dxil_debug.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_debug.cpp @@ -2595,7 +2595,7 @@ bool ThreadState::ExecuteInstruction(const rdcarray &workgroup) auto it = m_GlobalState.constantBlocksDatas.find(constantBlockRef); if(it != m_GlobalState.constantBlocksDatas.end()) { - const bytebuf &cbufferData = it->second; + const bytebuf &cbufferData = it->second.bufferData; if(cbufferData.size() != 0) { size_t offset = 0; @@ -2681,9 +2681,9 @@ bool ThreadState::ExecuteInstruction(const rdcarray &workgroup) auto it = m_GlobalState.constantBlocksDatas.find(constantBlockRef); if(it != m_GlobalState.constantBlocksDatas.end()) { - const bytebuf &cbufferData = it->second; - const uint32_t bufferSize = (uint32_t)cbufferData.size(); - const uint32_t maxIndex = AlignUp16(bufferSize) / 16; + const bytebuf &cbufferData = it->second.bufferData; + const uint32_t dataSize = (uint32_t)(it->second.byteSize); + const uint32_t maxIndex = AlignUp16(dataSize) / 16; RDCASSERTMSG("Out of bounds cbuffer load", regIndex < maxIndex, regIndex, maxIndex); if(regIndex < maxIndex) { @@ -2691,7 +2691,7 @@ bool ThreadState::ExecuteInstruction(const rdcarray &workgroup) const uint32_t byteWidth = 4; const byte *base = cbufferData.data() + dataOffset; const uint32_t *data = (const uint32_t *)base; - const uint32_t numComps = RDCMIN(4U, (bufferSize - dataOffset) / byteWidth); + const uint32_t numComps = RDCMIN(4U, (dataSize - dataOffset) / byteWidth); for(uint32_t c = 0; c < numComps; c++) result.value.u32v[c] = data[c]; } diff --git a/renderdoc/driver/shaders/dxil/dxil_debug.h b/renderdoc/driver/shaders/dxil/dxil_debug.h index 07ee9158e..fb8b56671 100644 --- a/renderdoc/driver/shaders/dxil/dxil_debug.h +++ b/renderdoc/driver/shaders/dxil/dxil_debug.h @@ -263,6 +263,12 @@ struct SRVInfo ResourceInfo resInfo; }; +struct ConstantBlockData +{ + bytebuf bufferData; + size_t byteSize; +}; + enum class ThreadProperty : uint32_t { Helper, @@ -346,7 +352,7 @@ public: virtual const ShaderVariable &GetInputPlaceholder() const = 0; virtual const rdcarray &GetWorkgroupProperties() const = 0; virtual const rdcarray &GetConstantBlocks() const = 0; - virtual const std::map &GetConstantBlocksDatas() const = 0; + virtual const std::map &GetConstantBlocksDatas() const = 0; virtual const BuiltinInputs &GetBuiltins() const = 0; virtual uint32_t GetSubgroupSize() const = 0; virtual const rdcarray> &GetThreadsBuiltins() const = 0; @@ -795,7 +801,7 @@ struct GlobalState // allocated storage for opaque uniform blocks, does not change over the course of debugging rdcarray constantBlocks; - std::map constantBlocksDatas; + std::map constantBlocksDatas; rdcarray groupSharedMemoryIds; // resources may be read-write but the variable itself doesn't change