Skip to content

Commit

Permalink
Implement support for new barriers & resource creation functions
Browse files Browse the repository at this point in the history
  • Loading branch information
baldurk committed May 22, 2023
1 parent 2777a25 commit 780ea47
Show file tree
Hide file tree
Showing 13 changed files with 541 additions and 81 deletions.
237 changes: 235 additions & 2 deletions renderdoc/driver/d3d12/d3d12_command_list7_wrap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,241 @@
******************************************************************************/

#include "d3d12_command_list.h"
#include "d3d12_debug.h"

void STDMETHODCALLTYPE WrappedID3D12GraphicsCommandList::Barrier(
UINT32 NumBarrierGroups, const D3D12_BARRIER_GROUP *pBarrierGroups)
template <typename SerialiserType>
bool WrappedID3D12GraphicsCommandList::Serialise_Barrier(SerialiserType &ser, UINT32 NumBarrierGroups,
const D3D12_BARRIER_GROUP *pBarrierGroups)
{
ID3D12GraphicsCommandList7 *pCommandList = this;
SERIALISE_ELEMENT(pCommandList);
SERIALISE_ELEMENT(NumBarrierGroups);
SERIALISE_ELEMENT_ARRAY(pBarrierGroups, NumBarrierGroups).Important();

SERIALISE_CHECK_READ_ERRORS();

if(IsReplayingAndReading())
{
if(GetWrapped(pCommandList)->GetReal7() == NULL)
{
SET_ERROR_RESULT(m_Cmd->m_FailedReplayResult, ResultCode::APIHardwareUnsupported,
"Capture requires ID3D12GraphicsCommandList7 which isn't available");
return false;
}

m_Cmd->m_LastCmdListID = GetResourceManager()->GetOriginalID(GetResID(pCommandList));

rdcarray<D3D12_BUFFER_BARRIER> filteredUnwrappedBuf;
rdcarray<D3D12_TEXTURE_BARRIER> filteredUnwrappedTex;
rdcarray<D3D12_BARRIER_GROUP> filteredUnwrapped;

// resize so we can take pointers
for(UINT i = 0; i < NumBarrierGroups; i++)
{
if(pBarrierGroups[i].Type == D3D12_BARRIER_TYPE_BUFFER)
filteredUnwrappedBuf.resize(filteredUnwrappedBuf.size() + pBarrierGroups[i].NumBarriers);
else if(pBarrierGroups[i].Type == D3D12_BARRIER_TYPE_TEXTURE)
filteredUnwrappedTex.resize(filteredUnwrappedTex.size() + pBarrierGroups[i].NumBarriers);
}

D3D12_TEXTURE_BARRIER *tex = filteredUnwrappedTex.data();
D3D12_BUFFER_BARRIER *buf = filteredUnwrappedBuf.data();

BakedCmdListInfo &cmdinfo = m_Cmd->m_BakedCmdListInfo[m_Cmd->m_LastCmdListID];

// filter out any barriers that reference a NULL resource - this means the resource wasn't used
// elsewhere so was discarded from the capture
for(UINT i = 0; i < NumBarrierGroups; i++)
{
D3D12_BARRIER_GROUP group = pBarrierGroups[i];

if(pBarrierGroups[i].Type == D3D12_BARRIER_TYPE_BUFFER)
{
const UINT num = group.NumBarriers;

group.NumBarriers = 0;

for(UINT b = 0; b < num; b++)
{
ID3D12Resource *res = group.pBufferBarriers[b].pResource;
if(res)
{
buf[group.NumBarriers] = group.pBufferBarriers[b];
buf[group.NumBarriers].pResource = Unwrap(res);
group.NumBarriers++;

cmdinfo.resourceUsage.push_back(make_rdcpair(
GetResID(res), EventUsage(cmdinfo.curEventID, ResourceUsage::Barrier)));
}
}

group.pBufferBarriers = buf;
buf += group.NumBarriers;

if(group.NumBarriers > 0)
filteredUnwrapped.push_back(group);
}
else if(pBarrierGroups[i].Type == D3D12_BARRIER_TYPE_TEXTURE)
{
const UINT num = group.NumBarriers;

group.NumBarriers = 0;

for(UINT b = 0; b < num; b++)
{
ID3D12Resource *res = group.pTextureBarriers[b].pResource;
if(res)
{
tex[group.NumBarriers] = group.pTextureBarriers[b];
tex[group.NumBarriers].pResource = Unwrap(res);
group.NumBarriers++;

cmdinfo.resourceUsage.push_back(make_rdcpair(
GetResID(res), EventUsage(cmdinfo.curEventID, ResourceUsage::Barrier)));
}
}

group.pTextureBarriers = tex;
tex += group.NumBarriers;

if(group.NumBarriers > 0)
filteredUnwrapped.push_back(group);
}
else
{
filteredUnwrapped.push_back(group);
}
}

if(IsActiveReplaying(m_State))
{
if(m_Cmd->InRerecordRange(m_Cmd->m_LastCmdListID))
{
ID3D12GraphicsCommandListX *rerecord = m_Cmd->RerecordCmdList(m_Cmd->m_LastCmdListID);
pCommandList = rerecord;

if(!filteredUnwrapped.empty())
{
Unwrap7(pCommandList)->Barrier((UINT)filteredUnwrapped.size(), filteredUnwrapped.data());

if(m_pDevice->GetReplayOptions().optimisation != ReplayOptimisationLevel::Fastest)
{
for(UINT i = 0; i < NumBarrierGroups; i++)
{
if(pBarrierGroups[i].Type == D3D12_BARRIER_TYPE_TEXTURE)
{
for(UINT b = 0; b < pBarrierGroups[i].NumBarriers; b++)
{
const D3D12_TEXTURE_BARRIER &barrier = pBarrierGroups[i].pTextureBarriers[b];
if(barrier.pResource && (barrier.Flags & D3D12_TEXTURE_BARRIER_FLAG_DISCARD))
{
m_pDevice->GetDebugManager()->FillWithDiscardPattern(
rerecord, m_Cmd->m_BakedCmdListInfo[m_Cmd->m_LastCmdListID].state,
DiscardType::UndefinedTransition, barrier.pResource, NULL,
barrier.LayoutAfter);
}
}
}
}
}
}
}
else
{
pCommandList = NULL;
}
}
else
{
if(!filteredUnwrapped.empty())
{
Unwrap7(pCommandList)->Barrier((UINT)filteredUnwrapped.size(), filteredUnwrapped.data());
GetCrackedList7()->Barrier((UINT)filteredUnwrapped.size(), filteredUnwrapped.data());
}
}

if(pCommandList)
{
ResourceId cmd = GetResID(pCommandList);

for(UINT i = 0; i < NumBarrierGroups; i++)
{
if(pBarrierGroups[i].Type == D3D12_BARRIER_TYPE_TEXTURE)
{
for(UINT b = 0; b < pBarrierGroups[i].NumBarriers; b++)
{
if(pBarrierGroups[i].pTextureBarriers[b].pResource)
m_Cmd->m_BakedCmdListInfo[cmd].barriers.newBarriers.push_back(
pBarrierGroups[i].pTextureBarriers[b]);
}
}
}
}
}

return true;
}

