mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 09:00:44 +00:00
DXIL Debugger support for direct heap access Constant Buffers
This commit is contained in:
@@ -1297,6 +1297,85 @@ SRVInfo D3D12APIWrapper::FetchSRV(const BindingSlot &slot)
|
||||
return srvData;
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
bool D3D12APIWrapper::IsCBVCached(const BindingSlot &slot) const
|
||||
{
|
||||
SCOPED_READLOCK(m_CBVsLock);
|
||||
return m_CBVBuffers.find(slot) != m_CBVBuffers.end();
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
void D3D12APIWrapper::GetCBV(const BindingSlot &slot)
|
||||
{
|
||||
{
|
||||
SCOPED_READLOCK(m_CBVsLock);
|
||||
auto it = m_CBVBuffers.find(slot);
|
||||
if(it != m_CBVBuffers.end())
|
||||
return;
|
||||
}
|
||||
|
||||
FetchCBV(slot);
|
||||
}
|
||||
|
||||
// Must be called from the replay manager thread (the debugger thread)
|
||||
void D3D12APIWrapper::FetchCBV(const BindingSlot &slot)
|
||||
{
|
||||
CHECK_DEVICE_THREAD();
|
||||
|
||||
const HeapDescriptorType heapType = slot.heapType;
|
||||
const uint32_t descriptorIndex = slot.descriptorIndex;
|
||||
const D3D12Descriptor resDescriptor =
|
||||
D3D12ShaderDebug::FindDescriptor(m_Device, heapType, descriptorIndex);
|
||||
|
||||
bytebuf data;
|
||||
D3D12ResourceManager *rm = m_Device->GetResourceManager();
|
||||
ResourceId cbvId = WrappedID3D12Resource::GetResIDFromAddr(resDescriptor.GetCBV().BufferLocation);
|
||||
ID3D12Resource *pResource = rm->GetResAs<ID3D12Resource>(cbvId);
|
||||
if(pResource)
|
||||
m_Device->GetDebugManager()->GetBufferData(pResource, 0, 0, data);
|
||||
|
||||
{
|
||||
SCOPED_WRITELOCK(m_CBVsLock);
|
||||
auto bufferIt = m_CBVBuffers.insert(std::make_pair(slot, data));
|
||||
RDCASSERT(bufferIt.second);
|
||||
}
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
// Resource must be cached
|
||||
ShaderValue D3D12APIWrapper::CBVLoad(const BindingSlot &slot, uint32_t regIndex) const
|
||||
{
|
||||
ShaderValue result;
|
||||
result.u32v[0] = 0;
|
||||
result.u32v[1] = 0;
|
||||
result.u32v[2] = 0;
|
||||
result.u32v[3] = 0;
|
||||
|
||||
SCOPED_READLOCK(m_CBVsLock);
|
||||
auto it = m_CBVBuffers.find(slot);
|
||||
if(it == m_CBVBuffers.end())
|
||||
{
|
||||
RDCERR("CBV Load slot %u space %u desc Index %u no cached data", slot.shaderRegister,
|
||||
slot.registerSpace, slot.descriptorIndex);
|
||||
return result;
|
||||
}
|
||||
const bytebuf &cbufferData = it->second;
|
||||
const uint32_t bufferSize = (uint32_t)cbufferData.size();
|
||||
const uint32_t maxIndex = AlignUp16(bufferSize) / 16;
|
||||
RDCASSERTMSG("Out of bounds cbuffer load", regIndex < maxIndex, regIndex, maxIndex);
|
||||
if(regIndex < maxIndex)
|
||||
{
|
||||
const uint32_t dataOffset = regIndex * 16;
|
||||
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);
|
||||
for(uint32_t c = 0; c < numComps; c++)
|
||||
result.u32v[c] = data[c];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
// Resource must be cached
|
||||
ShaderValue D3D12APIWrapper::TypedUAVLoad(const BindingSlot &slot, const DXILDebug::ViewFmt &fmt,
|
||||
|
||||
@@ -43,6 +43,7 @@ public:
|
||||
|
||||
void FetchConstantBufferData(const D3D12RenderState::RootSignature &rootsig);
|
||||
|
||||
ShaderValue CBVLoad(const BindingSlot &slot, uint32_t dataOffset) const override;
|
||||
ShaderValue TypedUAVLoad(const BindingSlot &slot, const DXILDebug::ViewFmt &fmt,
|
||||
uint64_t dataOffset) const override;
|
||||
ShaderValue TypedSRVLoad(const BindingSlot &slot, const DXILDebug::ViewFmt &fmt,
|
||||
@@ -51,6 +52,7 @@ public:
|
||||
const ShaderValue &value) override;
|
||||
bool TypedSRVStore(const BindingSlot &slot, const DXILDebug::ViewFmt &fmt, uint64_t dataOffset,
|
||||
const ShaderValue &value) override;
|
||||
void GetCBV(const BindingSlot &slot) override;
|
||||
UAVInfo GetUAV(const BindingSlot &slot) override;
|
||||
SRVInfo GetSRV(const BindingSlot &slot) override;
|
||||
|
||||
@@ -75,6 +77,7 @@ public:
|
||||
ShaderDirectAccess GetShaderDirectAccess(DescriptorType type,
|
||||
const DXDebug::BindingSlot &slot) override;
|
||||
|
||||
bool IsCBVCached(const DXDebug::BindingSlot &slot) const override;
|
||||
bool IsSRVCached(const DXDebug::BindingSlot &slot) const override;
|
||||
bool IsUAVCached(const DXDebug::BindingSlot &slot) const override;
|
||||
bool IsResourceInfoCached(const DXDebug::BindingSlot &slot, uint32_t mipLevel) override;
|
||||
@@ -138,6 +141,8 @@ private:
|
||||
SRVInfo FetchSRV(const BindingSlot &slot);
|
||||
SRVInfo FetchSRV(const D3D12Descriptor *resDescriptor, const BindingSlot &slot);
|
||||
|
||||
void FetchCBV(const BindingSlot &slot);
|
||||
|
||||
UAVInfo FetchUAV(const BindingSlot &slot);
|
||||
UAVInfo FetchUAV(const D3D12Descriptor *resDescriptor, const BindingSlot &slot);
|
||||
|
||||
@@ -177,6 +182,8 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
mutable Threading::RWLock m_CBVsLock;
|
||||
std::map<BindingSlot, bytebuf> m_CBVBuffers;
|
||||
mutable Threading::RWLock m_UAVsLock;
|
||||
std::map<BindingSlot, UAVInfo> m_UAVInfos;
|
||||
std::map<BindingSlot, bytebuf> m_UAVBuffers;
|
||||
|
||||
@@ -2351,7 +2351,6 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
|
||||
SetStepNeedsDeviceThread();
|
||||
break;
|
||||
}
|
||||
RDCASSERT(m_DirectHeapAccessBindings.count(resultId) == 0);
|
||||
m_DirectHeapAccessBindings[resultId] = resRefInfo;
|
||||
|
||||
// Default to unannotated handle
|
||||
@@ -2377,7 +2376,6 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
|
||||
// Update m_DirectHeapAccessBindings for the annotated handle
|
||||
// to use the data from the source resource
|
||||
RDCASSERT(m_DirectHeapAccessBindings.count(baseResourceId) > 0);
|
||||
RDCASSERT(m_DirectHeapAccessBindings.count(resultId) == 0);
|
||||
m_DirectHeapAccessBindings[resultId] = m_DirectHeapAccessBindings.at(baseResourceId);
|
||||
}
|
||||
else
|
||||
@@ -2431,16 +2429,19 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
|
||||
}
|
||||
else if(resKind == ResourceKind::CBuffer)
|
||||
{
|
||||
// Create the cbuffer handle reference for the annotated handle
|
||||
auto it = m_ConstantBlockHandles.find(baseResourceId);
|
||||
if(it != m_ConstantBlockHandles.end())
|
||||
if(!resource.IsDirectAccess())
|
||||
{
|
||||
m_ConstantBlockHandles[resultId] = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Annotated handle resName:%s %s has no cbuffer handle reference %u",
|
||||
resName.c_str(), baseResource.c_str(), baseResourceId);
|
||||
// Create the cbuffer handle reference for the annotated handle
|
||||
auto it = m_ConstantBlockHandles.find(baseResourceId);
|
||||
if(it != m_ConstantBlockHandles.end())
|
||||
{
|
||||
m_ConstantBlockHandles[resultId] = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Annotated handle resName:%s %s has no cbuffer handle reference %u",
|
||||
resName.c_str(), baseResource.c_str(), baseResourceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Store the annotate properties for the result
|
||||
@@ -2648,42 +2649,63 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
|
||||
uint32_t regIndex = arg.value.u32v[0];
|
||||
|
||||
RDCASSERT(m_Live[handleId]);
|
||||
const ShaderVariable &handleVar = m_Variables[handleId];
|
||||
ShaderVariable handleVar;
|
||||
|
||||
bool annotatedHandle = false;
|
||||
ResourceReferenceInfo resRefInfo = GetResource(handleId, annotatedHandle, handleVar);
|
||||
if(!resRefInfo.Valid())
|
||||
{
|
||||
RDCERR("Invalid cbuffer resource %u", handleId);
|
||||
break;
|
||||
}
|
||||
|
||||
result.value.u32v[0] = 0;
|
||||
result.value.u32v[1] = 0;
|
||||
result.value.u32v[2] = 0;
|
||||
result.value.u32v[3] = 0;
|
||||
auto constantBlockRefIt = m_ConstantBlockHandles.find(handleId);
|
||||
if(constantBlockRefIt != m_ConstantBlockHandles.end())
|
||||
if(handleVar.IsDirectAccess())
|
||||
{
|
||||
const ConstantBlockReference &constantBlockRef = constantBlockRefIt->second;
|
||||
auto it = m_GlobalState.constantBlocksDatas.find(constantBlockRef);
|
||||
if(it != m_GlobalState.constantBlocksDatas.end())
|
||||
const BindingSlot &slot = resRefInfo.binding;
|
||||
if(m_Debugger.LoadCBVData(slot, regIndex, result.value) == DeviceOpResult::NeedsDevice)
|
||||
{
|
||||
const bytebuf &cbufferData = it->second;
|
||||
const uint32_t bufferSize = (uint32_t)cbufferData.size();
|
||||
const uint32_t maxIndex = AlignUp16(bufferSize) / 16;
|
||||
RDCASSERTMSG("Out of bounds cbuffer load", regIndex < maxIndex, regIndex, maxIndex);
|
||||
if(regIndex < maxIndex)
|
||||
{
|
||||
const uint32_t dataOffset = regIndex * 16;
|
||||
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);
|
||||
for(uint32_t c = 0; c < numComps; c++)
|
||||
result.value.u32v[c] = data[c];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Failed to find data for constant block data for %s", handleVar.name.c_str());
|
||||
SetStepNeedsDeviceThread();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Failed to find data for cbuffer %s", handleVar.name.c_str());
|
||||
auto constantBlockRefIt = m_ConstantBlockHandles.find(handleId);
|
||||
if(constantBlockRefIt != m_ConstantBlockHandles.end())
|
||||
{
|
||||
const ConstantBlockReference &constantBlockRef = constantBlockRefIt->second;
|
||||
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;
|
||||
RDCASSERTMSG("Out of bounds cbuffer load", regIndex < maxIndex, regIndex, maxIndex);
|
||||
if(regIndex < maxIndex)
|
||||
{
|
||||
const uint32_t dataOffset = regIndex * 16;
|
||||
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);
|
||||
for(uint32_t c = 0; c < numComps; c++)
|
||||
result.value.u32v[c] = data[c];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Failed to find data for constant block data for %s",
|
||||
handleVar.name.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Failed to find data for cbuffer %s", handleVar.name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// DXIL will create a vector of a single type with total size of 16-bytes
|
||||
@@ -10452,6 +10474,18 @@ bool Debugger::TypedResourceStore(DXIL::ResourceClass resClass, const BindingSlo
|
||||
return false;
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
DeviceOpResult Debugger::LoadCBVData(const BindingSlot &slot, uint32_t regIndex, ShaderValue &value)
|
||||
{
|
||||
if(!IsDeviceThread() && !m_ApiWrapper->IsCBVCached(slot))
|
||||
return DeviceOpResult::NeedsDevice;
|
||||
|
||||
m_ApiWrapper->GetCBV(slot);
|
||||
|
||||
value = m_ApiWrapper->CBVLoad(slot, regIndex);
|
||||
return DeviceOpResult::Succeeded;
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
DeviceOpResult Debugger::GetUAV(const BindingSlot &slot, UAVInfo &uavInfo) const
|
||||
{
|
||||
|
||||
@@ -299,6 +299,7 @@ class DebugAPIWrapper
|
||||
public:
|
||||
virtual ~DebugAPIWrapper() {}
|
||||
|
||||
virtual ShaderValue CBVLoad(const BindingSlot &slot, uint32_t regIndex) const = 0;
|
||||
virtual ShaderValue TypedUAVLoad(const BindingSlot &slot, const DXILDebug::ViewFmt &fmt,
|
||||
uint64_t dataOffset) const = 0;
|
||||
virtual ShaderValue TypedSRVLoad(const BindingSlot &slot, const DXILDebug::ViewFmt &fmt,
|
||||
@@ -309,6 +310,7 @@ public:
|
||||
uint64_t dataOffset, const ShaderValue &value) = 0;
|
||||
|
||||
// These will fetch the data on demand.
|
||||
virtual void GetCBV(const BindingSlot &slot) = 0;
|
||||
virtual UAVInfo GetUAV(const BindingSlot &slot) = 0;
|
||||
virtual SRVInfo GetSRV(const BindingSlot &slot) = 0;
|
||||
|
||||
@@ -332,6 +334,7 @@ public:
|
||||
virtual ShaderDirectAccess GetShaderDirectAccess(DescriptorType type,
|
||||
const DXDebug::BindingSlot &slot) = 0;
|
||||
|
||||
virtual bool IsCBVCached(const DXDebug::BindingSlot &slot) const = 0;
|
||||
virtual bool IsSRVCached(const DXDebug::BindingSlot &slot) const = 0;
|
||||
virtual bool IsUAVCached(const DXDebug::BindingSlot &slot) const = 0;
|
||||
virtual bool IsResourceInfoCached(const DXDebug::BindingSlot &slot, uint32_t mipLevel) = 0;
|
||||
@@ -932,6 +935,7 @@ public:
|
||||
bool TypedResourceStore(DXIL::ResourceClass resClass, const BindingSlot &slot,
|
||||
const DXILDebug::ViewFmt &fmt, uint64_t dataOffset, ShaderValue &value);
|
||||
|
||||
DeviceOpResult LoadCBVData(const BindingSlot &slot, uint32_t regIndex, ShaderValue &value);
|
||||
DeviceOpResult GetUAV(const BindingSlot &slot, UAVInfo &uavInfo) const;
|
||||
DeviceOpResult GetSRV(const BindingSlot &slot, SRVInfo &srvInfo) const;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user