//-------------------------------------------------------------------------- void VeRenderWindowD3D12::ResizeBundleList(VeSizeT stNum) noexcept { for (VeInt32 i(0); i < VeRendererD3D12::FRAME_COUNT; ++i) { FrameCache& kFrame = m_akFrameCache[i]; VE_ASSERT_GE(kFrame.m_pkBundleAllocator->Reset(), S_OK); VeSizeT stCurrentNum = kFrame.m_kBundleCommandList.size(); if (stNum >= stCurrentNum) { for (auto& list : kFrame.m_kBundleCommandList) { VE_ASSERT_GE(list->Reset(kFrame.m_pkBundleAllocator, nullptr), S_OK); } kFrame.m_kBundleCommandList.resize(stNum); VeRendererD3D12& kRenderer = *VeMemberCast( &VeRendererD3D12::m_kRenderWindowList, m_kNode.get_list()); for (VeSizeT i(stCurrentNum); i < stNum; ++i) { VE_ASSERT_GE(kRenderer.m_pkDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_BUNDLE, kFrame.m_pkBundleAllocator, nullptr, IID_PPV_ARGS(&kFrame.m_kBundleCommandList[i])), S_OK); } } else if (stNum < stCurrentNum) { for (VeSizeT i(stNum); i < stCurrentNum; ++i) { VE_ASSERT_GE(kFrame.m_kBundleCommandList[i]->Close(), S_OK); VE_SAFE_RELEASE(kFrame.m_kBundleCommandList[i]); } kFrame.m_kBundleCommandList.resize(stNum); } } }
//-------------------------------------------------------------------------- void D3D12RenderWindow::End() noexcept { VE_ASSERT(IsValid() && m_u32FramePtr < D3D12Renderer::FRAME_COUNT); FrameCache& kFrame = m_akFrameCache[m_u32FramePtr]; VE_ASSERT_GE(kFrame.m_pkTestList->Reset(kFrame.m_pkDirectAllocator, nullptr), S_OK); { auto kTrans = BarrierTransition(kFrame.m_pkBufferResource, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET); kFrame.m_pkTestList->ResourceBarrier(1, &kTrans); } // Record commands. const float clearColor[] = { 0.0f, 0.2f, 0.4f, 1.0f }; kFrame.m_pkTestList->ClearRenderTargetView(kFrame.m_hHandle, clearColor, 0, nullptr); { auto kTrans = BarrierTransition(kFrame.m_pkBufferResource, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); kFrame.m_pkTestList->ResourceBarrier(1, &kTrans); } VE_ASSERT_GE(kFrame.m_pkTestList->Close(), S_OK); m_pkCommandQueue->ExecuteCommandLists(1, (ID3D12CommandList*const*)&kFrame.m_pkTestList); VE_ASSERT_GE(m_pkSwapChain->Present(m_bSync ? 1 : 0, 0), S_OK); m_u32FramePtr = m_pkSwapChain->GetCurrentBackBufferIndex(); kFrame.m_u64FenceValue = m_u64FenceValue; VE_ASSERT_GE(m_pkCommandQueue->Signal(m_pkFence, m_u64FenceValue++), S_OK); ++m_u64FrameIndex; }
//-------------------------------------------------------------------------- void VeRenderWindowD3D12::RecordScene(VeUInt32 u32Thread) noexcept { for (auto& cam : m_kCameraList) { for (auto idx : cam.m_kStageList) { FrameCache& kFrame = m_akFrameCache[m_u32FrameIndex]; ID3D12GraphicsCommandList* pkGCL = kFrame.m_kDirectCommandList[idx + u32Thread]; VE_ASSERT_GE(pkGCL->Reset(kFrame.m_pkDirectAllocator, nullptr), S_OK); VE_ASSERT_GE(pkGCL->Close(), S_OK); } } }
//-------------------------------------------------------------------------- void VeRenderWindowD3D12::Term() noexcept { if (m_kNode.is_attach()) { VeRendererD3D12& kRenderer = *VeMemberCast( &VeRendererD3D12::m_kRenderWindowList, m_kNode.get_list()); const VeUInt64 u64LastCompleted = m_pkFence->GetCompletedValue(); VE_ASSERT_GE(m_pkCommandQueue->Signal(m_pkFence, m_u64FenceValue), S_OK); if (u64LastCompleted < m_u64FenceValue) { VE_ASSERT_GE(m_pkFence->SetEventOnCompletion(m_u64FenceValue, m_kFenceEvent), S_OK); WaitForSingleObject(m_kFenceEvent, INFINITE); } CloseHandle(m_kFenceEvent); VE_SAFE_RELEASE(m_pkFence); m_kResourceMap.clear(); m_kRecorderList.clear(); m_kCameraList.clear(); m_kProcessList.clear(); for (VeInt32 i(VeRendererD3D12::FRAME_COUNT - 1); i >= 0; --i) { FrameCache& kFrame = m_akFrameCache[i]; for (auto& list : kFrame.m_kDirectCommandList) { VE_SAFE_RELEASE(list); } VE_SAFE_RELEASE(kFrame.m_pkDirectAllocator); kFrame.m_kDirectCommandList.clear(); for (auto& list : kFrame.m_kBundleCommandList) { VE_SAFE_RELEASE(list); } VE_SAFE_RELEASE(kFrame.m_pkBundleAllocator); kFrame.m_kBundleCommandList.clear(); kRenderer.m_kRTVHeap.Free(kFrame.m_hHandle.ptr - kRenderer.m_kRTVHeap.GetCPUStart().ptr); VE_SAFE_RELEASE(kFrame.m_pkBufferResource); } VE_SAFE_RELEASE(m_pkCommandQueue); VE_SAFE_RELEASE(m_pkSwapChain); m_kNode.detach(); } }
//-------------------------------------------------------------------------- void D3D12RenderWindow::Begin() noexcept { VE_ASSERT(IsValid() && m_u32FramePtr < D3D12Renderer::FRAME_COUNT); FrameCache& kFrame = m_akFrameCache[m_u32FramePtr]; if (kFrame.m_u64FenceValue > m_pkFence->GetCompletedValue()) { VE_ASSERT_GE(m_pkFence->SetEventOnCompletion( kFrame.m_u64FenceValue, m_kFenceEvent), S_OK); WaitForSingleObject(m_kFenceEvent, INFINITE); } /*VeRendererD3D12& kRenderer = *vtd::member_cast( &VeRendererD3D12::m_kRenderWindowList, m_kNode.get_list()); if (kRenderer.m_kCopyResList.size()) { m_pkCommandQueue->Wait(kRenderer.m_pkCopyFence, kRenderer.m_u64CopyFenceValue); }*/ VE_ASSERT_GE(kFrame.m_pkDirectAllocator->Reset(), S_OK); }
//-------------------------------------------------------------------------- void D3D12RenderWindow::Term() noexcept { if (m_kNode.is_attach()) { D3D12Renderer& kRenderer = *vtd::member_cast( &D3D12Renderer::m_kRenderWindowList, m_kNode.get_list()); const uint64_t u64LastCompleted = m_pkFence->GetCompletedValue(); VE_ASSERT_GE(m_pkCommandQueue->Signal(m_pkFence, m_u64FenceValue), S_OK); if (u64LastCompleted < m_u64FenceValue) { VE_ASSERT_GE(m_pkFence->SetEventOnCompletion(m_u64FenceValue, m_kFenceEvent), S_OK); WaitForSingleObject(m_kFenceEvent, INFINITE); } CloseHandle(m_kFenceEvent); VE_SAFE_RELEASE(m_pkFence); for (auto& kFrame : m_akFrameCache) { VE_SAFE_RELEASE(kFrame.m_pkTestList); for (auto& list : kFrame.m_kDirectCommandList) { VE_SAFE_RELEASE(list); } VE_SAFE_RELEASE(kFrame.m_pkDirectAllocator); kFrame.m_kDirectCommandList.clear(); for (auto& list : kFrame.m_kBundleCommandList) { VE_SAFE_RELEASE(list); } VE_SAFE_RELEASE(kFrame.m_pkBundleAllocator); kFrame.m_kBundleCommandList.clear(); kRenderer.m_kRTVHeap.Free((uint32_t)(kFrame.m_hHandle.ptr - kRenderer.m_kRTVHeap.GetCPUStart().ptr)); VE_SAFE_RELEASE(kFrame.m_pkBufferResource); } VE_SAFE_RELEASE(m_pkCommandQueue); VE_SAFE_RELEASE(m_pkSwapChain); m_kNode.detach(); } }
//-------------------------------------------------------------------------- void VeRenderWindowD3D12::End() noexcept { FrameCache& kFrame = m_akFrameCache[m_u32FrameIndex]; for (auto& process : m_kProcessList) { switch (process.m_eType) { case TYPE_EXCUTE: m_pkCommandQueue->ExecuteCommandLists(process.m_u16Num, (ID3D12CommandList*const*)&kFrame.m_kDirectCommandList[process.m_u16Start]); break; default: break; } } VE_ASSERT_GE(m_pkSwapChain->Present(m_bSync? 1 : 0, 0), S_OK); m_u32FrameIndex = m_pkSwapChain->GetCurrentBackBufferIndex(); kFrame.m_u64FenceValue = m_u64FenceValue; VE_ASSERT_GE(m_pkCommandQueue->Signal(m_pkFence, m_u64FenceValue++), S_OK); }
//-------------------------------------------------------------------------- void D3D12RenderWindow::Init(D3D12Renderer& kRenderer) noexcept { if ((!m_kNode.is_attach()) && m_spTargetWindow) { D3D12_COMMAND_QUEUE_DESC kQueueDesc = {}; kQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; kQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; VE_ASSERT_GE(kRenderer.m_pkDevice->CreateCommandQueue(&kQueueDesc, IID_PPV_ARGS(&m_pkCommandQueue)), S_OK); DXGI_SWAP_CHAIN_DESC kSwapChainDesc = {}; kSwapChainDesc.BufferCount = D3D12Renderer::FRAME_COUNT; kSwapChainDesc.BufferDesc.Width = m_spTargetWindow->GetWidth(); kSwapChainDesc.BufferDesc.Height = m_spTargetWindow->GetHeight(); kSwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM; kSwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; kSwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; kSwapChainDesc.OutputWindow = (HWND)(m_spTargetWindow->GetNativeHandle()); kSwapChainDesc.SampleDesc.Count = 1; kSwapChainDesc.Windowed = TRUE; IDXGISwapChain* pkSwapChain; VE_ASSERT_GE(kRenderer.m_pkDXGIFactory->CreateSwapChain(m_pkCommandQueue, &kSwapChainDesc, &pkSwapChain), S_OK); VE_ASSERT_GE(pkSwapChain->QueryInterface(IID_PPV_ARGS(&m_pkSwapChain)), S_OK); VE_SAFE_RELEASE(pkSwapChain); VE_ASSERT(m_pkCommandQueue && m_pkSwapChain); for (uint32_t i(0); i < D3D12Renderer::FRAME_COUNT; ++i) { FrameCache& kFrame = m_akFrameCache[i]; VE_ASSERT_GE(m_pkSwapChain->GetBuffer(i, IID_PPV_ARGS(&kFrame.m_pkBufferResource)), S_OK); kFrame.m_hHandle.ptr = kRenderer.m_kRTVHeap.GetCPUStart().ptr + kRenderer.m_kRTVHeap.Alloc(); kRenderer.m_pkDevice->CreateRenderTargetView( kFrame.m_pkBufferResource, nullptr, kFrame.m_hHandle); VE_ASSERT_GE(kRenderer.m_pkDevice->CreateCommandAllocator( D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&kFrame.m_pkDirectAllocator)), S_OK); VE_ASSERT_GE(kRenderer.m_pkDevice->CreateCommandAllocator( D3D12_COMMAND_LIST_TYPE_BUNDLE, IID_PPV_ARGS(&kFrame.m_pkBundleAllocator)), S_OK); kFrame.m_u64FenceValue = 0; VE_ASSERT_GE(kRenderer.m_pkDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, kFrame.m_pkDirectAllocator, nullptr, IID_PPV_ARGS(&kFrame.m_pkTestList)), S_OK); VE_ASSERT_GE(kFrame.m_pkTestList->Close(), S_OK); } m_u64FenceValue = 0; VE_ASSERT_GE(kRenderer.m_pkDevice->CreateFence(m_u64FenceValue++, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_pkFence)), S_OK); m_kFenceEvent = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS); VE_ASSERT(m_kFenceEvent); const uint64_t u64FenceToWaitFor = m_u64FenceValue++; VE_ASSERT_GE(m_pkCommandQueue->Signal(m_pkFence, u64FenceToWaitFor), S_OK); VE_ASSERT_GE(m_pkFence->SetEventOnCompletion(u64FenceToWaitFor, m_kFenceEvent), S_OK); WaitForSingleObject(m_kFenceEvent, INFINITE); m_u32FramePtr = m_pkSwapChain->GetCurrentBackBufferIndex(); m_u64FrameIndex = 0; m_spTargetWindow->Show(); kRenderer.m_kRenderWindowList.attach_back(m_kNode); } }
//-------------------------------------------------------------------------- void VeRenderWindowD3D12::Init(VeRendererD3D12& kRenderer) noexcept { if ((!m_kNode.is_attach()) && m_spTargetWindow) { D3D12_COMMAND_QUEUE_DESC kQueueDesc = {}; kQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; kQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; if (FAILED(kRenderer.m_pkDevice->CreateCommandQueue(&kQueueDesc, IID_PPV_ARGS(&m_pkCommandQueue)))) { VE_SAFE_RELEASE(m_pkCommandQueue); VE_SAFE_RELEASE(m_pkSwapChain); return; } DXGI_SWAP_CHAIN_DESC kSwapChainDesc = {}; kSwapChainDesc.BufferCount = VeRendererD3D12::FRAME_COUNT; kSwapChainDesc.BufferDesc.Width = m_spTargetWindow->GetWidth(); kSwapChainDesc.BufferDesc.Height = m_spTargetWindow->GetHeight(); kSwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM; kSwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; kSwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; kSwapChainDesc.OutputWindow = m_spTargetWindow->GetWMInfo().win.window; kSwapChainDesc.SampleDesc.Count = 1; kSwapChainDesc.Windowed = TRUE; IDXGISwapChain* pkSwapChain; if (FAILED(kRenderer.m_pkDXGIFactory->CreateSwapChain(m_pkCommandQueue, &kSwapChainDesc, &pkSwapChain))) { VE_SAFE_RELEASE(m_pkCommandQueue); VE_SAFE_RELEASE(pkSwapChain); return; } if (FAILED(pkSwapChain->QueryInterface(IID_PPV_ARGS(&m_pkSwapChain)))) { VE_SAFE_RELEASE(m_pkCommandQueue); VE_SAFE_RELEASE(pkSwapChain); VE_SAFE_RELEASE(m_pkSwapChain); return; } else { VE_SAFE_RELEASE(pkSwapChain); } VE_ASSERT(m_pkCommandQueue && m_pkSwapChain); for (VeInt32 i(0); i < VeRendererD3D12::FRAME_COUNT; ++i) { FrameCache& kFrame = m_akFrameCache[i]; VE_ASSERT_GE(m_pkSwapChain->GetBuffer(i, IID_PPV_ARGS(&kFrame.m_pkBufferResource)), S_OK); kFrame.m_hHandle.ptr = kRenderer.m_kRTVHeap.GetCPUStart().ptr + kRenderer.m_kRTVHeap.Alloc(); kRenderer.m_pkDevice->CreateRenderTargetView( kFrame.m_pkBufferResource, nullptr, kFrame.m_hHandle); VE_ASSERT_GE(kRenderer.m_pkDevice->CreateCommandAllocator( D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&kFrame.m_pkDirectAllocator)), S_OK); VE_ASSERT_GE(kRenderer.m_pkDevice->CreateCommandAllocator( D3D12_COMMAND_LIST_TYPE_BUNDLE, IID_PPV_ARGS(&kFrame.m_pkBundleAllocator)), S_OK); kFrame.m_u64FenceValue = 0; } m_u64FenceValue = 0; VE_ASSERT_GE(kRenderer.m_pkDevice->CreateFence(m_u64FenceValue++, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_pkFence)), S_OK); m_kFenceEvent = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS); VE_ASSERT(m_kFenceEvent); const VeUInt64 u64FenceToWaitFor = m_u64FenceValue++; VE_ASSERT_GE(m_pkCommandQueue->Signal(m_pkFence, u64FenceToWaitFor), S_OK); VE_ASSERT_GE(m_pkFence->SetEventOnCompletion(u64FenceToWaitFor, m_kFenceEvent), S_OK); WaitForSingleObject(m_kFenceEvent, INFINITE); m_u32FrameIndex = m_pkSwapChain->GetCurrentBackBufferIndex(); kRenderer.m_kRenderWindowList.attach_back(m_kNode); } m_kViewport.TopLeftX = 0; m_kViewport.TopLeftY = 0; m_kViewport.Width = m_spTargetWindow->GetWidth(); m_kViewport.Height = m_spTargetWindow->GetHeight(); m_kViewport.MinDepth = 0.0f; m_kViewport.MaxDepth = 1.0f; m_kScissorRect.left = 0; m_kScissorRect.right = m_spTargetWindow->GetWidth(); m_kScissorRect.top = 0; m_kScissorRect.bottom = m_spTargetWindow->GetHeight(); { m_vertexBufferView.BufferLocation = kRenderer.m_kRenderBufferList.get_tail_node()->m_Content->m_pkResource->GetGPUVirtualAddress(); m_vertexBufferView.StrideInBytes = sizeof(VE_FLOAT3); m_vertexBufferView.SizeInBytes = kRenderer.m_kRenderBufferList.get_head_node()->m_Content->GetSize(); } }
//-------------------------------------------------------------------------- void VeRenderWindowD3D12::Record(VeUInt32 u32Index) noexcept { VeRendererD3D12& kRenderer = *VeMemberCast( &VeRendererD3D12::m_kRenderWindowList, m_kNode.get_list()); VE_ASSERT(u32Index < m_kRecorderList.size()); Recorder& kRecorder = m_kRecorderList[u32Index]; FrameCache& kFrame = m_akFrameCache[m_u32FrameIndex]; ID3D12GraphicsCommandList* pkGCL = kFrame.m_kDirectCommandList[kRecorder.m_u32CommandIndex]; VE_ASSERT_GE(pkGCL->Reset(kFrame.m_pkDirectAllocator, nullptr), S_OK); ID3D12DescriptorHeap* ppHeaps[] = { kRenderer.m_kSRVHeap.Get() }; pkGCL->SetDescriptorHeaps(1, ppHeaps); for (auto& task : kRecorder.m_kTaskList) { switch (task->m_eType) { case REC_BARRIER: { auto& list = ((RecordBarrier*)task)->m_akBarrierList[m_u32FrameIndex]; pkGCL->ResourceBarrier((VeUInt32)list.size(), &list.front()); } break; case REC_CLEAR_RTV: { RecordClearRTV& rec = *((RecordClearRTV*)task); pkGCL->ClearRenderTargetView(rec.m_ahHandle[m_u32FrameIndex], (const FLOAT*)&(rec.m_kColor), 0, nullptr); } break; case REC_CLEAR_DSV: { RecordClearDSV& rec = *((RecordClearDSV*)task); pkGCL->ClearDepthStencilView(rec.m_ahHandle[m_u32FrameIndex], rec.m_eFlags, rec.m_f32Depth, rec.m_u8Stencil, 0, nullptr); } break; case REC_RENDER_TARGET: { RecordRenderTarget& rec = *((RecordRenderTarget*)task); pkGCL->OMSetRenderTargets((VeUInt32)rec.m_akRTVList[m_u32FrameIndex].size(), &rec.m_akRTVList[m_u32FrameIndex].front(), FALSE, rec.m_ahDSV[m_u32FrameIndex].ptr ? &rec.m_ahDSV[m_u32FrameIndex] : nullptr); } break; case REC_VIEWPORT: { RecordViewport& rec = *((RecordViewport*)task); pkGCL->RSSetViewports((VeUInt32)rec.m_kViewportList.size(), &rec.m_kViewportList.front()); } break; case REC_SCISSOR_RECT: { RecordScissorRect& rec = *((RecordScissorRect*)task); pkGCL->RSSetScissorRects((VeUInt32)rec.m_kScissorRectList.size(), &rec.m_kScissorRectList.front()); } break; case REC_RENDER_QUAD: { RecordRenderQuad& rec = *((RecordRenderQuad*)task); pkGCL->SetPipelineState(rec.m_pkPipelineState); pkGCL->SetGraphicsRootSignature(rec.m_pkRootSignature); for (auto& itTab : rec.m_kTable) { pkGCL->SetGraphicsRootDescriptorTable(itTab.first, itTab.second); } pkGCL->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); pkGCL->IASetVertexBuffers(0, 1, &kRenderer.m_kQuadVBV); pkGCL->DrawInstanced(4, 1, 0, 0); } break; default: break; } } VE_ASSERT_GE(pkGCL->Close(), S_OK); }