void WrappedID3D12GraphicsCommandList::Barrier(UINT32 NumBarrierGroups,
const D3D12_BARRIER_GROUP *pBarrierGroups)
{
size_t memSize = sizeof(D3D12_BARRIER_GROUP) * NumBarrierGroups;
for(UINT i = 0; i < NumBarrierGroups; i++)
{
if(pBarrierGroups[i].Type == D3D12_BARRIER_TYPE_BUFFER)
memSize += pBarrierGroups[i].NumBarriers * sizeof(D3D12_BUFFER_BARRIER);
else if(pBarrierGroups[i].Type == D3D12_BARRIER_TYPE_TEXTURE)
memSize += pBarrierGroups[i].NumBarriers * sizeof(D3D12_TEXTURE_BARRIER);
}

byte *mem = m_pDevice->GetTempMemory(memSize);
D3D12_BARRIER_GROUP *barriers = (D3D12_BARRIER_GROUP *)mem;
mem += sizeof(D3D12_BARRIER_GROUP) * NumBarrierGroups;

for(UINT i = 0; i < NumBarrierGroups; i++)
{
barriers[i] = pBarrierGroups[i];

if(barriers[i].Type == D3D12_BARRIER_TYPE_BUFFER)
{
D3D12_BUFFER_BARRIER *buf = (D3D12_BUFFER_BARRIER *)mem;
mem += sizeof(D3D12_BUFFER_BARRIER) * barriers[i].NumBarriers;
for(UINT b = 0; b < barriers[i].NumBarriers; b++)
{
buf[b] = barriers[i].pBufferBarriers[b];
buf[b].pResource = Unwrap(buf[b].pResource);
}
barriers[i].pBufferBarriers = buf;
}
else if(barriers[i].Type == D3D12_BARRIER_TYPE_TEXTURE)
{
D3D12_TEXTURE_BARRIER *tex = (D3D12_TEXTURE_BARRIER *)mem;
mem += sizeof(D3D12_TEXTURE_BARRIER) * barriers[i].NumBarriers;
for(UINT b = 0; b < barriers[i].NumBarriers; b++)
{
tex[b] = barriers[i].pTextureBarriers[b];
tex[b].pResource = Unwrap(tex[b].pResource);
}
barriers[i].pTextureBarriers = tex;
}
}

SERIALISE_TIME_CALL(m_pList7->Barrier(NumBarrierGroups, barriers));

if(IsCaptureMode(m_State))
{
CACHE_THREAD_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D12Chunk::List_Barrier);
Serialise_Barrier(ser, NumBarrierGroups, pBarrierGroups);

m_ListRecord->AddChunk(scope.Get(m_ListRecord->cmdInfo->alloc));

for(UINT i = 0; i < NumBarrierGroups; i++)
if(pBarrierGroups[i].Type == D3D12_BARRIER_TYPE_TEXTURE)
m_ListRecord->cmdInfo->barriers.newBarriers.append(pBarrierGroups[i].pTextureBarriers,
pBarrierGroups[i].NumBarriers);
}
}

