mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 17:10:47 +00:00
Refactor D3D12 ExecuteIndirect handling to patch arguments on GPU
This commit is contained in:
@@ -133,3 +133,113 @@ uint4 RENDERDOC_DiscardIntPS(float4 pos : SV_Position, out float depth : SV_Dept
|
||||
|
||||
return val.xxxx;
|
||||
}
|
||||
|
||||
cbuffer executepatchdata : register(b0)
|
||||
{
|
||||
uint argCount;
|
||||
uint bufCount;
|
||||
uint argStride;
|
||||
uint4 argOffsets[32];
|
||||
};
|
||||
|
||||
cbuffer countbuffer : register(b1)
|
||||
{
|
||||
uint numExecutes;
|
||||
};
|
||||
|
||||
cbuffer countbuffer : register(b2)
|
||||
{
|
||||
uint maxNumExecutes;
|
||||
};
|
||||
|
||||
struct buffermapping
|
||||
{
|
||||
// {.x = LSB, .y = MSB} to match uint64 order
|
||||
uint2 origBase;
|
||||
uint2 origEnd;
|
||||
uint2 newBase;
|
||||
uint2 pad;
|
||||
};
|
||||
|
||||
StructuredBuffer<buffermapping> buffers : register(t0);
|
||||
RWByteAddressBuffer arguments : register(u0);
|
||||
|
||||
bool uint64LessThan(uint2 a, uint2 b)
|
||||
{
|
||||
// either MSB is less, or MSB is equal and LSB is less-equal
|
||||
return a.y < b.y || (a.y == b.y && a.x < b.x);
|
||||
}
|
||||
|
||||
bool uint64LessEqual(uint2 a, uint2 b)
|
||||
{
|
||||
return uint64LessThan(a, b) || (a.y == b.y && a.x == b.x);
|
||||
}
|
||||
|
||||
uint2 uint64Add(uint2 a, uint2 b)
|
||||
{
|
||||
uint msb = 0, lsb = 0;
|
||||
if(b.x > 0 && a.x > 0xffffffff - b.x)
|
||||
{
|
||||
uint x = max(a.x, b.x) - 0x80000000;
|
||||
uint y = min(a.x, b.x);
|
||||
|
||||
uint sum = x + y;
|
||||
|
||||
msb = a.y + b.y + 1;
|
||||
lsb = sum - 0x80000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
msb = a.y + b.y;
|
||||
lsb = a.x + b.x;
|
||||
}
|
||||
|
||||
return uint2(lsb, msb);
|
||||
}
|
||||
|
||||
uint2 uint64Sub(uint2 a, uint2 b)
|
||||
{
|
||||
uint msb = 0, lsb = 0;
|
||||
if(a.x < b.x)
|
||||
{
|
||||
uint diff = b.x - a.x;
|
||||
|
||||
msb = a.y - b.y - 1;
|
||||
lsb = 0xffffffff - (diff - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
msb = a.y - b.y;
|
||||
lsb = a.x - b.x;
|
||||
}
|
||||
|
||||
return uint2(lsb, msb);
|
||||
}
|
||||
|
||||
uint2 PatchAddress(uint2 addr)
|
||||
{
|
||||
for(uint i = 0; i < bufCount; i++)
|
||||
{
|
||||
buffermapping b = buffers[i];
|
||||
|
||||
if(uint64LessEqual(b.origBase, addr) && uint64LessThan(addr, b.origEnd))
|
||||
{
|
||||
return uint64Add(b.newBase, uint64Sub(addr, b.origBase));
|
||||
}
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
[numthreads(128, 1, 1)] void RENDERDOC_ExecuteIndirectPatchCS(uint idx
|
||||
: SV_GroupIndex) {
|
||||
if(idx < argCount)
|
||||
{
|
||||
for(uint i = 0; i < min(numExecutes, maxNumExecutes); i++)
|
||||
{
|
||||
uint offs = argStride * i + argOffsets[idx / 4][idx % 4];
|
||||
|
||||
arguments.Store2(offs, PatchAddress(arguments.Load2(offs)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,17 +212,17 @@ public:
|
||||
WrappedID3D12Device *GetWrappedDevice() { return m_pDevice; }
|
||||
D3D12ResourceRecord *GetResourceRecord() { return m_ListRecord; }
|
||||
D3D12ResourceRecord *GetCreationRecord() { return m_CreationRecord; }
|
||||
ID3D12GraphicsCommandList *GetCrackedList();
|
||||
ID3D12GraphicsCommandList1 *GetCrackedList1();
|
||||
ID3D12GraphicsCommandList2 *GetCrackedList2();
|
||||
ID3D12GraphicsCommandList3 *GetCrackedList3();
|
||||
ID3D12GraphicsCommandList4 *GetCrackedList4();
|
||||
ID3D12GraphicsCommandList5 *GetCrackedList5();
|
||||
ID3D12GraphicsCommandList6 *GetCrackedList6();
|
||||
ID3D12GraphicsCommandList7 *GetCrackedList7();
|
||||
ID3D12GraphicsCommandList8 *GetCrackedList8();
|
||||
ID3D12GraphicsCommandList9 *GetCrackedList9();
|
||||
ID3D12GraphicsCommandListX *GetWrappedCrackedList();
|
||||
|
||||
void FinaliseExecuteIndirectEvents(BakedCmdListInfo &info, BakedCmdListInfo::ExecuteData &exec);
|
||||
void SaveExecuteIndirectParameters(ID3D12GraphicsCommandListX *list,
|
||||
ID3D12CommandSignature *pCommandSignature, UINT MaxCommandCount,
|
||||
ID3D12Resource *pArgumentBuffer, UINT64 ArgumentBufferOffset,
|
||||
ID3D12Resource *pCountBuffer, UINT64 CountBufferOffset);
|
||||
void ResetAndRecordExecuteIndirectStates(ID3D12GraphicsCommandListX *list, uint32_t baseEventID,
|
||||
uint32_t execCount,
|
||||
ID3D12CommandSignature *pCommandSignature,
|
||||
ID3D12Resource *pArgumentBuffer,
|
||||
UINT64 ArgumentBufferOffset, uint32_t argumentsReplayed);
|
||||
|
||||
void SetAMDMarkerInterface(IAmdExtD3DCommandListMarker *marker) { m_AMDMarkers = marker; }
|
||||
void SetCommandData(D3D12CommandData *cmd) { m_Cmd = cmd; }
|
||||
@@ -477,11 +477,6 @@ public:
|
||||
|
||||
IMPLEMENT_FUNCTION_SERIALISED(virtual void STDMETHODCALLTYPE, EndEvent, );
|
||||
|
||||
void ReserveExecuteIndirect(ID3D12GraphicsCommandList *list,
|
||||
WrappedID3D12CommandSignature *comSig, UINT maxCount);
|
||||
void PatchExecuteIndirect(BakedCmdListInfo &info, uint32_t executeIndex);
|
||||
void ReplayExecuteIndirect(ID3D12GraphicsCommandList *list);
|
||||
|
||||
IMPLEMENT_FUNCTION_SERIALISED(virtual void STDMETHODCALLTYPE, ExecuteIndirect,
|
||||
ID3D12CommandSignature *pCommandSignature, UINT MaxCommandCount,
|
||||
ID3D12Resource *pArgumentBuffer, UINT64 ArgumentBufferOffset,
|
||||
|
||||
@@ -79,9 +79,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_AtomicCopyBufferUINT(
|
||||
Unwrap1(pCommandList)
|
||||
->AtomicCopyBufferUINT(Unwrap(pDstBuffer), DstOffset, Unwrap(pSrcBuffer), SrcOffset,
|
||||
Dependencies, deps.data(), pDependentSubresourceRanges);
|
||||
GetCrackedList1()->AtomicCopyBufferUINT(Unwrap(pDstBuffer), DstOffset, Unwrap(pSrcBuffer),
|
||||
SrcOffset, Dependencies, deps.data(),
|
||||
pDependentSubresourceRanges);
|
||||
|
||||
{
|
||||
m_Cmd->AddEvent();
|
||||
@@ -195,9 +192,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_AtomicCopyBufferUINT64(
|
||||
Unwrap1(pCommandList)
|
||||
->AtomicCopyBufferUINT64(Unwrap(pDstBuffer), DstOffset, Unwrap(pSrcBuffer), SrcOffset,
|
||||
Dependencies, deps.data(), pDependentSubresourceRanges);
|
||||
GetCrackedList1()->AtomicCopyBufferUINT64(Unwrap(pDstBuffer), DstOffset, Unwrap(pSrcBuffer),
|
||||
SrcOffset, Dependencies, deps.data(),
|
||||
pDependentSubresourceRanges);
|
||||
|
||||
{
|
||||
m_Cmd->AddEvent();
|
||||
@@ -313,7 +307,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_OMSetDepthBounds(SerialiserType
|
||||
else
|
||||
{
|
||||
Unwrap1(pCommandList)->OMSetDepthBounds(Min, Max);
|
||||
GetCrackedList1()->OMSetDepthBounds(Min, Max);
|
||||
|
||||
stateUpdate = true;
|
||||
}
|
||||
@@ -403,7 +396,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetSamplePositions(
|
||||
else
|
||||
{
|
||||
Unwrap1(pCommandList)->SetSamplePositions(NumSamplesPerPixel, NumPixels, pSamplePositions);
|
||||
GetCrackedList1()->SetSamplePositions(NumSamplesPerPixel, NumPixels, pSamplePositions);
|
||||
|
||||
stateUpdate = true;
|
||||
}
|
||||
@@ -483,9 +475,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_ResolveSubresourceRegion(
|
||||
->ResolveSubresourceRegion(Unwrap(pDstResource), DstSubresource, DstX, DstY,
|
||||
Unwrap(pSrcResource), SrcSubresource, pSrcRect, Format,
|
||||
ResolveMode);
|
||||
GetCrackedList1()->ResolveSubresourceRegion(Unwrap(pDstResource), DstSubresource, DstX, DstY,
|
||||
Unwrap(pSrcResource), SrcSubresource, pSrcRect,
|
||||
Format, ResolveMode);
|
||||
|
||||
{
|
||||
m_Cmd->AddEvent();
|
||||
@@ -595,7 +584,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetViewInstanceMask(SerialiserT
|
||||
else
|
||||
{
|
||||
Unwrap1(pCommandList)->SetViewInstanceMask(Mask);
|
||||
GetCrackedList1()->SetViewInstanceMask(Mask);
|
||||
|
||||
stateUpdate = true;
|
||||
}
|
||||
|
||||
@@ -59,7 +59,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_WriteBufferImmediate(
|
||||
else
|
||||
{
|
||||
Unwrap2(pCommandList)->WriteBufferImmediate(Count, pParams, pModes);
|
||||
GetCrackedList2()->WriteBufferImmediate(Count, pParams, pModes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -349,12 +349,9 @@ bool WrappedID3D12GraphicsCommandList::Serialise_BeginRenderPass(
|
||||
// need to unwrap here, as FromPortableHandle unwraps too.
|
||||
Unwrap(pCommandList)
|
||||
->OMSetRenderTargets(NumRenderTargets, rtHandles, FALSE, dsvHandle.ptr ? &dsvHandle : NULL);
|
||||
GetCrackedList()->OMSetRenderTargets(NumRenderTargets, rtHandles, FALSE,
|
||||
dsvHandle.ptr ? &dsvHandle : NULL);
|
||||
|
||||
// Unwrap4(pCommandList)->BeginRenderPass(NumRenderTargets, pRenderTargets, pDepthStencil,
|
||||
// Flags);
|
||||
// GetCrackedList4()->BeginRenderPass(NumRenderTargets, pRenderTargets, pDepthStencil, Flags);
|
||||
|
||||
m_Cmd->AddEvent();
|
||||
|
||||
@@ -663,7 +660,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_EndRenderPass(SerialiserType &s
|
||||
else
|
||||
{
|
||||
// Unwrap4(pCommandList)->EndRenderPass();
|
||||
// GetCrackedList4()->EndRenderPass();
|
||||
|
||||
m_Cmd->AddEvent();
|
||||
|
||||
|
||||
@@ -86,7 +86,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_RSSetShadingRate(
|
||||
else
|
||||
{
|
||||
Unwrap5(pCommandList)->RSSetShadingRate(baseShadingRate, combiners);
|
||||
GetCrackedList5()->RSSetShadingRate(baseShadingRate, combiners);
|
||||
|
||||
stateUpdate = true;
|
||||
}
|
||||
@@ -181,7 +180,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_RSSetShadingRateImage(Serialise
|
||||
else
|
||||
{
|
||||
Unwrap5(pCommandList)->RSSetShadingRateImage(Unwrap(shadingRateImage));
|
||||
GetCrackedList5()->RSSetShadingRateImage(Unwrap(shadingRateImage));
|
||||
|
||||
stateUpdate = true;
|
||||
}
|
||||
|
||||
@@ -172,7 +172,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Barrier(SerialiserType &ser, UI
|
||||
if(!filteredUnwrapped.empty())
|
||||
{
|
||||
Unwrap7(pCommandList)->Barrier((UINT)filteredUnwrapped.size(), filteredUnwrapped.data());
|
||||
GetCrackedList7()->Barrier((UINT)filteredUnwrapped.size(), filteredUnwrapped.data());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_OMSetFrontAndBackStencilRef(Ser
|
||||
else
|
||||
{
|
||||
Unwrap8(pCommandList)->OMSetFrontAndBackStencilRef(FrontStencilRef, BackStencilRef);
|
||||
GetCrackedList8()->OMSetFrontAndBackStencilRef(FrontStencilRef, BackStencilRef);
|
||||
|
||||
stateUpdate = true;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_RSSetDepthBias(SerialiserType &
|
||||
else
|
||||
{
|
||||
Unwrap9(pCommandList)->RSSetDepthBias(DepthBias, DepthBiasClamp, SlopeScaledDepthBias);
|
||||
GetCrackedList9()->RSSetDepthBias(DepthBias, DepthBiasClamp, SlopeScaledDepthBias);
|
||||
|
||||
stateUpdate = true;
|
||||
}
|
||||
@@ -140,7 +139,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_IASetIndexBufferStripCutValue(
|
||||
else
|
||||
{
|
||||
Unwrap9(pCommandList)->IASetIndexBufferStripCutValue(IBStripCutValue);
|
||||
GetCrackedList9()->IASetIndexBufferStripCutValue(IBStripCutValue);
|
||||
|
||||
stateUpdate = true;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -487,46 +487,24 @@ bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(SerialiserType &se
|
||||
{
|
||||
ResourceId cmd = GetResourceManager()->GetOriginalID(GetResID(ppCommandLists[i]));
|
||||
|
||||
if(m_Cmd.m_BakedCmdListInfo[cmd].executeEvents.empty() ||
|
||||
m_Cmd.m_BakedCmdListInfo[cmd].executeEvents[0].patched)
|
||||
ID3D12CommandList *list = Unwrap(ppCommandLists[i]);
|
||||
real->ExecuteCommandLists(1, &list);
|
||||
if(D3D12_Debug_SingleSubmitFlushing())
|
||||
m_pDevice->GPUSync();
|
||||
|
||||
BakedCmdListInfo &info = m_Cmd.m_BakedCmdListInfo[cmd];
|
||||
|
||||
if(!info.executeEvents.empty())
|
||||
{
|
||||
ID3D12CommandList *list = Unwrap(ppCommandLists[i]);
|
||||
real->ExecuteCommandLists(1, &list);
|
||||
if(D3D12_Debug_SingleSubmitFlushing())
|
||||
m_pDevice->GPUSync();
|
||||
}
|
||||
else
|
||||
{
|
||||
BakedCmdListInfo &info = m_Cmd.m_BakedCmdListInfo[cmd];
|
||||
// ensure all GPU work has finished for readback of arguments
|
||||
m_pDevice->GPUSync();
|
||||
|
||||
// execute the first half of the cracked list
|
||||
ID3D12CommandList *list = Unwrap(info.crackedLists[0]);
|
||||
real->ExecuteCommandLists(1, &list);
|
||||
if(m_pDevice->HasFatalError())
|
||||
return false;
|
||||
|
||||
for(size_t c = 1; c < info.crackedLists.size(); c++)
|
||||
{
|
||||
// ensure all GPU work has finished
|
||||
m_pDevice->GPUSync();
|
||||
|
||||
if(m_pDevice->HasFatalError())
|
||||
return false;
|
||||
|
||||
// readback the patch buffer and perform patching
|
||||
m_ReplayList->PatchExecuteIndirect(info, uint32_t(c - 1));
|
||||
|
||||
if(m_pDevice->HasFatalError())
|
||||
return false;
|
||||
|
||||
// execute next list with this indirect.
|
||||
list = Unwrap(info.crackedLists[c]);
|
||||
real->ExecuteCommandLists(1, &list);
|
||||
|
||||
if(m_pDevice->HasFatalError())
|
||||
return false;
|
||||
}
|
||||
|
||||
if(D3D12_Debug_SingleSubmitFlushing())
|
||||
m_pDevice->GPUSync();
|
||||
// readback the patch buffer and update recorded events
|
||||
for(size_t c = 0; c < info.executeEvents.size(); c++)
|
||||
m_ReplayList->FinaliseExecuteIndirectEvents(info, info.executeEvents[c]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -535,9 +535,6 @@ WrappedID3D12CommandQueue::~WrappedID3D12CommandQueue()
|
||||
|
||||
SAFE_RELEASE(m_pDownlevel);
|
||||
|
||||
for(size_t i = 0; i < m_Cmd.m_IndirectBuffers.size(); i++)
|
||||
SAFE_RELEASE(m_Cmd.m_IndirectBuffers[i]);
|
||||
|
||||
SAFE_RELEASE(m_WrappedCompat.m_pReal);
|
||||
SAFE_RELEASE(m_WrappedDebug.m_pReal);
|
||||
SAFE_RELEASE(m_WrappedDebug.m_pReal1);
|
||||
@@ -1115,6 +1112,13 @@ RDResult WrappedID3D12CommandQueue::ReplayLog(CaptureState readType, uint32_t st
|
||||
m_Cmd.m_LastEventID = ~0U;
|
||||
}
|
||||
|
||||
if(IsReplayMode(m_State))
|
||||
{
|
||||
for(size_t i = 0; i < m_Cmd.m_IndirectBuffers.size(); i++)
|
||||
SAFE_RELEASE(m_Cmd.m_IndirectBuffers[i]);
|
||||
m_Cmd.m_IndirectBuffers.clear();
|
||||
}
|
||||
|
||||
uint64_t startOffset = ser.GetReader()->GetOffset();
|
||||
|
||||
for(;;)
|
||||
@@ -1631,12 +1635,7 @@ void BakedCmdListInfo::ShiftForRemoved(uint32_t shiftActionID, uint32_t shiftEID
|
||||
for(size_t i = 0; i < executeEvents.size(); i++)
|
||||
{
|
||||
if(executeEvents[i].baseEvent >= lastEID)
|
||||
{
|
||||
executeEvents[i].baseEvent -= shiftEID;
|
||||
|
||||
if(executeEvents[i].lastEvent > 0)
|
||||
executeEvents[i].lastEvent -= shiftEID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1646,6 +1645,17 @@ void BakedCmdListInfo::ShiftForRemoved(uint32_t shiftActionID, uint32_t shiftEID
|
||||
}
|
||||
}
|
||||
|
||||
SubresourceStateVector BakedCmdListInfo::GetState(WrappedID3D12Device *device, ResourceId id)
|
||||
{
|
||||
std::map<ResourceId, SubresourceStateVector> data;
|
||||
|
||||
data[id] = device->GetSubresourceStates(id);
|
||||
|
||||
device->GetResourceManager()->ApplyBarriers(barriers, data);
|
||||
|
||||
return data[id];
|
||||
}
|
||||
|
||||
D3D12CommandData::D3D12CommandData()
|
||||
{
|
||||
m_CurChunkOffset = 0;
|
||||
@@ -1686,22 +1696,20 @@ void D3D12CommandData::GetIndirectBuffer(size_t size, ID3D12Resource **buf, uint
|
||||
indirectDesc.SampleDesc.Quality = 0;
|
||||
indirectDesc.Width = RDCMAX(AlignUp((uint64_t)size, 64ULL), m_IndirectSize);
|
||||
|
||||
// create a custom heap that sits in CPU memory and is mappable, but we can
|
||||
// use for indirect args (unlike upload and readback).
|
||||
D3D12_HEAP_PROPERTIES heapProps;
|
||||
heapProps.Type = D3D12_HEAP_TYPE_CUSTOM;
|
||||
heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE;
|
||||
heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_L0;
|
||||
heapProps.Type = D3D12_HEAP_TYPE_READBACK;
|
||||
heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
heapProps.CreationNodeMask = 1;
|
||||
heapProps.VisibleNodeMask = 1;
|
||||
|
||||
ID3D12Resource *argbuf = NULL;
|
||||
|
||||
HRESULT hr = m_pDevice->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &indirectDesc,
|
||||
D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT, NULL,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST, NULL,
|
||||
__uuidof(ID3D12Resource), (void **)&argbuf);
|
||||
|
||||
SetObjName(argbuf, StringFormat::Fmt("Indirect Arg Buf (%llu bytes)", (uint64_t)size));
|
||||
SetObjName(argbuf, StringFormat::Fmt("Indirect Readback Buf (%llu bytes)", (uint64_t)size));
|
||||
|
||||
if(FAILED(hr))
|
||||
RDCERR("Failed to create indirect buffer, HRESULT: %s", ToStr(hr).c_str());
|
||||
|
||||
@@ -178,21 +178,19 @@ struct BakedCmdListInfo
|
||||
~BakedCmdListInfo() { SAFE_DELETE(action); }
|
||||
void ShiftForRemoved(uint32_t shiftActionID, uint32_t shiftEID, size_t idx);
|
||||
|
||||
SubresourceStateVector GetState(WrappedID3D12Device *device, ResourceId id);
|
||||
|
||||
struct ExecuteData
|
||||
{
|
||||
uint32_t baseEvent = 0;
|
||||
uint32_t lastEvent = 0;
|
||||
bool patched = false;
|
||||
ID3D12Resource *argBuf = NULL;
|
||||
ID3D12Resource *countBuf = NULL;
|
||||
uint64_t argOffs = 0;
|
||||
uint64_t countOffs = 0;
|
||||
WrappedID3D12CommandSignature *sig = NULL;
|
||||
UINT maxCount = 0;
|
||||
UINT realCount = 0;
|
||||
};
|
||||
|
||||
rdcarray<ID3D12GraphicsCommandListX *> crackedLists;
|
||||
rdcarray<ExecuteData> executeEvents;
|
||||
|
||||
rdcarray<APIEvent> curEvents;
|
||||
@@ -237,8 +235,6 @@ struct D3D12CommandData
|
||||
|
||||
RDResult m_FailedReplayResult = ResultCode::APIReplayFailed;
|
||||
|
||||
std::map<ResourceId, ID3D12CommandAllocator *> m_CrackedAllocators;
|
||||
|
||||
rdcarray<ID3D12Resource *> m_IndirectBuffers;
|
||||
static const uint64_t m_IndirectSize = 4 * 1024 * 1024;
|
||||
uint64_t m_IndirectOffset;
|
||||
|
||||
@@ -457,8 +457,8 @@ DECLARE_REFLECTION_STRUCT(D3D12RootSignature);
|
||||
struct D3D12CommandSignature
|
||||
{
|
||||
bool graphics = true;
|
||||
UINT numActions = 0;
|
||||
UINT ByteStride = 0;
|
||||
UINT PackedByteSize = 0;
|
||||
rdcarray<D3D12_INDIRECT_ARGUMENT_DESC> arguments;
|
||||
};
|
||||
|
||||
|
||||
@@ -53,6 +53,32 @@ inline static D3D12_ROOT_PARAMETER1 cbvParam(D3D12_SHADER_VISIBILITY vis, UINT s
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline static D3D12_ROOT_PARAMETER1 srvParam(D3D12_SHADER_VISIBILITY vis, UINT space, UINT reg)
|
||||
{
|
||||
D3D12_ROOT_PARAMETER1 ret;
|
||||
|
||||
ret.ShaderVisibility = vis;
|
||||
ret.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;
|
||||
ret.Descriptor.RegisterSpace = space;
|
||||
ret.Descriptor.ShaderRegister = reg;
|
||||
ret.Descriptor.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline static D3D12_ROOT_PARAMETER1 uavParam(D3D12_SHADER_VISIBILITY vis, UINT space, UINT reg)
|
||||
{
|
||||
D3D12_ROOT_PARAMETER1 ret;
|
||||
|
||||
ret.ShaderVisibility = vis;
|
||||
ret.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;
|
||||
ret.Descriptor.RegisterSpace = space;
|
||||
ret.Descriptor.ShaderRegister = reg;
|
||||
ret.Descriptor.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline static D3D12_ROOT_PARAMETER1 constParam(D3D12_SHADER_VISIBILITY vis, UINT space, UINT reg,
|
||||
UINT num)
|
||||
{
|
||||
@@ -528,11 +554,11 @@ bool D3D12DebugManager::CreateShaderDebugResources()
|
||||
range.OffsetInDescriptorsFromTableStart = 0;
|
||||
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
||||
|
||||
D3D12RootSignatureParameter srvParam;
|
||||
srvParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
srvParam.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
srvParam.ranges.push_back(range);
|
||||
rootSig.Parameters.push_back(srvParam);
|
||||
D3D12RootSignatureParameter srv;
|
||||
srv.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
srv.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
srv.ranges.push_back(range);
|
||||
rootSig.Parameters.push_back(srv);
|
||||
|
||||
range.NumDescriptors = 2;
|
||||
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
|
||||
@@ -861,6 +887,132 @@ void D3D12DebugManager::ResetDebugAlloc()
|
||||
m_DebugAlloc->Reset();
|
||||
}
|
||||
|
||||
rdcpair<ID3D12Resource *, UINT64> D3D12DebugManager::PatchExecuteIndirect(
|
||||
ID3D12GraphicsCommandListX *cmd, const D3D12RenderState &state, ID3D12CommandSignature *comSig,
|
||||
ID3D12Resource *argBuf, UINT64 argBufOffset, D3D12_GPU_VIRTUAL_ADDRESS countBufAddr,
|
||||
UINT maxCount)
|
||||
{
|
||||
rdcarray<uint32_t> argOffsets;
|
||||
|
||||
WrappedID3D12CommandSignature *wrappedComSig = (WrappedID3D12CommandSignature *)comSig;
|
||||
uint32_t offset = 0;
|
||||
for(const D3D12_INDIRECT_ARGUMENT_DESC &arg : wrappedComSig->sig.arguments)
|
||||
{
|
||||
switch(arg.Type)
|
||||
{
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW:
|
||||
{
|
||||
offset += sizeof(D3D12_DRAW_ARGUMENTS);
|
||||
break;
|
||||
}
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED:
|
||||
{
|
||||
offset += sizeof(D3D12_DRAW_INDEXED_ARGUMENTS);
|
||||
break;
|
||||
}
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH:
|
||||
{
|
||||
offset += sizeof(D3D12_DISPATCH_ARGUMENTS);
|
||||
break;
|
||||
}
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT:
|
||||
{
|
||||
offset += sizeof(uint32_t) * arg.Constant.Num32BitValuesToSet;
|
||||
break;
|
||||
}
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW:
|
||||
{
|
||||
argOffsets.push_back(offset);
|
||||
offset += sizeof(D3D12_VERTEX_BUFFER_VIEW);
|
||||
|
||||
break;
|
||||
}
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW:
|
||||
{
|
||||
argOffsets.push_back(offset);
|
||||
offset += sizeof(D3D12_INDEX_BUFFER_VIEW);
|
||||
break;
|
||||
}
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW:
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_SHADER_RESOURCE_VIEW:
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_UNORDERED_ACCESS_VIEW:
|
||||
{
|
||||
argOffsets.push_back(offset);
|
||||
offset += sizeof(D3D12_GPU_VIRTUAL_ADDRESS);
|
||||
break;
|
||||
}
|
||||
default: RDCERR("Unexpected argument type! %d", arg.Type); break;
|
||||
}
|
||||
}
|
||||
|
||||
// early out if the command signature doesn't reference anything with addresses
|
||||
if(argOffsets.empty())
|
||||
return {argBuf, argBufOffset};
|
||||
|
||||
// only handle patching 128 address based arguments...
|
||||
RDCASSERT(argOffsets.size() <= 128);
|
||||
|
||||
D3D12MarkerRegion marker(cmd, "Patch execute indirect");
|
||||
|
||||
argOffsets.insert(0, (uint32_t)argOffsets.size());
|
||||
argOffsets.insert(1, m_EIPatchBufferCount);
|
||||
argOffsets.insert(2, wrappedComSig->sig.ByteStride);
|
||||
argOffsets.resize(128 + 3);
|
||||
// argOffsets is now the executepatchdata cbuffer
|
||||
|
||||
const UINT64 argDataSize =
|
||||
wrappedComSig->sig.ByteStride * (maxCount - 1) + wrappedComSig->sig.PackedByteSize;
|
||||
|
||||
if(m_EIPatchScratchOffset + argDataSize > m_EIPatchScratchBuffer->GetDesc().Width)
|
||||
m_EIPatchScratchOffset = 0;
|
||||
|
||||
RDCASSERT(m_EIPatchScratchOffset + argDataSize < m_EIPatchScratchBuffer->GetDesc().Width,
|
||||
wrappedComSig->sig.ByteStride, wrappedComSig->sig.PackedByteSize, maxCount);
|
||||
|
||||
rdcpair<ID3D12Resource *, UINT64> ret = {m_EIPatchScratchBuffer, m_EIPatchScratchOffset};
|
||||
|
||||
D3D12_RESOURCE_BARRIER b = {};
|
||||
b.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
b.Transition.pResource = m_EIPatchScratchBuffer;
|
||||
b.Transition.StateBefore = D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT;
|
||||
b.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
|
||||
cmd->ResourceBarrier(1, &b);
|
||||
|
||||
cmd->CopyBufferRegion(m_EIPatchScratchBuffer, m_EIPatchScratchOffset, argBuf, argBufOffset,
|
||||
argDataSize);
|
||||
|
||||
b.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
b.Transition.StateAfter = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
|
||||
cmd->ResourceBarrier(1, &b);
|
||||
|
||||
cmd->SetPipelineState(m_EIPatchPso);
|
||||
cmd->SetComputeRootSignature(m_EIPatchRootSig);
|
||||
cmd->SetComputeRootConstantBufferView(0, UploadConstants(argOffsets.data(), argOffsets.byteSize()));
|
||||
if(countBufAddr == 0)
|
||||
cmd->SetComputeRootConstantBufferView(1, UploadConstants(&maxCount, sizeof(uint32_t)));
|
||||
else
|
||||
cmd->SetComputeRootConstantBufferView(1, countBufAddr);
|
||||
cmd->SetComputeRoot32BitConstant(2, maxCount, 0);
|
||||
cmd->SetComputeRootShaderResourceView(3, m_EIPatchBufferData->GetGPUVirtualAddress());
|
||||
cmd->SetComputeRootUnorderedAccessView(4, ret.first->GetGPUVirtualAddress() + ret.second);
|
||||
cmd->Dispatch(1, 1, 1);
|
||||
|
||||
b.Transition.StateBefore = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
|
||||
b.Transition.StateAfter = D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT;
|
||||
cmd->ResourceBarrier(1, &b);
|
||||
|
||||
b.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
|
||||
b.UAV.pResource = m_EIPatchScratchBuffer;
|
||||
cmd->ResourceBarrier(1, &b);
|
||||
|
||||
state.ApplyState(m_pDevice, cmd);
|
||||
|
||||
m_EIPatchScratchOffset += wrappedComSig->sig.ByteStride * maxCount;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void D3D12DebugManager::FillWithDiscardPattern(ID3D12GraphicsCommandListX *cmd,
|
||||
const D3D12RenderState &state, DiscardType type,
|
||||
ID3D12Resource *res,
|
||||
@@ -1523,6 +1675,131 @@ D3D12_CPU_DESCRIPTOR_HANDLE D3D12DebugManager::GetUAVClearHandle(CBVUAVSRVSlot s
|
||||
return ret;
|
||||
}
|
||||
|
||||
void D3D12DebugManager::PrepareExecuteIndirectPatching(const GPUAddressRangeTracker &origAddresses)
|
||||
{
|
||||
D3D12ShaderCache *shaderCache = m_pDevice->GetShaderCache();
|
||||
|
||||
shaderCache->SetCaching(true);
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
{
|
||||
ID3DBlob *root = shaderCache->MakeRootSig({
|
||||
cbvParam(D3D12_SHADER_VISIBILITY_ALL, 0, 0),
|
||||
cbvParam(D3D12_SHADER_VISIBILITY_ALL, 0, 1),
|
||||
constParam(D3D12_SHADER_VISIBILITY_ALL, 0, 2, 1),
|
||||
srvParam(D3D12_SHADER_VISIBILITY_ALL, 0, 0),
|
||||
uavParam(D3D12_SHADER_VISIBILITY_ALL, 0, 0),
|
||||
});
|
||||
|
||||
RDCASSERT(root);
|
||||
|
||||
hr = m_pDevice->CreateRootSignature(0, root->GetBufferPointer(), root->GetBufferSize(),
|
||||
__uuidof(ID3D12RootSignature), (void **)&m_EIPatchRootSig);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Couldn't create execute indirect patching RootSig! HRESULT: %s", ToStr(hr).c_str());
|
||||
}
|
||||
|
||||
SAFE_RELEASE(root);
|
||||
}
|
||||
|
||||
{
|
||||
rdcstr mischlsl = GetEmbeddedResource(misc_hlsl);
|
||||
|
||||
ID3DBlob *eiPatchCS;
|
||||
|
||||
shaderCache->GetShaderBlob(mischlsl.c_str(), "RENDERDOC_ExecuteIndirectPatchCS",
|
||||
D3DCOMPILE_WARNINGS_ARE_ERRORS, {}, "cs_5_0", &eiPatchCS);
|
||||
|
||||
RDCASSERT(eiPatchCS);
|
||||
|
||||
D3D12_COMPUTE_PIPELINE_STATE_DESC compPipeDesc = {};
|
||||
compPipeDesc.pRootSignature = m_EIPatchRootSig;
|
||||
compPipeDesc.CS.BytecodeLength = eiPatchCS->GetBufferSize();
|
||||
compPipeDesc.CS.pShaderBytecode = eiPatchCS->GetBufferPointer();
|
||||
|
||||
hr = m_pDevice->CreateComputePipelineState(&compPipeDesc, __uuidof(ID3D12PipelineState),
|
||||
(void **)&m_EIPatchPso);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Couldn't create m_MeshPickPipe! HRESULT: %s", ToStr(hr).c_str());
|
||||
}
|
||||
|
||||
SAFE_RELEASE(eiPatchCS);
|
||||
}
|
||||
|
||||
shaderCache->SetCaching(false);
|
||||
|
||||
struct buffermapping
|
||||
{
|
||||
uint64_t origBase;
|
||||
uint64_t origEnd;
|
||||
uint64_t newBase;
|
||||
uint64_t pad;
|
||||
};
|
||||
rdcarray<buffermapping> buffers;
|
||||
|
||||
for(const GPUAddressRange &addr : origAddresses.addresses)
|
||||
{
|
||||
buffermapping b = {};
|
||||
b.origBase = addr.start;
|
||||
b.origEnd = addr.end;
|
||||
b.newBase =
|
||||
m_pDevice->GetResourceManager()->GetLiveAs<ID3D12Resource>(addr.id)->GetGPUVirtualAddress();
|
||||
buffers.push_back(b);
|
||||
}
|
||||
|
||||
m_EIPatchBufferCount = (uint32_t)buffers.size();
|
||||
|
||||
if(!buffers.empty())
|
||||
{
|
||||
m_EIPatchBufferData = MakeCBuffer(buffers.byteSize());
|
||||
FillBuffer(m_EIPatchBufferData, 0, buffers.data(), buffers.byteSize());
|
||||
}
|
||||
|
||||
// estimated sizing for scratch buffers:
|
||||
// 65536 maxcount
|
||||
// 128 bytes command signature
|
||||
// = 8MB per EI
|
||||
// 64MB = ring for 8 such executes (or many more smaller)
|
||||
{
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
desc.Alignment = 0;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
||||
desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
desc.Height = 1;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
desc.MipLevels = 1;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Width = 64 * 1024 * 1024;
|
||||
|
||||
D3D12_HEAP_PROPERTIES heapProps;
|
||||
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
heapProps.CreationNodeMask = 1;
|
||||
heapProps.VisibleNodeMask = 1;
|
||||
|
||||
hr = m_pDevice->CreateCommittedResource(
|
||||
&heapProps, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT, NULL,
|
||||
__uuidof(ID3D12Resource), (void **)&m_EIPatchScratchBuffer);
|
||||
|
||||
m_EIPatchScratchBuffer->SetName(L"m_EIPatchScratchBuffer");
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Failed to create scratch buffer, HRESULT: %s", ToStr(hr).c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void D3D12DebugManager::GetBufferData(ID3D12Resource *buffer, uint64_t offset, uint64_t length,
|
||||
bytebuf &ret)
|
||||
{
|
||||
|
||||
@@ -155,6 +155,13 @@ public:
|
||||
DiscardType type, ID3D12Resource *res,
|
||||
const D3D12_DISCARD_REGION *region, D3D12_BARRIER_LAYOUT LayoutAfter);
|
||||
|
||||
rdcpair<ID3D12Resource *, UINT64> PatchExecuteIndirect(ID3D12GraphicsCommandListX *cmd,
|
||||
const D3D12RenderState &state,
|
||||
ID3D12CommandSignature *comSig,
|
||||
ID3D12Resource *argBuf, UINT64 argBufOffset,
|
||||
D3D12_GPU_VIRTUAL_ADDRESS countBufAddr,
|
||||
UINT maxCount);
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE GetCPUHandle(CBVUAVSRVSlot slot);
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE GetCPUHandle(RTVSlot slot);
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE GetCPUHandle(DSVSlot slot);
|
||||
@@ -174,6 +181,7 @@ public:
|
||||
|
||||
void PrepareTextureSampling(ID3D12Resource *resource, CompType typeCast, int &resType,
|
||||
BarrierSet &barrierSet);
|
||||
void PrepareExecuteIndirectPatching(const GPUAddressRangeTracker &origAddresses);
|
||||
|
||||
MeshDisplayPipelines CacheMeshDisplayPipelines(const MeshFormat &primary,
|
||||
const MeshFormat &secondary);
|
||||
@@ -249,6 +257,14 @@ private:
|
||||
ID3D12Resource *m_DiscardConstantsUndefined = NULL;
|
||||
ID3D12RootSignature *m_DiscardRootSig = NULL;
|
||||
|
||||
// Execute Indirect patching
|
||||
ID3D12RootSignature *m_EIPatchRootSig = NULL;
|
||||
ID3D12Resource *m_EIPatchBufferData = NULL;
|
||||
uint32_t m_EIPatchBufferCount = 0;
|
||||
ID3D12PipelineState *m_EIPatchPso = NULL;
|
||||
ID3D12Resource *m_EIPatchScratchBuffer = NULL;
|
||||
uint64_t m_EIPatchScratchOffset = 0;
|
||||
|
||||
std::map<rdcpair<DXGI_FORMAT, UINT>, ID3D12PipelineState *> m_DiscardPipes;
|
||||
std::map<rdcpair<DiscardType, DXGI_FORMAT>, ID3D12Resource *> m_DiscardPatterns;
|
||||
rdcarray<ID3D12Resource *> m_DiscardBuffers;
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "strings/string_utils.h"
|
||||
#include "d3d12_command_list.h"
|
||||
#include "d3d12_command_queue.h"
|
||||
#include "d3d12_debug.h"
|
||||
#include "d3d12_rendertext.h"
|
||||
#include "d3d12_replay.h"
|
||||
#include "d3d12_resources.h"
|
||||
@@ -2452,6 +2453,8 @@ bool WrappedID3D12Device::Serialise_BeginCaptureFrame(SerialiserType &ser)
|
||||
if(IsReplayingAndReading() && IsLoading(m_State))
|
||||
{
|
||||
m_InitialResourceStates = m_ResourceStates;
|
||||
|
||||
GetDebugManager()->PrepareExecuteIndirectPatching(m_OrigGPUAddresses);
|
||||
}
|
||||
|
||||
std::map<ResourceId, SubresourceStateVector> initialStates;
|
||||
@@ -3321,7 +3324,7 @@ rdcarray<DebugMessage> WrappedID3D12Device::GetDebugMessages()
|
||||
msg.description = rdcstr(message->pDescription);
|
||||
|
||||
// during capture add all messages. Otherwise only add this message if it's different to the
|
||||
// last one - due to our replay with real and cracked lists we get many duplicated messages
|
||||
// last one - we can sometimes get duplicated messages
|
||||
if(!IsLoading(m_State) || ret.empty() || !(ret.back() == msg))
|
||||
ret.push_back(msg);
|
||||
|
||||
@@ -4578,18 +4581,6 @@ RDResult WrappedID3D12Device::ReadLogInitialisation(RDCFile *rdc, bool storeStru
|
||||
m_Queue->GetParentAction().children.clear();
|
||||
|
||||
SetupActionPointers(m_Actions, GetReplay()->WriteFrameRecord().actionList);
|
||||
|
||||
D3D12CommandData &cmd = *m_Queue->GetCommandData();
|
||||
|
||||
for(auto it = cmd.m_BakedCmdListInfo.begin(); it != cmd.m_BakedCmdListInfo.end(); it++)
|
||||
{
|
||||
for(size_t i = 0; i < it->second.crackedLists.size(); i++)
|
||||
SAFE_RELEASE(it->second.crackedLists[i]);
|
||||
it->second.crackedLists.clear();
|
||||
}
|
||||
|
||||
for(auto it = cmd.m_CrackedAllocators.begin(); it != cmd.m_CrackedAllocators.end(); it++)
|
||||
SAFE_RELEASE(it->second);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -4790,6 +4781,7 @@ void WrappedID3D12Device::ReplayLog(uint32_t startEventID, uint32_t endEventID,
|
||||
|
||||
cmd.m_RenderState =
|
||||
cmd.m_BakedCmdListInfo[cmd.m_Partial[D3D12CommandData::Primary].partialParent].state;
|
||||
cmd.m_RenderState.ResolvePendingIndirectState(this);
|
||||
|
||||
if(D3D12_Debug_SingleSubmitFlushing())
|
||||
{
|
||||
|
||||
@@ -748,7 +748,7 @@ private:
|
||||
Threading::CriticalSection m_DynDescLock;
|
||||
rdcarray<D3D12Descriptor> m_DynamicDescriptorRefs;
|
||||
|
||||
GPUAddressRangeTracker m_GPUAddresses;
|
||||
GPUAddressRangeTracker m_OrigGPUAddresses;
|
||||
|
||||
// used both on capture and replay side to track resource states. Only locked
|
||||
// in capture
|
||||
@@ -910,9 +910,9 @@ public:
|
||||
m_DynamicDescriptorRefs.swap(refs);
|
||||
}
|
||||
|
||||
void GetResIDFromAddr(D3D12_GPU_VIRTUAL_ADDRESS addr, ResourceId &id, UINT64 &offs)
|
||||
void GetResIDFromOrigAddr(D3D12_GPU_VIRTUAL_ADDRESS addr, ResourceId &id, UINT64 &offs)
|
||||
{
|
||||
m_GPUAddresses.GetResIDFromAddr(addr, id, offs);
|
||||
m_OrigGPUAddresses.GetResIDFromAddr(addr, id, offs);
|
||||
}
|
||||
|
||||
bool IsCubemap(ResourceId id) { return m_Cubemaps.find(id) != m_Cubemaps.end(); }
|
||||
|
||||
@@ -78,7 +78,7 @@ bool WrappedID3D12Device::Serialise_CreateResource(
|
||||
range.end = gpuAddress + desc.Width;
|
||||
range.id = pResource;
|
||||
|
||||
m_GPUAddresses.AddTo(range);
|
||||
m_OrigGPUAddresses.AddTo(range);
|
||||
}
|
||||
|
||||
// check for device requirement
|
||||
|
||||
@@ -1756,7 +1756,7 @@ bool WrappedID3D12Device::Serialise_CreateCommandSignature(SerialiserType &ser,
|
||||
wrapped->sig.arguments.assign(Descriptor.pArgumentDescs, Descriptor.NumArgumentDescs);
|
||||
|
||||
wrapped->sig.graphics = true;
|
||||
wrapped->sig.numActions = 0;
|
||||
wrapped->sig.PackedByteSize = 0;
|
||||
|
||||
// From MSDN, command signatures are either graphics or compute so just search for dispatches:
|
||||
// "A given command signature is either an action or a compute command signature. If a command
|
||||
@@ -1765,13 +1765,49 @@ bool WrappedID3D12Device::Serialise_CreateCommandSignature(SerialiserType &ser,
|
||||
// signature."
|
||||
for(uint32_t i = 0; i < Descriptor.NumArgumentDescs; i++)
|
||||
{
|
||||
if(Descriptor.pArgumentDescs[i].Type == D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH)
|
||||
wrapped->sig.graphics = false;
|
||||
|
||||
if(Descriptor.pArgumentDescs[i].Type == D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH ||
|
||||
Descriptor.pArgumentDescs[i].Type == D3D12_INDIRECT_ARGUMENT_TYPE_DRAW ||
|
||||
Descriptor.pArgumentDescs[i].Type == D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED)
|
||||
wrapped->sig.numActions++;
|
||||
switch(Descriptor.pArgumentDescs[i].Type)
|
||||
{
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW:
|
||||
{
|
||||
wrapped->sig.PackedByteSize += sizeof(D3D12_DRAW_ARGUMENTS);
|
||||
break;
|
||||
}
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED:
|
||||
{
|
||||
wrapped->sig.PackedByteSize += sizeof(D3D12_DRAW_INDEXED_ARGUMENTS);
|
||||
break;
|
||||
}
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH:
|
||||
{
|
||||
wrapped->sig.PackedByteSize += sizeof(D3D12_DISPATCH_ARGUMENTS);
|
||||
wrapped->sig.graphics = false;
|
||||
break;
|
||||
}
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT:
|
||||
{
|
||||
wrapped->sig.PackedByteSize +=
|
||||
sizeof(uint32_t) * Descriptor.pArgumentDescs[i].Constant.Num32BitValuesToSet;
|
||||
break;
|
||||
}
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW:
|
||||
{
|
||||
wrapped->sig.PackedByteSize += sizeof(D3D12_VERTEX_BUFFER_VIEW);
|
||||
break;
|
||||
}
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW:
|
||||
{
|
||||
wrapped->sig.PackedByteSize += sizeof(D3D12_INDEX_BUFFER_VIEW);
|
||||
break;
|
||||
}
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW:
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_SHADER_RESOURCE_VIEW:
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_UNORDERED_ACCESS_VIEW:
|
||||
{
|
||||
wrapped->sig.PackedByteSize += sizeof(D3D12_GPU_VIRTUAL_ADDRESS);
|
||||
break;
|
||||
}
|
||||
default: RDCERR("Unexpected argument type! %d", Descriptor.pArgumentDescs[i].Type); break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = wrapped;
|
||||
|
||||
@@ -491,6 +491,7 @@ void D3D12Replay::GetOutputWindowData(uint64_t id, bytebuf &retData)
|
||||
|
||||
// transition back
|
||||
std::swap(barrier.Transition.StateBefore, barrier.Transition.StateAfter);
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
||||
list->ResourceBarrier(1, &barrier);
|
||||
|
||||
list->Close();
|
||||
|
||||
@@ -62,6 +62,147 @@ ResourceId D3D12RenderState::GetDSVID() const
|
||||
return dsv.GetResResourceId();
|
||||
}
|
||||
|
||||
void D3D12RenderState::ResolvePendingIndirectState(WrappedID3D12Device *device)
|
||||
{
|
||||
if(indirectState.argsBuf == NULL)
|
||||
return;
|
||||
|
||||
device->GPUSync();
|
||||
|
||||
D3D12_RANGE range = {0, D3D12CommandData::m_IndirectSize};
|
||||
byte *mapPtr = NULL;
|
||||
device->CheckHRESULT(indirectState.argsBuf->Map(0, &range, (void **)&mapPtr));
|
||||
|
||||
if(device->HasFatalError())
|
||||
return;
|
||||
|
||||
WrappedID3D12CommandSignature *comSig = (WrappedID3D12CommandSignature *)indirectState.comSig;
|
||||
|
||||
{
|
||||
byte *data = mapPtr + indirectState.argsOffs;
|
||||
mapPtr += comSig->sig.ByteStride;
|
||||
|
||||
for(uint32_t argIdx = 0; argIdx < indirectState.argsToProcess; argIdx++)
|
||||
{
|
||||
uint32_t a = argIdx % comSig->sig.arguments.size();
|
||||
const D3D12_INDIRECT_ARGUMENT_DESC &arg = comSig->sig.arguments[a];
|
||||
|
||||
switch(arg.Type)
|
||||
{
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW:
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED:
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH: break;
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT:
|
||||
{
|
||||
size_t argSize = sizeof(uint32_t) * arg.Constant.Num32BitValuesToSet;
|
||||
const uint32_t *data32 = (uint32_t *)data;
|
||||
data += argSize;
|
||||
|
||||
if(comSig->sig.graphics)
|
||||
{
|
||||
graphics.sigelems.resize_for_index(arg.ConstantBufferView.RootParameterIndex);
|
||||
graphics.sigelems[arg.Constant.RootParameterIndex].constants.assign(
|
||||
data32, arg.Constant.Num32BitValuesToSet);
|
||||
}
|
||||
else
|
||||
{
|
||||
compute.sigelems.resize_for_index(arg.ConstantBufferView.RootParameterIndex);
|
||||
compute.sigelems[arg.Constant.RootParameterIndex].constants.assign(
|
||||
data32, arg.Constant.Num32BitValuesToSet);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW:
|
||||
{
|
||||
const D3D12_VERTEX_BUFFER_VIEW *vb = (D3D12_VERTEX_BUFFER_VIEW *)data;
|
||||
data += sizeof(D3D12_VERTEX_BUFFER_VIEW);
|
||||
|
||||
ResourceId id;
|
||||
uint64_t offs = 0;
|
||||
D3D12_GPU_VIRTUAL_ADDRESS va = vb->BufferLocation;
|
||||
device->GetResIDFromOrigAddr(va, id, offs);
|
||||
|
||||
ID3D12Resource *res = GetResourceManager()->GetLiveAs<ID3D12Resource>(id);
|
||||
RDCASSERT(res);
|
||||
|
||||
if(arg.VertexBuffer.Slot >= vbuffers.size())
|
||||
vbuffers.resize(arg.VertexBuffer.Slot + 1);
|
||||
|
||||
vbuffers[arg.VertexBuffer.Slot].buf = GetResID(res);
|
||||
vbuffers[arg.VertexBuffer.Slot].offs = offs;
|
||||
vbuffers[arg.VertexBuffer.Slot].size = vb->SizeInBytes;
|
||||
vbuffers[arg.VertexBuffer.Slot].stride = vb->StrideInBytes;
|
||||
|
||||
break;
|
||||
}
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW:
|
||||
{
|
||||
const D3D12_INDEX_BUFFER_VIEW *ib = (D3D12_INDEX_BUFFER_VIEW *)data;
|
||||
data += sizeof(D3D12_INDEX_BUFFER_VIEW);
|
||||
|
||||
ResourceId id;
|
||||
uint64_t offs = 0;
|
||||
device->GetResIDFromOrigAddr(ib->BufferLocation, id, offs);
|
||||
|
||||
ID3D12Resource *res = GetResourceManager()->GetLiveAs<ID3D12Resource>(id);
|
||||
RDCASSERT(res);
|
||||
|
||||
ibuffer.buf = GetResID(res);
|
||||
ibuffer.offs = offs;
|
||||
ibuffer.size = ib->SizeInBytes;
|
||||
ibuffer.bytewidth = ib->Format == DXGI_FORMAT_R32_UINT ? 4 : 2;
|
||||
|
||||
break;
|
||||
}
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW:
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_SHADER_RESOURCE_VIEW:
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_UNORDERED_ACCESS_VIEW:
|
||||
{
|
||||
const D3D12_GPU_VIRTUAL_ADDRESS *addr = (D3D12_GPU_VIRTUAL_ADDRESS *)data;
|
||||
data += sizeof(D3D12_GPU_VIRTUAL_ADDRESS);
|
||||
|
||||
ResourceId id;
|
||||
uint64_t offs = 0;
|
||||
device->GetResIDFromOrigAddr(*addr, id, offs);
|
||||
|
||||
ID3D12Resource *res = GetResourceManager()->GetLiveAs<ID3D12Resource>(id);
|
||||
|
||||
SignatureElementType t = eRootCBV;
|
||||
if(arg.Type == D3D12_INDIRECT_ARGUMENT_TYPE_SHADER_RESOURCE_VIEW)
|
||||
t = eRootSRV;
|
||||
if(arg.Type == D3D12_INDIRECT_ARGUMENT_TYPE_UNORDERED_ACCESS_VIEW)
|
||||
t = eRootUAV;
|
||||
|
||||
// ConstantBufferView, ShaderResourceView and UnorderedAccessView all have one member -
|
||||
// RootParameterIndex
|
||||
if(comSig->sig.graphics)
|
||||
{
|
||||
graphics.sigelems.resize_for_index(arg.ConstantBufferView.RootParameterIndex);
|
||||
graphics.sigelems[arg.ConstantBufferView.RootParameterIndex] =
|
||||
D3D12RenderState::SignatureElement(t, GetResID(res), offs);
|
||||
}
|
||||
else
|
||||
{
|
||||
compute.sigelems.resize_for_index(arg.ConstantBufferView.RootParameterIndex);
|
||||
compute.sigelems[arg.ConstantBufferView.RootParameterIndex] =
|
||||
D3D12RenderState::SignatureElement(t, GetResID(res), offs);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default: RDCERR("Unexpected argument type! %d", arg.Type); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
indirectState.argsBuf->Unmap(0, &range);
|
||||
indirectState.argsBuf = NULL;
|
||||
indirectState.argsOffs = 0;
|
||||
indirectState.comSig = NULL;
|
||||
indirectState.argsToProcess = 0;
|
||||
}
|
||||
|
||||
void D3D12RenderState::ApplyState(WrappedID3D12Device *dev, ID3D12GraphicsCommandListX *cmd) const
|
||||
{
|
||||
D3D12_COMMAND_LIST_TYPE type = cmd->GetType();
|
||||
|
||||
@@ -218,4 +218,13 @@ struct D3D12RenderState
|
||||
|
||||
D3D12DebugManager *GetDebugManager() const { return m_DebugManager; }
|
||||
D3D12DebugManager *m_DebugManager = NULL;
|
||||
|
||||
struct IndirectPendingState
|
||||
{
|
||||
ID3D12Resource *argsBuf = NULL;
|
||||
uint64_t argsOffs = 0;
|
||||
ID3D12CommandSignature *comSig = NULL;
|
||||
uint32_t argsToProcess = 0;
|
||||
} indirectState;
|
||||
void ResolvePendingIndirectState(WrappedID3D12Device *device);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user