Track renderstate as we go, and allow replaying single draws with it

This commit is contained in:
baldurk
2016-08-06 18:31:22 +02:00
parent 609126a909
commit 407bca01e8
15 changed files with 538 additions and 79 deletions
@@ -55,7 +55,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Close()
{
ID3D12GraphicsCommandList *list = m_Cmd->RerecordCmdList(CommandList);
#ifdef VERBOSE_PARTIAL_REPLAY
RDCDEBUG("Ending partial command buffer for %llu baked to %llu", CommandList, bakeId);
RDCDEBUG("Ending partial command list for %llu baked to %llu", CommandList, bakeId);
#endif
list->Close();
@@ -151,7 +151,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Reset(ID3D12CommandAllocator *p
bool partial = false;
int partialType = D3D12CommandData::ePartialNum;
// check for partial execution of this command buffer
// check for partial execution of this command list
for(int p = 0; p < D3D12CommandData::ePartialNum; p++)
{
const vector<uint32_t> &baseEvents = m_Cmd->m_Partial[p].cmdListExecs[bakeId];
@@ -161,8 +161,8 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Reset(ID3D12CommandAllocator *p
if(*it <= m_Cmd->m_LastEventID && m_Cmd->m_LastEventID < (*it + length))
{
#ifdef VERBOSE_PARTIAL_REPLAY
RDCDEBUG("vkBegin - partial detected %u < %u < %u, %llu -> %llu", *it,
m_Cmd->m_LastEventID, *it + length, CommandList, bakeId);
RDCDEBUG("Reset - partial detected %u < %u < %u, %llu -> %llu", *it, m_Cmd->m_LastEventID,
*it + length, CommandList, bakeId);
#endif
m_Cmd->m_Partial[p].partialParent = CommandList;
@@ -206,9 +206,9 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Reset(ID3D12CommandAllocator *p
// can be found in the subsequent serialised commands that ref the
// non-baked ID. The baked ID is referenced by the submit itself.
//
// In vkEndCommandBuffer we erase the non-baked reference, and since
// we know you can only be recording a command buffer once at a time
// (even if it's baked to several command buffers in the frame)
// In Close() we erase the non-baked reference, and since
// we know you can only be recording a command list once at a time
// (even if it's baked to several command listsin the frame)
// there's no issue with clashes here.
m_Cmd->m_RerecordCmds[bakeId] = list;
m_Cmd->m_RerecordCmds[CommandList] = list;
@@ -230,7 +230,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_Reset(ID3D12CommandAllocator *p
GetResourceManager()->AddLiveResource(bakeId, list);
// whenever a vkCmd command-building chunk asks for the command buffer, it
// whenever a command-building chunk asks for the command list, it
// will get our baked version.
GetResourceManager()->ReplaceResource(CommandList, bakeId);
}
@@ -539,7 +539,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_IASetPrimitiveTopology(
{
Unwrap(m_Cmd->RerecordCmdList(CommandList))->IASetPrimitiveTopology(topo);
// m_RenderState.topo = topo;
m_Cmd->m_RenderState.topo = topo;
}
}
else if(m_State == READING)
@@ -581,12 +581,11 @@ bool WrappedID3D12GraphicsCommandList::Serialise_RSSetViewports(UINT NumViewport
{
Unwrap(m_Cmd->RerecordCmdList(CommandList))->RSSetViewports(num, views);
/*
if(m_RenderState.views.size() < first + count)
m_RenderState.views.resize(first + count);
if(m_Cmd->m_RenderState.views.size() < num)
m_Cmd->m_RenderState.views.resize(num);
for(uint32_t i = 0; i < count; i++)
m_RenderState.views[first + i] = views[i];*/
for(UINT i = 0; i < num; i++)
m_Cmd->m_RenderState.views[i] = views[i];
}
}
else if(m_State == READING)
@@ -629,12 +628,11 @@ bool WrappedID3D12GraphicsCommandList::Serialise_RSSetScissorRects(UINT NumRects
{
Unwrap(m_Cmd->RerecordCmdList(CommandList))->RSSetScissorRects(num, rects);
/*
if(m_RenderState.scissors.size() < first + count)
m_RenderState.scissors.resize(first + count);
if(m_Cmd->m_RenderState.scissors.size() < num)
m_Cmd->m_RenderState.scissors.resize(num);
for(uint32_t i = 0; i < count; i++)
m_RenderState.scissors[first + i] = scissors[i];*/
for(UINT i = 0; i < num; i++)
m_Cmd->m_RenderState.scissors[i] = rects[i];
}
}
else if(m_State == READING)
@@ -685,7 +683,7 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetPipelineState(ID3D12Pipeline
pPipelineState = GetResourceManager()->GetLiveAs<ID3D12PipelineState>(pipe);
Unwrap(m_Cmd->RerecordCmdList(CommandList))->SetPipelineState(Unwrap(pPipelineState));
// m_RenderState.pipe = ;
m_Cmd->m_RenderState.pipe = GetResID(pPipelineState);
}
}
else if(m_State == READING)
@@ -878,6 +876,8 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetGraphicsRootSignature(
{
pRootSignature = GetResourceManager()->GetLiveAs<ID3D12RootSignature>(sig);
Unwrap(m_Cmd->RerecordCmdList(CommandList))->SetGraphicsRootSignature(Unwrap(pRootSignature));
m_Cmd->m_RenderState.graphics.rootsig = GetResID(pRootSignature);
}
}
else if(m_State == READING)
@@ -979,6 +979,12 @@ bool WrappedID3D12GraphicsCommandList::Serialise_SetGraphicsRootConstantBufferVi
Unwrap(m_Cmd->RerecordCmdList(CommandList))
->SetGraphicsRootConstantBufferView(idx, pRes->GetGPUVirtualAddress() + byteOffset);
if(m_Cmd->m_RenderState.graphics.sigelems.size() < idx + 1)
m_Cmd->m_RenderState.graphics.sigelems.resize(idx + 1);
m_Cmd->m_RenderState.graphics.sigelems[idx] =
D3D12RenderState::SignatureElement(eRootCBV, GetResID(pRes), byteOffset);
}
}
else if(m_State == READING)
@@ -1054,17 +1060,18 @@ bool WrappedID3D12GraphicsCommandList::Serialise_IASetIndexBuffer(const D3D12_IN
{
Unwrap(list)->IASetIndexBuffer(&view);
// WrappedID3D12Resource::GetResIDFromAddr(view.BufferLocation, m_RenderState.ibuffer.buf,
// m_RenderState.ibuffer.offs);
// m_RenderState.ibuffer.bytewidth = (view.Format == DXGI_FORMAT_R32_UINT ? 4 : 2);
WrappedID3D12Resource::GetResIDFromAddr(
view.BufferLocation, m_Cmd->m_RenderState.ibuffer.buf, m_Cmd->m_RenderState.ibuffer.offs);
m_Cmd->m_RenderState.ibuffer.bytewidth = (view.Format == DXGI_FORMAT_R32_UINT ? 4 : 2);
m_Cmd->m_RenderState.ibuffer.size = view.SizeInBytes;
}
else
{
Unwrap(list)->IASetIndexBuffer(NULL);
// m_RenderState.ibuffer.buf = ResourceId();
// m_RenderState.ibuffer.offs = 0;
// m_RenderState.ibuffer.bytewidth = 2;
m_Cmd->m_RenderState.ibuffer.buf = ResourceId();
m_Cmd->m_RenderState.ibuffer.offs = 0;
m_Cmd->m_RenderState.ibuffer.bytewidth = 2;
}
}
}
@@ -1076,9 +1083,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_IASetIndexBuffer(const D3D12_IN
{
list->IASetIndexBuffer(&view);
UINT64 dummy = 0;
WrappedID3D12Resource::GetResIDFromAddr(
view.BufferLocation, m_Cmd->m_BakedCmdListInfo[CommandList].state.ibuffer, dummy);
m_Cmd->m_BakedCmdListInfo[CommandList].state.idxWidth =
(view.Format == DXGI_FORMAT_R32_UINT ? 4 : 2);
}
@@ -1086,7 +1090,6 @@ bool WrappedID3D12GraphicsCommandList::Serialise_IASetIndexBuffer(const D3D12_IN
{
list->IASetIndexBuffer(NULL);
m_Cmd->m_BakedCmdListInfo[CommandList].state.ibuffer = ResourceId();
m_Cmd->m_BakedCmdListInfo[CommandList].state.idxWidth = 2;
}
}
@@ -1132,7 +1135,18 @@ bool WrappedID3D12GraphicsCommandList::Serialise_IASetVertexBuffers(
{
Unwrap(m_Cmd->RerecordCmdList(CommandList))->IASetVertexBuffers(start, num, views);
// m_RenderState.vbuffers = ;
if(m_Cmd->m_RenderState.vbuffers.size() < start + num)
m_Cmd->m_RenderState.vbuffers.resize(start + num);
for(UINT i = 0; i < num; i++)
{
WrappedID3D12Resource::GetResIDFromAddr(views[i].BufferLocation,
m_Cmd->m_RenderState.vbuffers[start + i].buf,
m_Cmd->m_RenderState.vbuffers[start + i].offs);
m_Cmd->m_RenderState.vbuffers[start + i].stride = views[i].StrideInBytes;
m_Cmd->m_RenderState.vbuffers[start + i].size = views[i].SizeInBytes;
}
}
}
else if(m_State == READING)
@@ -1218,6 +1232,15 @@ bool WrappedID3D12GraphicsCommandList::Serialise_OMSetRenderTargets(
->OMSetRenderTargets(num, rtHandles, singlehandle ? TRUE : FALSE,
dsv.heap != ResourceId() ? &dsvHandle : NULL);
m_Cmd->m_RenderState.rts.resize(num);
for(UINT i = 0; i < numHandles; i++)
m_Cmd->m_RenderState.rts[i] = rts[i];
m_Cmd->m_RenderState.rtSingle = singlehandle;
m_Cmd->m_RenderState.dsv = dsv;
SAFE_DELETE_ARRAY(rtHandles);
}
}
@@ -1234,6 +1257,48 @@ bool WrappedID3D12GraphicsCommandList::Serialise_OMSetRenderTargets(
->OMSetRenderTargets(num, rtHandles, singlehandle ? TRUE : FALSE,
dsv.heap != ResourceId() ? &dsvHandle : NULL);
RDCEraseEl(m_Cmd->m_BakedCmdListInfo[CommandList].state.dsv);
RDCEraseEl(m_Cmd->m_BakedCmdListInfo[CommandList].state.rts);
if(singlehandle)
{
WrappedID3D12DescriptorHeap *heap =
GetResourceManager()->GetLiveAs<WrappedID3D12DescriptorHeap>(rts[0].heap);
const D3D12Descriptor *descs = heap->GetDescriptors() + rts[0].index;
for(UINT i = 0; i < num; i++)
{
RDCASSERT(descs[i].GetType() == D3D12Descriptor::TypeRTV);
m_Cmd->m_BakedCmdListInfo[CommandList].state.rts[i] = GetResID(descs[i].nonsamp.resource);
}
}
else
{
for(UINT i = 0; i < num; i++)
{
WrappedID3D12DescriptorHeap *heap =
GetResourceManager()->GetLiveAs<WrappedID3D12DescriptorHeap>(rts[0].heap);
const D3D12Descriptor &desc = heap->GetDescriptors()[rts[i].index];
RDCASSERT(desc.GetType() == D3D12Descriptor::TypeRTV);
m_Cmd->m_BakedCmdListInfo[CommandList].state.rts[i] = GetResID(desc.nonsamp.resource);
}
}
if(dsv.heap != ResourceId())
{
WrappedID3D12DescriptorHeap *heap =
GetResourceManager()->GetLiveAs<WrappedID3D12DescriptorHeap>(dsv.heap);
const D3D12Descriptor &desc = heap->GetDescriptors()[dsv.index];
RDCASSERT(desc.GetType() == D3D12Descriptor::TypeDSV);
m_Cmd->m_BakedCmdListInfo[CommandList].state.dsv = GetResID(desc.nonsamp.resource);
}
SAFE_DELETE_ARRAY(rtHandles);
}
@@ -114,7 +114,7 @@ bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(UINT NumCommandLis
BakedCmdListInfo &cmdBufInfo = m_Cmd.m_BakedCmdListInfo[cmdIds[c]];
// insert the baked command buffer in-line into this list of notes, assigning new event and
// insert the baked command list in-line into this list of notes, assigning new event and
// drawIDs
m_Cmd.InsertDrawsAndRefreshIDs(cmdBufInfo.draw->children);
@@ -136,7 +136,7 @@ bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(UINT NumCommandLis
}
*/
// only primary command buffers can be submitted
// only primary command lists can be submitted
m_Cmd.m_Partial[D3D12CommandData::Primary].cmdListExecs[cmdIds[c]].push_back(
m_Cmd.m_RootEventID);
@@ -165,7 +165,7 @@ bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(UINT NumCommandLis
// advance m_CurEventID to match the events added when reading
for(uint32_t c = 0; c < numCmds; c++)
{
// 2 extra for the virtual labels around the command buffer
// 2 extra for the virtual labels around the command list
m_Cmd.m_RootEventID += 2 + m_Cmd.m_BakedCmdListInfo[cmdIds[c]].eventCount;
m_Cmd.m_RootDrawcallID += 2 + m_Cmd.m_BakedCmdListInfo[cmdIds[c]].drawCount;
}
@@ -222,7 +222,7 @@ bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(UINT NumCommandLis
for(uint32_t c = 0; c < numCmds; c++)
{
// account for the virtual vkBeginCommandBuffer label at the start of the events here
// account for the virtual label at the start of the events here
// so it matches up to baseEvent
eid++;
@@ -254,7 +254,7 @@ bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(UINT NumCommandLis
#endif
}
// 1 extra to account for the virtual end command buffer label (begin is accounted for
// 1 extra to account for the virtual end command list label (begin is accounted for
// above)
eid += 1 + m_Cmd.m_BakedCmdListInfo[cmdIds[c]].eventCount;
}
@@ -340,11 +340,11 @@ void STDMETHODCALLTYPE WrappedID3D12CommandQueue::ExecuteCommandLists(
if(capframe)
{
// pull in frame refs from this baked command buffer
// pull in frame refs from this baked command list
record->bakedCommands->AddResourceReferences(GetResourceManager());
record->bakedCommands->AddReferencedIDs(refdIDs);
// ref the parent command buffer by itself, this will pull in the cmd buffer pool
// ref the parent command list by itself, this will pull in the cmd buffer pool
GetResourceManager()->MarkResourceFrameReferenced(record->GetResourceID(), eFrameRef_Read);
// reference all executed bundles as well
+17 -8
View File
@@ -23,6 +23,7 @@
******************************************************************************/
#include <algorithm>
#include "driver/dxgi/dxgi_common.h"
#include "d3d12_command_list.h"
#include "d3d12_command_queue.h"
@@ -357,8 +358,13 @@ void WrappedID3D12CommandQueue::ReplayLog(LogState readType, uint32_t startEvent
m_pDevice->Serialise_BeginCaptureFrame(!partial);
m_pDevice->ExecuteLists();
m_pDevice->FlushLists();
if(readType == READING)
{
GetResourceManager()->ApplyInitialContents();
m_pDevice->ExecuteLists();
m_pDevice->FlushLists();
}
m_pSerialiser->PopContext(header);
@@ -370,7 +376,7 @@ void WrappedID3D12CommandQueue::ReplayLog(LogState readType, uint32_t startEvent
m_Cmd.m_RootEventID = ev.eventID;
// if not partial, we need to be sure to replay
// past the command buffer records, so can't
// past the command list records, so can't
// skip to the file offset of the first event
if(partial)
m_pSerialiser->SetOffset(ev.fileOffset);
@@ -391,7 +397,7 @@ void WrappedID3D12CommandQueue::ReplayLog(LogState readType, uint32_t startEvent
if(m_State == EXECUTING && m_Cmd.m_RootEventID > endEventID)
{
// we can just break out if we've done all the events desired.
// note that the command buffer events aren't 'real' and we just blaze through them
// note that the command list events aren't 'real' and we just blaze through them
break;
}
@@ -417,7 +423,7 @@ void WrappedID3D12CommandQueue::ReplayLog(LogState readType, uint32_t startEvent
// increment root event ID either if we didn't just replay a cmd
// buffer event, OR if we are doing a frame sub-section replay,
// in which case it's up to the calling code to make sure we only
// replay inside a command buffer (if we crossed command buffer
// replay inside a command list (if we crossed command list
// boundaries, the event IDs would no longer match up).
if(m_Cmd.m_LastCmdListID == ResourceId() || startEventID > 1)
{
@@ -432,9 +438,6 @@ void WrappedID3D12CommandQueue::ReplayLog(LogState readType, uint32_t startEvent
}
}
m_pDevice->ExecuteLists();
m_pDevice->FlushLists(true);
if(m_State == READING)
{
struct SortEID
@@ -708,6 +711,12 @@ void D3D12CommandData::AddDrawcall(const FetchDrawcall &d, bool hasEvents)
if(m_LastCmdListID != ResourceId())
{
// TODO fill from m_BakedCmdListInfo[m_LastCmdListID].state
draw.topology = MakePrimitiveTopology(m_BakedCmdListInfo[m_LastCmdListID].state.topo);
draw.indexByteWidth = m_BakedCmdListInfo[m_LastCmdListID].state.idxWidth;
memcpy(draw.outputs, m_BakedCmdListInfo[m_LastCmdListID].state.rts, sizeof(draw.outputs));
draw.depthOut = m_BakedCmdListInfo[m_LastCmdListID].state.dsv;
}
if(m_LastCmdListID != ResourceId())
+4 -5
View File
@@ -24,9 +24,10 @@
#pragma once
#include "common/common.h"
#include "api/replay/renderdoc_replay.h"
#include "common/common.h"
#include "d3d12_common.h"
#include "d3d12_state.h"
struct D3D12DrawcallTreeNode
{
@@ -110,13 +111,9 @@ struct BakedCmdListInfo
struct CmdListState
{
ResourceId pipeline;
D3D12_PRIMITIVE_TOPOLOGY topo;
uint32_t idxWidth;
ResourceId ibuffer;
vector<ResourceId> vbuffers;
ResourceId rts[8];
ResourceId dsv;
@@ -140,6 +137,8 @@ struct D3D12CommandData
map<ResourceId, BakedCmdListInfo> m_BakedCmdListInfo;
D3D12RenderState m_RenderState;
enum PartialReplayIndex
{
Primary,
+16 -6
View File
@@ -90,6 +90,17 @@ string ToStrHelper<false, D3D12ComponentMapping>::Get(const D3D12ComponentMappin
: Unwrap(rm->GetLiveAs<type>(id)); \
}
#define SerialiseWrappedObject(type, name, obj) \
{ \
D3D12ResourceManager *rm = (D3D12ResourceManager *)GetUserData(); \
ResourceId id; \
if(m_Mode >= WRITING) \
id = GetResID(obj); \
Serialise(name, id); \
if(m_Mode < WRITING) \
obj = (id == ResourceId() || !rm->HasLiveResource(id)) ? NULL : rm->GetLiveAs<type>(id); \
}
template <>
void Serialiser::Serialise(const char *name, D3D12Descriptor &el)
{
@@ -131,32 +142,31 @@ void Serialiser::Serialise(const char *name, D3D12Descriptor &el)
}
case D3D12Descriptor::TypeCBV:
{
SerialiseObject(ID3D12Resource, "Resource", el.nonsamp.resource);
Serialise("Descriptor", el.nonsamp.cbv);
break;
}
case D3D12Descriptor::TypeSRV:
{
SerialiseObject(ID3D12Resource, "Resource", el.nonsamp.resource);
SerialiseWrappedObject(ID3D12Resource, "Resource", el.nonsamp.resource);
Serialise("Descriptor", el.nonsamp.srv);
break;
}
case D3D12Descriptor::TypeRTV:
{
SerialiseObject(ID3D12Resource, "Resource", el.nonsamp.resource);
SerialiseWrappedObject(ID3D12Resource, "Resource", el.nonsamp.resource);
Serialise("Descriptor", el.nonsamp.rtv);
break;
}
case D3D12Descriptor::TypeDSV:
{
SerialiseObject(ID3D12Resource, "Resource", el.nonsamp.resource);
SerialiseWrappedObject(ID3D12Resource, "Resource", el.nonsamp.resource);
Serialise("Descriptor", el.nonsamp.dsv);
break;
}
case D3D12Descriptor::TypeUAV:
{
SerialiseObject(ID3D12Resource, "Resource", el.nonsamp.resource);
SerialiseObject(ID3D12Resource, "CounterResource", el.nonsamp.uav.counterResource);
SerialiseWrappedObject(ID3D12Resource, "Resource", el.nonsamp.resource);
SerialiseWrappedObject(ID3D12Resource, "CounterResource", el.nonsamp.uav.counterResource);
// special case because of extra resource and squeezed descriptor
D3D12_UNORDERED_ACCESS_VIEW_DESC desc = el.nonsamp.uav.desc.AsDesc();
+52 -12
View File
@@ -951,7 +951,7 @@ void WrappedID3D12Device::StartFrameCapture(void *dev, void *wnd)
Serialise_BeginCaptureFrame(false);
// need to hold onto this as it must come right after the capture chunk,
// before any command buffers
// before any command lists
m_HeaderChunk = scope.Get();
}
@@ -1082,14 +1082,13 @@ bool WrappedID3D12Device::EndFrameCapture(void *dev, void *wnd)
{
const vector<D3D12ResourceRecord *> &cmdListRecords = m_Queue->GetCmdLists();
RDCDEBUG("Flushing %u command buffer records to file serialiser",
(uint32_t)cmdListRecords.size());
RDCDEBUG("Flushing %u command list records to file serialiser", (uint32_t)cmdListRecords.size());
for(size_t i = 0; i < cmdListRecords.size(); i++)
{
cmdListRecords[i]->Insert(recordlist);
RDCDEBUG("Adding %u chunks to file serialiser from command buffer %llu",
RDCDEBUG("Adding %u chunks to file serialiser from command list %llu",
(uint32_t)recordlist.size(), cmdListRecords[i]->GetResourceID());
}
@@ -1553,12 +1552,53 @@ void WrappedID3D12Device::ReplayLog(uint32_t startEventID, uint32_t endEventID,
m_State = EXECUTING;
if(replayType == eReplay_Full)
m_Queue->ReplayLog(EXECUTING, startEventID, endEventID, partial);
else if(replayType == eReplay_WithoutDraw)
m_Queue->ReplayLog(EXECUTING, startEventID, RDCMAX(1U, endEventID) - 1, partial);
else if(replayType == eReplay_OnlyDraw)
m_Queue->ReplayLog(EXECUTING, endEventID, endEventID, partial);
else
RDCFATAL("Unexpected replay type");
{
D3D12CommandData &cmd = *m_Queue->GetCommandData();
if(!partial)
{
RDCASSERT(cmd.m_Partial[D3D12CommandData::Primary].resultPartialCmdList == NULL);
RDCASSERT(cmd.m_Partial[D3D12CommandData::Secondary].resultPartialCmdList == NULL);
cmd.m_Partial[D3D12CommandData::Primary].Reset();
cmd.m_Partial[D3D12CommandData::Secondary].Reset();
cmd.m_RenderState = D3D12RenderState();
cmd.m_RenderState.m_ResourceManager = GetResourceManager();
}
// we'll need our own command list if we're replaying just a subsection
// of events within a single command list record - always if it's only
// one drawcall, or if start event ID is > 0 we assume the outside code
// has chosen a subsection that lies within a command list
if(partial)
{
ID3D12GraphicsCommandList *list = cmd.m_Partial[D3D12CommandData::Primary].outsideCmdList =
GetNewList();
cmd.m_RenderState.ApplyState(list);
}
if(replayType == eReplay_Full)
m_Queue->ReplayLog(EXECUTING, startEventID, endEventID, partial);
else if(replayType == eReplay_WithoutDraw)
m_Queue->ReplayLog(EXECUTING, startEventID, RDCMAX(1U, endEventID) - 1, partial);
else if(replayType == eReplay_OnlyDraw)
m_Queue->ReplayLog(EXECUTING, endEventID, endEventID, partial);
else
RDCFATAL("Unexpected replay type");
if(cmd.m_Partial[D3D12CommandData::Primary].outsideCmdList != NULL)
{
ID3D12GraphicsCommandList *list = cmd.m_Partial[D3D12CommandData::Primary].outsideCmdList;
list->Close();
ExecuteLists();
cmd.m_Partial[D3D12CommandData::Primary].outsideCmdList = NULL;
}
#if defined(SINGLE_FLUSH_VALIDATE)
FlushLists(true);
#endif
}
}
+1 -1
View File
@@ -303,7 +303,7 @@ public:
WrappedID3D12Device(ID3D12Device *realDevice, D3D12InitParams *params);
virtual ~WrappedID3D12Device();
UINT GetDescriptorIncrement(D3D12_DESCRIPTOR_HEAP_TYPE type)
UINT GetUnwrappedDescriptorIncrement(D3D12_DESCRIPTOR_HEAP_TYPE type)
{
return m_DescriptorIncrements[type];
}
@@ -845,6 +845,8 @@ void WrappedID3D12Device::CopyDescriptors(
NumSrcDescriptorRanges, srcStarts, pSrcDescriptorRangeSizes,
DescriptorHeapsType);
RDCUNIMPLEMENTED("CopyDescriptors does not copy our internal descriptor data");
SAFE_DELETE_ARRAY(dstStarts);
SAFE_DELETE_ARRAY(srcStarts);
}
@@ -856,6 +858,21 @@ void WrappedID3D12Device::CopyDescriptorsSimple(UINT NumDescriptors,
{
m_pDevice->CopyDescriptorsSimple(NumDescriptors, Unwrap(DestDescriptorRangeStart),
Unwrap(SrcDescriptorRangeStart), DescriptorHeapsType);
D3D12Descriptor *src = GetWrapped(SrcDescriptorRangeStart);
D3D12Descriptor *dst = GetWrapped(DestDescriptorRangeStart);
for(UINT i = 0; i < NumDescriptors; i++)
{
// save these so we can do a straight copy then restore them
WrappedID3D12DescriptorHeap *heap = dst[i].samp.heap;
uint32_t index = dst[i].samp.idx;
dst[i] = src[i];
dst[i].samp.heap = heap;
dst[i].samp.idx = index;
}
}
HRESULT WrappedID3D12Device::OpenSharedHandle(HANDLE NTHandle, REFIID riid, void **ppvObj)
+6 -6
View File
@@ -469,8 +469,8 @@ bool D3D12ResourceManager::Serialise_InitialState(ResourceId resid, ID3D12Device
desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
ID3D12DescriptorHeap *copyheap = NULL;
HRESULT hr = m_Device->GetReal()->CreateDescriptorHeap(&desc, __uuidof(ID3D12DescriptorHeap),
(void **)&copyheap);
HRESULT hr =
m_Device->CreateDescriptorHeap(&desc, __uuidof(ID3D12DescriptorHeap), (void **)&copyheap);
if(FAILED(hr))
{
@@ -480,11 +480,11 @@ bool D3D12ResourceManager::Serialise_InitialState(ResourceId resid, ID3D12Device
D3D12_CPU_DESCRIPTOR_HANDLE handle = copyheap->GetCPUDescriptorHandleForHeapStart();
UINT increment = m_Device->GetDescriptorIncrement(desc.Type);
UINT increment = m_Device->GetDescriptorHandleIncrementSize(desc.Type);
for(uint32_t i = 0; i < numElems; i++)
{
descs[i].Create(m_Device->GetReal(), handle);
descs[i].Create(m_Device, handle);
handle.ptr += increment;
}
@@ -599,13 +599,13 @@ void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, InitialCo
if(type == Resource_DescriptorHeap)
{
ID3D12DescriptorHeap *dstheap = Unwrap((ID3D12DescriptorHeap *)live);
ID3D12DescriptorHeap *dstheap = (ID3D12DescriptorHeap *)live;
ID3D12DescriptorHeap *srcheap = (ID3D12DescriptorHeap *)data.resource;
if(srcheap)
{
// copy the whole heap
m_Device->GetReal()->CopyDescriptorsSimple(
m_Device->CopyDescriptorsSimple(
srcheap->GetDesc().NumDescriptors, dstheap->GetCPUDescriptorHandleForHeapStart(),
srcheap->GetCPUDescriptorHandleForHeapStart(), srcheap->GetDesc().Type);
}
+8 -2
View File
@@ -130,7 +130,7 @@ struct D3D12Descriptor
TypeUndefined,
};
DescriptorType GetType()
DescriptorType GetType() const
{
RDCCOMPILE_ASSERT(sizeof(D3D12Descriptor) <= 64, "D3D12Descriptor has gotten larger");
@@ -223,7 +223,7 @@ struct CmdListRecordingInfo
{
vector<D3D12_RESOURCE_BARRIER> barriers;
// a list of all resources dirtied by this command buffer
// a list of all resources dirtied by this command list
set<ResourceId> dirtied;
// bundles executed
@@ -291,6 +291,12 @@ public:
return (T *)GetLiveResource(id);
}
template <class T>
T *GetCurrentAs(ResourceId id)
{
return (T *)GetCurrentResource(id);
}
void ApplyBarriers(vector<D3D12_RESOURCE_BARRIER> &barriers,
map<ResourceId, SubresourceStateVector> &states);
+1 -1
View File
@@ -148,7 +148,7 @@ WrappedID3D12DescriptorHeap::WrappedID3D12DescriptorHeap(ID3D12DescriptorHeap *r
realCPUBase = real->GetCPUDescriptorHandleForHeapStart();
realGPUBase = real->GetGPUDescriptorHandleForHeapStart();
increment = device->GetDescriptorIncrement(desc.Type);
increment = device->GetUnwrappedDescriptorIncrement(desc.Type);
descriptors = new D3D12Descriptor[desc.NumDescriptors];
+153
View File
@@ -0,0 +1,153 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2016 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include "d3d12_state.h"
#include "d3d12_command_list.h"
#include "d3d12_manager.h"
#include "d3d12_resources.h"
D3D12RenderState::D3D12RenderState()
{
views.clear();
scissors.clear();
rts.clear();
rtSingle = false;
dsv = PortableHandle();
m_ResourceManager = NULL;
pipe = graphics.rootsig = compute.rootsig = ResourceId();
graphics.sigelems.clear();
compute.sigelems.clear();
topo = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
RDCEraseEl(ibuffer);
vbuffers.clear();
}
D3D12RenderState &D3D12RenderState::operator=(const D3D12RenderState &o)
{
views = o.views;
scissors = o.scissors;
rts = o.rts;
rtSingle = o.rtSingle;
dsv = o.dsv;
pipe = o.pipe;
graphics.rootsig = o.graphics.rootsig;
graphics.sigelems = o.graphics.sigelems;
compute.rootsig = o.compute.rootsig;
compute.sigelems = o.compute.sigelems;
topo = o.topo;
ibuffer = o.ibuffer;
vbuffers = o.vbuffers;
return *this;
}
void D3D12RenderState::ApplyState(ID3D12GraphicsCommandList *cmd)
{
if(pipe != ResourceId())
cmd->SetPipelineState(GetResourceManager()->GetCurrentAs<ID3D12PipelineState>(pipe));
if(!views.empty())
cmd->RSSetViewports((UINT)views.size(), &views[0]);
if(!scissors.empty())
cmd->RSSetScissorRects((UINT)scissors.size(), &scissors[0]);
if(topo != D3D_PRIMITIVE_TOPOLOGY_UNDEFINED)
cmd->IASetPrimitiveTopology(topo);
if(ibuffer.buf != ResourceId())
{
D3D12_INDEX_BUFFER_VIEW ib;
ID3D12Resource *res = GetResourceManager()->GetCurrentAs<ID3D12Resource>(ibuffer.buf);
if(res)
ib.BufferLocation = res->GetGPUVirtualAddress() + ibuffer.offs;
else
ib.BufferLocation = 0;
ib.Format = (ibuffer.bytewidth == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT);
ib.SizeInBytes = ibuffer.size;
cmd->IASetIndexBuffer(&ib);
}
for(size_t i = 0; i < vbuffers.size(); i++)
{
D3D12_VERTEX_BUFFER_VIEW vb;
ID3D12Resource *res = GetResourceManager()->GetCurrentAs<ID3D12Resource>(vbuffers[i].buf);
if(res)
vb.BufferLocation = res->GetGPUVirtualAddress() + vbuffers[i].offs;
else
vb.BufferLocation = 0;
vb.StrideInBytes = vbuffers[i].stride;
vb.SizeInBytes = vbuffers[i].size;
cmd->IASetVertexBuffers((UINT)i, 1, &vb);
}
if(!rts.empty() || dsv.heap != ResourceId())
{
D3D12_CPU_DESCRIPTOR_HANDLE rtHandles[8];
D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = FromPortableHandle(GetResourceManager(), dsv);
UINT numActualHandles = rtSingle ? 1 : (UINT)rts.size();
for(UINT i = 0; i < numActualHandles; i++)
rtHandles[i] = FromPortableHandle(GetResourceManager(), rts[i]);
// need to unwrap here, as FromPortableHandle unwraps too.
Unwrap(cmd)->OMSetRenderTargets((UINT)rts.size(), rtHandles, rtSingle ? TRUE : FALSE,
dsv.heap != ResourceId() ? &dsvHandle : NULL);
}
if(graphics.rootsig != ResourceId())
{
cmd->SetGraphicsRootSignature(
GetResourceManager()->GetCurrentAs<ID3D12RootSignature>(graphics.rootsig));
for(size_t i = 0; i < graphics.sigelems.size(); i++)
graphics.sigelems[i].SetToCommandList(GetResourceManager(), cmd, (UINT)i);
}
if(compute.rootsig != ResourceId())
{
cmd->SetComputeRootSignature(
GetResourceManager()->GetCurrentAs<ID3D12RootSignature>(compute.rootsig));
for(size_t i = 0; i < compute.sigelems.size(); i++)
compute.sigelems[i].SetToCommandList(GetResourceManager(), cmd, (UINT)i);
}
}
+152
View File
@@ -0,0 +1,152 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2016 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#pragma once
#include <vector>
#include "d3d12_common.h"
#include "d3d12_manager.h"
class D3D12ResourceManager;
enum SignatureElementType
{
eRootUnknown,
eRootConst,
eRootTable,
eRootCBV,
eRootSRV,
eRootUAV,
};
struct D3D12RenderState
{
D3D12RenderState();
D3D12RenderState &operator=(const D3D12RenderState &o);
void ApplyState(ID3D12GraphicsCommandList *list);
vector<D3D12_VIEWPORT> views;
vector<D3D12_RECT> scissors;
vector<PortableHandle> rts;
bool rtSingle;
PortableHandle dsv;
struct SignatureElement
{
SignatureElement() : type(eRootUnknown), offset(0) {}
SignatureElement(SignatureElementType t, ResourceId i, UINT64 o) : type(t), id(i), offset(o) {}
SignatureElement(UINT val) : type(eRootConst), offset(0) { constants.push_back(val); }
SignatureElement(UINT numVals, const void *vals, UINT destIdx)
{
SetValues(numVals, vals, destIdx);
}
void SetValues(UINT numVals, const void *vals, UINT destIdx)
{
type = eRootConst;
offset = 0;
if(constants.size() < destIdx + numVals)
constants.resize(destIdx + numVals);
memcpy(&constants[destIdx], vals, numVals * sizeof(UINT));
}
void SetToCommandList(D3D12ResourceManager *rm, ID3D12GraphicsCommandList *cmd, UINT slot)
{
if(type == eRootConst)
{
if(constants.size() == 1)
cmd->SetGraphicsRoot32BitConstant(slot, constants[0], 0);
else
cmd->SetGraphicsRoot32BitConstants(slot, (UINT)constants.size(), &constants[0], 0);
}
else if(type == eRootTable)
{
D3D12_GPU_DESCRIPTOR_HANDLE handle =
rm->GetCurrentAs<ID3D12DescriptorHeap>(id)->GetGPUDescriptorHandleForHeapStart();
handle.ptr += sizeof(D3D12Descriptor) * offset;
cmd->SetGraphicsRootDescriptorTable(slot, handle);
}
else if(type == eRootCBV)
{
ID3D12Resource *res = rm->GetCurrentAs<ID3D12Resource>(id);
cmd->SetGraphicsRootConstantBufferView(slot, res->GetGPUVirtualAddress() + offset);
}
else if(type == eRootSRV)
{
ID3D12Resource *res = rm->GetCurrentAs<ID3D12Resource>(id);
cmd->SetGraphicsRootShaderResourceView(slot, res->GetGPUVirtualAddress() + offset);
}
else if(type == eRootUAV)
{
ID3D12Resource *res = rm->GetCurrentAs<ID3D12Resource>(id);
cmd->SetGraphicsRootUnorderedAccessView(slot, res->GetGPUVirtualAddress() + offset);
}
else
{
RDCWARN("Unexpected root signature element of type '%u' - skipping.", type);
}
}
SignatureElementType type;
ResourceId id;
UINT64 offset;
vector<UINT> constants;
};
struct Pipeline
{
ResourceId rootsig;
vector<SignatureElement> sigelems;
} compute, graphics;
ResourceId pipe;
D3D12_PRIMITIVE_TOPOLOGY topo;
struct IdxBuffer
{
ResourceId buf;
UINT64 offs;
int bytewidth;
UINT size;
} ibuffer;
struct VertBuffer
{
ResourceId buf;
UINT64 offs;
UINT stride;
UINT size;
};
vector<VertBuffer> vbuffers;
D3D12ResourceManager *GetResourceManager() { return m_ResourceManager; }
D3D12ResourceManager *m_ResourceManager;
};
@@ -195,6 +195,7 @@
<ClCompile Include="d3d12_manager.cpp" />
<ClCompile Include="d3d12_replay.cpp" />
<ClCompile Include="d3d12_resources.cpp" />
<ClCompile Include="d3d12_state.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="d3d12_commands.h" />
@@ -208,6 +209,7 @@
<ClInclude Include="..\dx\official\d3d12sdklayers.h" />
<ClInclude Include="d3d12_replay.h" />
<ClInclude Include="d3d12_resources.h" />
<ClInclude Include="d3d12_state.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\shaders\dxbc\renderdoc_dxbc.vcxproj">
@@ -54,6 +54,9 @@
<ClInclude Include="d3d12_commands.h">
<Filter>Core IFaces</Filter>
</ClInclude>
<ClInclude Include="d3d12_state.h">
<Filter>Util</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="d3d12_common.cpp">
@@ -89,5 +92,8 @@
<ClCompile Include="d3d12_debug.cpp">
<Filter>Replay</Filter>
</ClCompile>
<ClCompile Include="d3d12_state.cpp">
<Filter>Util</Filter>
</ClCompile>
</ItemGroup>
</Project>