INSTANTIATE_FUNCTION_SERIALISED(void, WrappedID3D12GraphicsCommandList, Barrier,
UINT32 NumBarrierGroups, const D3D12_BARRIER_GROUP *pBarrierGroups);
4 changes: 4 additions & 0 deletions renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,8 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Reset(SerialiserType &ser,
m_Cmd->m_BakedCmdListInfo[BakedCommandList].curEventID = 0;
m_Cmd->m_BakedCmdListInfo[CommandList].executeEvents =
m_Cmd->m_BakedCmdListInfo[BakedCommandList].executeEvents;
m_Cmd->m_BakedCmdListInfo[CommandList].barriers.clear();
m_Cmd->m_BakedCmdListInfo[BakedCommandList].barriers.clear();
}
else
{
Expand Down Expand Up @@ -400,6 +402,8 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Reset(SerialiserType &ser,
m_Cmd->m_BakedCmdListInfo[BakedCommandList].nodeMask = nodeMask;
m_Cmd->m_BakedCmdListInfo[CommandList].allocator =
m_Cmd->m_BakedCmdListInfo[BakedCommandList].allocator = GetResID(pAllocator);
m_Cmd->m_BakedCmdListInfo[CommandList].barriers.clear();
m_Cmd->m_BakedCmdListInfo[BakedCommandList].barriers.clear();

// On list execute we increment all child events/actions by
// m_RootEventID and insert them into the tree.
Expand Down
1 change: 1 addition & 0 deletions renderdoc/driver/d3d12/d3d12_commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,7 @@ bool WrappedID3D12CommandQueue::ProcessChunk(ReadSerialiser &ser, D3D12Chunk chu
ret = m_ReplayList->Serialise_IASetIndexBufferStripCutValue(
ser, D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED);
break;
case D3D12Chunk::List_Barrier: ret = m_ReplayList->Serialise_Barrier(ser, 0, NULL); break;

case D3D12Chunk::PushMarker: ret = m_ReplayList->Serialise_BeginEvent(ser, 0, NULL, 0); break;
case D3D12Chunk::PopMarker: ret = m_ReplayList->Serialise_EndEvent(ser); break;
Expand Down
4 changes: 4 additions & 0 deletions renderdoc/driver/d3d12/d3d12_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ void BarrierSet::Configure(ID3D12Resource *res, const SubresourceStateVector &st

b.AccessBefore = D3D12_BARRIER_ACCESS_COMMON;
b.SyncBefore = D3D12_BARRIER_SYNC_ALL;

if(b.LayoutBefore == D3D12_BARRIER_LAYOUT_UNDEFINED)
b.AccessBefore = D3D12_BARRIER_ACCESS_NO_ACCESS;

b.AccessAfter = resourceAccess;
b.SyncAfter = resourceSync;
b.LayoutAfter = resourceLayout;
Expand Down
12 changes: 9 additions & 3 deletions renderdoc/driver/d3d12/d3d12_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,19 @@ struct D3D12ResourceLayout
bool IsLayout() const { return (value & LayoutBit) != 0; }
bool IsStates() const { return (value & LayoutBit) == 0; }
D3D12_RESOURCE_STATES ToStates() const { return D3D12_RESOURCE_STATES(value & ~LayoutBit); }
D3D12_BARRIER_LAYOUT ToLayout() const { return D3D12_BARRIER_LAYOUT(value & ~LayoutBit); }
D3D12_BARRIER_LAYOUT ToLayout() const
{
if(value == D3D12_BARRIER_LAYOUT_UNDEFINED)
return D3D12_BARRIER_LAYOUT_UNDEFINED;
return D3D12_BARRIER_LAYOUT(value & ~LayoutBit);
}
bool operator==(const D3D12ResourceLayout &o) const { return value == o.value; }
bool operator!=(const D3D12ResourceLayout &o) const { return !(*this == o); }
private:
explicit D3D12ResourceLayout(uint32_t v) : value(v) {}
// layouts are an enum so this bit should hopefully never be used. Note that LAYOUT_UNDEFINED is
// ~0U but that's not valid except as a previous state for discards, it's not a layout anything
// can be put into so stored here.
// ~0U and annoyingly it has to be specified for buffers (instead of D3D12_BARRIER_LAYOUT_COMMON)
// so we need to special-case it.
// states are a bitmask but they only use just over 6 hex digits so far, and we assume they won't
// be extended (or not by much).
// We set the bit for layouts and not for states so that we can serialise this
Expand Down Expand Up @@ -1032,5 +1037,6 @@ enum class D3D12Chunk : uint32_t
List_OMSetFrontAndBackStencilRef,
List_RSSetDepthBias,
List_IASetIndexBufferStripCutValue,
List_Barrier,
Max,
};
23 changes: 19 additions & 4 deletions renderdoc/driver/d3d12/d3d12_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4158,6 +4158,19 @@ bool WrappedID3D12Device::ProcessChunk(ReadSerialiser &ser, D3D12Chunk context)
IID(), NULL);
case D3D12Chunk::Device_CreateCommandQueue1:
return Serialise_CreateCommandQueue1(ser, NULL, IID(), IID(), NULL);
case D3D12Chunk::Device_CreateCommittedResource3:
return Serialise_CreateCommittedResource3(ser, NULL, D3D12_HEAP_FLAG_NONE, NULL,
D3D12_BARRIER_LAYOUT_COMMON, NULL, NULL, 0, NULL,
IID(), NULL);
case D3D12Chunk::Device_CreatePlacedResource2:
return Serialise_CreatePlacedResource2(ser, NULL, 0, NULL, D3D12_BARRIER_LAYOUT_COMMON, NULL,
0, NULL, IID(), NULL);
case D3D12Chunk::Device_CreateReservedResource1:
return Serialise_CreateReservedResource1(ser, NULL, D3D12_RESOURCE_STATE_COMMON, NULL, NULL,
IID(), NULL);
case D3D12Chunk::Device_CreateReservedResource2:
return Serialise_CreateReservedResource2(ser, NULL, D3D12_BARRIER_LAYOUT_COMMON, NULL, NULL,
0, NULL, IID(), NULL);

// in order to get a warning if we miss a case, we explicitly handle the list/queue chunks here.
// If we actually encounter one it's an error (we should hit CaptureBegin first and switch to
Expand Down Expand Up @@ -4246,13 +4259,10 @@ bool WrappedID3D12Device::ProcessChunk(ReadSerialiser &ser, D3D12Chunk context)
case D3D12Chunk::List_ClearState:
case D3D12Chunk::CoherentMapWrite:
case D3D12Chunk::Device_CreateSampler2:
case D3D12Chunk::Device_CreateCommittedResource3:
case D3D12Chunk::Device_CreatePlacedResource2:
case D3D12Chunk::Device_CreateReservedResource1:
case D3D12Chunk::Device_CreateReservedResource2:
case D3D12Chunk::List_OMSetFrontAndBackStencilRef:
case D3D12Chunk::List_RSSetDepthBias:
case D3D12Chunk::List_IASetIndexBufferStripCutValue:
case D3D12Chunk::List_Barrier:
RDCERR("Unexpected chunk while processing initialisation: %s", ToStr(context).c_str());
return false;

Expand Down Expand Up @@ -4719,6 +4729,8 @@ void WrappedID3D12Device::ReplayLog(uint32_t startEventID, uint32_t endEventID,
{
ID3D12GraphicsCommandListX *list = cmd.m_OutsideCmdList = GetNewList();

cmd.m_BakedCmdListInfo[GetResID(cmd.m_OutsideCmdList)].barriers.clear();

if(!list)
return;

Expand All @@ -4740,6 +4752,9 @@ void WrappedID3D12Device::ReplayLog(uint32_t startEventID, uint32_t endEventID,

if(cmd.m_OutsideCmdList != NULL)
{
if(replayType == eReplay_OnlyDraw)
ApplyBarriers(cmd.m_BakedCmdListInfo[GetResID(cmd.m_OutsideCmdList)].barriers);

ID3D12GraphicsCommandList *list = cmd.m_OutsideCmdList;

CheckHRESULT(list->Close());
Expand Down
Loading

0 comments on commit 780ea47

Please sign in to comment.