Use flip model for swapchain, render to intermediate target then copy

This commit is contained in:
baldurk
2016-07-08 17:16:25 +03:00
parent 9d9c90456b
commit 84e5bf3a7e
2 changed files with 119 additions and 47 deletions
+115 -46
View File
@@ -93,12 +93,53 @@ D3D12DebugManager::~D3D12DebugManager()
RenderDoc::Inst().GetCrashHandler()->UnregisterMemoryRegion(this);
}
void D3D12DebugManager::OutputWindow::MakeRTV(bool multisampled)
{
SAFE_RELEASE(col);
D3D12_RESOURCE_DESC texDesc = bb[0]->GetDesc();
texDesc.SampleDesc.Count = multisampled ? 4 : 1;
texDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
D3D12_HEAP_PROPERTIES heapProps;
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
heapProps.CreationNodeMask = 1;
heapProps.VisibleNodeMask = 1;
HRESULT hr = dev->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &texDesc,
D3D12_RESOURCE_STATE_RENDER_TARGET, NULL,
__uuidof(ID3D12Resource), (void **)&col);
if(FAILED(hr))
{
RDCERR("Failed to create colour texture for window, HRESULT: 0x%08x", hr);
return;
}
dev->CreateRenderTargetView(col, NULL, rtv);
if(FAILED(hr))
{
RDCERR("Failed to create RTV for main window, HRESULT: 0x%08x", hr);
SAFE_RELEASE(swap);
SAFE_RELEASE(col);
SAFE_RELEASE(depth);
SAFE_RELEASE(bb[0]);
SAFE_RELEASE(bb[1]);
return;
}
}
void D3D12DebugManager::OutputWindow::MakeDSV()
{
SAFE_RELEASE(depth);
D3D12_RESOURCE_DESC texDesc = bb->GetDesc();
D3D12_RESOURCE_DESC texDesc = bb[0]->GetDesc();
texDesc.SampleDesc.Count = 4;
texDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
texDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
@@ -110,13 +151,13 @@ void D3D12DebugManager::OutputWindow::MakeDSV()
heapProps.VisibleNodeMask = 1;
HRESULT hr = dev->CreateCommittedResource(
&heapProps, D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES, &texDesc,
&heapProps, D3D12_HEAP_FLAG_NONE, &texDesc,
D3D12_RESOURCE_STATE_DEPTH_WRITE | D3D12_RESOURCE_STATE_DEPTH_READ, NULL,
__uuidof(ID3D12Resource), (void **)&depth);
if(FAILED(hr))
{
RDCERR("Failed to create DSV texture for main output, HRESULT: 0x%08x", hr);
RDCERR("Failed to create DSV texture for output window, HRESULT: 0x%08x", hr);
return;
}
@@ -124,10 +165,12 @@ void D3D12DebugManager::OutputWindow::MakeDSV()
if(FAILED(hr))
{
RDCERR("Failed to create DSV for main output, HRESULT: 0x%08x", hr);
RDCERR("Failed to create DSV for output window, HRESULT: 0x%08x", hr);
SAFE_RELEASE(swap);
SAFE_RELEASE(col);
SAFE_RELEASE(depth);
SAFE_RELEASE(bb);
SAFE_RELEASE(bb[0]);
SAFE_RELEASE(bb[1]);
return;
}
}
@@ -145,15 +188,15 @@ uint64_t D3D12DebugManager::MakeOutputWindow(void *w, bool depth)
GetClientRect(outw.wnd, &rect);
swapDesc.BufferCount = 2;
swapDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
swapDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
outw.width = swapDesc.BufferDesc.Width = rect.right - rect.left;
outw.height = swapDesc.BufferDesc.Height = rect.bottom - rect.top;
swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapDesc.SampleDesc.Count = depth ? 4 : 1;
swapDesc.SampleDesc.Count = 1;
swapDesc.SampleDesc.Quality = 0;
swapDesc.OutputWindow = outw.wnd;
swapDesc.Windowed = TRUE;
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
swapDesc.Flags = 0;
HRESULT hr = S_OK;
@@ -166,7 +209,10 @@ uint64_t D3D12DebugManager::MakeOutputWindow(void *w, bool depth)
return 0;
}
outw.swap->GetBuffer(0, __uuidof(ID3D12Resource), (void **)&outw.bb);
outw.swap->GetBuffer(0, __uuidof(ID3D12Resource), (void **)&outw.bb[0]);
outw.swap->GetBuffer(1, __uuidof(ID3D12Resource), (void **)&outw.bb[1]);
outw.bbIdx = 0;
outw.rtv = rtvHeap->GetCPUDescriptorHandleForHeapStart();
outw.rtv.ptr += m_OutputWindowID *
@@ -176,7 +222,9 @@ uint64_t D3D12DebugManager::MakeOutputWindow(void *w, bool depth)
outw.dsv.ptr += m_OutputWindowID *
m_WrappedDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);
m_WrappedDevice->CreateRenderTargetView(outw.bb, NULL, outw.rtv);
outw.col = NULL;
outw.MakeRTV(depth);
m_WrappedDevice->CreateRenderTargetView(outw.col, NULL, outw.rtv);
outw.depth = NULL;
if(depth)
@@ -196,7 +244,9 @@ void D3D12DebugManager::DestroyOutputWindow(uint64_t id)
OutputWindow &outw = it->second;
SAFE_RELEASE(outw.swap);
SAFE_RELEASE(outw.bb);
SAFE_RELEASE(outw.bb[0]);
SAFE_RELEASE(outw.bb[1]);
SAFE_RELEASE(outw.col);
SAFE_RELEASE(outw.depth);
m_OutputWindows.erase(it);
@@ -226,7 +276,8 @@ bool D3D12DebugManager::CheckResizeOutputWindow(uint64_t id)
if(outw.width > 0 && outw.height > 0)
{
SAFE_RELEASE(outw.bb);
SAFE_RELEASE(outw.bb[0]);
SAFE_RELEASE(outw.bb[1]);
DXGI_SWAP_CHAIN_DESC desc;
outw.swap->GetDesc(&desc);
@@ -240,11 +291,20 @@ bool D3D12DebugManager::CheckResizeOutputWindow(uint64_t id)
return true;
}
outw.swap->GetBuffer(0, __uuidof(ID3D12Resource), (void **)&outw.bb);
outw.swap->GetBuffer(0, __uuidof(ID3D12Resource), (void **)&outw.bb[0]);
outw.swap->GetBuffer(1, __uuidof(ID3D12Resource), (void **)&outw.bb[1]);
outw.bbIdx = 0;
m_WrappedDevice->CreateRenderTargetView(outw.bb, NULL, outw.rtv);
if(outw.depth)
{
outw.MakeRTV(true);
outw.MakeDSV();
}
else
{
outw.MakeRTV(false);
}
}
return true;
@@ -301,27 +361,11 @@ void D3D12DebugManager::BindOutputWindow(uint64_t id, bool depth)
OutputWindow &outw = m_OutputWindows[id];
if(outw.bb == NULL)
if(outw.bb[0] == NULL)
return;
m_width = (int32_t)outw.width;
m_height = (int32_t)outw.height;
D3D12_RESOURCE_BARRIER barrier;
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
barrier.Transition.pResource = Unwrap(m_OutputWindows[id].bb);
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
m_WrappedDevice->GetList()->Reset(m_WrappedDevice->GetAlloc(), NULL);
m_WrappedDevice->GetList()->ResourceBarrier(1, &barrier);
m_WrappedDevice->GetList()->Close();
ID3D12CommandList *list = (ID3D12CommandList *)m_WrappedDevice->GetList();
m_WrappedDevice->GetQueue()->GetReal()->ExecuteCommandLists(1, &list);
}
bool D3D12DebugManager::IsOutputWindowVisible(uint64_t id)
@@ -337,24 +381,49 @@ void D3D12DebugManager::FlipOutputWindow(uint64_t id)
if(id == 0 || m_OutputWindows.find(id) == m_OutputWindows.end())
return;
if(m_OutputWindows[id].swap)
{
D3D12_RESOURCE_BARRIER barrier;
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
barrier.Transition.pResource = Unwrap(m_OutputWindows[id].bb);
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
OutputWindow &outw = m_OutputWindows[id];
m_WrappedDevice->GetList()->Reset(m_WrappedDevice->GetAlloc(), NULL);
if(m_OutputWindows[id].bb[0] == NULL)
return;
m_WrappedDevice->GetList()->ResourceBarrier(1, &barrier);
D3D12_RESOURCE_BARRIER barriers[2];
RDCEraseEl(barriers);
m_WrappedDevice->GetList()->Close();
barriers[0].Transition.pResource = Unwrap(outw.col);
barriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
barriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE;
ID3D12CommandList *list = (ID3D12CommandList *)m_WrappedDevice->GetList();
m_WrappedDevice->GetQueue()->GetReal()->ExecuteCommandLists(1, &list);
barriers[1].Transition.pResource = Unwrap(outw.bb[outw.bbIdx]);
barriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
barriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
m_OutputWindows[id].swap->Present(0, 0);
}
m_WrappedDevice->GetList()->Reset(m_WrappedDevice->GetAlloc(), NULL);
// transition colour to copy source, backbuffer to copy test
m_WrappedDevice->GetList()->ResourceBarrier(2, barriers);
// resolve or copy from colour to backbuffer
if(outw.depth)
m_WrappedDevice->GetList()->ResolveSubresource(barriers[1].Transition.pResource, 0,
barriers[0].Transition.pResource, 0,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB);
else
m_WrappedDevice->GetList()->CopyResource(barriers[1].Transition.pResource,
barriers[0].Transition.pResource);
std::swap(barriers[0].Transition.StateBefore, barriers[0].Transition.StateAfter);
std::swap(barriers[1].Transition.StateBefore, barriers[1].Transition.StateAfter);
// transition colour back to render target, and backbuffer back to present
m_WrappedDevice->GetList()->ResourceBarrier(2, barriers);
m_WrappedDevice->GetList()->Close();
ID3D12CommandList *list = (ID3D12CommandList *)m_WrappedDevice->GetList();
m_WrappedDevice->GetQueue()->GetReal()->ExecuteCommandLists(1, &list);
outw.swap->Present(0, 0);
outw.bbIdx++;
outw.bbIdx %= 2;
}
+4 -1
View File
@@ -60,13 +60,16 @@ private:
{
HWND wnd;
IDXGISwapChain *swap;
ID3D12Resource *bb;
ID3D12Resource *bb[2];
uint32_t bbIdx;
ID3D12Resource *col;
ID3D12Resource *depth;
D3D12_CPU_DESCRIPTOR_HANDLE rtv;
D3D12_CPU_DESCRIPTOR_HANDLE dsv;
WrappedID3D12Device *dev;
void MakeRTV(bool multisampled);
void MakeDSV();
int width, height;