mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-09-17 03:05:44 +00:00
Added caching to DXIL APIWrapper and Debugger
Added TypedUAV Load/Store to APIWrapper
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
#include "d3d12_dxil_debug.h"
|
||||
#include "data/hlsl/hlsl_cbuffers.h"
|
||||
#include "driver/dxgi/dxgi_common.h"
|
||||
#include "maths/formatpacking.h"
|
||||
#include "d3d12_command_queue.h"
|
||||
#include "d3d12_debug.h"
|
||||
#include "d3d12_replay.h"
|
||||
@@ -45,6 +46,300 @@ using namespace DXILDebug;
|
||||
|
||||
namespace DXILDebug
|
||||
{
|
||||
static ShaderValue TypedUAVLoad(const DXILDebug::ViewFmt &fmt, const byte *base, uint64_t offset)
|
||||
{
|
||||
const byte *data = base + offset;
|
||||
ShaderValue result;
|
||||
result.f32v[0] = 0.0f;
|
||||
result.f32v[1] = 0.0f;
|
||||
result.f32v[2] = 0.0f;
|
||||
result.f32v[3] = 0.0f;
|
||||
|
||||
if(fmt.byteWidth == 10)
|
||||
{
|
||||
uint32_t u;
|
||||
memcpy(&u, data, sizeof(uint32_t));
|
||||
|
||||
if(fmt.compType == CompType::UInt)
|
||||
{
|
||||
result.u32v[0] = (u >> 0) & 0x3ff;
|
||||
result.u32v[1] = (u >> 10) & 0x3ff;
|
||||
result.u32v[2] = (u >> 20) & 0x3ff;
|
||||
result.u32v[3] = (u >> 30) & 0x003;
|
||||
}
|
||||
else if(fmt.compType == CompType::UNorm)
|
||||
{
|
||||
Vec4f res = ConvertFromR10G10B10A2(u);
|
||||
result.f32v[0] = res.x;
|
||||
result.f32v[1] = res.y;
|
||||
result.f32v[2] = res.z;
|
||||
result.f32v[3] = res.w;
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Unexpected format type on buffer resource");
|
||||
}
|
||||
}
|
||||
else if(fmt.byteWidth == 11)
|
||||
{
|
||||
uint32_t u;
|
||||
memcpy(&u, data, sizeof(uint32_t));
|
||||
|
||||
Vec3f res = ConvertFromR11G11B10(u);
|
||||
result.f32v[0] = res.x;
|
||||
result.f32v[1] = res.y;
|
||||
result.f32v[2] = res.z;
|
||||
result.f32v[3] = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(fmt.byteWidth == 4)
|
||||
{
|
||||
const uint32_t *u = (const uint32_t *)data;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
result.u32v[c] = u[c];
|
||||
}
|
||||
else if(fmt.byteWidth == 2)
|
||||
{
|
||||
if(fmt.compType == CompType::Float)
|
||||
{
|
||||
const uint16_t *u = (const uint16_t *)data;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
result.f32v[c] = ConvertFromHalf(u[c]);
|
||||
}
|
||||
else if(fmt.compType == CompType::UInt)
|
||||
{
|
||||
const uint16_t *u = (const uint16_t *)data;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
result.u32v[c] = u[c];
|
||||
}
|
||||
else if(fmt.compType == CompType::SInt)
|
||||
{
|
||||
const int16_t *in = (const int16_t *)data;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
result.s32v[c] = in[c];
|
||||
}
|
||||
else if(fmt.compType == CompType::UNorm || fmt.compType == CompType::UNormSRGB)
|
||||
{
|
||||
const uint16_t *u = (const uint16_t *)data;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
result.f32v[c] = float(u[c]) / float(0xffff);
|
||||
}
|
||||
else if(fmt.compType == CompType::SNorm)
|
||||
{
|
||||
const int16_t *in = (const int16_t *)data;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
{
|
||||
// -32768 is mapped to -1, then -32767 to -32767 are mapped to -1 to 1
|
||||
if(in[c] == -32768)
|
||||
result.f32v[c] = -1.0f;
|
||||
else
|
||||
result.f32v[c] = float(in[c]) / 32767.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Unexpected format type on buffer resource");
|
||||
}
|
||||
}
|
||||
else if(fmt.byteWidth == 1)
|
||||
{
|
||||
if(fmt.compType == CompType::UInt)
|
||||
{
|
||||
const uint8_t *u = (const uint8_t *)data;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
result.u32v[c] = u[c];
|
||||
}
|
||||
else if(fmt.compType == CompType::SInt)
|
||||
{
|
||||
const int8_t *in = (const int8_t *)data;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
result.s32v[c] = in[c];
|
||||
}
|
||||
else if(fmt.compType == CompType::UNorm || fmt.compType == CompType::UNormSRGB)
|
||||
{
|
||||
const uint8_t *u = (const uint8_t *)data;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
result.f32v[c] = float(u[c]) / float(0xff);
|
||||
}
|
||||
else if(fmt.compType == CompType::SNorm)
|
||||
{
|
||||
const int8_t *in = (const int8_t *)data;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
{
|
||||
// -128 is mapped to -1, then -127 to -127 are mapped to -1 to 1
|
||||
if(in[c] == -128)
|
||||
result.f32v[c] = -1.0f;
|
||||
else
|
||||
result.f32v[c] = float(in[c]) / 127.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Unexpected format type on buffer resource");
|
||||
}
|
||||
}
|
||||
|
||||
// fill in alpha with 1.0 or 1 as appropriate
|
||||
if(fmt.numComps < 4)
|
||||
{
|
||||
if(fmt.compType == CompType::UNorm || fmt.compType == CompType::UNormSRGB ||
|
||||
fmt.compType == CompType::SNorm || fmt.compType == CompType::Float)
|
||||
result.f32v[3] = 1.0f;
|
||||
else
|
||||
result.u32v[3] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void TypedUAVStore(const DXILDebug::ViewFmt &fmt, byte *base, uint64_t offset,
|
||||
const ShaderValue &value)
|
||||
{
|
||||
byte *data = base + offset;
|
||||
if(fmt.byteWidth == 10)
|
||||
{
|
||||
uint32_t u = 0;
|
||||
|
||||
if(fmt.compType == CompType::UInt)
|
||||
{
|
||||
u |= (value.u32v[0] & 0x3ff) << 0;
|
||||
u |= (value.u32v[1] & 0x3ff) << 10;
|
||||
u |= (value.u32v[2] & 0x3ff) << 20;
|
||||
u |= (value.u32v[3] & 0x3) << 30;
|
||||
}
|
||||
else if(fmt.compType == CompType::UNorm)
|
||||
{
|
||||
u = ConvertToR10G10B10A2(Vec4f(value.f32v[0], value.f32v[1], value.f32v[2], value.f32v[3]));
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Unexpected format type on buffer resource");
|
||||
}
|
||||
memcpy(data, &u, sizeof(uint32_t));
|
||||
}
|
||||
else if(fmt.byteWidth == 11)
|
||||
{
|
||||
uint32_t u = ConvertToR11G11B10(Vec3f(value.f32v[0], value.f32v[1], value.f32v[2]));
|
||||
memcpy(data, &u, sizeof(uint32_t));
|
||||
}
|
||||
else if(fmt.byteWidth == 4)
|
||||
{
|
||||
uint32_t *u = (uint32_t *)data;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
u[c] = value.u32v[c];
|
||||
}
|
||||
else if(fmt.byteWidth == 2)
|
||||
{
|
||||
if(fmt.compType == CompType::Float)
|
||||
{
|
||||
uint16_t *u = (uint16_t *)data;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
u[c] = ConvertToHalf(value.f32v[c]);
|
||||
}
|
||||
else if(fmt.compType == CompType::UInt)
|
||||
{
|
||||
uint16_t *u = (uint16_t *)data;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
u[c] = value.u32v[c] & 0xffff;
|
||||
}
|
||||
else if(fmt.compType == CompType::SInt)
|
||||
{
|
||||
int16_t *i = (int16_t *)data;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
i[c] = (int16_t)RDCCLAMP(value.s32v[c], (int32_t)INT16_MIN, (int32_t)INT16_MAX);
|
||||
}
|
||||
else if(fmt.compType == CompType::UNorm || fmt.compType == CompType::UNormSRGB)
|
||||
{
|
||||
uint16_t *u = (uint16_t *)data;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
{
|
||||
float f = RDCCLAMP(value.f32v[c], 0.0f, 1.0f) * float(0xffff) + 0.5f;
|
||||
u[c] = uint16_t(f);
|
||||
}
|
||||
}
|
||||
else if(fmt.compType == CompType::SNorm)
|
||||
{
|
||||
int16_t *i = (int16_t *)data;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
{
|
||||
float f = RDCCLAMP(value.f32v[c], -1.0f, 1.0f) * 0x7fff;
|
||||
|
||||
if(f < 0.0f)
|
||||
i[c] = int16_t(f - 0.5f);
|
||||
else
|
||||
i[c] = int16_t(f + 0.5f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Unexpected format type on buffer resource");
|
||||
}
|
||||
}
|
||||
else if(fmt.byteWidth == 1)
|
||||
{
|
||||
if(fmt.compType == CompType::UInt)
|
||||
{
|
||||
uint8_t *u = (uint8_t *)data;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
u[c] = value.u32v[c] & 0xff;
|
||||
}
|
||||
else if(fmt.compType == CompType::SInt)
|
||||
{
|
||||
int8_t *i = (int8_t *)data;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
i[c] = (int8_t)RDCCLAMP(value.s32v[c], (int32_t)INT8_MIN, (int32_t)INT8_MAX);
|
||||
}
|
||||
else if(fmt.compType == CompType::UNorm || fmt.compType == CompType::UNormSRGB)
|
||||
{
|
||||
uint8_t *u = (uint8_t *)data;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
{
|
||||
float f = RDCCLAMP(value.f32v[c], 0.0f, 1.0f) * float(0xff) + 0.5f;
|
||||
u[c] = uint8_t(f);
|
||||
}
|
||||
}
|
||||
else if(fmt.compType == CompType::SNorm)
|
||||
{
|
||||
int8_t *i = (int8_t *)data;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
{
|
||||
float f = RDCCLAMP(value.f32v[c], -1.0f, 1.0f) * 0x7f;
|
||||
|
||||
if(f < 0.0f)
|
||||
i[c] = int8_t(f - 0.5f);
|
||||
else
|
||||
i[c] = int8_t(f + 0.5f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Unexpected format type on buffer resource");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DXBC::ResourceRetType ConvertCompTypeToResourceRetType(const CompType compType)
|
||||
{
|
||||
switch(compType)
|
||||
@@ -721,11 +1016,45 @@ void D3D12APIWrapper::AddCBufferToGlobalState(const BindingSlot &slot, bytebuf &
|
||||
}
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
// Resource must be cached
|
||||
ShaderValue D3D12APIWrapper::TypedSRVLoad(const BindingSlot &slot, const DXILDebug::ViewFmt &fmt,
|
||||
uint64_t dataOffset) const
|
||||
{
|
||||
SCOPED_READLOCK(m_SRVsLock);
|
||||
auto it = m_SRVBuffers.find(slot);
|
||||
if(it == m_SRVBuffers.end())
|
||||
{
|
||||
RDCERR("Load SRV slot %u space %u no cached data", slot.shaderRegister, slot.registerSpace);
|
||||
return ShaderValue();
|
||||
}
|
||||
const bytebuf &data = it->second;
|
||||
return DXILDebug::TypedUAVLoad(fmt, data.data(), dataOffset);
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
// Resource must be cached
|
||||
bool D3D12APIWrapper::TypedSRVStore(const BindingSlot &slot, const DXILDebug::ViewFmt &fmt,
|
||||
uint64_t dataOffset, const ShaderValue &value)
|
||||
{
|
||||
SCOPED_READLOCK(m_SRVsLock);
|
||||
auto it = m_SRVBuffers.find(slot);
|
||||
if(it == m_SRVBuffers.end())
|
||||
{
|
||||
RDCERR("Store SRV slot %u space %u no cached data", slot.shaderRegister, slot.registerSpace);
|
||||
return false;
|
||||
}
|
||||
bytebuf &data = it->second;
|
||||
DXILDebug::TypedUAVStore(fmt, data.data(), dataOffset, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Must be called from the replay manager thread (the debugger thread)
|
||||
SRVData &D3D12APIWrapper::FetchSRV(const D3D12Descriptor *resDescriptor, const BindingSlot &slot)
|
||||
SRVInfo D3D12APIWrapper::FetchSRV(const D3D12Descriptor *resDescriptor, const BindingSlot &slot)
|
||||
{
|
||||
CHECK_DEVICE_THREAD();
|
||||
SRVData &srvData = m_SRVs[slot];
|
||||
SRVInfo srvData;
|
||||
bytebuf data;
|
||||
if(resDescriptor)
|
||||
{
|
||||
D3D12ResourceManager *rm = m_Device->GetResourceManager();
|
||||
@@ -760,16 +1089,25 @@ SRVData &D3D12APIWrapper::FetchSRV(const D3D12Descriptor *resDescriptor, const B
|
||||
if(mdStride != 0)
|
||||
srvData.resInfo.format.stride = mdStride;
|
||||
|
||||
m_Device->GetDebugManager()->GetBufferData(pResource, 0, 0, srvData.data);
|
||||
m_Device->GetDebugManager()->GetBufferData(pResource, 0, 0, data);
|
||||
}
|
||||
// Textures are sampled via a pixel shader, so there's no need to copy their data
|
||||
}
|
||||
}
|
||||
srvData.resInfo.hasData = data.data() != NULL;
|
||||
srvData.resInfo.dataSize = data.size();
|
||||
{
|
||||
SCOPED_WRITELOCK(m_SRVsLock);
|
||||
auto it = m_SRVInfos.insert(std::make_pair(slot, srvData));
|
||||
RDCASSERT(it.second);
|
||||
auto bufferIt = m_SRVBuffers.insert(std::make_pair(slot, data));
|
||||
RDCASSERT(bufferIt.second);
|
||||
}
|
||||
return srvData;
|
||||
}
|
||||
|
||||
// Must be called from the replay manager thread (the debugger thread)
|
||||
SRVData &D3D12APIWrapper::FetchSRV(const BindingSlot &slot)
|
||||
SRVInfo D3D12APIWrapper::FetchSRV(const BindingSlot &slot)
|
||||
{
|
||||
CHECK_DEVICE_THREAD();
|
||||
// the resources might be dirty from side-effects, replay back to right before it.
|
||||
@@ -785,6 +1123,8 @@ SRVData &D3D12APIWrapper::FetchSRV(const BindingSlot &slot)
|
||||
return FetchSRV(&srvDesc, slot);
|
||||
}
|
||||
|
||||
SRVInfo srvData;
|
||||
bytebuf data;
|
||||
const D3D12RenderState &rs = m_Device->GetQueue()->GetCommandData()->m_RenderState;
|
||||
D3D12ResourceManager *rm = m_Device->GetResourceManager();
|
||||
|
||||
@@ -819,7 +1159,6 @@ SRVData &D3D12APIWrapper::FetchSRV(const BindingSlot &slot)
|
||||
if(param.Descriptor.ShaderRegister == slot.shaderRegister &&
|
||||
param.Descriptor.RegisterSpace == slot.registerSpace)
|
||||
{
|
||||
SRVData &srvData = m_SRVs[slot];
|
||||
// Found the requested SRV
|
||||
ID3D12Resource *pResource = rm->GetCurrentAs<ID3D12Resource>(element.id);
|
||||
if(pResource)
|
||||
@@ -848,10 +1187,18 @@ SRVData &D3D12APIWrapper::FetchSRV(const BindingSlot &slot)
|
||||
DXILDebug::GetSRVBufferStrideFromShaderMetadata(m_EntryPointInterface, slot);
|
||||
if(mdStride != 0)
|
||||
srvData.resInfo.format.stride = mdStride;
|
||||
m_Device->GetDebugManager()->GetBufferData(pResource, element.offset, 0,
|
||||
srvData.data);
|
||||
m_Device->GetDebugManager()->GetBufferData(pResource, element.offset, 0, data);
|
||||
}
|
||||
}
|
||||
srvData.resInfo.hasData = data.data() != NULL;
|
||||
srvData.resInfo.dataSize = data.size();
|
||||
{
|
||||
SCOPED_WRITELOCK(m_SRVsLock);
|
||||
auto it = m_SRVInfos.insert(std::make_pair(slot, srvData));
|
||||
RDCASSERT(it.second);
|
||||
auto bufferIt = m_SRVBuffers.insert(std::make_pair(slot, data));
|
||||
RDCASSERT(bufferIt.second);
|
||||
}
|
||||
return srvData;
|
||||
}
|
||||
}
|
||||
@@ -906,19 +1253,61 @@ SRVData &D3D12APIWrapper::FetchSRV(const BindingSlot &slot)
|
||||
|
||||
RDCERR("Couldn't find root signature parameter corresponding to SRV %u in space %u",
|
||||
slot.shaderRegister, slot.registerSpace);
|
||||
return m_SRVs[slot];
|
||||
{
|
||||
SCOPED_WRITELOCK(m_SRVsLock);
|
||||
m_SRVInfos[slot] = srvData;
|
||||
}
|
||||
return srvData;
|
||||
}
|
||||
|
||||
RDCERR("No root signature bound, couldn't identify SRV %u in space %u", slot.shaderRegister,
|
||||
slot.registerSpace);
|
||||
return m_SRVs[slot];
|
||||
{
|
||||
SCOPED_WRITELOCK(m_SRVsLock);
|
||||
m_SRVInfos[slot] = srvData;
|
||||
}
|
||||
return srvData;
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
// Resource must be cached
|
||||
ShaderValue D3D12APIWrapper::TypedUAVLoad(const BindingSlot &slot, const DXILDebug::ViewFmt &fmt,
|
||||
uint64_t dataOffset) const
|
||||
{
|
||||
SCOPED_READLOCK(m_UAVsLock);
|
||||
auto it = m_UAVBuffers.find(slot);
|
||||
if(it == m_UAVBuffers.end())
|
||||
{
|
||||
RDCERR("Load UAV slot %u space %u no cached data", slot.shaderRegister, slot.registerSpace);
|
||||
return ShaderValue();
|
||||
}
|
||||
const bytebuf &data = it->second;
|
||||
return DXILDebug::TypedUAVLoad(fmt, data.data(), dataOffset);
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
// Resource must be cached
|
||||
bool D3D12APIWrapper::TypedUAVStore(const BindingSlot &slot, const DXILDebug::ViewFmt &fmt,
|
||||
uint64_t dataOffset, const ShaderValue &value)
|
||||
{
|
||||
SCOPED_READLOCK(m_UAVsLock);
|
||||
auto it = m_UAVBuffers.find(slot);
|
||||
if(it == m_UAVBuffers.end())
|
||||
{
|
||||
RDCERR("Store UAV slot %u space %u no cached data", slot.shaderRegister, slot.registerSpace);
|
||||
return false;
|
||||
}
|
||||
bytebuf &data = it->second;
|
||||
DXILDebug::TypedUAVStore(fmt, data.data(), dataOffset, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Must be called from the replay manager thread (the debugger thread)
|
||||
UAVData &D3D12APIWrapper::FetchUAV(const D3D12Descriptor *resDescriptor, const BindingSlot &slot)
|
||||
UAVInfo D3D12APIWrapper::FetchUAV(const D3D12Descriptor *resDescriptor, const BindingSlot &slot)
|
||||
{
|
||||
CHECK_DEVICE_THREAD();
|
||||
UAVData &uavData = m_UAVs[slot];
|
||||
UAVInfo uavData;
|
||||
bytebuf data;
|
||||
if(resDescriptor)
|
||||
{
|
||||
D3D12ResourceManager *rm = m_Device->GetResourceManager();
|
||||
@@ -950,13 +1339,12 @@ UAVData &D3D12APIWrapper::FetchUAV(const D3D12Descriptor *resDescriptor, const B
|
||||
if(mdStride != 0)
|
||||
uavData.resInfo.format.stride = mdStride;
|
||||
|
||||
m_Device->GetDebugManager()->GetBufferData(pResource, 0, 0, uavData.data);
|
||||
m_Device->GetDebugManager()->GetBufferData(pResource, 0, 0, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
uavData.tex = true;
|
||||
m_Device->GetReplay()->GetTextureData(uavId, Subresource(), GetTextureDataParams(),
|
||||
uavData.data);
|
||||
m_Device->GetReplay()->GetTextureData(uavId, Subresource(), GetTextureDataParams(), data);
|
||||
|
||||
uavDesc.Format = D3D12ShaderDebug::GetUAVResourceFormat(uavDesc, pResource);
|
||||
DXILDebug::FillViewFmtFromResourceFormat(uavDesc.Format, uavData.resInfo.format);
|
||||
@@ -967,11 +1355,20 @@ UAVData &D3D12APIWrapper::FetchUAV(const D3D12Descriptor *resDescriptor, const B
|
||||
}
|
||||
}
|
||||
}
|
||||
uavData.resInfo.hasData = data.data() != NULL;
|
||||
uavData.resInfo.dataSize = data.size();
|
||||
{
|
||||
SCOPED_WRITELOCK(m_UAVsLock);
|
||||
auto it = m_UAVInfos.insert(std::make_pair(slot, uavData));
|
||||
RDCASSERT(it.second);
|
||||
auto bufferIt = m_UAVBuffers.insert(std::make_pair(slot, data));
|
||||
RDCASSERT(bufferIt.second);
|
||||
}
|
||||
return uavData;
|
||||
}
|
||||
|
||||
// Must be called from the replay manager thread (the debugger thread)
|
||||
UAVData &D3D12APIWrapper::FetchUAV(const BindingSlot &slot)
|
||||
UAVInfo D3D12APIWrapper::FetchUAV(const BindingSlot &slot)
|
||||
{
|
||||
CHECK_DEVICE_THREAD();
|
||||
// the resources might be dirty from side-effects, replay back to right before it.
|
||||
@@ -987,6 +1384,8 @@ UAVData &D3D12APIWrapper::FetchUAV(const BindingSlot &slot)
|
||||
return FetchUAV(&uavDesc, slot);
|
||||
}
|
||||
|
||||
UAVInfo uavData;
|
||||
bytebuf data;
|
||||
const D3D12RenderState &rs = m_Device->GetQueue()->GetCommandData()->m_RenderState;
|
||||
D3D12ResourceManager *rm = m_Device->GetResourceManager();
|
||||
|
||||
@@ -1023,7 +1422,6 @@ UAVData &D3D12APIWrapper::FetchUAV(const BindingSlot &slot)
|
||||
{
|
||||
// Found the requested UAV
|
||||
ID3D12Resource *pResource = rm->GetCurrentAs<ID3D12Resource>(element.id);
|
||||
UAVData &uavData = m_UAVs[slot];
|
||||
|
||||
if(pResource)
|
||||
{
|
||||
@@ -1052,11 +1450,19 @@ UAVData &D3D12APIWrapper::FetchUAV(const BindingSlot &slot)
|
||||
DXILDebug::GetUAVBufferStrideFromShaderMetadata(m_EntryPointInterface, slot);
|
||||
if(mdStride != 0)
|
||||
uavData.resInfo.format.stride = mdStride;
|
||||
m_Device->GetDebugManager()->GetBufferData(pResource, element.offset, 0,
|
||||
uavData.data);
|
||||
m_Device->GetDebugManager()->GetBufferData(pResource, element.offset, 0, data);
|
||||
}
|
||||
}
|
||||
|
||||
uavData.resInfo.hasData = data.data() != NULL;
|
||||
uavData.resInfo.dataSize = data.size();
|
||||
{
|
||||
SCOPED_WRITELOCK(m_UAVsLock);
|
||||
auto it = m_UAVInfos.insert(std::make_pair(slot, uavData));
|
||||
RDCASSERT(it.second);
|
||||
auto bufferIt = m_UAVBuffers.insert(std::make_pair(slot, data));
|
||||
RDCASSERT(bufferIt.second);
|
||||
}
|
||||
return uavData;
|
||||
}
|
||||
}
|
||||
@@ -1111,60 +1517,60 @@ UAVData &D3D12APIWrapper::FetchUAV(const BindingSlot &slot)
|
||||
|
||||
RDCERR("Couldn't find root signature parameter corresponding to UAV %u in space %u",
|
||||
slot.shaderRegister, slot.registerSpace);
|
||||
return m_UAVs[slot];
|
||||
{
|
||||
SCOPED_WRITELOCK(m_UAVsLock);
|
||||
m_UAVInfos[slot] = uavData;
|
||||
}
|
||||
return uavData;
|
||||
}
|
||||
|
||||
RDCERR("No root signature bound, couldn't identify UAV %u in space %u", slot.shaderRegister,
|
||||
slot.registerSpace);
|
||||
return m_UAVs[slot];
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
bool D3D12APIWrapper::IsSRVCached(const BindingSlot &slot)
|
||||
{
|
||||
SCOPED_READLOCK(m_SRVsLock);
|
||||
return m_SRVs.find(slot) != m_SRVs.end();
|
||||
}
|
||||
|
||||
// Must be called from the replay manager thread (the debugger thread)
|
||||
const SRVData &D3D12APIWrapper::GetSRVData(const BindingSlot &slot)
|
||||
{
|
||||
CHECK_DEVICE_THREAD();
|
||||
{
|
||||
SCOPED_READLOCK(m_SRVsLock);
|
||||
auto it = m_SRVs.find(slot);
|
||||
if(it != m_SRVs.end())
|
||||
return it->second;
|
||||
}
|
||||
|
||||
{
|
||||
SCOPED_WRITELOCK(m_SRVsLock);
|
||||
return FetchSRV(slot);
|
||||
}
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
bool D3D12APIWrapper::IsUAVCached(const BindingSlot &slot)
|
||||
{
|
||||
SCOPED_READLOCK(m_UAVsLock);
|
||||
return m_UAVs.find(slot) != m_UAVs.end();
|
||||
}
|
||||
|
||||
// Must be called from the replay manager thread (the debugger thread)
|
||||
const UAVData &D3D12APIWrapper::GetUAVData(const BindingSlot &slot)
|
||||
{
|
||||
CHECK_DEVICE_THREAD();
|
||||
{
|
||||
SCOPED_READLOCK(m_UAVsLock);
|
||||
auto it = m_UAVs.find(slot);
|
||||
if(it != m_UAVs.end())
|
||||
return it->second;
|
||||
}
|
||||
|
||||
{
|
||||
SCOPED_WRITELOCK(m_UAVsLock);
|
||||
return FetchUAV(slot);
|
||||
m_UAVInfos[slot] = uavData;
|
||||
}
|
||||
return uavData;
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
bool D3D12APIWrapper::IsSRVCached(const BindingSlot &slot) const
|
||||
{
|
||||
SCOPED_READLOCK(m_SRVsLock);
|
||||
return m_SRVInfos.find(slot) != m_SRVInfos.end();
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
SRVInfo D3D12APIWrapper::GetSRV(const BindingSlot &slot)
|
||||
{
|
||||
{
|
||||
SCOPED_READLOCK(m_SRVsLock);
|
||||
auto it = m_SRVInfos.find(slot);
|
||||
if(it != m_SRVInfos.end())
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return FetchSRV(slot);
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
bool D3D12APIWrapper::IsUAVCached(const BindingSlot &slot) const
|
||||
{
|
||||
SCOPED_READLOCK(m_UAVsLock);
|
||||
return m_UAVInfos.find(slot) != m_UAVInfos.end();
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
UAVInfo D3D12APIWrapper::GetUAV(const BindingSlot &slot)
|
||||
{
|
||||
{
|
||||
SCOPED_READLOCK(m_UAVsLock);
|
||||
auto it = m_UAVInfos.find(slot);
|
||||
if(it != m_UAVInfos.end())
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return FetchUAV(slot);
|
||||
}
|
||||
|
||||
// Must be called from the replay manager thread (the debugger thread)
|
||||
@@ -1242,10 +1648,38 @@ bool D3D12APIWrapper::CalculateSampleGather(
|
||||
instructionIdx, opString, output);
|
||||
}
|
||||
|
||||
// Must be called from the replay manager thread (the debugger thread)
|
||||
// Called from any thread
|
||||
bool D3D12APIWrapper::IsResourceInfoCached(const DXDebug::BindingSlot &slot, uint32_t mipLevel)
|
||||
{
|
||||
SCOPED_READLOCK(m_ResourceInfosLock);
|
||||
ResourceInfoMiplevel resInfoMip = {slot, mipLevel};
|
||||
return m_ResourceInfos.find(resInfoMip) != m_ResourceInfos.end();
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
// Caller guarantees that if the data is not cached then we are on the device thread
|
||||
ShaderVariable D3D12APIWrapper::GetResourceInfo(DXIL::ResourceClass resClass,
|
||||
const DXDebug::BindingSlot &slot,
|
||||
uint32_t mipLevel) const
|
||||
const DXDebug::BindingSlot &slot, uint32_t mipLevel)
|
||||
{
|
||||
ResourceInfoMiplevel resInfoMip = {slot, mipLevel};
|
||||
{
|
||||
SCOPED_READLOCK(m_ResourceInfosLock);
|
||||
auto it = m_ResourceInfos.find(resInfoMip);
|
||||
if(it != m_ResourceInfos.end())
|
||||
return it->second;
|
||||
}
|
||||
CHECK_DEVICE_THREAD();
|
||||
ShaderVariable resourceInfo = FetchResourceInfo(resClass, slot, mipLevel);
|
||||
{
|
||||
SCOPED_WRITELOCK(m_ResourceInfosLock);
|
||||
m_ResourceInfos[resInfoMip] = resourceInfo;
|
||||
return resourceInfo;
|
||||
}
|
||||
}
|
||||
|
||||
// Must be called from the replay manager thread (the debugger thread)
|
||||
ShaderVariable D3D12APIWrapper::FetchResourceInfo(DXIL::ResourceClass resClass,
|
||||
const DXDebug::BindingSlot &slot, uint32_t mipLevel)
|
||||
{
|
||||
CHECK_DEVICE_THREAD();
|
||||
D3D12_DESCRIPTOR_RANGE_TYPE descType;
|
||||
@@ -1264,10 +1698,37 @@ ShaderVariable D3D12APIWrapper::GetResourceInfo(DXIL::ResourceClass resClass,
|
||||
true);
|
||||
}
|
||||
|
||||
// Must be called from the replay manager thread (the debugger thread)
|
||||
// Called from any thread
|
||||
bool D3D12APIWrapper::IsSampleInfoCached(const DXDebug::BindingSlot &slot)
|
||||
{
|
||||
SCOPED_READLOCK(m_SampleInfosLock);
|
||||
return m_SampleInfos.find(slot) != m_SampleInfos.end();
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
// Caller guarantees that if the data is not cached then we are on the device thread
|
||||
ShaderVariable D3D12APIWrapper::GetSampleInfo(DXIL::ResourceClass resClass,
|
||||
const DXDebug::BindingSlot &slot,
|
||||
const char *opString) const
|
||||
const DXDebug::BindingSlot &slot, const char *opString)
|
||||
{
|
||||
{
|
||||
SCOPED_READLOCK(m_SampleInfosLock);
|
||||
auto it = m_SampleInfos.find(slot);
|
||||
if(it != m_SampleInfos.end())
|
||||
return it->second;
|
||||
}
|
||||
CHECK_DEVICE_THREAD();
|
||||
ShaderVariable sampleInfo = FetchSampleInfo(resClass, slot, opString);
|
||||
{
|
||||
SCOPED_WRITELOCK(m_SampleInfosLock);
|
||||
m_SampleInfos[slot] = sampleInfo;
|
||||
return sampleInfo;
|
||||
}
|
||||
}
|
||||
|
||||
// Must be called from the replay manager thread (the debugger thread)
|
||||
ShaderVariable D3D12APIWrapper::FetchSampleInfo(DXIL::ResourceClass resClass,
|
||||
const DXDebug::BindingSlot &slot,
|
||||
const char *opString)
|
||||
{
|
||||
CHECK_DEVICE_THREAD();
|
||||
D3D12_DESCRIPTOR_RANGE_TYPE descType;
|
||||
@@ -1284,15 +1745,61 @@ ShaderVariable D3D12APIWrapper::GetSampleInfo(DXIL::ResourceClass resClass,
|
||||
return D3D12ShaderDebug::GetSampleInfo(m_Device, descType, slot, m_ShaderType, opString);
|
||||
}
|
||||
|
||||
// Must be called from the replay manager thread (the debugger thread)
|
||||
ShaderVariable D3D12APIWrapper::GetRenderTargetSampleInfo(const char *opString) const
|
||||
// Called from any thread
|
||||
bool D3D12APIWrapper::IsRenderTargetSampleInfoCached()
|
||||
{
|
||||
SCOPED_READLOCK(m_RenderTargetSampleInfoLock);
|
||||
return m_RenderTargetSampleInfoValid;
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
// Caller guarantees that if the data is not cached then we are on the device thread
|
||||
ShaderVariable D3D12APIWrapper::GetRenderTargetSampleInfo(const char *opString)
|
||||
{
|
||||
{
|
||||
SCOPED_READLOCK(m_RenderTargetSampleInfoLock);
|
||||
if(m_RenderTargetSampleInfoValid)
|
||||
return m_RenderTargetSampleInfo;
|
||||
}
|
||||
CHECK_DEVICE_THREAD();
|
||||
return D3D12ShaderDebug::GetRenderTargetSampleInfo(m_Device, m_ShaderType, opString);
|
||||
ShaderVariable renderTargetSampleInfo =
|
||||
D3D12ShaderDebug::GetRenderTargetSampleInfo(m_Device, m_ShaderType, opString);
|
||||
{
|
||||
SCOPED_WRITELOCK(m_RenderTargetSampleInfoLock);
|
||||
m_RenderTargetSampleInfoValid = true;
|
||||
m_RenderTargetSampleInfo = renderTargetSampleInfo;
|
||||
return m_RenderTargetSampleInfo;
|
||||
}
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
bool D3D12APIWrapper::IsResourceReferenceInfoCached(const DXDebug::BindingSlot &slot)
|
||||
{
|
||||
SCOPED_READLOCK(m_ResourceReferenceInfosLock);
|
||||
return m_ResourceReferenceInfos.find(slot) != m_ResourceReferenceInfos.end();
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
// Caller guarantees that if the data is not cached then we are on the device thread
|
||||
ResourceReferenceInfo D3D12APIWrapper::GetResourceReferenceInfo(const DXDebug::BindingSlot &slot)
|
||||
{
|
||||
{
|
||||
SCOPED_READLOCK(m_ResourceReferenceInfosLock);
|
||||
auto it = m_ResourceReferenceInfos.find(slot);
|
||||
if(it != m_ResourceReferenceInfos.end())
|
||||
return it->second;
|
||||
}
|
||||
CHECK_DEVICE_THREAD();
|
||||
ResourceReferenceInfo resRefInfo = FetchResourceReferenceInfo(slot);
|
||||
{
|
||||
SCOPED_WRITELOCK(m_ResourceReferenceInfosLock);
|
||||
m_ResourceReferenceInfos[slot] = resRefInfo;
|
||||
return resRefInfo;
|
||||
}
|
||||
}
|
||||
|
||||
// Must be called from the replay manager thread (the debugger thread)
|
||||
ResourceReferenceInfo D3D12APIWrapper::GetResourceReferenceInfo(const DXDebug::BindingSlot &slot) const
|
||||
ResourceReferenceInfo D3D12APIWrapper::FetchResourceReferenceInfo(const DXDebug::BindingSlot &slot)
|
||||
{
|
||||
CHECK_DEVICE_THREAD();
|
||||
const HeapDescriptorType heapType = slot.heapType;
|
||||
@@ -1390,9 +1897,36 @@ ResourceReferenceInfo D3D12APIWrapper::GetResourceReferenceInfo(const DXDebug::B
|
||||
return resRefInfo;
|
||||
}
|
||||
|
||||
// Must be called from the replay manager thread (the debugger thread)
|
||||
// Called from any thread
|
||||
bool D3D12APIWrapper::IsShaderDirectAccessCached(const DXDebug::BindingSlot &slot)
|
||||
{
|
||||
SCOPED_READLOCK(m_ShaderDirectAccessesLock);
|
||||
return m_ShaderDirectAccesses.find(slot) != m_ShaderDirectAccesses.end();
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
// Caller guarantees that if the data is not cached then we are on the device thread
|
||||
ShaderDirectAccess D3D12APIWrapper::GetShaderDirectAccess(DescriptorType type,
|
||||
const DXDebug::BindingSlot &slot) const
|
||||
const DXDebug::BindingSlot &slot)
|
||||
{
|
||||
{
|
||||
SCOPED_READLOCK(m_ShaderDirectAccessesLock);
|
||||
auto it = m_ShaderDirectAccesses.find(slot);
|
||||
if(it != m_ShaderDirectAccesses.end())
|
||||
return it->second;
|
||||
}
|
||||
CHECK_DEVICE_THREAD();
|
||||
ShaderDirectAccess access = FetchShaderDirectAccess(type, slot);
|
||||
{
|
||||
SCOPED_WRITELOCK(m_ShaderDirectAccessesLock);
|
||||
m_ShaderDirectAccesses[slot] = access;
|
||||
return access;
|
||||
}
|
||||
}
|
||||
|
||||
// Must be called from the replay manager thread (the debugger thread)
|
||||
ShaderDirectAccess D3D12APIWrapper::FetchShaderDirectAccess(DescriptorType type,
|
||||
const DXDebug::BindingSlot &slot)
|
||||
{
|
||||
CHECK_DEVICE_THREAD();
|
||||
const HeapDescriptorType heapType = slot.heapType;
|
||||
|
||||
@@ -43,8 +43,16 @@ public:
|
||||
|
||||
void FetchConstantBufferData(const D3D12RenderState::RootSignature &rootsig);
|
||||
|
||||
const UAVData &GetUAVData(const BindingSlot &slot) override;
|
||||
const SRVData &GetSRVData(const BindingSlot &slot) override;
|
||||
ShaderValue TypedUAVLoad(const BindingSlot &slot, const DXILDebug::ViewFmt &fmt,
|
||||
uint64_t dataOffset) const override;
|
||||
ShaderValue TypedSRVLoad(const BindingSlot &slot, const DXILDebug::ViewFmt &fmt,
|
||||
uint64_t dataOffset) const override;
|
||||
bool TypedUAVStore(const BindingSlot &slot, const DXILDebug::ViewFmt &fmt, uint64_t dataOffset,
|
||||
const ShaderValue &value) override;
|
||||
bool TypedSRVStore(const BindingSlot &slot, const DXILDebug::ViewFmt &fmt, uint64_t dataOffset,
|
||||
const ShaderValue &value) override;
|
||||
UAVInfo GetUAV(const BindingSlot &slot) override;
|
||||
SRVInfo GetSRV(const BindingSlot &slot) override;
|
||||
|
||||
bool CalculateMathIntrinsic(DXIL::DXOp dxOp, const ShaderVariable &input,
|
||||
ShaderVariable &output) override;
|
||||
@@ -56,16 +64,21 @@ public:
|
||||
uint32_t instructionIdx, ShaderVariable &output) override;
|
||||
|
||||
ShaderVariable GetResourceInfo(DXIL::ResourceClass resClass, const DXDebug::BindingSlot &slot,
|
||||
uint32_t mipLevel) const override;
|
||||
uint32_t mipLevel) override;
|
||||
ShaderVariable GetSampleInfo(DXIL::ResourceClass resClass, const DXDebug::BindingSlot &slot,
|
||||
const char *opString) const override;
|
||||
ShaderVariable GetRenderTargetSampleInfo(const char *opString) const override;
|
||||
ResourceReferenceInfo GetResourceReferenceInfo(const DXDebug::BindingSlot &slot) const override;
|
||||
const char *opString) override;
|
||||
ShaderVariable GetRenderTargetSampleInfo(const char *opString) override;
|
||||
ResourceReferenceInfo GetResourceReferenceInfo(const DXDebug::BindingSlot &slot) override;
|
||||
ShaderDirectAccess GetShaderDirectAccess(DescriptorType type,
|
||||
const DXDebug::BindingSlot &slot) const override;
|
||||
const DXDebug::BindingSlot &slot) override;
|
||||
|
||||
bool IsSRVCached(const DXDebug::BindingSlot &slot) override;
|
||||
bool IsUAVCached(const DXDebug::BindingSlot &slot) 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;
|
||||
bool IsSampleInfoCached(const DXDebug::BindingSlot &slot) override;
|
||||
bool IsRenderTargetSampleInfoCached() override;
|
||||
bool IsResourceReferenceInfoCached(const DXDebug::BindingSlot &slot) override;
|
||||
bool IsShaderDirectAccessCached(const DXDebug::BindingSlot &slot) override;
|
||||
|
||||
void ResetReplay();
|
||||
|
||||
@@ -119,11 +132,18 @@ private:
|
||||
const rdcarray<ShaderVariable> &invars, rdcarray<ShaderVariable> &outvars,
|
||||
const rdcstr &prefix, uint32_t baseOffset);
|
||||
|
||||
SRVData &FetchSRV(const BindingSlot &slot);
|
||||
SRVData &FetchSRV(const D3D12Descriptor *resDescriptor, const BindingSlot &slot);
|
||||
SRVInfo FetchSRV(const BindingSlot &slot);
|
||||
SRVInfo FetchSRV(const D3D12Descriptor *resDescriptor, const BindingSlot &slot);
|
||||
|
||||
UAVData &FetchUAV(const BindingSlot &slot);
|
||||
UAVData &FetchUAV(const D3D12Descriptor *resDescriptor, const BindingSlot &slot);
|
||||
UAVInfo FetchUAV(const BindingSlot &slot);
|
||||
UAVInfo FetchUAV(const D3D12Descriptor *resDescriptor, const BindingSlot &slot);
|
||||
|
||||
ShaderVariable FetchResourceInfo(DXIL::ResourceClass resClass, const DXDebug::BindingSlot &slot,
|
||||
uint32_t mipLevel);
|
||||
ShaderVariable FetchSampleInfo(DXIL::ResourceClass resClass, const DXDebug::BindingSlot &slot,
|
||||
const char *opString);
|
||||
ResourceReferenceInfo FetchResourceReferenceInfo(const DXDebug::BindingSlot &slot);
|
||||
ShaderDirectAccess FetchShaderDirectAccess(DescriptorType type, const DXDebug::BindingSlot &slot);
|
||||
|
||||
BuiltinInputs m_Builtins;
|
||||
rdcarray<DXILDebug::ThreadProperties> m_WorkgroupProperties;
|
||||
@@ -135,10 +155,43 @@ private:
|
||||
ShaderVariable m_InputPlaceholder;
|
||||
uint32_t m_SubgroupSize = 1;
|
||||
|
||||
Threading::RWLock m_UAVsLock;
|
||||
std::map<BindingSlot, UAVData> m_UAVs;
|
||||
Threading::RWLock m_SRVsLock;
|
||||
std::map<BindingSlot, SRVData> m_SRVs;
|
||||
struct ResourceInfoMiplevel
|
||||
{
|
||||
BindingSlot slot;
|
||||
uint32_t mipLevel;
|
||||
|
||||
bool operator<(const ResourceInfoMiplevel &o) const
|
||||
{
|
||||
if(mipLevel == o.mipLevel)
|
||||
return slot < o.slot;
|
||||
return mipLevel < o.mipLevel;
|
||||
}
|
||||
|
||||
bool operator==(const ResourceInfoMiplevel &o) const
|
||||
{
|
||||
return slot == o.slot && mipLevel == o.mipLevel;
|
||||
}
|
||||
};
|
||||
|
||||
mutable Threading::RWLock m_UAVsLock;
|
||||
std::map<BindingSlot, UAVInfo> m_UAVInfos;
|
||||
std::map<BindingSlot, bytebuf> m_UAVBuffers;
|
||||
mutable Threading::RWLock m_SRVsLock;
|
||||
std::map<BindingSlot, SRVInfo> m_SRVInfos;
|
||||
std::map<BindingSlot, bytebuf> m_SRVBuffers;
|
||||
Threading::RWLock m_ResourceInfosLock;
|
||||
std::map<ResourceInfoMiplevel, ShaderVariable> m_ResourceInfos;
|
||||
Threading::RWLock m_SampleInfosLock;
|
||||
std::map<BindingSlot, ShaderVariable> m_SampleInfos;
|
||||
Threading::RWLock m_ResourceReferenceInfosLock;
|
||||
std::map<BindingSlot, ResourceReferenceInfo> m_ResourceReferenceInfos;
|
||||
|
||||
Threading::RWLock m_RenderTargetSampleInfoLock;
|
||||
ShaderVariable m_RenderTargetSampleInfo;
|
||||
bool m_RenderTargetSampleInfoValid = false;
|
||||
|
||||
Threading::RWLock m_ShaderDirectAccessesLock;
|
||||
std::map<BindingSlot, ShaderDirectAccess> m_ShaderDirectAccesses;
|
||||
|
||||
const ShaderReflection &m_Reflection;
|
||||
WrappedID3D12Device *m_Device = NULL;
|
||||
|
||||
@@ -1240,297 +1240,6 @@ static size_t ComputeDXILTypeByteSize(const Type *type)
|
||||
return byteSize;
|
||||
}
|
||||
|
||||
static void TypedUAVStore(DXILDebug::ViewFmt &fmt, byte *d, const ShaderValue &value)
|
||||
{
|
||||
if(fmt.byteWidth == 10)
|
||||
{
|
||||
uint32_t u = 0;
|
||||
|
||||
if(fmt.compType == CompType::UInt)
|
||||
{
|
||||
u |= (value.u32v[0] & 0x3ff) << 0;
|
||||
u |= (value.u32v[1] & 0x3ff) << 10;
|
||||
u |= (value.u32v[2] & 0x3ff) << 20;
|
||||
u |= (value.u32v[3] & 0x3) << 30;
|
||||
}
|
||||
else if(fmt.compType == CompType::UNorm)
|
||||
{
|
||||
u = ConvertToR10G10B10A2(Vec4f(value.f32v[0], value.f32v[1], value.f32v[2], value.f32v[3]));
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Unexpected format type on buffer resource");
|
||||
}
|
||||
memcpy(d, &u, sizeof(uint32_t));
|
||||
}
|
||||
else if(fmt.byteWidth == 11)
|
||||
{
|
||||
uint32_t u = ConvertToR11G11B10(Vec3f(value.f32v[0], value.f32v[1], value.f32v[2]));
|
||||
memcpy(d, &u, sizeof(uint32_t));
|
||||
}
|
||||
else if(fmt.byteWidth == 4)
|
||||
{
|
||||
uint32_t *u = (uint32_t *)d;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
u[c] = value.u32v[c];
|
||||
}
|
||||
else if(fmt.byteWidth == 2)
|
||||
{
|
||||
if(fmt.compType == CompType::Float)
|
||||
{
|
||||
uint16_t *u = (uint16_t *)d;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
u[c] = ConvertToHalf(value.f32v[c]);
|
||||
}
|
||||
else if(fmt.compType == CompType::UInt)
|
||||
{
|
||||
uint16_t *u = (uint16_t *)d;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
u[c] = value.u32v[c] & 0xffff;
|
||||
}
|
||||
else if(fmt.compType == CompType::SInt)
|
||||
{
|
||||
int16_t *i = (int16_t *)d;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
i[c] = (int16_t)RDCCLAMP(value.s32v[c], (int32_t)INT16_MIN, (int32_t)INT16_MAX);
|
||||
}
|
||||
else if(fmt.compType == CompType::UNorm || fmt.compType == CompType::UNormSRGB)
|
||||
{
|
||||
uint16_t *u = (uint16_t *)d;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
{
|
||||
float f = RDCCLAMP(value.f32v[c], 0.0f, 1.0f) * float(0xffff) + 0.5f;
|
||||
u[c] = uint16_t(f);
|
||||
}
|
||||
}
|
||||
else if(fmt.compType == CompType::SNorm)
|
||||
{
|
||||
int16_t *i = (int16_t *)d;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
{
|
||||
float f = RDCCLAMP(value.f32v[c], -1.0f, 1.0f) * 0x7fff;
|
||||
|
||||
if(f < 0.0f)
|
||||
i[c] = int16_t(f - 0.5f);
|
||||
else
|
||||
i[c] = int16_t(f + 0.5f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Unexpected format type on buffer resource");
|
||||
}
|
||||
}
|
||||
else if(fmt.byteWidth == 1)
|
||||
{
|
||||
if(fmt.compType == CompType::UInt)
|
||||
{
|
||||
uint8_t *u = (uint8_t *)d;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
u[c] = value.u32v[c] & 0xff;
|
||||
}
|
||||
else if(fmt.compType == CompType::SInt)
|
||||
{
|
||||
int8_t *i = (int8_t *)d;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
i[c] = (int8_t)RDCCLAMP(value.s32v[c], (int32_t)INT8_MIN, (int32_t)INT8_MAX);
|
||||
}
|
||||
else if(fmt.compType == CompType::UNorm || fmt.compType == CompType::UNormSRGB)
|
||||
{
|
||||
uint8_t *u = (uint8_t *)d;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
{
|
||||
float f = RDCCLAMP(value.f32v[c], 0.0f, 1.0f) * float(0xff) + 0.5f;
|
||||
u[c] = uint8_t(f);
|
||||
}
|
||||
}
|
||||
else if(fmt.compType == CompType::SNorm)
|
||||
{
|
||||
int8_t *i = (int8_t *)d;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
{
|
||||
float f = RDCCLAMP(value.f32v[c], -1.0f, 1.0f) * 0x7f;
|
||||
|
||||
if(f < 0.0f)
|
||||
i[c] = int8_t(f - 0.5f);
|
||||
else
|
||||
i[c] = int8_t(f + 0.5f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Unexpected format type on buffer resource");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ShaderValue TypedUAVLoad(DXILDebug::ViewFmt &fmt, const byte *d)
|
||||
{
|
||||
ShaderValue result;
|
||||
result.f32v[0] = 0.0f;
|
||||
result.f32v[1] = 0.0f;
|
||||
result.f32v[2] = 0.0f;
|
||||
result.f32v[3] = 0.0f;
|
||||
|
||||
if(fmt.byteWidth == 10)
|
||||
{
|
||||
uint32_t u;
|
||||
memcpy(&u, d, sizeof(uint32_t));
|
||||
|
||||
if(fmt.compType == CompType::UInt)
|
||||
{
|
||||
result.u32v[0] = (u >> 0) & 0x3ff;
|
||||
result.u32v[1] = (u >> 10) & 0x3ff;
|
||||
result.u32v[2] = (u >> 20) & 0x3ff;
|
||||
result.u32v[3] = (u >> 30) & 0x003;
|
||||
}
|
||||
else if(fmt.compType == CompType::UNorm)
|
||||
{
|
||||
Vec4f res = ConvertFromR10G10B10A2(u);
|
||||
result.f32v[0] = res.x;
|
||||
result.f32v[1] = res.y;
|
||||
result.f32v[2] = res.z;
|
||||
result.f32v[3] = res.w;
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Unexpected format type on buffer resource");
|
||||
}
|
||||
}
|
||||
else if(fmt.byteWidth == 11)
|
||||
{
|
||||
uint32_t u;
|
||||
memcpy(&u, d, sizeof(uint32_t));
|
||||
|
||||
Vec3f res = ConvertFromR11G11B10(u);
|
||||
result.f32v[0] = res.x;
|
||||
result.f32v[1] = res.y;
|
||||
result.f32v[2] = res.z;
|
||||
result.f32v[3] = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(fmt.byteWidth == 4)
|
||||
{
|
||||
const uint32_t *u = (const uint32_t *)d;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
result.u32v[c] = u[c];
|
||||
}
|
||||
else if(fmt.byteWidth == 2)
|
||||
{
|
||||
if(fmt.compType == CompType::Float)
|
||||
{
|
||||
const uint16_t *u = (const uint16_t *)d;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
result.f32v[c] = ConvertFromHalf(u[c]);
|
||||
}
|
||||
else if(fmt.compType == CompType::UInt)
|
||||
{
|
||||
const uint16_t *u = (const uint16_t *)d;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
result.u32v[c] = u[c];
|
||||
}
|
||||
else if(fmt.compType == CompType::SInt)
|
||||
{
|
||||
const int16_t *in = (const int16_t *)d;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
result.s32v[c] = in[c];
|
||||
}
|
||||
else if(fmt.compType == CompType::UNorm || fmt.compType == CompType::UNormSRGB)
|
||||
{
|
||||
const uint16_t *u = (const uint16_t *)d;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
result.f32v[c] = float(u[c]) / float(0xffff);
|
||||
}
|
||||
else if(fmt.compType == CompType::SNorm)
|
||||
{
|
||||
const int16_t *in = (const int16_t *)d;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
{
|
||||
// -32768 is mapped to -1, then -32767 to -32767 are mapped to -1 to 1
|
||||
if(in[c] == -32768)
|
||||
result.f32v[c] = -1.0f;
|
||||
else
|
||||
result.f32v[c] = float(in[c]) / 32767.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Unexpected format type on buffer resource");
|
||||
}
|
||||
}
|
||||
else if(fmt.byteWidth == 1)
|
||||
{
|
||||
if(fmt.compType == CompType::UInt)
|
||||
{
|
||||
const uint8_t *u = (const uint8_t *)d;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
result.u32v[c] = u[c];
|
||||
}
|
||||
else if(fmt.compType == CompType::SInt)
|
||||
{
|
||||
const int8_t *in = (const int8_t *)d;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
result.s32v[c] = in[c];
|
||||
}
|
||||
else if(fmt.compType == CompType::UNorm || fmt.compType == CompType::UNormSRGB)
|
||||
{
|
||||
const uint8_t *u = (const uint8_t *)d;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
result.f32v[c] = float(u[c]) / float(0xff);
|
||||
}
|
||||
else if(fmt.compType == CompType::SNorm)
|
||||
{
|
||||
const int8_t *in = (const int8_t *)d;
|
||||
|
||||
for(int c = 0; c < fmt.numComps; c++)
|
||||
{
|
||||
// -128 is mapped to -1, then -127 to -127 are mapped to -1 to 1
|
||||
if(in[c] == -128)
|
||||
result.f32v[c] = -1.0f;
|
||||
else
|
||||
result.f32v[c] = float(in[c]) / 127.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Unexpected format type on buffer resource");
|
||||
}
|
||||
}
|
||||
|
||||
// fill in alpha with 1.0 or 1 as appropriate
|
||||
if(fmt.numComps < 4)
|
||||
{
|
||||
if(fmt.compType == CompType::UNorm || fmt.compType == CompType::UNormSRGB ||
|
||||
fmt.compType == CompType::SNorm || fmt.compType == CompType::Float)
|
||||
result.f32v[3] = 1.0f;
|
||||
else
|
||||
result.u32v[3] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ConvertTypeToViewFormat(const DXIL::Type *type, DXILDebug::ViewFmt &fmt)
|
||||
{
|
||||
// variable should be a pointer to the underlying type
|
||||
@@ -1945,10 +1654,8 @@ void ThreadState::EnterEntryPoint(const Function *function, bool hasDebugState)
|
||||
UpdateCurrentInstruction();
|
||||
}
|
||||
|
||||
// Must be called from the replay manager thread (the debugger thread)
|
||||
void ThreadState::FillCallstack(ShaderDebugState &state)
|
||||
{
|
||||
THREADSTATE_CHECK_DEBUGGER_THREAD();
|
||||
if(m_FunctionInfo->callstacks.size() == 1)
|
||||
{
|
||||
state.callstack = m_FunctionInfo->callstacks.begin()->second;
|
||||
@@ -2376,7 +2083,6 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
|
||||
}
|
||||
break;
|
||||
}
|
||||
MarkResourceAccess(handleVar);
|
||||
|
||||
const bool load = (dxOpCode == DXOp::TextureLoad) || (dxOpCode == DXOp::BufferLoad) ||
|
||||
(dxOpCode == DXOp::RawBufferLoad);
|
||||
@@ -2434,8 +2140,6 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
|
||||
}
|
||||
|
||||
uint32_t structOffset = 0;
|
||||
const byte *data = NULL;
|
||||
size_t dataSize = 0;
|
||||
bool texData = false;
|
||||
uint32_t rowPitch = 0;
|
||||
uint32_t depthPitch = 0;
|
||||
@@ -2449,31 +2153,43 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
|
||||
|
||||
RDCASSERT((resClass == ResourceClass::SRV || resClass == ResourceClass::UAV), resClass);
|
||||
ResourceInfo resInfo;
|
||||
DeviceOpResult opResult = DeviceOpResult::Unknown;
|
||||
const BindingSlot &slot = resRefInfo.binding;
|
||||
switch(resClass)
|
||||
{
|
||||
case ResourceClass::UAV:
|
||||
{
|
||||
const UAVData &uav = m_Debugger.GetUAVData(resRefInfo.binding);
|
||||
resInfo = uav.resInfo;
|
||||
data = uav.data.data();
|
||||
dataSize = uav.data.size();
|
||||
texData = uav.tex;
|
||||
rowPitch = uav.rowPitch;
|
||||
depthPitch = uav.depthPitch;
|
||||
UAVInfo uav;
|
||||
opResult = m_Debugger.GetUAV(slot, uav);
|
||||
if(opResult == DeviceOpResult::Succeeded)
|
||||
{
|
||||
resInfo = uav.resInfo;
|
||||
texData = uav.tex;
|
||||
rowPitch = uav.rowPitch;
|
||||
depthPitch = uav.depthPitch;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ResourceClass::SRV:
|
||||
{
|
||||
const SRVData &srv = m_Debugger.GetSRVData(resRefInfo.binding);
|
||||
resInfo = srv.resInfo;
|
||||
data = srv.data.data();
|
||||
dataSize = srv.data.size();
|
||||
SRVInfo srv;
|
||||
opResult = m_Debugger.GetSRV(slot, srv);
|
||||
if(opResult == DeviceOpResult::Succeeded)
|
||||
{
|
||||
resInfo = srv.resInfo;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: RDCERR("Unexpected ResourceClass %s", ToStr(resClass).c_str()); break;
|
||||
}
|
||||
if(opResult == DeviceOpResult::NeedsDevice)
|
||||
{
|
||||
SetStepNeedsDeviceThread();
|
||||
break;
|
||||
}
|
||||
MarkResourceAccess(handleVar);
|
||||
// Unbound resource
|
||||
if(data == NULL)
|
||||
if(!resInfo.hasData)
|
||||
{
|
||||
if(load)
|
||||
{
|
||||
@@ -2577,6 +2293,7 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
|
||||
dataOffset += structOffset;
|
||||
}
|
||||
|
||||
const uint64_t dataSize = resInfo.dataSize;
|
||||
// NULL resource or out of bounds
|
||||
if((!texData && elemIdx >= numElems) || (texData && dataOffset >= dataSize))
|
||||
{
|
||||
@@ -2590,7 +2307,6 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
|
||||
}
|
||||
else
|
||||
{
|
||||
data += dataOffset;
|
||||
int numComps = fmt.numComps;
|
||||
int maxNumComps = fmt.numComps;
|
||||
// Clamp the number of components to read based on the amount of data in the buffer
|
||||
@@ -2606,7 +2322,7 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
|
||||
|
||||
// For stores load the whole data, update the component, save the whole data back
|
||||
// This is to support per component writes to packed formats
|
||||
result.value = TypedUAVLoad(fmt, data);
|
||||
result.value = m_Debugger.TypedResourceLoad(resClass, slot, fmt, dataOffset);
|
||||
|
||||
// Zero out any out of bounds components
|
||||
if(fmt.numComps < numComps)
|
||||
@@ -2632,7 +2348,7 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
|
||||
}
|
||||
}
|
||||
fmt.numComps = RDCMIN(numComps, maxNumComps);
|
||||
TypedUAVStore(fmt, (byte *)data, result.value);
|
||||
m_Debugger.TypedResourceStore(resClass, slot, fmt, dataOffset, result.value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2990,15 +2706,11 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
|
||||
{
|
||||
const uint32_t dataOffset = regIndex * 16;
|
||||
const uint32_t byteWidth = 4;
|
||||
const byte *data = cbufferData.data() + dataOffset;
|
||||
const byte *base = cbufferData.data() + dataOffset;
|
||||
const uint32_t *data = (const uint32_t *)base;
|
||||
const uint32_t numComps = RDCMIN(4U, (bufferSize - dataOffset) / byteWidth);
|
||||
ViewFmt cbufferFmt;
|
||||
cbufferFmt.byteWidth = byteWidth;
|
||||
cbufferFmt.numComps = numComps;
|
||||
cbufferFmt.compType = CompType::Float;
|
||||
cbufferFmt.stride = 16;
|
||||
|
||||
result.value = TypedUAVLoad(cbufferFmt, data);
|
||||
for(uint32_t c = 0; c < numComps; c++)
|
||||
result.value.u32v[c] = data[c];
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -3596,7 +3308,6 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
|
||||
ResourceReferenceInfo resRefInfo = GetResource(handleId, annotatedHandle, handleVar);
|
||||
if(!resRefInfo.Valid())
|
||||
break;
|
||||
MarkResourceAccess(handleVar);
|
||||
|
||||
ResourceClass resClass = resRefInfo.resClass;
|
||||
// handle must be a UAV
|
||||
@@ -3610,8 +3321,6 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
|
||||
ShaderVariable a;
|
||||
|
||||
uint32_t structOffset = 0;
|
||||
const byte *data = NULL;
|
||||
size_t dataSize = 0;
|
||||
bool texData = false;
|
||||
uint32_t rowPitch = 0;
|
||||
uint32_t depthPitch = 0;
|
||||
@@ -3619,16 +3328,22 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
|
||||
uint32_t numElems = 0;
|
||||
ViewFmt fmt;
|
||||
|
||||
const UAVData &uav = m_Debugger.GetUAVData(resRefInfo.binding);
|
||||
const ResourceInfo resInfo = uav.resInfo;
|
||||
data = uav.data.data();
|
||||
dataSize = uav.data.size();
|
||||
texData = uav.tex;
|
||||
rowPitch = uav.rowPitch;
|
||||
depthPitch = uav.depthPitch;
|
||||
const BindingSlot &slot = resRefInfo.binding;
|
||||
UAVInfo uavInfo;
|
||||
if(m_Debugger.GetUAV(slot, uavInfo) == DeviceOpResult::NeedsDevice)
|
||||
{
|
||||
SetStepNeedsDeviceThread();
|
||||
break;
|
||||
}
|
||||
MarkResourceAccess(handleVar);
|
||||
|
||||
const ResourceInfo resInfo = uavInfo.resInfo;
|
||||
texData = uavInfo.tex;
|
||||
rowPitch = uavInfo.rowPitch;
|
||||
depthPitch = uavInfo.depthPitch;
|
||||
|
||||
// Unbound resource
|
||||
if(data == NULL)
|
||||
if(!resInfo.hasData)
|
||||
{
|
||||
RDCERR("Unbound resource %s", GetArgumentName(1).c_str());
|
||||
a.value.u32v[0] = 0;
|
||||
@@ -3722,6 +3437,7 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
|
||||
dataOffset += (firstElem + elemIdx) * stride;
|
||||
}
|
||||
|
||||
const uint64_t dataSize = resInfo.dataSize;
|
||||
// NULL resource or out of bounds
|
||||
if((!texData && elemIdx >= numElems) || (texData && dataOffset >= dataSize))
|
||||
{
|
||||
@@ -3732,7 +3448,6 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
|
||||
}
|
||||
else
|
||||
{
|
||||
data += dataOffset;
|
||||
// Clamp the number of components to read based on the amount of data in the buffer
|
||||
if(!texData)
|
||||
{
|
||||
@@ -3743,7 +3458,7 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
|
||||
maxNumComps = (int)((maxOffset - dataOffset) / fmt.byteWidth);
|
||||
fmt.numComps = RDCMIN(fmt.numComps, maxNumComps);
|
||||
}
|
||||
a.value = TypedUAVLoad(fmt, data);
|
||||
a.value = m_Debugger.TypedResourceLoad(resClass, slot, fmt, dataOffset);
|
||||
}
|
||||
|
||||
ShaderVariable b;
|
||||
@@ -3864,7 +3579,7 @@ bool ThreadState::ExecuteInstruction(const rdcarray<ThreadState> &workgroup)
|
||||
}
|
||||
else
|
||||
{
|
||||
TypedUAVStore(fmt, (byte *)data, res.value);
|
||||
m_Debugger.TypedResourceStore(resClass, slot, fmt, dataOffset, res.value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10373,18 +10088,63 @@ const FunctionInfo *Debugger::GetFunctionInfo(const DXIL::Function *function) co
|
||||
return &m_FunctionInfos.at(function);
|
||||
}
|
||||
|
||||
// Must be called from the replay manager thread (the debugger thread)
|
||||
const UAVData &Debugger::GetUAVData(const BindingSlot &slot) const
|
||||
// Called from any thread
|
||||
// Resource must be cached
|
||||
ShaderValue Debugger::TypedResourceLoad(DXIL::ResourceClass resClass, const BindingSlot &slot,
|
||||
const DXILDebug::ViewFmt &fmt, uint64_t dataOffset)
|
||||
{
|
||||
CHECK_DEBUGGER_THREAD();
|
||||
return m_ApiWrapper->GetUAVData(slot);
|
||||
if(resClass == DXIL::ResourceClass::UAV)
|
||||
{
|
||||
DXIL_DEBUG_RDCASSERT(m_ApiWrapper->IsUAVCached(slot));
|
||||
return m_ApiWrapper->TypedUAVLoad(slot, fmt, dataOffset);
|
||||
}
|
||||
else if(resClass == DXIL::ResourceClass::SRV)
|
||||
{
|
||||
DXIL_DEBUG_RDCASSERT(m_ApiWrapper->IsSRVCached(slot));
|
||||
return m_ApiWrapper->TypedSRVLoad(slot, fmt, dataOffset);
|
||||
}
|
||||
RDCERR("Unexpected resource class %s", ToStr(resClass).c_str());
|
||||
return ShaderValue();
|
||||
}
|
||||
|
||||
// Must be called from the replay manager thread (the debugger thread)
|
||||
const SRVData &Debugger::GetSRVData(const BindingSlot &slot) const
|
||||
// Called from any thread
|
||||
// Resource must be cached
|
||||
bool Debugger::TypedResourceStore(DXIL::ResourceClass resClass, const BindingSlot &slot,
|
||||
const DXILDebug::ViewFmt &fmt, uint64_t dataOffset,
|
||||
ShaderValue &value)
|
||||
{
|
||||
CHECK_DEBUGGER_THREAD();
|
||||
return m_ApiWrapper->GetSRVData(slot);
|
||||
if(resClass == DXIL::ResourceClass::UAV)
|
||||
{
|
||||
DXIL_DEBUG_RDCASSERT(m_ApiWrapper->IsUAVCached(slot));
|
||||
return m_ApiWrapper->TypedUAVStore(slot, fmt, dataOffset, value);
|
||||
}
|
||||
else if(resClass == DXIL::ResourceClass::SRV)
|
||||
{
|
||||
DXIL_DEBUG_RDCASSERT(m_ApiWrapper->IsSRVCached(slot));
|
||||
return m_ApiWrapper->TypedSRVStore(slot, fmt, dataOffset, value);
|
||||
}
|
||||
RDCERR("Unexpected resource class %s", ToStr(resClass).c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
DeviceOpResult Debugger::GetUAV(const BindingSlot &slot, UAVInfo &uavInfo) const
|
||||
{
|
||||
if(!IsDeviceThread() && !m_ApiWrapper->IsUAVCached(slot))
|
||||
return DeviceOpResult::NeedsDevice;
|
||||
|
||||
uavInfo = m_ApiWrapper->GetUAV(slot);
|
||||
return DeviceOpResult::Succeeded;
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
DeviceOpResult Debugger::GetSRV(const BindingSlot &slot, SRVInfo &srvInfo) const
|
||||
{
|
||||
if(!IsDeviceThread() && !m_ApiWrapper->IsSRVCached(slot))
|
||||
return DeviceOpResult::NeedsDevice;
|
||||
|
||||
srvInfo = m_ApiWrapper->GetSRV(slot);
|
||||
return DeviceOpResult::Succeeded;
|
||||
}
|
||||
|
||||
// Called from any thread
|
||||
@@ -10392,10 +10152,9 @@ DeviceOpResult Debugger::GetResourceInfo(DXIL::ResourceClass resClass,
|
||||
const DXDebug::BindingSlot &slot, uint32_t mipLevel,
|
||||
ShaderVariable &result) const
|
||||
{
|
||||
if(!IsDeviceThread())
|
||||
if(!IsDeviceThread() && !m_ApiWrapper->IsResourceInfoCached(slot, mipLevel))
|
||||
return DeviceOpResult::NeedsDevice;
|
||||
|
||||
CHECK_DEBUGGER_THREAD();
|
||||
result = m_ApiWrapper->GetResourceInfo(resClass, slot, mipLevel);
|
||||
return DeviceOpResult::Succeeded;
|
||||
}
|
||||
@@ -10404,10 +10163,9 @@ DeviceOpResult Debugger::GetResourceInfo(DXIL::ResourceClass resClass,
|
||||
DeviceOpResult Debugger::GetSampleInfo(DXIL::ResourceClass resClass, const DXDebug::BindingSlot &slot,
|
||||
const char *opString, ShaderVariable &result) const
|
||||
{
|
||||
if(!IsDeviceThread())
|
||||
if(!IsDeviceThread() && !m_ApiWrapper->IsSampleInfoCached(slot))
|
||||
return DeviceOpResult::NeedsDevice;
|
||||
|
||||
CHECK_DEBUGGER_THREAD();
|
||||
result = m_ApiWrapper->GetSampleInfo(resClass, slot, opString);
|
||||
return DeviceOpResult::Succeeded;
|
||||
}
|
||||
@@ -10415,10 +10173,9 @@ DeviceOpResult Debugger::GetSampleInfo(DXIL::ResourceClass resClass, const DXDeb
|
||||
// Called from any thread
|
||||
DeviceOpResult Debugger::GetRenderTargetSampleInfo(const char *opString, ShaderVariable &result) const
|
||||
{
|
||||
if(!IsDeviceThread())
|
||||
if(!IsDeviceThread() && !m_ApiWrapper->IsRenderTargetSampleInfoCached())
|
||||
return DeviceOpResult::NeedsDevice;
|
||||
|
||||
CHECK_DEBUGGER_THREAD();
|
||||
result = m_ApiWrapper->GetRenderTargetSampleInfo(opString);
|
||||
return DeviceOpResult::Succeeded;
|
||||
}
|
||||
@@ -10427,10 +10184,9 @@ DeviceOpResult Debugger::GetRenderTargetSampleInfo(const char *opString, ShaderV
|
||||
DeviceOpResult Debugger::GetResourceReferenceInfo(const DXDebug::BindingSlot &slot,
|
||||
ResourceReferenceInfo &result) const
|
||||
{
|
||||
if(!IsDeviceThread())
|
||||
if(!IsDeviceThread() && !m_ApiWrapper->IsResourceReferenceInfoCached(slot))
|
||||
return DeviceOpResult::NeedsDevice;
|
||||
|
||||
CHECK_DEBUGGER_THREAD();
|
||||
result = m_ApiWrapper->GetResourceReferenceInfo(slot);
|
||||
return DeviceOpResult::Succeeded;
|
||||
}
|
||||
@@ -10439,10 +10195,9 @@ DeviceOpResult Debugger::GetResourceReferenceInfo(const DXDebug::BindingSlot &sl
|
||||
DeviceOpResult Debugger::GetShaderDirectAccess(DescriptorType type, const DXDebug::BindingSlot &slot,
|
||||
ShaderDirectAccess &result) const
|
||||
{
|
||||
if(!IsDeviceThread())
|
||||
if(!IsDeviceThread() && !m_ApiWrapper->IsShaderDirectAccessCached(slot))
|
||||
return DeviceOpResult::NeedsDevice;
|
||||
|
||||
CHECK_DEBUGGER_THREAD();
|
||||
result = m_ApiWrapper->GetShaderDirectAccess(type, slot);
|
||||
return DeviceOpResult::Succeeded;
|
||||
}
|
||||
|
||||
@@ -228,21 +228,22 @@ struct ResourceInfo
|
||||
{
|
||||
ResourceInfo() : firstElement(0), numElements(0), isByteBuffer(false), isRootDescriptor(false) {}
|
||||
|
||||
size_t dataSize = 0;
|
||||
uint32_t firstElement;
|
||||
uint32_t numElements;
|
||||
|
||||
bool hasData = false;
|
||||
bool isByteBuffer;
|
||||
bool isRootDescriptor;
|
||||
// Buffer stride is stored in format.stride
|
||||
ViewFmt format;
|
||||
};
|
||||
|
||||
struct UAVData
|
||||
struct UAVInfo
|
||||
{
|
||||
UAVData() = default;
|
||||
UAVInfo() = default;
|
||||
|
||||
ResourceInfo resInfo;
|
||||
bytebuf data;
|
||||
|
||||
uint32_t rowPitch = 0;
|
||||
uint32_t depthPitch = 0;
|
||||
@@ -250,12 +251,11 @@ struct UAVData
|
||||
bool tex = false;
|
||||
};
|
||||
|
||||
struct SRVData
|
||||
struct SRVInfo
|
||||
{
|
||||
SRVData() = default;
|
||||
SRVInfo() = default;
|
||||
|
||||
ResourceInfo resInfo;
|
||||
bytebuf data;
|
||||
};
|
||||
|
||||
enum class ThreadProperty : uint32_t
|
||||
@@ -294,9 +294,18 @@ class DebugAPIWrapper
|
||||
public:
|
||||
virtual ~DebugAPIWrapper() {}
|
||||
|
||||
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,
|
||||
uint64_t dataOffset) const = 0;
|
||||
virtual bool TypedUAVStore(const BindingSlot &slot, const DXILDebug::ViewFmt &fmt,
|
||||
uint64_t dataOffset, const ShaderValue &value) = 0;
|
||||
virtual bool TypedSRVStore(const BindingSlot &slot, const DXILDebug::ViewFmt &fmt,
|
||||
uint64_t dataOffset, const ShaderValue &value) = 0;
|
||||
|
||||
// These will fetch the data on demand.
|
||||
virtual const UAVData &GetUAVData(const BindingSlot &slot) = 0;
|
||||
virtual const SRVData &GetSRVData(const BindingSlot &slot) = 0;
|
||||
virtual UAVInfo GetUAV(const BindingSlot &slot) = 0;
|
||||
virtual SRVInfo GetSRV(const BindingSlot &slot) = 0;
|
||||
|
||||
virtual bool CalculateMathIntrinsic(DXIL::DXOp dxOp, const ShaderVariable &input,
|
||||
ShaderVariable &output) = 0;
|
||||
@@ -307,17 +316,21 @@ public:
|
||||
float lodValue, float compareValue, GatherChannel gatherChannel,
|
||||
uint32_t instructionIdx, ShaderVariable &output) = 0;
|
||||
virtual ShaderVariable GetResourceInfo(DXIL::ResourceClass resClass,
|
||||
const DXDebug::BindingSlot &slot,
|
||||
uint32_t mipLevel) const = 0;
|
||||
virtual ShaderVariable GetSampleInfo(DXIL::ResourceClass resClass, const DXDebug::BindingSlot &slot,
|
||||
const char *opString) const = 0;
|
||||
virtual ShaderVariable GetRenderTargetSampleInfo(const char *opString) const = 0;
|
||||
virtual ResourceReferenceInfo GetResourceReferenceInfo(const DXDebug::BindingSlot &slot) const = 0;
|
||||
const DXDebug::BindingSlot &slot, uint32_t mipLevel) = 0;
|
||||
virtual ShaderVariable GetSampleInfo(DXIL::ResourceClass resClass,
|
||||
const DXDebug::BindingSlot &slot, const char *opString) = 0;
|
||||
virtual ShaderVariable GetRenderTargetSampleInfo(const char *opString) = 0;
|
||||
virtual ResourceReferenceInfo GetResourceReferenceInfo(const DXDebug::BindingSlot &slot) = 0;
|
||||
virtual ShaderDirectAccess GetShaderDirectAccess(DescriptorType type,
|
||||
const DXDebug::BindingSlot &slot) const = 0;
|
||||
const DXDebug::BindingSlot &slot) = 0;
|
||||
|
||||
virtual bool IsSRVCached(const DXDebug::BindingSlot &slot) = 0;
|
||||
virtual bool IsUAVCached(const DXDebug::BindingSlot &slot) = 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;
|
||||
virtual bool IsSampleInfoCached(const DXDebug::BindingSlot &slot) = 0;
|
||||
virtual bool IsRenderTargetSampleInfoCached() = 0;
|
||||
virtual bool IsResourceReferenceInfoCached(const DXDebug::BindingSlot &slot) = 0;
|
||||
virtual bool IsShaderDirectAccessCached(const DXDebug::BindingSlot &slot) = 0;
|
||||
|
||||
virtual const ShaderVariable &GetInputPlaceholder() const = 0;
|
||||
virtual const rdcarray<DXILDebug::ThreadProperties> &GetWorkgroupProperties() const = 0;
|
||||
@@ -887,8 +900,13 @@ public:
|
||||
static rdcstr GetResourceReferenceName(const DXIL::Program *program, DXIL::ResourceClass resClass,
|
||||
const BindingSlot &slot);
|
||||
|
||||
const UAVData &GetUAVData(const BindingSlot &slot) const;
|
||||
const SRVData &GetSRVData(const BindingSlot &slot) const;
|
||||
ShaderValue TypedResourceLoad(DXIL::ResourceClass resClass, const BindingSlot &slot,
|
||||
const DXILDebug::ViewFmt &fmt, uint64_t dataOffset);
|
||||
bool TypedResourceStore(DXIL::ResourceClass resClass, const BindingSlot &slot,
|
||||
const DXILDebug::ViewFmt &fmt, uint64_t dataOffset, ShaderValue &value);
|
||||
|
||||
DeviceOpResult GetUAV(const BindingSlot &slot, UAVInfo &uavInfo) const;
|
||||
DeviceOpResult GetSRV(const BindingSlot &slot, SRVInfo &srvInfo) const;
|
||||
|
||||
DeviceOpResult GetResourceInfo(DXIL::ResourceClass resClass, const DXDebug::BindingSlot &slot,
|
||||
uint32_t mipLevel, ShaderVariable &result) const;
|
||||
|
||||
Reference in New Issue
Block a user