diff --git a/renderdoc/driver/d3d12/d3d12_debug.cpp b/renderdoc/driver/d3d12/d3d12_debug.cpp index 4c31a381e..4d3db433d 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.cpp +++ b/renderdoc/driver/d3d12/d3d12_debug.cpp @@ -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; } diff --git a/renderdoc/driver/d3d12/d3d12_debug.h b/renderdoc/driver/d3d12/d3d12_debug.h index 151c70498..39242dbf5 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.h +++ b/renderdoc/driver/d3d12/d3d12_debug.h @@ -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;