Refactor D3D12 ExecuteIndirect handling to patch arguments on GPU

This commit is contained in:
baldurk
2023-09-07 17:53:53 +01:00
parent cb7048e1a4
commit 55dae7ebc6
23 changed files with 1001 additions and 872 deletions
+110
View File
@@ -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)));
}
}
}
+11 -16
View File
@@ -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]);
}
}
+23 -15
View File
@@ -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());
+2 -6
View File
@@ -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;
+1 -1
View File
@@ -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;
};
+282 -5
View File
@@ -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)
{
+16
View File
@@ -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;
+5 -13
View File
@@ -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())
{
+3 -3
View File
@@ -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
+44 -8
View File
@@ -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();
+141
View File
@@ -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();
+9
View File
@@ -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);
};