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
This commit is contained in:
Jake Turner
2026-05-11 12:29:51 +01:00
parent 0a212d07d0
commit 57a393f96c
4 changed files with 16 additions and 10 deletions
+1 -1
View File
@@ -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;
+2 -2
View File
@@ -113,7 +113,7 @@ public:
return m_WorkgroupProperties;
}
const rdcarray<ShaderVariable> &GetConstantBlocks() const override { return m_ConstantBlocks; }
const std::map<ConstantBlockReference, bytebuf> &GetConstantBlocksDatas() const override
const std::map<ConstantBlockReference, ConstantBlockData> &GetConstantBlocksDatas() const override
{
return m_ConstantBlocksDatas;
}
@@ -160,7 +160,7 @@ private:
rdcarray<rdcflatmap<ShaderBuiltin, ShaderVariable>> m_ThreadsBuiltins;
rdcarray<SourceVariableMapping> m_SourceVars;
rdcarray<ShaderVariable> m_ConstantBlocks;
std::map<ConstantBlockReference, bytebuf> m_ConstantBlocksDatas;
std::map<ConstantBlockReference, ConstantBlockData> m_ConstantBlocksDatas;
ShaderVariable m_InputPlaceholder;
uint32_t m_SubgroupSize = 1;
+5 -5
View File
@@ -2595,7 +2595,7 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &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<ThreadState> &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<ThreadState> &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];
}
+8 -2
View File
@@ -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<DXILDebug::ThreadProperties> &GetWorkgroupProperties() const = 0;
virtual const rdcarray<ShaderVariable> &GetConstantBlocks() const = 0;
virtual const std::map<ConstantBlockReference, bytebuf> &GetConstantBlocksDatas() const = 0;
virtual const std::map<ConstantBlockReference, ConstantBlockData> &GetConstantBlocksDatas() const = 0;
virtual const BuiltinInputs &GetBuiltins() const = 0;
virtual uint32_t GetSubgroupSize() const = 0;
virtual const rdcarray<rdcflatmap<ShaderBuiltin, ShaderVariable>> &GetThreadsBuiltins() const = 0;
@@ -795,7 +801,7 @@ struct GlobalState
// allocated storage for opaque uniform blocks, does not change over the course of debugging
rdcarray<ShaderVariable> constantBlocks;
std::map<ConstantBlockReference, bytebuf> constantBlocksDatas;
std::map<ConstantBlockReference, ConstantBlockData> constantBlocksDatas;
rdcarray<Id> groupSharedMemoryIds;
// resources may be read-write but the variable itself doesn't change