Add support for D3D12On7

This commit is contained in:
baldurk
2019-08-22 18:43:48 +01:00
parent 346ee91f70
commit c2fe16b44a
19 changed files with 1077 additions and 258 deletions
+41 -50
View File
@@ -903,7 +903,8 @@ bool WrappedID3D11Device::ProcessChunk(ReadSerialiser &ser, D3D11Chunk context)
return true;
}
case D3D11Chunk::SetResourceName: return Serialise_SetResourceName(ser, 0x0, "");
case D3D11Chunk::CreateSwapBuffer: return Serialise_WrapSwapchainBuffer(ser, 0x0, 0x0, 0, 0x0);
case D3D11Chunk::CreateSwapBuffer:
return Serialise_WrapSwapchainBuffer(ser, 0x0, DXGI_FORMAT_UNKNOWN, 0, 0x0);
case D3D11Chunk::CreateTexture1D: return Serialise_CreateTexture1D(ser, 0x0, 0x0, 0x0);
case D3D11Chunk::CreateTexture2D: return Serialise_CreateTexture2D(ser, 0x0, 0x0, 0x0);
@@ -1254,7 +1255,7 @@ void WrappedID3D11Device::ReplayLog(uint32_t startEventID, uint32_t endEventID,
D3D11MarkerRegion::Set("!!!!RenderDoc Internal: Done replay");
}
void WrappedID3D11Device::ReleaseSwapchainResources(WrappedIDXGISwapChain4 *swap, UINT QueueCount,
void WrappedID3D11Device::ReleaseSwapchainResources(IDXGISwapper *swapper, UINT QueueCount,
IUnknown *const *ppPresentQueue,
IUnknown **unwrappedQueues)
{
@@ -1267,9 +1268,9 @@ void WrappedID3D11Device::ReleaseSwapchainResources(WrappedIDXGISwapChain4 *swap
unwrappedQueues[i] = ppPresentQueue[i];
}
for(int i = 0; i < swap->GetNumBackbuffers(); i++)
for(int i = 0; i < swapper->GetNumBackbuffers(); i++)
{
WrappedID3D11Texture2D1 *wrapped11 = (WrappedID3D11Texture2D1 *)swap->GetBackbuffers()[i];
WrappedID3D11Texture2D1 *wrapped11 = (WrappedID3D11Texture2D1 *)swapper->GetBackbuffers()[i];
if(wrapped11)
{
ResourceRange range(wrapped11);
@@ -1292,16 +1293,16 @@ void WrappedID3D11Device::ReleaseSwapchainResources(WrappedIDXGISwapChain4 *swap
wrapped11 = NULL;
}
if(swap)
HWND wnd = swapper->GetHWND();
if(wnd)
{
DXGI_SWAP_CHAIN_DESC desc = swap->GetDescWithHWND();
Keyboard::RemoveInputWindow(wnd);
Keyboard::RemoveInputWindow(desc.OutputWindow);
RenderDoc::Inst().RemoveFrameCapturer((ID3D11Device *)this, desc.OutputWindow);
RenderDoc::Inst().RemoveFrameCapturer((ID3D11Device *)this, wnd);
}
auto it = m_SwapChains.find(swap);
auto it = m_SwapChains.find(swapper);
if(it != m_SwapChains.end())
{
SAFE_RELEASE(it->second);
@@ -1310,9 +1311,8 @@ void WrappedID3D11Device::ReleaseSwapchainResources(WrappedIDXGISwapChain4 *swap
}
template <typename SerialiserType>
bool WrappedID3D11Device::Serialise_WrapSwapchainBuffer(SerialiserType &ser,
WrappedIDXGISwapChain4 *swap,
DXGI_SWAP_CHAIN_DESC *swapDesc, UINT Buffer,
bool WrappedID3D11Device::Serialise_WrapSwapchainBuffer(SerialiserType &ser, IDXGISwapper *swapper,
DXGI_FORMAT bufferFormat, UINT Buffer,
IUnknown *realSurface)
{
WrappedID3D11Texture2D1 *pTex = (WrappedID3D11Texture2D1 *)realSurface;
@@ -1367,9 +1367,8 @@ bool WrappedID3D11Device::Serialise_WrapSwapchainBuffer(SerialiserType &ser,
return true;
}
IUnknown *WrappedID3D11Device::WrapSwapchainBuffer(WrappedIDXGISwapChain4 *swap,
DXGI_SWAP_CHAIN_DESC *swapDesc, UINT buffer,
IUnknown *realSurface)
IUnknown *WrappedID3D11Device::WrapSwapchainBuffer(IDXGISwapper *swapper, DXGI_FORMAT bufferFormat,
UINT buffer, IUnknown *realSurface)
{
if(GetResourceManager()->HasWrapper((ID3D11DeviceChild *)realSurface))
{
@@ -1415,7 +1414,7 @@ IUnknown *WrappedID3D11Device::WrapSwapchainBuffer(WrappedIDXGISwapChain4 *swap,
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CreateSwapBuffer);
Serialise_WrapSwapchainBuffer(ser, swap, swapDesc, buffer, pTex);
Serialise_WrapSwapchainBuffer(ser, swapper, bufferFormat, buffer, pTex);
record->AddChunk(scope.Get());
}
@@ -1428,16 +1427,16 @@ IUnknown *WrappedID3D11Device::WrapSwapchainBuffer(WrappedIDXGISwapChain4 *swap,
if(FAILED(hr))
RDCERR("Couldn't create RTV for swapchain tex HRESULT: %s", ToStr(hr).c_str());
m_SwapChains[swap] = rtv;
m_SwapChains[swapper] = rtv;
}
if(swap)
HWND wnd = swapper->GetHWND();
if(wnd)
{
DXGI_SWAP_CHAIN_DESC sdesc = swap->GetDescWithHWND();
Keyboard::AddInputWindow(wnd);
Keyboard::AddInputWindow(sdesc.OutputWindow);
RenderDoc::Inst().AddFrameCapturer((ID3D11Device *)this, sdesc.OutputWindow, this);
RenderDoc::Inst().AddFrameCapturer((ID3D11Device *)this, wnd, this);
}
return pTex;
@@ -1531,22 +1530,20 @@ bool WrappedID3D11Device::EndFrameCapture(void *dev, void *wnd)
CaptureFailReason reason;
WrappedIDXGISwapChain4 *swap = NULL;
IDXGISwapper *swapper = NULL;
if(wnd)
{
for(auto it = m_SwapChains.begin(); it != m_SwapChains.end(); ++it)
{
DXGI_SWAP_CHAIN_DESC swapDesc = it->first->GetDescWithHWND();
if(swapDesc.OutputWindow == wnd)
if(it->first->GetHWND() == wnd)
{
swap = it->first;
swapper = it->first;
break;
}
}
if(swap == NULL)
if(swapper == NULL)
{
RDCERR("Output window %p provided for frame capture corresponds with no known swap chain", wnd);
return false;
@@ -1581,9 +1578,9 @@ bool WrappedID3D11Device::EndFrameCapture(void *dev, void *wnd)
const uint32_t maxSize = 2048;
RenderDoc::FramePixels fp;
if(swap != NULL)
if(swapper != NULL)
{
ID3D11RenderTargetView *rtv = m_SwapChains[swap];
ID3D11RenderTargetView *rtv = m_SwapChains[swapper];
ID3D11Resource *res = NULL;
@@ -1828,19 +1825,18 @@ bool WrappedID3D11Device::EndFrameCapture(void *dev, void *wnd)
m_Failures++;
if((RenderDoc::Inst().GetOverlayBits() & eRENDERDOC_Overlay_Enabled) && swap != NULL)
if((RenderDoc::Inst().GetOverlayBits() & eRENDERDOC_Overlay_Enabled) && swapper)
{
D3D11RenderState old = *m_pImmediateContext->GetCurrentPipelineState();
ID3D11RenderTargetView *rtv = m_SwapChains[swap];
ID3D11RenderTargetView *rtv = m_SwapChains[swapper];
if(rtv)
{
m_pImmediateContext->GetReal()->OMSetRenderTargets(1, &rtv, NULL);
DXGI_SWAP_CHAIN_DESC swapDesc = swap->GetDescWithHWND();
m_TextRenderer->SetOutputDimensions(swapDesc.BufferDesc.Width, swapDesc.BufferDesc.Height);
m_TextRenderer->SetOutputWindow(swapDesc.OutputWindow);
m_TextRenderer->SetOutputDimensions(swapper->GetWidth(), swapper->GetHeight());
m_TextRenderer->SetOutputWindow(swapper->GetHWND());
m_TextRenderer->RenderText(0.0f, 0.0f, "Failed to capture frame %u: %s", m_FrameCounter,
reasonString);
@@ -2091,20 +2087,18 @@ void WrappedID3D11Device::UnlockForChunkRemoval()
}
}
void WrappedID3D11Device::FirstFrame(WrappedIDXGISwapChain4 *swapChain)
void WrappedID3D11Device::FirstFrame(IDXGISwapper *swapper)
{
DXGI_SWAP_CHAIN_DESC swapdesc = swapChain->GetDescWithHWND();
// if we have to capture the first frame, begin capturing immediately
if(IsBackgroundCapturing(m_State) && RenderDoc::Inst().ShouldTriggerCapture(0))
{
RenderDoc::Inst().StartFrameCapture((ID3D11Device *)this, swapdesc.OutputWindow);
RenderDoc::Inst().StartFrameCapture((ID3D11Device *)this, swapper->GetHWND());
m_AppControlledCapture = false;
}
}
HRESULT WrappedID3D11Device::Present(WrappedIDXGISwapChain4 *swap, UINT SyncInterval, UINT Flags)
HRESULT WrappedID3D11Device::Present(IDXGISwapper *swapper, UINT SyncInterval, UINT Flags)
{
if((Flags & DXGI_PRESENT_TEST) != 0)
return S_OK;
@@ -2120,8 +2114,7 @@ HRESULT WrappedID3D11Device::Present(WrappedIDXGISwapChain4 *swap, UINT SyncInte
m_pImmediateContext->BeginFrame();
DXGI_SWAP_CHAIN_DESC swapdesc = swap->GetDescWithHWND();
bool activeWindow = RenderDoc::Inst().IsActiveWindow((ID3D11Device *)this, swapdesc.OutputWindow);
bool activeWindow = RenderDoc::Inst().IsActiveWindow((ID3D11Device *)this, swapper->GetHWND());
if(IsBackgroundCapturing(m_State))
{
@@ -2131,14 +2124,12 @@ HRESULT WrappedID3D11Device::Present(WrappedIDXGISwapChain4 *swap, UINT SyncInte
if(overlay & eRENDERDOC_Overlay_Enabled)
{
ID3D11RenderTargetView *rtv = m_SwapChains[swap];
ID3D11RenderTargetView *rtv = m_SwapChains[swapper];
m_pImmediateContext->GetReal()->OMSetRenderTargets(1, &rtv, NULL);
DXGI_SWAP_CHAIN_DESC swapDesc = {0};
swap->GetDesc(&swapDesc);
m_TextRenderer->SetOutputDimensions(swapDesc.BufferDesc.Width, swapDesc.BufferDesc.Height);
m_TextRenderer->SetOutputWindow(swapDesc.OutputWindow);
m_TextRenderer->SetOutputDimensions(swapper->GetWidth(), swapper->GetHeight());
m_TextRenderer->SetOutputWindow(swapper->GetHWND());
int flags = activeWindow ? RenderDoc::eOverlay_ActiveWindow : 0;
std::string overlayText =
@@ -2175,12 +2166,12 @@ HRESULT WrappedID3D11Device::Present(WrappedIDXGISwapChain4 *swap, UINT SyncInte
{
m_pImmediateContext->Present(SyncInterval, Flags);
RenderDoc::Inst().EndFrameCapture((ID3D11Device *)this, swapdesc.OutputWindow);
RenderDoc::Inst().EndFrameCapture((ID3D11Device *)this, swapper->GetHWND());
}
if(IsBackgroundCapturing(m_State) && RenderDoc::Inst().ShouldTriggerCapture(m_FrameCounter))
{
RenderDoc::Inst().StartFrameCapture((ID3D11Device *)this, swapdesc.OutputWindow);
RenderDoc::Inst().StartFrameCapture((ID3D11Device *)this, swapper->GetHWND());
m_AppControlledCapture = false;
}
+6 -6
View File
@@ -371,7 +371,7 @@ private:
static WrappedID3D11Device *m_pCurrentWrappedDevice;
std::map<WrappedIDXGISwapChain4 *, ID3D11RenderTargetView *> m_SwapChains;
std::map<IDXGISwapper *, ID3D11RenderTargetView *> m_SwapChains;
uint32_t m_FrameCounter;
uint32_t m_FailedFrame;
@@ -440,7 +440,7 @@ public:
void UnlockForChunkRemoval();
SDFile &GetStructuredFile() { return *m_StructuredFile; }
void FirstFrame(WrappedIDXGISwapChain4 *swapChain);
void FirstFrame(IDXGISwapper *swapper);
std::vector<DebugMessage> GetDebugMessages();
void AddDebugMessage(DebugMessage msg);
@@ -519,8 +519,8 @@ public:
const char *Path);
// Swap Chain
IMPLEMENT_FUNCTION_SERIALISED(IUnknown *, WrapSwapchainBuffer, WrappedIDXGISwapChain4 *swap,
DXGI_SWAP_CHAIN_DESC *desc, UINT buffer, IUnknown *realSurface);
IMPLEMENT_FUNCTION_SERIALISED(IUnknown *, WrapSwapchainBuffer, IDXGISwapper *swapper,
DXGI_FORMAT bufferFormat, UINT buffer, IUnknown *realSurface);
// this is defined as a macro so that we can re-use it to explicitly instantiate these functions as
// templates in the wrapper definition file.
@@ -536,11 +536,11 @@ public:
SERIALISED_ID3D11DEVICE_FAKE_FUNCTIONS();
HRESULT Present(WrappedIDXGISwapChain4 *swap, UINT SyncInterval, UINT Flags);
HRESULT Present(IDXGISwapper *swapper, UINT SyncInterval, UINT Flags);
void NewSwapchainBuffer(IUnknown *backbuffer);
void ReleaseSwapchainResources(WrappedIDXGISwapChain4 *swap, UINT QueueCount,
void ReleaseSwapchainResources(IDXGISwapper *swapper, UINT QueueCount,
IUnknown *const *ppPresentQueue, IUnknown **unwrappedQueues);
ResourceId GetBackbufferResourceID() { return m_BBID; }
+60 -9
View File
@@ -68,18 +68,43 @@ struct WrappedID3D12DebugCommandQueue : public ID3D12DebugCommandQueue
}
};
struct WrappedDownlevelQueue : public ID3D12CommandQueueDownlevel
{
WrappedID3D12CommandQueue &m_pQueue;
WrappedDownlevelQueue(WrappedID3D12CommandQueue &q) : m_pQueue(q) {}
//////////////////////////////
// implement IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
//////////////////////////////
// implement ID3D12CommandQueueDownlevel
virtual HRESULT STDMETHODCALLTYPE Present(ID3D12GraphicsCommandList *pOpenCommandList,
ID3D12Resource *pSourceTex2D, HWND hWindow,
D3D12_DOWNLEVEL_PRESENT_FLAGS Flags);
};
class WrappedID3D12GraphicsCommandList;
class WrappedID3D12CommandQueue : public ID3D12CommandQueue,
public RefCounter12<ID3D12CommandQueue>,
public ID3DDevice
public ID3DDevice,
public IDXGISwapper
{
friend class WrappedID3D12GraphicsCommandList;
ID3D12CommandQueueDownlevel *m_pDownlevel;
WrappedDownlevelQueue m_WrappedDownlevel;
WrappedID3D12Device *m_pDevice;
WrappedID3D12GraphicsCommandList *m_ReplayList;
ID3D12Resource *m_pPresentSource = NULL;
HWND m_pPresentHWND = NULL;
ResourceId m_ResourceID;
D3D12ResourceRecord *m_QueueRecord;
@@ -155,27 +180,48 @@ public:
return NULL;
}
// the rest forward to the device
virtual void FirstFrame(WrappedIDXGISwapChain4 *swapChain) { m_pDevice->FirstFrame(swapChain); }
virtual void FirstFrame(IDXGISwapper *swapper) { m_pDevice->FirstFrame(swapper); }
virtual void NewSwapchainBuffer(IUnknown *backbuffer)
{
m_pDevice->NewSwapchainBuffer(backbuffer);
}
virtual void ReleaseSwapchainResources(WrappedIDXGISwapChain4 *swapChain, UINT QueueCount,
virtual void ReleaseSwapchainResources(IDXGISwapper *swapper, UINT QueueCount,
IUnknown *const *ppPresentQueue, IUnknown **unwrappedQueues)
{
m_pDevice->ReleaseSwapchainResources(swapChain, QueueCount, ppPresentQueue, unwrappedQueues);
m_pDevice->ReleaseSwapchainResources(swapper, QueueCount, ppPresentQueue, unwrappedQueues);
}
virtual IUnknown *WrapSwapchainBuffer(WrappedIDXGISwapChain4 *swap, DXGI_SWAP_CHAIN_DESC *swapDesc,
virtual IUnknown *WrapSwapchainBuffer(IDXGISwapper *swapper, DXGI_FORMAT bufferFormat,
UINT buffer, IUnknown *realSurface)
{
return m_pDevice->WrapSwapchainBuffer(swap, swapDesc, buffer, realSurface);
return m_pDevice->WrapSwapchainBuffer(swapper, bufferFormat, buffer, realSurface);
}
virtual HRESULT Present(WrappedIDXGISwapChain4 *swapChain, UINT SyncInterval, UINT Flags)
virtual HRESULT Present(IDXGISwapper *swapper, UINT SyncInterval, UINT Flags)
{
return m_pDevice->Present(swapChain, SyncInterval, Flags);
return m_pDevice->Present(swapper, SyncInterval, Flags);
}
// fake pretending to be a swapchain for when we're doing downlevel mega-hacky presents
virtual ID3DDevice *GetD3DDevice() { return this; }
virtual int GetNumBackbuffers() { return 1; }
virtual IUnknown **GetBackbuffers() { return (IUnknown **)&m_pPresentSource; }
virtual int GetLastPresentedBuffer() { return 0; }
virtual UINT GetWidth()
{
D3D12_RESOURCE_DESC desc = m_pPresentSource->GetDesc();
return (UINT)desc.Width;
}
virtual UINT GetHeight()
{
D3D12_RESOURCE_DESC desc = m_pPresentSource->GetDesc();
return desc.Height;
}
virtual DXGI_FORMAT GetFormat()
{
D3D12_RESOURCE_DESC desc = m_pPresentSource->GetDesc();
return desc.Format;
}
virtual HWND GetHWND() { return m_pPresentHWND; }
//////////////////////////////
// implement IUnknown
@@ -252,7 +298,7 @@ public:
virtual void ExecuteCommandListsInternal(UINT NumCommandLists,
ID3D12CommandList *const *ppCommandLists,
bool InFrameCaptureBoundary);
bool InFrameCaptureBoundary, bool SkipRealExecute);
IMPLEMENT_FUNCTION_SERIALISED(virtual void STDMETHODCALLTYPE, SetMarker, UINT Metadata,
const void *pData, UINT Size);
@@ -275,6 +321,11 @@ public:
UINT64 *pGpuTimestamp, UINT64 *pCpuTimestamp);
virtual D3D12_COMMAND_QUEUE_DESC STDMETHODCALLTYPE GetDesc() { return m_pReal->GetDesc(); }
//////////////////////////////
// implement ID3D12CommandQueueDownlevel
virtual HRESULT STDMETHODCALLTYPE Present(ID3D12GraphicsCommandList *pOpenCommandList,
ID3D12Resource *pSourceTex2D, HWND hWindow,
D3D12_DOWNLEVEL_PRESENT_FLAGS Flags);
};
template <>
@@ -324,12 +324,13 @@ bool WrappedID3D12CommandQueue::Serialise_ExecuteCommandLists(SerialiserType &se
void WrappedID3D12CommandQueue::ExecuteCommandLists(UINT NumCommandLists,
ID3D12CommandList *const *ppCommandLists)
{
ExecuteCommandListsInternal(NumCommandLists, ppCommandLists, false);
ExecuteCommandListsInternal(NumCommandLists, ppCommandLists, false, false);
}
void WrappedID3D12CommandQueue::ExecuteCommandListsInternal(UINT NumCommandLists,
ID3D12CommandList *const *ppCommandLists,
bool InFrameCaptureBoundary)
bool InFrameCaptureBoundary,
bool SkipRealExecute)
{
ID3D12CommandList **unwrapped = m_pDevice->GetTempArray<ID3D12CommandList *>(NumCommandLists);
for(UINT i = 0; i < NumCommandLists; i++)
@@ -344,7 +345,10 @@ void WrappedID3D12CommandQueue::ExecuteCommandListsInternal(UINT NumCommandLists
if(IsActiveCapturing(m_State))
m_pDevice->AddCaptureSubmission();
SERIALISE_TIME_CALL(m_pReal->ExecuteCommandLists(NumCommandLists, unwrapped));
if(!SkipRealExecute)
{
SERIALISE_TIME_CALL(m_pReal->ExecuteCommandLists(NumCommandLists, unwrapped));
}
if(IsCaptureMode(m_State))
{
@@ -766,6 +770,65 @@ HRESULT STDMETHODCALLTYPE WrappedID3D12CommandQueue::GetClockCalibration(UINT64
return m_pReal->GetClockCalibration(pGpuTimestamp, pCpuTimestamp);
}
HRESULT STDMETHODCALLTYPE WrappedID3D12CommandQueue::Present(
_In_ ID3D12GraphicsCommandList *pOpenCommandList, _In_ ID3D12Resource *pSourceTex2D,
_In_ HWND hWindow, D3D12_DOWNLEVEL_PRESENT_FLAGS Flags)
{
// D3D12 on windows 7
if(!RenderDoc::Inst().GetCaptureOptions().allowVSync)
{
Flags = D3D12_DOWNLEVEL_PRESENT_FLAG_NONE;
}
// store the timestamp, thread ID etc. Don't store the duration
SERIALISE_TIME_CALL();
if(IsCaptureMode(m_State))
{
WrappedID3D12GraphicsCommandList *list = (WrappedID3D12GraphicsCommandList *)pOpenCommandList;
// add a marker
const char str[] = "ID3D12CommandQueueDownlevel::Present()";
list->SetMarker(PIX_EVENT_ANSI_VERSION, str, sizeof(str));
// the list is implicitly closed, serialise that
D3D12ResourceRecord *listRecord = GetRecord(list);
{
CACHE_THREAD_SERIALISER();
ser.SetDrawChunk();
SCOPED_SERIALISE_CHUNK(D3D12Chunk::List_Close);
list->Serialise_Close(ser);
listRecord->AddChunk(scope.Get());
}
listRecord->Bake();
// this queue implicitly submits the list, serialise that
ID3D12CommandList *submitlist = list;
ExecuteCommandListsInternal(1, &submitlist, false, true);
}
if(m_pPresentHWND != NULL)
{
// don't let the device actually release any refs on the resource, just make it release internal
// resources
m_pPresentSource->AddRef();
m_pDevice->ReleaseSwapchainResources(this, 0, NULL, NULL);
}
m_pPresentSource = pSourceTex2D;
m_pPresentHWND = hWindow;
m_pDevice->WrapSwapchainBuffer(this, GetFormat(), 0, m_pPresentSource);
m_pDevice->Present(pOpenCommandList, this,
Flags == D3D12_DOWNLEVEL_PRESENT_FLAG_WAIT_FOR_VBLANK ? 1 : 0, 0);
return m_pDownlevel->Present(Unwrap(pOpenCommandList), Unwrap(pSourceTex2D), hWindow, Flags);
}
INSTANTIATE_FUNCTION_SERIALISED(
void, WrappedID3D12CommandQueue, UpdateTileMappings, ID3D12Resource *pResource,
UINT NumResourceRegions, const D3D12_TILED_RESOURCE_COORDINATE *pResourceRegionStartCoordinates,
+42 -1
View File
@@ -256,17 +256,43 @@ ULONG STDMETHODCALLTYPE WrappedID3D12DebugCommandList::Release()
return 1;
}
HRESULT STDMETHODCALLTYPE WrappedDownlevelQueue::QueryInterface(REFIID riid, void **ppvObject)
{
return m_pQueue.QueryInterface(riid, ppvObject);
}
ULONG STDMETHODCALLTYPE WrappedDownlevelQueue::AddRef()
{
return m_pQueue.AddRef();
}
ULONG STDMETHODCALLTYPE WrappedDownlevelQueue::Release()
{
return m_pQueue.Release();
}
HRESULT STDMETHODCALLTYPE WrappedDownlevelQueue::Present(ID3D12GraphicsCommandList *pOpenCommandList,
ID3D12Resource *pSourceTex2D, HWND hWindow,
D3D12_DOWNLEVEL_PRESENT_FLAGS Flags)
{
return m_pQueue.Present(pOpenCommandList, pSourceTex2D, hWindow, Flags);
}
WrappedID3D12CommandQueue::WrappedID3D12CommandQueue(ID3D12CommandQueue *real,
WrappedID3D12Device *device, CaptureState &state)
: RefCounter12(real), m_pDevice(device), m_State(state)
: RefCounter12(real), m_pDevice(device), m_State(state), m_WrappedDownlevel(*this)
{
if(RenderDoc::Inst().GetCrashHandler())
RenderDoc::Inst().GetCrashHandler()->RegisterMemoryRegion(this,
sizeof(WrappedID3D12CommandQueue));
m_WrappedDebug.m_pReal = NULL;
m_pDownlevel = NULL;
if(m_pReal)
{
m_pReal->QueryInterface(__uuidof(ID3D12DebugCommandQueue), (void **)&m_WrappedDebug.m_pReal);
m_pReal->QueryInterface(__uuidof(ID3D12CommandQueueDownlevel), (void **)&m_pDownlevel);
}
if(RenderDoc::Inst().IsReplayApp())
{
@@ -305,6 +331,8 @@ WrappedID3D12CommandQueue::~WrappedID3D12CommandQueue()
m_pDevice->GetResourceManager()->ReleaseCurrentResource(GetResourceID());
m_pDevice->RemoveQueue(this);
SAFE_RELEASE(m_pDownlevel);
for(size_t i = 0; i < m_Cmd.m_IndirectBuffers.size(); i++)
SAFE_RELEASE(m_Cmd.m_IndirectBuffers[i]);
@@ -357,6 +385,19 @@ HRESULT STDMETHODCALLTYPE WrappedID3D12CommandQueue::QueryInterface(REFIID riid,
AddRef();
return S_OK;
}
else if(riid == __uuidof(ID3D12CommandQueueDownlevel))
{
if(m_pDownlevel)
{
*ppvObject = &m_WrappedDownlevel;
AddRef();
return S_OK;
}
else
{
return E_NOINTERFACE;
}
}
else
{
WarnUnknownGUID("ID3D12CommandQueue", riid);
+36
View File
@@ -140,6 +140,10 @@ bool EnableD3D12DebugLayer(PFN_D3D12_GET_DEBUG_INTERFACE getDebugInterface)
return true;
}
else if(hr == DXGI_ERROR_SDK_COMPONENT_MISSING)
{
RDCWARN("Debug layer not available: DXGI_ERROR_SDK_COMPONENT_MISSING");
}
else
{
RDCERR("Couldn't enable debug layer: %x", hr);
@@ -148,6 +152,38 @@ bool EnableD3D12DebugLayer(PFN_D3D12_GET_DEBUG_INTERFACE getDebugInterface)
return false;
}
HRESULT EnumAdapterByLuid(IDXGIFactory1 *factory, LUID luid, IDXGIAdapter **pAdapter)
{
HRESULT hr = S_OK;
*pAdapter = NULL;
for(UINT i = 0; i < 10; i++)
{
IDXGIAdapter *adapter = NULL;
hr = factory->EnumAdapters(i, &adapter);
if(hr == S_OK && adapter)
{
DXGI_ADAPTER_DESC desc;
adapter->GetDesc(&desc);
if(desc.AdapterLuid.LowPart == luid.LowPart && desc.AdapterLuid.HighPart == luid.HighPart)
{
*pAdapter = adapter;
return S_OK;
}
adapter->Release();
}
else
{
break;
}
}
return E_FAIL;
}
D3D12InitParams::D3D12InitParams()
{
MinimumFeatureLevel = D3D_FEATURE_LEVEL_11_0;
+2
View File
@@ -28,6 +28,7 @@
#include "api/replay/renderdoc_replay.h"
#include "core/core.h"
#include "driver/dx/official/D3D12Downlevel.h"
#include "driver/dx/official/d3d12.h"
#include "driver/dx/official/dxgi1_4.h"
#include "driver/shaders/dxbc/dxbc_compile.h"
@@ -53,6 +54,7 @@ struct D3D12MarkerRegion
};
bool EnableD3D12DebugLayer(PFN_D3D12_GET_DEBUG_INTERFACE getDebugInterface = NULL);
HRESULT EnumAdapterByLuid(IDXGIFactory1 *factory, LUID luid, IDXGIAdapter **pAdapter);
inline void SetObjName(ID3D12Object *obj, const std::string &utf8name)
{
+161 -114
View File
@@ -134,12 +134,35 @@ HRESULT STDMETHODCALLTYPE WrappedID3D12DebugDevice::QueryInterface(REFIID riid,
return m_pDebug->QueryInterface(riid, ppvObject);
}
HRESULT STDMETHODCALLTYPE WrappedDownlevelDevice::QueryInterface(REFIID riid, void **ppvObject)
{
return m_pDevice.QueryInterface(riid, ppvObject);
}
ULONG STDMETHODCALLTYPE WrappedDownlevelDevice::AddRef()
{
return m_pDevice.AddRef();
}
ULONG STDMETHODCALLTYPE WrappedDownlevelDevice::Release()
{
return m_pDevice.Release();
}
HRESULT STDMETHODCALLTYPE WrappedDownlevelDevice::QueryVideoMemoryInfo(
UINT NodeIndex, DXGI_MEMORY_SEGMENT_GROUP MemorySegmentGroup,
_Out_ DXGI_QUERY_VIDEO_MEMORY_INFO *pVideoMemoryInfo)
{
return m_pDevice.QueryVideoMemoryInfo(NodeIndex, MemorySegmentGroup, pVideoMemoryInfo);
}
WrappedID3D12Device::WrappedID3D12Device(ID3D12Device *realDevice, D3D12InitParams params,
bool enabledDebugLayer)
: m_RefCounter(realDevice, false),
m_SoftRefCounter(NULL, false),
m_pDevice(realDevice),
m_debugLayerEnabled(enabledDebugLayer)
m_debugLayerEnabled(enabledDebugLayer),
m_WrappedDownlevel(*this)
{
if(RenderDoc::Inst().GetCrashHandler())
RenderDoc::Inst().GetCrashHandler()->RegisterMemoryRegion(this, sizeof(WrappedID3D12Device));
@@ -158,6 +181,7 @@ WrappedID3D12Device::WrappedID3D12Device(ID3D12Device *realDevice, D3D12InitPara
m_pDevice3 = NULL;
m_pDevice4 = NULL;
m_pDevice5 = NULL;
m_pDownlevel = NULL;
if(m_pDevice)
{
m_pDevice->QueryInterface(__uuidof(ID3D12Device1), (void **)&m_pDevice1);
@@ -165,6 +189,7 @@ WrappedID3D12Device::WrappedID3D12Device(ID3D12Device *realDevice, D3D12InitPara
m_pDevice->QueryInterface(__uuidof(ID3D12Device3), (void **)&m_pDevice3);
m_pDevice->QueryInterface(__uuidof(ID3D12Device4), (void **)&m_pDevice4);
m_pDevice->QueryInterface(__uuidof(ID3D12Device5), (void **)&m_pDevice5);
m_pDevice->QueryInterface(__uuidof(ID3D12DeviceDownlevel), (void **)&m_pDownlevel);
for(size_t i = 0; i < ARRAY_COUNT(m_DescriptorIncrements); i++)
m_DescriptorIncrements[i] =
@@ -235,8 +260,8 @@ WrappedID3D12Device::WrappedID3D12Device(ID3D12Device *realDevice, D3D12InitPara
PFN_CREATE_DXGI_FACTORY createFunc = (PFN_CREATE_DXGI_FACTORY)GetProcAddress(
GetModuleHandleA("dxgi.dll"), "CreateDXGIFactory1");
IDXGIFactory4 *tmpFactory = NULL;
HRESULT hr = createFunc(__uuidof(IDXGIFactory4), (void **)&tmpFactory);
IDXGIFactory1 *tmpFactory = NULL;
HRESULT hr = createFunc(__uuidof(IDXGIFactory1), (void **)&tmpFactory);
if(FAILED(hr))
{
@@ -246,8 +271,7 @@ WrappedID3D12Device::WrappedID3D12Device(ID3D12Device *realDevice, D3D12InitPara
if(tmpFactory)
{
IDXGIAdapter *pDXGIAdapter = NULL;
hr = tmpFactory->EnumAdapterByLuid(m_pDevice->GetAdapterLuid(), __uuidof(IDXGIAdapter),
(void **)&pDXGIAdapter);
hr = EnumAdapterByLuid(tmpFactory, m_pDevice->GetAdapterLuid(), &pDXGIAdapter);
if(FAILED(hr))
{
@@ -432,6 +456,7 @@ WrappedID3D12Device::~WrappedID3D12Device()
SAFE_DELETE(m_ResourceManager);
SAFE_RELEASE(m_pDownlevel);
SAFE_RELEASE(m_pDevice5);
SAFE_RELEASE(m_pDevice4);
SAFE_RELEASE(m_pDevice3);
@@ -614,6 +639,19 @@ HRESULT WrappedID3D12Device::QueryInterface(REFIID riid, void **ppvObject)
return E_NOINTERFACE;
}
}
else if(riid == __uuidof(ID3D12DeviceDownlevel))
{
if(m_pDownlevel)
{
*ppvObject = &m_WrappedDownlevel;
AddRef();
return S_OK;
}
else
{
return E_NOINTERFACE;
}
}
else if(riid == __uuidof(ID3D12InfoQueue))
{
RDCWARN(
@@ -783,17 +821,12 @@ void WrappedID3D12Device::CheckForDeath()
}
}
void WrappedID3D12Device::FirstFrame(WrappedIDXGISwapChain4 *swap)
void WrappedID3D12Device::FirstFrame(IDXGISwapper *swapper)
{
DXGI_SWAP_CHAIN_DESC swapdesc = {};
if(swap)
swapdesc = swap->GetDescWithHWND();
// if we have to capture the first frame, begin capturing immediately
if(IsBackgroundCapturing(m_State) && RenderDoc::Inst().ShouldTriggerCapture(0))
{
RenderDoc::Inst().StartFrameCapture((ID3D12Device *)this, swapdesc.OutputWindow);
RenderDoc::Inst().StartFrameCapture((ID3D12Device *)this, swapper->GetHWND());
m_AppControlledCapture = false;
}
@@ -805,7 +838,7 @@ void WrappedID3D12Device::ApplyBarriers(std::vector<D3D12_RESOURCE_BARRIER> &bar
GetResourceManager()->ApplyBarriers(barriers, m_ResourceStates);
}
void WrappedID3D12Device::ReleaseSwapchainResources(WrappedIDXGISwapChain4 *swap, UINT QueueCount,
void WrappedID3D12Device::ReleaseSwapchainResources(IDXGISwapper *swapper, UINT QueueCount,
IUnknown *const *ppPresentQueue,
IUnknown **unwrappedQueues)
{
@@ -820,9 +853,9 @@ void WrappedID3D12Device::ReleaseSwapchainResources(WrappedIDXGISwapChain4 *swap
}
}
for(int i = 0; i < swap->GetNumBackbuffers(); i++)
for(int i = 0; i < swapper->GetNumBackbuffers(); i++)
{
ID3D12Resource *res = (ID3D12Resource *)swap->GetBackbuffers()[i];
ID3D12Resource *res = (ID3D12Resource *)swapper->GetBackbuffers()[i];
if(!res)
continue;
@@ -832,19 +865,19 @@ void WrappedID3D12Device::ReleaseSwapchainResources(WrappedIDXGISwapChain4 *swap
SAFE_RELEASE(wrapped);
}
if(swap)
HWND wnd = swapper->GetHWND();
if(wnd)
{
DXGI_SWAP_CHAIN_DESC desc = swap->GetDescWithHWND();
Keyboard::RemoveInputWindow(wnd);
Keyboard::RemoveInputWindow(desc.OutputWindow);
RenderDoc::Inst().RemoveFrameCapturer((ID3D12Device *)this, desc.OutputWindow);
RenderDoc::Inst().RemoveFrameCapturer((ID3D12Device *)this, wnd);
}
auto it = m_SwapChains.find(swap);
auto it = m_SwapChains.find(swapper);
if(it != m_SwapChains.end())
{
for(int i = 0; i < swap->GetNumBackbuffers(); i++)
for(int i = 0; i < swapper->GetNumBackbuffers(); i++)
FreeRTV(it->second.rtvs[i]);
m_SwapChains.erase(it);
@@ -863,9 +896,8 @@ void WrappedID3D12Device::NewSwapchainBuffer(IUnknown *backbuffer)
}
template <typename SerialiserType>
bool WrappedID3D12Device::Serialise_WrapSwapchainBuffer(SerialiserType &ser,
WrappedIDXGISwapChain4 *swap,
DXGI_SWAP_CHAIN_DESC *swapDesc, UINT Buffer,
bool WrappedID3D12Device::Serialise_WrapSwapchainBuffer(SerialiserType &ser, IDXGISwapper *swapper,
DXGI_FORMAT bufferFormat, UINT Buffer,
IUnknown *realSurface)
{
WrappedID3D12Resource1 *pRes = (WrappedID3D12Resource1 *)realSurface;
@@ -928,60 +960,70 @@ bool WrappedID3D12Device::Serialise_WrapSwapchainBuffer(SerialiserType &ser,
return true;
}
IUnknown *WrappedID3D12Device::WrapSwapchainBuffer(WrappedIDXGISwapChain4 *swap,
DXGI_SWAP_CHAIN_DESC *swapDesc, UINT buffer,
IUnknown *realSurface)
IUnknown *WrappedID3D12Device::WrapSwapchainBuffer(IDXGISwapper *swapper, DXGI_FORMAT bufferFormat,
UINT buffer, IUnknown *realSurface)
{
if(GetResourceManager()->HasWrapper((ID3D12DeviceChild *)realSurface))
ID3D12Resource *pRes = NULL;
ID3D12Resource *query = NULL;
realSurface->QueryInterface(__uuidof(ID3D12Resource), (void **)&query);
if(query)
query->Release();
if(GetResourceManager()->HasWrapper(query))
{
ID3D12Resource *tex =
(ID3D12Resource *)GetResourceManager()->GetWrapper((ID3D12DeviceChild *)realSurface);
tex->AddRef();
pRes = (ID3D12Resource *)GetResourceManager()->GetWrapper(query);
pRes->AddRef();
realSurface->Release();
return tex;
}
ID3D12Resource *pRes = new WrappedID3D12Resource1((ID3D12Resource *)realSurface, this);
ResourceId id = GetResID(pRes);
// there shouldn't be a resource record for this texture as it wasn't created via
// Create*Resource
RDCASSERT(id != ResourceId() && !GetResourceManager()->HasResourceRecord(id));
if(IsCaptureMode(m_State))
else if(WrappedID3D12Resource1::IsAlloc(query))
{
D3D12ResourceRecord *record = GetResourceManager()->AddResourceRecord(id);
record->type = Resource_Resource;
record->DataInSerialiser = false;
record->Length = 0;
// this could be possible if we're doing downlevel presenting
pRes = query;
}
else
{
pRes = new WrappedID3D12Resource1((ID3D12Resource *)realSurface, this);
WrappedID3D12Resource1 *wrapped = (WrappedID3D12Resource1 *)pRes;
ResourceId id = GetResID(pRes);
wrapped->SetResourceRecord(record);
WriteSerialiser &ser = GetThreadSerialiser();
SCOPED_SERIALISE_CHUNK(D3D12Chunk::CreateSwapBuffer);
Serialise_WrapSwapchainBuffer(ser, swap, swapDesc, buffer, pRes);
record->AddChunk(scope.Get());
// there shouldn't be a resource record for this texture as it wasn't created via
// Create*Resource
RDCASSERT(id != ResourceId() && !GetResourceManager()->HasResourceRecord(id));
if(IsCaptureMode(m_State))
{
SCOPED_LOCK(m_ResourceStatesLock);
SubresourceStateVector &states = m_ResourceStates[id];
D3D12ResourceRecord *record = GetResourceManager()->AddResourceRecord(id);
record->type = Resource_Resource;
record->DataInSerialiser = false;
record->Length = 0;
states.resize(1, D3D12_RESOURCE_STATE_PRESENT);
WrappedID3D12Resource1 *wrapped = (WrappedID3D12Resource1 *)pRes;
wrapped->SetResourceRecord(record);
WriteSerialiser &ser = GetThreadSerialiser();
SCOPED_SERIALISE_CHUNK(D3D12Chunk::CreateSwapBuffer);
Serialise_WrapSwapchainBuffer(ser, swapper, bufferFormat, buffer, pRes);
record->AddChunk(scope.Get());
{
SCOPED_LOCK(m_ResourceStatesLock);
SubresourceStateVector &states = m_ResourceStates[id];
states.resize(1, D3D12_RESOURCE_STATE_PRESENT);
}
}
}
if(IsCaptureMode(m_State))
{
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc;
rtvDesc.Format = GetSRGBFormat(swapDesc->BufferDesc.Format);
rtvDesc.Format = GetSRGBFormat(bufferFormat);
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = 0;
rtvDesc.Texture2D.PlaneSlice = 0;
@@ -991,23 +1033,20 @@ IUnknown *WrappedID3D12Device::WrapSwapchainBuffer(WrappedIDXGISwapChain4 *swap,
if(rtv.ptr != 0)
CreateRenderTargetView(pRes, NULL, rtv);
m_SwapChains[swap].rtvs[buffer] = rtv;
m_SwapChains[swapper].rtvs[buffer] = rtv;
ID3DDevice *swapQ = swap->GetD3DDevice();
ID3DDevice *swapQ = swapper->GetD3DDevice();
RDCASSERT(WrappedID3D12CommandQueue::IsAlloc(swapQ));
m_SwapChains[swap].queue = (WrappedID3D12CommandQueue *)swapQ;
// start at -1 so that we know we've never presented before
m_SwapChains[swap].lastPresentedBuffer = -1;
m_SwapChains[swapper].queue = (WrappedID3D12CommandQueue *)swapQ;
}
if(swap)
HWND wnd = swapper->GetHWND();
if(wnd)
{
DXGI_SWAP_CHAIN_DESC sdesc = swap->GetDescWithHWND();
Keyboard::AddInputWindow(wnd);
Keyboard::AddInputWindow(sdesc.OutputWindow);
RenderDoc::Inst().AddFrameCapturer((ID3D12Device *)this, sdesc.OutputWindow, this);
RenderDoc::Inst().AddFrameCapturer((ID3D12Device *)this, wnd, this);
}
return pRes;
@@ -1330,7 +1369,8 @@ void WrappedID3D12Device::WriteToSubresource(ID3D12Resource *Resource, UINT Subr
}
}
HRESULT WrappedID3D12Device::Present(WrappedIDXGISwapChain4 *swap, UINT SyncInterval, UINT Flags)
HRESULT WrappedID3D12Device::Present(ID3D12GraphicsCommandList *pOverlayCommandList,
IDXGISwapper *swapper, UINT SyncInterval, UINT Flags)
{
if((Flags & DXGI_PRESENT_TEST) != 0)
return S_OK;
@@ -1340,22 +1380,9 @@ HRESULT WrappedID3D12Device::Present(WrappedIDXGISwapChain4 *swap, UINT SyncInte
m_FrameCounter++; // first present becomes frame #1, this function is at the end of the frame
DXGI_SWAP_CHAIN_DESC swapdesc = swap->GetDescWithHWND();
bool activeWindow = RenderDoc::Inst().IsActiveWindow((ID3D12Device *)this, swapdesc.OutputWindow);
bool activeWindow = RenderDoc::Inst().IsActiveWindow((ID3D12Device *)this, swapper->GetHWND());
m_LastSwap = swap;
if(swapdesc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD)
{
// discard always presents from 0
m_SwapChains[swap].lastPresentedBuffer = 0;
}
else
{
// other modes use each buffer in turn
m_SwapChains[swap].lastPresentedBuffer++;
m_SwapChains[swap].lastPresentedBuffer %= swapdesc.BufferCount;
}
m_LastSwap = swapper;
if(IsBackgroundCapturing(m_State))
{
@@ -1363,20 +1390,27 @@ HRESULT WrappedID3D12Device::Present(WrappedIDXGISwapChain4 *swap, UINT SyncInte
if(overlay & eRENDERDOC_Overlay_Enabled)
{
SwapPresentInfo &swapInfo = m_SwapChains[swap];
D3D12_CPU_DESCRIPTOR_HANDLE rtv = swapInfo.rtvs[swapInfo.lastPresentedBuffer];
SwapPresentInfo &swapInfo = m_SwapChains[swapper];
D3D12_CPU_DESCRIPTOR_HANDLE rtv = swapInfo.rtvs[swapper->GetLastPresentedBuffer()];
if(rtv.ptr)
{
m_TextRenderer->SetOutputDimensions(swapdesc.BufferDesc.Width, swapdesc.BufferDesc.Height,
swapdesc.BufferDesc.Format);
m_TextRenderer->SetOutputDimensions(swapper->GetWidth(), swapper->GetHeight(),
swapper->GetFormat());
ID3D12GraphicsCommandList *list = GetNewList();
ID3D12GraphicsCommandList *list = pOverlayCommandList;
bool submitlist = false;
if(!list)
{
list = GetNewList();
submitlist = true;
}
// buffer will be in common for presentation, transition to render target
D3D12_RESOURCE_BARRIER barrier = {};
barrier.Transition.pResource =
(ID3D12Resource *)swap->GetBackbuffers()[swapInfo.lastPresentedBuffer];
(ID3D12Resource *)swapper->GetBackbuffers()[swapper->GetLastPresentedBuffer()];
barrier.Transition.Subresource = 0;
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COMMON;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
@@ -1399,10 +1433,13 @@ HRESULT WrappedID3D12Device::Present(WrappedIDXGISwapChain4 *swap, UINT SyncInte
std::swap(barrier.Transition.StateBefore, barrier.Transition.StateAfter);
list->ResourceBarrier(1, &barrier);
list->Close();
if(submitlist)
{
list->Close();
ExecuteLists(swapInfo.queue);
FlushLists(false, swapInfo.queue);
ExecuteLists(swapInfo.queue);
FlushLists(false, swapInfo.queue);
}
}
}
}
@@ -1418,11 +1455,11 @@ HRESULT WrappedID3D12Device::Present(WrappedIDXGISwapChain4 *swap, UINT SyncInte
// kill any current capture that isn't application defined
if(IsActiveCapturing(m_State) && !m_AppControlledCapture)
RenderDoc::Inst().EndFrameCapture((ID3D12Device *)this, swapdesc.OutputWindow);
RenderDoc::Inst().EndFrameCapture((ID3D12Device *)this, swapper->GetHWND());
if(IsBackgroundCapturing(m_State) && RenderDoc::Inst().ShouldTriggerCapture(m_FrameCounter))
{
RenderDoc::Inst().StartFrameCapture((ID3D12Device *)this, swapdesc.OutputWindow);
RenderDoc::Inst().StartFrameCapture((ID3D12Device *)this, swapper->GetHWND());
m_AppControlledCapture = false;
}
@@ -1565,24 +1602,22 @@ bool WrappedID3D12Device::EndFrameCapture(void *dev, void *wnd)
if(!IsActiveCapturing(m_State))
return true;
WrappedIDXGISwapChain4 *swap = NULL;
IDXGISwapper *swapper = NULL;
SwapPresentInfo swapInfo = {};
if(wnd)
{
for(auto it = m_SwapChains.begin(); it != m_SwapChains.end(); ++it)
{
DXGI_SWAP_CHAIN_DESC swapDesc = it->first->GetDescWithHWND();
if(swapDesc.OutputWindow == wnd)
if(it->first->GetHWND() == wnd)
{
swap = it->first;
swapper = it->first;
swapInfo = it->second;
break;
}
}
if(swap == NULL)
if(swapper == NULL)
{
RDCERR("Output window %p provided for frame capture corresponds with no known swap chain", wnd);
return false;
@@ -1593,14 +1628,14 @@ bool WrappedID3D12Device::EndFrameCapture(void *dev, void *wnd)
ID3D12Resource *backbuffer = NULL;
if(swap == NULL)
if(swapper == NULL)
{
swap = m_LastSwap;
swapInfo = m_SwapChains[swap];
swapper = m_LastSwap;
swapInfo = m_SwapChains[swapper];
}
if(swap != NULL)
backbuffer = (ID3D12Resource *)swap->GetBackbuffers()[swapInfo.lastPresentedBuffer];
if(swapper != NULL)
backbuffer = (ID3D12Resource *)swapper->GetBackbuffers()[swapper->GetLastPresentedBuffer()];
std::vector<WrappedID3D12CommandQueue *> queues;
RDCFile *rdc = NULL;
@@ -2266,6 +2301,13 @@ void WrappedID3D12Device::SetName(ID3D12DeviceChild *pResource, const char *Name
}
}
HRESULT STDMETHODCALLTYPE WrappedID3D12Device::QueryVideoMemoryInfo(
UINT NodeIndex, DXGI_MEMORY_SEGMENT_GROUP MemorySegmentGroup,
_Out_ DXGI_QUERY_VIDEO_MEMORY_INFO *pVideoMemoryInfo)
{
return m_pDownlevel->QueryVideoMemoryInfo(NodeIndex, MemorySegmentGroup, pVideoMemoryInfo);
}
byte *WrappedID3D12Device::GetTempMemory(size_t s)
{
TempMem *mem = (TempMem *)Threading::GetTLSValue(tempMemoryTLSSlot);
@@ -2577,8 +2619,13 @@ void WrappedID3D12Device::ExecuteList(ID3D12GraphicsCommandList4 *list,
queue = GetQueue();
ID3D12CommandList *l = list;
queue->ExecuteCommandListsInternal(1, &l, InFrameCaptureBoundary);
queue->ExecuteCommandListsInternal(1, &l, InFrameCaptureBoundary, false);
MarkListExecuted(list);
}
void WrappedID3D12Device::MarkListExecuted(ID3D12GraphicsCommandList4 *list)
{
for(auto it = m_InternalCmds.pendingcmds.begin(); it != m_InternalCmds.pendingcmds.end(); ++it)
{
if(list == *it)
@@ -2605,7 +2652,7 @@ void WrappedID3D12Device::ExecuteLists(WrappedID3D12CommandQueue *queue, bool In
if(queue == NULL)
queue = GetQueue();
queue->ExecuteCommandListsInternal((UINT)cmds.size(), &cmds[0], InFrameCaptureBoundary);
queue->ExecuteCommandListsInternal((UINT)cmds.size(), &cmds[0], InFrameCaptureBoundary, false);
m_InternalCmds.submittedcmds.insert(m_InternalCmds.submittedcmds.end(),
m_InternalCmds.pendingcmds.begin(),
@@ -2693,7 +2740,7 @@ bool WrappedID3D12Device::ProcessChunk(ReadSerialiser &ser, D3D12Chunk context)
return Serialise_SetShaderDebugPath(ser, NULL, NULL);
break;
case D3D12Chunk::CreateSwapBuffer:
return Serialise_WrapSwapchainBuffer(ser, NULL, NULL, 0, NULL);
return Serialise_WrapSwapchainBuffer(ser, NULL, DXGI_FORMAT_UNKNOWN, 0, NULL);
break;
case D3D12Chunk::Device_CreatePipelineState:
return Serialise_CreatePipelineState(ser, NULL, IID(), NULL);
+39 -10
View File
@@ -268,6 +268,23 @@ struct DummyID3D12DebugDevice : public ID3D12DebugDevice2, public ID3D12DebugDev
}
};
struct WrappedDownlevelDevice : public ID3D12DeviceDownlevel
{
WrappedID3D12Device &m_pDevice;
WrappedDownlevelDevice(WrappedID3D12Device &dev) : m_pDevice(dev) {}
//////////////////////////////
// implement IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
//////////////////////////////
// implement ID3D12DeviceDownlevel
virtual HRESULT STDMETHODCALLTYPE
QueryVideoMemoryInfo(UINT NodeIndex, DXGI_MEMORY_SEGMENT_GROUP MemorySegmentGroup,
_Out_ DXGI_QUERY_VIDEO_MEMORY_INFO *pVideoMemoryInfo);
};
class WrappedID3D12CommandQueue;
#define IMPLEMENT_FUNCTION_THREAD_SERIALISED(ret, func, ...) \
@@ -284,6 +301,7 @@ private:
ID3D12Device3 *m_pDevice3;
ID3D12Device4 *m_pDevice4;
ID3D12Device5 *m_pDevice5;
ID3D12DeviceDownlevel *m_pDownlevel;
// list of all queues being captured
std::vector<WrappedID3D12CommandQueue *> m_Queues;
@@ -299,6 +317,8 @@ private:
HANDLE m_GPUSyncHandle;
UINT64 m_GPUSyncCounter;
WrappedDownlevelDevice m_WrappedDownlevel;
std::vector<ID3D12CommandAllocator *> m_CommandAllocators;
D3D12_CPU_DESCRIPTOR_HANDLE AllocRTV();
@@ -405,14 +425,12 @@ private:
D3D12_CPU_DESCRIPTOR_HANDLE rtvs[8];
WrappedID3D12CommandQueue *queue;
int32_t lastPresentedBuffer;
};
std::map<WrappedIDXGISwapChain4 *, SwapPresentInfo> m_SwapChains;
std::map<IDXGISwapper *, SwapPresentInfo> m_SwapChains;
std::map<ResourceId, DXGI_FORMAT> m_BackbufferFormat;
WrappedIDXGISwapChain4 *m_LastSwap;
IDXGISwapper *m_LastSwap;
D3D12_FEATURE_DATA_D3D12_OPTIONS m_D3D12Opts;
D3D12_FEATURE_DATA_D3D12_OPTIONS1 m_D3D12Opts1;
@@ -460,7 +478,7 @@ public:
ResourceId GetResourceID() { return m_ResourceID; }
Threading::RWLock &GetCapTransitionLock() { return m_CapTransitionLock; }
void ReleaseSwapchainResources(IDXGISwapChain *swap, IUnknown **backbuffers, int numBackbuffers);
void FirstFrame(WrappedIDXGISwapChain4 *swap);
void FirstFrame(IDXGISwapper *swapper);
FrameRecord &GetFrameRecord() { return m_FrameRecord; }
const DrawcallDescription *GetDrawcall(uint32_t eventId);
@@ -551,6 +569,7 @@ public:
void ExecuteList(ID3D12GraphicsCommandList4 *list, WrappedID3D12CommandQueue *queue = NULL,
bool InFrameCaptureBoundary = false);
void MarkListExecuted(ID3D12GraphicsCommandList4 *list);
void ExecuteLists(WrappedID3D12CommandQueue *queue = NULL, bool InFrameCaptureBoundary = false);
void FlushLists(bool forceSync = false, ID3D12CommandQueue *queue = NULL);
@@ -611,13 +630,17 @@ public:
return NULL;
}
// Swap Chain
IMPLEMENT_FUNCTION_THREAD_SERIALISED(IUnknown *, WrapSwapchainBuffer,
WrappedIDXGISwapChain4 *swap, DXGI_SWAP_CHAIN_DESC *desc,
UINT buffer, IUnknown *realSurface);
HRESULT Present(WrappedIDXGISwapChain4 *swap, UINT SyncInterval, UINT Flags);
IMPLEMENT_FUNCTION_THREAD_SERIALISED(IUnknown *, WrapSwapchainBuffer, IDXGISwapper *swapper,
DXGI_FORMAT bufferFormat, UINT buffer, IUnknown *realSurface);
HRESULT Present(ID3D12GraphicsCommandList *pOverlayCommandList, IDXGISwapper *swapper,
UINT SyncInterval, UINT Flags);
HRESULT Present(IDXGISwapper *swapper, UINT SyncInterval, UINT Flags)
{
return Present(NULL, swapper, SyncInterval, Flags);
}
void NewSwapchainBuffer(IUnknown *backbuffer);
void ReleaseSwapchainResources(WrappedIDXGISwapChain4 *swap, UINT QueueCount,
void ReleaseSwapchainResources(IDXGISwapper *swapper, UINT QueueCount,
IUnknown *const *ppPresentQueue, IUnknown **unwrappedQueues);
void Map(ID3D12Resource *Resource, UINT Subresource);
@@ -1015,4 +1038,10 @@ public:
virtual D3D12_DRIVER_MATCHING_IDENTIFIER_STATUS STDMETHODCALLTYPE CheckDriverMatchingIdentifier(
_In_ D3D12_SERIALIZED_DATA_TYPE SerializedDataType,
_In_ const D3D12_SERIALIZED_DATA_DRIVER_MATCHING_IDENTIFIER *pIdentifierToCheck);
//////////////////////////////
// implement ID3D12DeviceDownlevel
virtual HRESULT STDMETHODCALLTYPE
QueryVideoMemoryInfo(UINT NodeIndex, DXGI_MEMORY_SEGMENT_GROUP MemorySegmentGroup,
_Out_ DXGI_QUERY_VIDEO_MEMORY_INFO *pVideoMemoryInfo);
};
+67
View File
@@ -28,6 +28,8 @@
#include "d3d12_command_queue.h"
#include "d3d12_device.h"
#include "driver/dx/official/D3D11On12On7.h"
#if ENABLED(RDOC_X64)
#define BIT_SPECIFIC_DLL(dll32, dll64) dll64
@@ -52,6 +54,60 @@ ID3DDevice *GetD3D12DeviceIfAlloc(IUnknown *dev)
return NULL;
}
class WrappedD3D11On12On7 : public RefCounter12<ID3D11On12On7>
{
public:
WrappedD3D11On12On7(ID3D11On12On7 *real) : RefCounter12(real) {}
virtual ~WrappedD3D11On12On7() {}
//////////////////////////////
// Implement IUnknown
ULONG STDMETHODCALLTYPE AddRef() { return RefCounter12::AddRef(); }
ULONG STDMETHODCALLTYPE Release() { return RefCounter12::Release(); }
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)
{
if(riid == __uuidof(IUnknown))
{
*ppvObject = (IUnknown *)this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
//////////////////////////////
// Implement ID3D11On12On7
// Enables usage similar to D3D11On12CreateDevice.
void STDMETHODCALLTYPE SetThreadDeviceCreationParams(ID3D12Device *pDevice,
ID3D12CommandQueue *pGraphicsQueue)
{
RDCASSERT(WrappedID3D12Device::IsAlloc(pDevice));
m_pReal->SetThreadDeviceCreationParams(((WrappedID3D12Device *)pDevice)->GetReal(),
Unwrap(pGraphicsQueue));
}
// Enables usage similar to ID3D11On12Device::CreateWrappedResource.
// Note that the D3D11 resource creation parameters should be similar to the D3D12 resource,
// or else unexpected/undefined behavior may occur.
void STDMETHODCALLTYPE SetThreadResourceCreationParams(ID3D12Resource *pResource)
{
m_pReal->SetThreadResourceCreationParams(Unwrap(pResource));
}
ID3D11On12On7Device *STDMETHODCALLTYPE GetThreadLastCreatedDevice()
{
// don't need to wrap/unwrap, it only deals with ID3D11On12On7Resource
return m_pReal->GetThreadLastCreatedDevice();
}
ID3D11On12On7Resource *STDMETHODCALLTYPE GetThreadLastCreatedResource()
{
// don't need to wrap/unwrap
return m_pReal->GetThreadLastCreatedResource();
}
};
// dummy class to present to the user, while we maintain control
//
// The inheritance is awful for these. See WrappedID3D12DebugDevice for why there are multiple
@@ -145,6 +201,8 @@ public:
GetDebugInterface.Register("d3d12.dll", "D3D12GetDebugInterface", D3D12GetDebugInterface_hook);
EnableExperimentalFeatures.Register("d3d12.dll", "D3D12EnableExperimentalFeatures",
D3D12EnableExperimentalFeatures_hook);
GetD3D11On12On7.Register("d3d11on12.dll", "GetD3D11On12On7Interface",
GetD3D11On12On7Interface_hook);
}
private:
@@ -165,6 +223,7 @@ private:
HookedFunction<PFN_D3D12_GET_DEBUG_INTERFACE> GetDebugInterface;
HookedFunction<PFN_D3D12_CREATE_DEVICE> CreateDevice;
HookedFunction<PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES> EnableExperimentalFeatures;
HookedFunction<PFNGetD3D11On12On7Interface> GetD3D11On12On7;
// re-entrancy detection (can happen in rare cases with e.g. fraps)
bool m_InsideCreate = false;
@@ -325,6 +384,14 @@ private:
return E_NOINTERFACE;
}
static HRESULT WINAPI GetD3D11On12On7Interface_hook(ID3D11On12On7 **ppIface)
{
ID3D11On12On7 *real = NULL;
d3d12hooks.GetD3D11On12On7()(&real);
*ppIface = (ID3D11On12On7 *)(new WrappedD3D11On12On7(real));
return S_OK;
}
static HRESULT WINAPI D3D12GetDebugInterface_hook(REFIID riid, void **ppvDebug)
{
if(riid != __uuidof(ID3D12Debug))
+115 -44
View File
@@ -33,9 +33,9 @@ void D3D12Replay::OutputWindow::MakeRTV(bool msaa)
D3D12_RESOURCE_DESC texDesc = {};
if(bb[0])
if(bbDesc.Width)
{
texDesc = bb[0]->GetDesc();
texDesc = bbDesc;
texDesc.SampleDesc.Count = msaa ? D3D12_MSAA_SAMPLECOUNT : 1;
@@ -46,16 +46,17 @@ void D3D12Replay::OutputWindow::MakeRTV(bool msaa)
texDesc.DepthOrArraySize = 1;
texDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
texDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
texDesc.Height = height;
texDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
texDesc.MipLevels = 1;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Width = width;
multisampled = false;
}
texDesc.Height = height;
texDesc.Width = width;
texDesc.Alignment = 0;
texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
texDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
@@ -191,7 +192,15 @@ uint64_t D3D12Replay::MakeOutputWindow(WindowingData window, bool depth)
HRESULT hr = S_OK;
hr = m_pFactory->CreateSwapChain(m_pDevice->GetQueue(), &swapDesc, &outw.swap);
// on 12On7 just skip creating the swapchain
if(m_D3D12On7)
{
outw.swap = NULL;
}
else
{
hr = m_pFactory->CreateSwapChain(m_pDevice->GetQueue(), &swapDesc, &outw.swap);
}
if(FAILED(hr))
{
@@ -199,8 +208,27 @@ uint64_t D3D12Replay::MakeOutputWindow(WindowingData window, bool depth)
return 0;
}
outw.swap->GetBuffer(0, __uuidof(ID3D12Resource), (void **)&outw.bb[0]);
outw.swap->GetBuffer(1, __uuidof(ID3D12Resource), (void **)&outw.bb[1]);
if(outw.swap)
{
outw.swap->GetBuffer(0, __uuidof(ID3D12Resource), (void **)&outw.bb[0]);
outw.swap->GetBuffer(1, __uuidof(ID3D12Resource), (void **)&outw.bb[1]);
outw.bbDesc = outw.bb[0]->GetDesc();
}
else
{
outw.bbDesc.DepthOrArraySize = 1;
outw.bbDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
outw.bbDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
outw.bbDesc.Height = outw.height;
outw.bbDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
outw.bbDesc.MipLevels = 1;
outw.bbDesc.SampleDesc.Count = 1;
outw.bbDesc.SampleDesc.Quality = 0;
outw.bbDesc.Width = outw.width;
outw.bbDesc.Alignment = 0;
outw.bbDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
outw.bbDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
}
}
else
{
@@ -262,7 +290,7 @@ bool D3D12Replay::CheckResizeOutputWindow(uint64_t id)
OutputWindow &outw = m_OutputWindows[id];
if(outw.wnd == NULL || outw.swap == NULL)
if(outw.wnd == NULL || (outw.swap == NULL && !m_D3D12On7))
return false;
RECT rect;
@@ -283,20 +311,23 @@ bool D3D12Replay::CheckResizeOutputWindow(uint64_t id)
SAFE_RELEASE(outw.bb[0]);
SAFE_RELEASE(outw.bb[1]);
DXGI_SWAP_CHAIN_DESC desc;
outw.swap->GetDesc(&desc);
HRESULT hr = outw.swap->ResizeBuffers(desc.BufferCount, outw.width, outw.height,
desc.BufferDesc.Format, desc.Flags);
if(FAILED(hr))
if(outw.swap)
{
RDCERR("Failed to resize swap chain, HRESULT: %s", ToStr(hr).c_str());
return true;
}
DXGI_SWAP_CHAIN_DESC desc;
outw.swap->GetDesc(&desc);
outw.swap->GetBuffer(0, __uuidof(ID3D12Resource), (void **)&outw.bb[0]);
outw.swap->GetBuffer(1, __uuidof(ID3D12Resource), (void **)&outw.bb[1]);
HRESULT hr = outw.swap->ResizeBuffers(desc.BufferCount, outw.width, outw.height,
desc.BufferDesc.Format, desc.Flags);
if(FAILED(hr))
{
RDCERR("Failed to resize swap chain, HRESULT: %s", ToStr(hr).c_str());
return true;
}
outw.swap->GetBuffer(0, __uuidof(ID3D12Resource), (void **)&outw.bb[0]);
outw.swap->GetBuffer(1, __uuidof(ID3D12Resource), (void **)&outw.bb[1]);
}
outw.bbIdx = 0;
@@ -524,24 +555,26 @@ void D3D12Replay::FlipOutputWindow(uint64_t id)
OutputWindow &outw = m_OutputWindows[id];
if(m_OutputWindows[id].bb[0] == NULL || m_OutputWindows[id].swap == NULL)
if(!m_D3D12On7 && (m_OutputWindows[id].bb[0] == NULL || m_OutputWindows[id].swap == NULL))
return;
D3D12_RESOURCE_BARRIER barriers[3];
RDCEraseEl(barriers);
if(m_OutputWindows[id].col == NULL)
return;
barriers[0].Transition.pResource = outw.col;
barriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
barriers[0].Transition.StateAfter =
D3D12_RESOURCE_BARRIER colbarrier = {}, bbbarrier = {}, resolvebarrier = {};
colbarrier.Transition.pResource = outw.col;
colbarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
colbarrier.Transition.StateAfter =
outw.multisampled ? D3D12_RESOURCE_STATE_RESOLVE_SOURCE : D3D12_RESOURCE_STATE_COPY_SOURCE;
barriers[1].Transition.pResource = outw.bb[outw.bbIdx];
barriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
barriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
bbbarrier.Transition.pResource = outw.bb[outw.bbIdx];
bbbarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
bbbarrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
barriers[2].Transition.pResource = outw.colResolve;
barriers[2].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE;
barriers[2].Transition.StateAfter = D3D12_RESOURCE_STATE_RESOLVE_DEST;
resolvebarrier.Transition.pResource = outw.colResolve;
resolvebarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE;
resolvebarrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RESOLVE_DEST;
ID3D12GraphicsCommandList *list = m_pDevice->GetNewList();
@@ -549,39 +582,77 @@ void D3D12Replay::FlipOutputWindow(uint64_t id)
if(outw.multisampled)
{
// transition colour to resolve source, resolve target to resolve dest, backbuffer to copy dest
list->ResourceBarrier(3, barriers);
list->ResourceBarrier(1, &colbarrier);
list->ResourceBarrier(1, &resolvebarrier);
if(bbbarrier.Transition.pResource)
list->ResourceBarrier(1, &bbbarrier);
// resolve then copy, as the resolve can't go from SRGB to non-SRGB target
list->ResolveSubresource(barriers[2].Transition.pResource, 0, barriers[0].Transition.pResource,
0, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB);
list->ResolveSubresource(outw.colResolve, 0, outw.col, 0, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB);
std::swap(barriers[2].Transition.StateBefore, barriers[2].Transition.StateAfter);
std::swap(resolvebarrier.Transition.StateBefore, resolvebarrier.Transition.StateAfter);
// now move the resolve target into copy source
list->ResourceBarrier(1, &barriers[2]);
list->ResourceBarrier(1, &resolvebarrier);
list->CopyResource(barriers[1].Transition.pResource, barriers[2].Transition.pResource);
if(bbbarrier.Transition.pResource)
list->CopyResource(bbbarrier.Transition.pResource, resolvebarrier.Transition.pResource);
}
else
{
// transition colour to copy source, backbuffer to copy dest
list->ResourceBarrier(2, barriers);
list->ResourceBarrier(1, &colbarrier);
list->CopyResource(barriers[1].Transition.pResource, barriers[0].Transition.pResource);
if(bbbarrier.Transition.pResource)
list->ResourceBarrier(1, &bbbarrier);
if(bbbarrier.Transition.pResource)
list->CopyResource(bbbarrier.Transition.pResource, colbarrier.Transition.pResource);
}
std::swap(barriers[0].Transition.StateBefore, barriers[0].Transition.StateAfter);
std::swap(barriers[1].Transition.StateBefore, barriers[1].Transition.StateAfter);
std::swap(colbarrier.Transition.StateBefore, colbarrier.Transition.StateAfter);
std::swap(bbbarrier.Transition.StateBefore, bbbarrier.Transition.StateAfter);
// transition colour back to render target, and backbuffer back to present
list->ResourceBarrier(2, barriers);
list->ResourceBarrier(1, &colbarrier);
if(bbbarrier.Transition.pResource)
list->ResourceBarrier(1, &bbbarrier);
if(m_D3D12On7)
{
ID3D12Resource *res = outw.multisampled ? outw.colResolve : outw.col;
D3D12_RESOURCE_BARRIER toPresent = {};
toPresent.Transition.pResource = res;
toPresent.Transition.StateBefore =
outw.multisampled ? D3D12_RESOURCE_STATE_COPY_SOURCE : D3D12_RESOURCE_STATE_RENDER_TARGET;
toPresent.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
list->ResourceBarrier(1, &toPresent);
ID3D12CommandQueueDownlevel *downlevel = NULL;
m_pDevice->GetQueue()->QueryInterface(__uuidof(ID3D12CommandQueueDownlevel), (void **)&downlevel);
downlevel->Present(list, res, outw.wnd, D3D12_DOWNLEVEL_PRESENT_FLAG_NONE);
SAFE_RELEASE(downlevel);
m_pDevice->MarkListExecuted((ID3D12GraphicsCommandList4 *)list);
list = m_pDevice->GetNewList();
std::swap(toPresent.Transition.StateBefore, toPresent.Transition.StateAfter);
list->ResourceBarrier(1, &toPresent);
}
list->Close();
m_pDevice->ExecuteLists();
m_pDevice->FlushLists();
outw.swap->Present(0, 0);
if(outw.swap)
outw.swap->Present(0, 0);
outw.bbIdx++;
outw.bbIdx %= 2;
+43 -6
View File
@@ -23,6 +23,7 @@
******************************************************************************/
#include "d3d12_replay.h"
#include "core/plugins.h"
#include "driver/dx/official/d3dcompiler.h"
#include "driver/dxgi/dxgi_common.h"
#include "driver/ihv/amd/amd_counters.h"
@@ -108,7 +109,7 @@ void D3D12Replay::Initialise()
PFN_CREATE_DXGI_FACTORY createFunc =
(PFN_CREATE_DXGI_FACTORY)GetProcAddress(GetModuleHandleA("dxgi.dll"), "CreateDXGIFactory1");
HRESULT hr = createFunc(__uuidof(IDXGIFactory4), (void **)&m_pFactory);
HRESULT hr = createFunc(__uuidof(IDXGIFactory1), (void **)&m_pFactory);
if(FAILED(hr))
{
@@ -119,12 +120,12 @@ void D3D12Replay::Initialise()
if(m_pFactory)
{
RefCountDXGIObject::HandleWrap(__uuidof(IDXGIFactory4), (void **)&m_pFactory);
RefCountDXGIObject::HandleWrap(__uuidof(IDXGIFactory1), (void **)&m_pFactory);
LUID luid = m_pDevice->GetAdapterLuid();
IDXGIAdapter *pDXGIAdapter;
hr = m_pFactory->EnumAdapterByLuid(luid, __uuidof(IDXGIAdapter), (void **)&pDXGIAdapter);
IDXGIAdapter *pDXGIAdapter = NULL;
hr = EnumAdapterByLuid(m_pFactory, luid, &pDXGIAdapter);
if(FAILED(hr))
{
@@ -3586,12 +3587,47 @@ ReplayStatus D3D12_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver)
WrappedIDXGISwapChain4::RegisterD3DDeviceCallback(GetD3D12DeviceIfAlloc);
bool d3d12on7 = false;
HMODULE lib = NULL;
lib = LoadLibraryA("d3d12.dll");
if(lib == NULL)
{
RDCERR("Failed to load d3d12.dll");
return ReplayStatus::APIInitFailed;
// if it fails try to find D3D12On7 DLLs
d3d12on7 = true;
// if it fails, try in the plugin directory
lib = (HMODULE)Process::LoadModule(LocatePluginFile("d3d12", "d3d12.dll").c_str());
// if that succeeded, also load dxilconv7.dll from there
if(lib)
{
HMODULE dxilconv =
(HMODULE)Process::LoadModule(LocatePluginFile("d3d12", "dxilconv7.dll").c_str());
if(!dxilconv)
{
RDCERR("Found d3d12.dll in plugin path, but couldn't load dxilconv7.dll");
return ReplayStatus::APIInitFailed;
}
}
else
{
// if it failed, try one more time in MS's subfolder convention
lib = LoadLibraryA("12on7/d3d12.dll");
if(lib)
{
RDCWARN(
"Loaded d3d12.dll from 12on7 subfolder."
"Please use RenderDoc's plugins/d3d12/ subfolder instead");
}
else
{
RDCERR("Failed to load d3d12.dll");
return ReplayStatus::APIInitFailed;
}
}
}
PFN_D3D12_CREATE_DEVICE createDevice =
@@ -3693,6 +3729,7 @@ ReplayStatus D3D12_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver)
RDCLOG("Created device.");
D3D12Replay *replay = wrappedDev->GetReplay();
replay->Set12On7(d3d12on7);
replay->SetProxy(rdc == NULL);
replay->SetRGP(rgp);
+4 -2
View File
@@ -55,6 +55,7 @@ public:
D3D12DebugManager *GetDebugManager() { return m_DebugManager; }
void SetRGP(AMDRGPControl *rgp) { m_RGP = rgp; }
void Set12On7(bool d3d12on7) { m_D3D12On7 = d3d12on7; }
void SetProxy(bool proxy) { m_Proxy = proxy; }
bool IsRemoteProxy() { return m_Proxy; }
void Initialise();
@@ -288,7 +289,7 @@ private:
ID3D12Resource *m_SOPatchedIndexBuffer = NULL;
ID3D12QueryHeap *m_SOQueryHeap = NULL;
bool m_Proxy;
bool m_Proxy, m_D3D12On7;
std::vector<ID3D12Resource *> m_ProxyResources;
@@ -303,6 +304,7 @@ private:
ID3D12Resource *depth;
D3D12_CPU_DESCRIPTOR_HANDLE rtv;
D3D12_CPU_DESCRIPTOR_HANDLE dsv;
D3D12_RESOURCE_DESC bbDesc;
WrappedID3D12Device *dev;
@@ -419,7 +421,7 @@ private:
D3D12DebugManager *m_DebugManager = NULL;
IDXGIFactory4 *m_pFactory = NULL;
IDXGIFactory1 *m_pFactory = NULL;
AMDCounters *m_pAMDCounters = NULL;
AMDRGPControl *m_RGP = NULL;
@@ -137,6 +137,8 @@
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\dx\official\D3D11On12On7.h" />
<ClInclude Include="..\dx\official\D3D12Downlevel.h" />
<ClInclude Include="d3d12_commands.h" />
<ClInclude Include="d3d12_command_list.h" />
<ClInclude Include="d3d12_command_queue.h" />
@@ -69,6 +69,12 @@
<ClInclude Include="d3d12_rendertext.h">
<Filter>Util</Filter>
</ClInclude>
<ClInclude Include="..\dx\official\D3D12Downlevel.h">
<Filter>official</Filter>
</ClInclude>
<ClInclude Include="..\dx\official\D3D11On12On7.h">
<Filter>official</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="d3d12_common.cpp">
@@ -0,0 +1,32 @@
#pragma once
// Just an identity interface, no functionality exposed, retrieved by ID3D11On12On7::GetThreadLastCreatedResource
interface ID3D11On12On7Resource { };
// Per-device, retrieved by ID3D11On12On7::GetThreadLastCreatedDevice
interface ID3D11On12On7Device
{
// Equivalent to ID3D11On12Device::AcquireWrappedResources:
// From this point on, the resource should be used by D3D11, not by D3D12 directly.
STDMETHOD(AcquireResource)(ID3D11On12On7Resource* pResource, D3D12_RESOURCE_STATES state) = 0;
// Equivalent to ID3D11On12Device::ReleaseWrappedResources:
// Note that this cannot unbind the resource from D3D11, that is the app's responsibility.
// After calling this, the app should call Flush() on the D3D11 device.
STDMETHOD(ReleaseResource)(ID3D11On12On7Resource* pResource, D3D12_RESOURCE_STATES state) = 0;
};
// Global, retrieved by GetD3D11On12On7Interface
interface ID3D11On12On7 : public IUnknown
{
// Enables usage similar to D3D11On12CreateDevice.
STDMETHOD_(void, SetThreadDeviceCreationParams)(ID3D12Device* pDevice, ID3D12CommandQueue* pGraphicsQueue) = 0;
// Enables usage similar to ID3D11On12Device::CreateWrappedResource.
// Note that the D3D11 resource creation parameters should be similar to the D3D12 resource,
// or else unexpected/undefined behavior may occur.
STDMETHOD_(void, SetThreadResourceCreationParams)(ID3D12Resource* pResource) = 0;
STDMETHOD_(ID3D11On12On7Device*, GetThreadLastCreatedDevice)() = 0;
STDMETHOD_(ID3D11On12On7Resource*, GetThreadLastCreatedResource)() = 0;
};
extern "C" HRESULT APIENTRY GetD3D11On12On7Interface(ID3D11On12On7** ppIface);
typedef HRESULT(APIENTRY *PFNGetD3D11On12On7Interface)(ID3D11On12On7** ppIface);
@@ -0,0 +1,280 @@
/*-------------------------------------------------------------------------------------
*
* Copyright (c) Microsoft Corporation
*
*-------------------------------------------------------------------------------------*/
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
/* File created by MIDL compiler version 8.01.0622 */
/* verify that the <rpcndr.h> version is high enough to compile this file*/
#ifndef __REQUIRED_RPCNDR_H_VERSION__
#define __REQUIRED_RPCNDR_H_VERSION__ 500
#endif
/* verify that the <rpcsal.h> version is high enough to compile this file*/
#ifndef __REQUIRED_RPCSAL_H_VERSION__
#define __REQUIRED_RPCSAL_H_VERSION__ 100
#endif
#include "rpc.h"
#include "rpcndr.h"
#ifndef __RPCNDR_H_VERSION__
#error this stub requires an updated version of <rpcndr.h>
#endif /* __RPCNDR_H_VERSION__ */
#ifndef COM_NO_WINDOWS_H
#include "windows.h"
#include "ole2.h"
#endif /*COM_NO_WINDOWS_H*/
#ifndef __d3d12downlevel_h__
#define __d3d12downlevel_h__
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
/* Forward Declarations */
#ifndef __ID3D12CommandQueueDownlevel_FWD_DEFINED__
#define __ID3D12CommandQueueDownlevel_FWD_DEFINED__
typedef interface ID3D12CommandQueueDownlevel ID3D12CommandQueueDownlevel;
#endif /* __ID3D12CommandQueueDownlevel_FWD_DEFINED__ */
#ifndef __ID3D12DeviceDownlevel_FWD_DEFINED__
#define __ID3D12DeviceDownlevel_FWD_DEFINED__
typedef interface ID3D12DeviceDownlevel ID3D12DeviceDownlevel;
#endif /* __ID3D12DeviceDownlevel_FWD_DEFINED__ */
/* header files for imported files */
#include "oaidl.h"
#include "ocidl.h"
#include "d3d12.h"
#include "dxgi1_4.h"
#ifdef __cplusplus
extern "C"{
#endif
/* interface __MIDL_itf_d3d12downlevel_0000_0000 */
/* [local] */
#include "winapifamily.h"
#pragma region Desktop Family
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
typedef
enum D3D12_DOWNLEVEL_PRESENT_FLAGS
{
D3D12_DOWNLEVEL_PRESENT_FLAG_NONE = 0,
D3D12_DOWNLEVEL_PRESENT_FLAG_WAIT_FOR_VBLANK = ( D3D12_DOWNLEVEL_PRESENT_FLAG_NONE + 1 )
} D3D12_DOWNLEVEL_PRESENT_FLAGS;
DEFINE_ENUM_FLAG_OPERATORS( D3D12_DOWNLEVEL_PRESENT_FLAGS );
extern RPC_IF_HANDLE __MIDL_itf_d3d12downlevel_0000_0000_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_d3d12downlevel_0000_0000_v0_0_s_ifspec;
#ifndef __ID3D12CommandQueueDownlevel_INTERFACE_DEFINED__
#define __ID3D12CommandQueueDownlevel_INTERFACE_DEFINED__
/* interface ID3D12CommandQueueDownlevel */
/* [unique][local][object][uuid] */
EXTERN_C const IID IID_ID3D12CommandQueueDownlevel;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("38a8c5ef-7ccb-4e81-914f-a6e9d072c494")
ID3D12CommandQueueDownlevel : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE Present(
_In_ ID3D12GraphicsCommandList *pOpenCommandList,
_In_ ID3D12Resource *pSourceTex2D,
_In_ HWND hWindow,
D3D12_DOWNLEVEL_PRESENT_FLAGS Flags) = 0;
};
#else /* C style interface */
typedef struct ID3D12CommandQueueDownlevelVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ID3D12CommandQueueDownlevel * This,
REFIID riid,
_COM_Outptr_ void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
ID3D12CommandQueueDownlevel * This);
ULONG ( STDMETHODCALLTYPE *Release )(
ID3D12CommandQueueDownlevel * This);
HRESULT ( STDMETHODCALLTYPE *Present )(
ID3D12CommandQueueDownlevel * This,
_In_ ID3D12GraphicsCommandList *pOpenCommandList,
_In_ ID3D12Resource *pSourceTex2D,
_In_ HWND hWindow,
D3D12_DOWNLEVEL_PRESENT_FLAGS Flags);
END_INTERFACE
} ID3D12CommandQueueDownlevelVtbl;
interface ID3D12CommandQueueDownlevel
{
CONST_VTBL struct ID3D12CommandQueueDownlevelVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define ID3D12CommandQueueDownlevel_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define ID3D12CommandQueueDownlevel_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define ID3D12CommandQueueDownlevel_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define ID3D12CommandQueueDownlevel_Present(This,pOpenCommandList,pSourceTex2D,hWindow,Flags) \
( (This)->lpVtbl -> Present(This,pOpenCommandList,pSourceTex2D,hWindow,Flags) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __ID3D12CommandQueueDownlevel_INTERFACE_DEFINED__ */
#ifndef __ID3D12DeviceDownlevel_INTERFACE_DEFINED__
#define __ID3D12DeviceDownlevel_INTERFACE_DEFINED__
/* interface ID3D12DeviceDownlevel */
/* [unique][local][object][uuid] */
EXTERN_C const IID IID_ID3D12DeviceDownlevel;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("74eaee3f-2f4b-476d-82ba-2b85cb49e310")
ID3D12DeviceDownlevel : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE QueryVideoMemoryInfo(
UINT NodeIndex,
DXGI_MEMORY_SEGMENT_GROUP MemorySegmentGroup,
_Out_ DXGI_QUERY_VIDEO_MEMORY_INFO *pVideoMemoryInfo) = 0;
};
#else /* C style interface */
typedef struct ID3D12DeviceDownlevelVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ID3D12DeviceDownlevel * This,
REFIID riid,
_COM_Outptr_ void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
ID3D12DeviceDownlevel * This);
ULONG ( STDMETHODCALLTYPE *Release )(
ID3D12DeviceDownlevel * This);
HRESULT ( STDMETHODCALLTYPE *QueryVideoMemoryInfo )(
ID3D12DeviceDownlevel * This,
UINT NodeIndex,
DXGI_MEMORY_SEGMENT_GROUP MemorySegmentGroup,
_Out_ DXGI_QUERY_VIDEO_MEMORY_INFO *pVideoMemoryInfo);
END_INTERFACE
} ID3D12DeviceDownlevelVtbl;
interface ID3D12DeviceDownlevel
{
CONST_VTBL struct ID3D12DeviceDownlevelVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define ID3D12DeviceDownlevel_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define ID3D12DeviceDownlevel_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define ID3D12DeviceDownlevel_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define ID3D12DeviceDownlevel_QueryVideoMemoryInfo(This,NodeIndex,MemorySegmentGroup,pVideoMemoryInfo) \
( (This)->lpVtbl -> QueryVideoMemoryInfo(This,NodeIndex,MemorySegmentGroup,pVideoMemoryInfo) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __ID3D12DeviceDownlevel_INTERFACE_DEFINED__ */
/* interface __MIDL_itf_d3d12downlevel_0000_0002 */
/* [local] */
#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */
#pragma endregion
DEFINE_GUID(IID_ID3D12CommandQueueDownlevel,0x38a8c5ef,0x7ccb,0x4e81,0x91,0x4f,0xa6,0xe9,0xd0,0x72,0xc4,0x94);
DEFINE_GUID(IID_ID3D12DeviceDownlevel,0x74eaee3f,0x2f4b,0x476d,0x82,0xba,0x2b,0x85,0xcb,0x49,0xe3,0x10);
extern RPC_IF_HANDLE __MIDL_itf_d3d12downlevel_0000_0002_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_d3d12downlevel_0000_0002_v0_0_s_ifspec;
/* Additional Prototypes for ALL interfaces */
/* end of Additional Prototypes */
#ifdef __cplusplus
}
#endif
#endif
+3 -1
View File
@@ -473,7 +473,7 @@ HRESULT WrappedIDXGISwapChain4::GetBuffer(
{
DXGI_SWAP_CHAIN_DESC desc;
GetDesc(&desc);
tex = m_pDevice->WrapSwapchainBuffer(this, &desc, Buffer, realSurface);
tex = m_pDevice->WrapSwapchainBuffer(this, desc.BufferDesc.Format, Buffer, realSurface);
}
// if the original UUID was IDXGISurface, fixup for the expected interface being returned
@@ -534,6 +534,7 @@ HRESULT WrappedIDXGISwapChain4::Present(
SyncInterval = 0;
}
TickLastPresentedBuffer();
m_pDevice->Present(this, SyncInterval, Flags);
return m_pReal->Present(SyncInterval, Flags);
@@ -547,6 +548,7 @@ HRESULT WrappedIDXGISwapChain4::Present1(UINT SyncInterval, UINT Flags,
SyncInterval = 0;
}
TickLastPresentedBuffer();
m_pDevice->Present(this, SyncInterval, Flags);
return m_pReal1->Present1(SyncInterval, Flags, pPresentParameters);
+72 -12
View File
@@ -155,7 +155,19 @@ public:
return RefCountDXGIObject::GetParent(riid, ppvObject); \
}
class WrappedIDXGISwapChain4;
struct ID3DDevice;
struct IDXGISwapper
{
virtual ID3DDevice *GetD3DDevice() = 0;
virtual int GetNumBackbuffers() = 0;
virtual IUnknown **GetBackbuffers() = 0;
virtual int GetLastPresentedBuffer() = 0;
virtual UINT GetWidth() = 0;
virtual UINT GetHeight() = 0;
virtual DXGI_FORMAT GetFormat() = 0;
virtual HWND GetHWND() = 0;
};
struct ID3DDevice
{
@@ -171,16 +183,16 @@ struct ID3DDevice
virtual bool IsDeviceUUID(REFIID guid) = 0;
virtual IUnknown *GetDeviceInterface(REFIID guid) = 0;
virtual void FirstFrame(WrappedIDXGISwapChain4 *swapChain) = 0;
virtual void FirstFrame(IDXGISwapper *swapper) = 0;
virtual void NewSwapchainBuffer(IUnknown *backbuffer) = 0;
virtual void ReleaseSwapchainResources(WrappedIDXGISwapChain4 *swapChain, UINT QueueCount,
virtual void ReleaseSwapchainResources(IDXGISwapper *swapper, UINT QueueCount,
IUnknown *const *ppPresentQueue,
IUnknown **unwrappedQueues) = 0;
virtual IUnknown *WrapSwapchainBuffer(WrappedIDXGISwapChain4 *swap, DXGI_SWAP_CHAIN_DESC *swapDesc,
virtual IUnknown *WrapSwapchainBuffer(IDXGISwapper *swapper, DXGI_FORMAT bufferFormat,
UINT buffer, IUnknown *realSurface) = 0;
virtual HRESULT Present(WrappedIDXGISwapChain4 *swapChain, UINT SyncInterval, UINT Flags) = 0;
virtual HRESULT Present(IDXGISwapper *swapper, UINT SyncInterval, UINT Flags) = 0;
};
typedef ID3DDevice *(*D3DDeviceCallback)(IUnknown *dev);
@@ -545,7 +557,7 @@ public:
}
};
class WrappedIDXGISwapChain4 : public IDXGISwapChain4, public RefCountDXGIObject
class WrappedIDXGISwapChain4 : public IDXGISwapChain4, public RefCountDXGIObject, public IDXGISwapper
{
IDXGISwapChain *m_pReal;
IDXGISwapChain1 *m_pReal1;
@@ -561,11 +573,31 @@ class WrappedIDXGISwapChain4 : public IDXGISwapChain4, public RefCountDXGIObject
static const int MAX_NUM_BACKBUFFERS = 8;
IUnknown *m_pBackBuffers[MAX_NUM_BACKBUFFERS];
int32_t m_LastPresentedBuffer = -1;
void ReleaseBuffersForResize(UINT QueueCount, IUnknown *const *ppPresentQueue,
IUnknown **unwrappedQueues);
void WrapBuffersAfterResize();
void TickLastPresentedBuffer()
{
DXGI_SWAP_CHAIN_DESC desc = {};
m_pReal->GetDesc(&desc);
if(desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD)
{
// discard always presents from 0
m_LastPresentedBuffer = 0;
}
else
{
// other modes use each buffer in turn
m_LastPresentedBuffer++;
m_LastPresentedBuffer %= desc.BufferCount;
}
}
public:
WrappedIDXGISwapChain4(IDXGISwapChain *real, HWND wnd, ID3DDevice *device);
virtual ~WrappedIDXGISwapChain4();
@@ -591,19 +623,47 @@ public:
ID3DDevice *GetD3DDevice() { return m_pDevice; }
int GetNumBackbuffers() { return MAX_NUM_BACKBUFFERS; }
IUnknown **GetBackbuffers() { return m_pBackBuffers; }
int GetLastPresentedBuffer() { return RDCMAX(m_LastPresentedBuffer, 0); }
IMPLEMENT_IDXGIOBJECT_WITH_REFCOUNTDXGIOBJECT_CUSTOMQUERY;
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
DXGI_SWAP_CHAIN_DESC GetDescWithHWND()
HWND GetHWND()
{
DXGI_SWAP_CHAIN_DESC ret = {};
DXGI_SWAP_CHAIN_DESC desc = {};
m_pReal->GetDesc(&ret);
m_pReal->GetDesc(&desc);
if(ret.OutputWindow == NULL)
ret.OutputWindow = m_Wnd;
if(desc.OutputWindow != NULL)
return desc.OutputWindow;
return ret;
return m_Wnd;
}
UINT GetWidth()
{
DXGI_SWAP_CHAIN_DESC desc = {};
m_pReal->GetDesc(&desc);
return desc.BufferDesc.Width;
}
UINT GetHeight()
{
DXGI_SWAP_CHAIN_DESC desc = {};
m_pReal->GetDesc(&desc);
return desc.BufferDesc.Height;
}
DXGI_FORMAT GetFormat()
{
DXGI_SWAP_CHAIN_DESC desc = {};
m_pReal->GetDesc(&desc);
return desc.BufferDesc.Format;
}
//////////////////////////////