diff --git a/editor/src/Application.cpp b/editor/src/Application.cpp index 91002b11..433e470e 100644 --- a/editor/src/Application.cpp +++ b/editor/src/Application.cpp @@ -38,7 +38,7 @@ bool Application::InitializeWindowRenderer(HWND hwnd) { return true; } - MessageBoxW(hwnd, L"Failed to create D3D12 device", L"Error", MB_OK | MB_ICONERROR); + MessageBoxW(hwnd, L"Failed to initialize editor window renderer", L"Error", MB_OK | MB_ICONERROR); return false; } diff --git a/editor/src/Application.h b/editor/src/Application.h index 9e4fcf8d..90d7cd16 100644 --- a/editor/src/Application.h +++ b/editor/src/Application.h @@ -4,6 +4,7 @@ #include "UI/ImGuiBackendBridge.h" #include "UI/ImGuiSession.h" +#include #include #include #include @@ -11,6 +12,11 @@ #include namespace XCEngine { +namespace RHI { +class RHIDevice; +class RHISwapChain; +} // namespace RHI + namespace Editor { class EditorLayer; @@ -26,6 +32,9 @@ public: void OnResize(int width, int height); bool SwitchProject(const std::string& projectPath); void SaveProjectState(); + Rendering::RenderContext GetMainRenderContext() const { return m_windowRenderer.GetRenderContext(); } + RHI::RHIDevice* GetMainRHIDevice() const { return m_windowRenderer.GetRHIDevice(); } + RHI::RHISwapChain* GetMainSwapChain() const { return m_windowRenderer.GetSwapChain(); } bool IsRenderReady() const { return m_renderReady; } HWND GetWindowHandle() const { return m_hwnd; } diff --git a/editor/src/Platform/D3D12WindowRenderer.h b/editor/src/Platform/D3D12WindowRenderer.h index 4964c434..8b5f6c34 100644 --- a/editor/src/Platform/D3D12WindowRenderer.h +++ b/editor/src/Platform/D3D12WindowRenderer.h @@ -2,9 +2,21 @@ #include "UI/ImGuiBackendBridge.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include -#include -#include +#include #include namespace XCEngine { @@ -14,106 +26,187 @@ namespace Platform { class D3D12WindowRenderer { public: static constexpr UINT kSrvDescriptorCount = 64; + static constexpr uint32_t kSwapChainBufferCount = 3; bool Initialize(HWND hwnd, int width, int height) { + Shutdown(); + + if (hwnd == nullptr || width <= 0 || height <= 0) { + return false; + } + m_hwnd = hwnd; m_width = width; m_height = height; - return CreateDevice() && CreateRenderTarget(); + + m_device = RHI::RHIFactory::CreateRHIDevice(RHI::RHIType::D3D12); + if (m_device == nullptr) { + Shutdown(); + return false; + } + + RHI::RHIDeviceDesc deviceDesc = {}; + if (!m_device->Initialize(deviceDesc)) { + Shutdown(); + return false; + } + + RHI::CommandQueueDesc queueDesc = {}; + queueDesc.queueType = static_cast(RHI::CommandQueueType::Direct); + m_commandQueue = m_device->CreateCommandQueue(queueDesc); + if (m_commandQueue == nullptr || GetD3D12CommandQueue() == nullptr) { + Shutdown(); + return false; + } + + RHI::CommandListDesc commandListDesc = {}; + commandListDesc.commandListType = static_cast(RHI::CommandQueueType::Direct); + m_commandList = m_device->CreateCommandList(commandListDesc); + if (m_commandList == nullptr || GetD3D12CommandList() == nullptr) { + Shutdown(); + return false; + } + m_commandList->Close(); + + RHI::SwapChainDesc swapChainDesc = {}; + swapChainDesc.windowHandle = hwnd; + swapChainDesc.width = static_cast(width); + swapChainDesc.height = static_cast(height); + swapChainDesc.bufferCount = kSwapChainBufferCount; + m_swapChain = m_device->CreateSwapChain(swapChainDesc, m_commandQueue); + if (m_swapChain == nullptr || GetD3D12SwapChain() == nullptr) { + Shutdown(); + return false; + } + + RHI::DescriptorPoolDesc srvPoolDesc = {}; + srvPoolDesc.type = RHI::DescriptorHeapType::CBV_SRV_UAV; + srvPoolDesc.descriptorCount = kSrvDescriptorCount; + srvPoolDesc.shaderVisible = true; + m_srvPool = m_device->CreateDescriptorPool(srvPoolDesc); + m_srvHeap = dynamic_cast(m_srvPool); + if (m_srvPool == nullptr || m_srvHeap == nullptr) { + Shutdown(); + return false; + } + + m_srvDescriptorSize = m_srvHeap->GetDescriptorSize(); + if (!RecreateBackBufferViews()) { + Shutdown(); + return false; + } + + return true; } void Shutdown() { - CleanupRenderTarget(); + WaitForGpuIdle(); + ReleaseBackBufferViews(); - if (m_fence) m_fence->Release(); - if (m_commandList) m_commandList->Release(); - if (m_commandAllocator) m_commandAllocator->Release(); - if (m_commandQueue) m_commandQueue->Release(); - if (m_rtvHeap) m_rtvHeap->Release(); - if (m_srvHeap) m_srvHeap->Release(); - if (m_swapChain) m_swapChain->Release(); - if (m_device) m_device->Release(); + if (m_srvPool) { + m_srvPool->Shutdown(); + delete m_srvPool; + m_srvPool = nullptr; + } + m_srvHeap = nullptr; + + if (m_swapChain) { + m_swapChain->Shutdown(); + delete m_swapChain; + m_swapChain = nullptr; + } + + if (m_commandList) { + m_commandList->Shutdown(); + delete m_commandList; + m_commandList = nullptr; + } + + if (m_commandQueue) { + m_commandQueue->Shutdown(); + delete m_commandQueue; + m_commandQueue = nullptr; + } + + if (m_device) { + m_device->Shutdown(); + delete m_device; + m_device = nullptr; + } m_hwnd = nullptr; - m_width = 1280; - m_height = 720; - m_fenceValue = 0; - m_rtvDescriptorSize = 0; + m_width = 0; + m_height = 0; m_srvDescriptorSize = 0; - m_frameIndex = 0; - m_srvDescriptorUsage.fill(false); } void Resize(int width, int height) { - if (width <= 0 || height <= 0) { + if (width <= 0 || height <= 0 || m_swapChain == nullptr) { return; } + WaitForGpuIdle(); + ReleaseBackBufferViews(); + + m_swapChain->Resize(static_cast(width), static_cast(height)); m_width = width; m_height = height; - - CleanupRenderTarget(); - - if (m_swapChain) { - DXGI_SWAP_CHAIN_DESC desc; - m_swapChain->GetDesc(&desc); - m_swapChain->ResizeBuffers(3, width, height, desc.BufferDesc.Format, desc.Flags); - } - - CreateRenderTarget(); + RecreateBackBufferViews(); } void Render(UI::ImGuiBackendBridge& imguiBackend, const float clearColor[4]) { - m_frameIndex = m_swapChain->GetCurrentBackBufferIndex(); - m_commandAllocator->Reset(); - m_commandList->Reset(m_commandAllocator, nullptr); - - D3D12_RESOURCE_BARRIER barrier = {}; - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - barrier.Transition.pResource = m_renderTargets[m_frameIndex]; - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; - barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; - barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - m_commandList->ResourceBarrier(1, &barrier); - - D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = m_rtvHeap->GetCPUDescriptorHandleForHeapStart(); - rtvHandle.ptr += m_frameIndex * m_rtvDescriptorSize; - - m_commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr); - m_commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr); - - ID3D12DescriptorHeap* heaps[] = { m_srvHeap }; - m_commandList->SetDescriptorHeaps(1, heaps); - imguiBackend.RenderDrawData(m_commandList); - - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; - barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; - m_commandList->ResourceBarrier(1, &barrier); - - m_commandList->Close(); - ID3D12CommandList* commandLists[] = { m_commandList }; - m_commandQueue->ExecuteCommandLists(1, commandLists); - - m_swapChain->Present(1, 0); - - ++m_fenceValue; - m_commandQueue->Signal(m_fence, m_fenceValue); - if (m_fence->GetCompletedValue() < m_fenceValue) { - m_fence->SetEventOnCompletion(m_fenceValue, nullptr); + auto* d3d12Queue = GetD3D12CommandQueue(); + auto* d3d12CommandList = GetD3D12CommandList(); + if (m_swapChain == nullptr || + d3d12Queue == nullptr || + d3d12CommandList == nullptr || + m_srvHeap == nullptr) { + return; } + + d3d12Queue->WaitForPreviousFrame(); + m_commandList->Reset(); + + const uint32_t backBufferIndex = m_swapChain->GetCurrentBackBufferIndex(); + if (backBufferIndex >= m_backBufferViews.size() || m_backBufferViews[backBufferIndex] == nullptr) { + return; + } + + RHI::RHIResourceView* renderTargetView = m_backBufferViews[backBufferIndex]; + d3d12CommandList->TransitionBarrier( + renderTargetView, + RHI::ResourceStates::Present, + RHI::ResourceStates::RenderTarget); + d3d12CommandList->SetRenderTargets(1, &renderTargetView, nullptr); + d3d12CommandList->ClearRenderTarget(renderTargetView, clearColor); + + ID3D12DescriptorHeap* descriptorHeaps[] = { m_srvHeap->GetDescriptorHeap() }; + d3d12CommandList->SetDescriptorHeaps(1, descriptorHeaps); + imguiBackend.RenderDrawData(d3d12CommandList->GetCommandList()); + + d3d12CommandList->TransitionBarrier( + renderTargetView, + RHI::ResourceStates::RenderTarget, + RHI::ResourceStates::Present); + m_commandList->Close(); + + void* commandLists[] = { m_commandList }; + m_commandQueue->ExecuteCommandLists(1, commandLists); + m_swapChain->Present(1, 0); } ID3D12Device* GetDevice() const { - return m_device; + const auto* device = GetD3D12Device(); + return device ? device->GetDevice() : nullptr; } ID3D12DescriptorHeap* GetSrvHeap() const { - return m_srvHeap; + return m_srvHeap ? m_srvHeap->GetDescriptorHeap() : nullptr; } ID3D12CommandQueue* GetCommandQueue() const { - return m_commandQueue; + const auto* queue = GetD3D12CommandQueue(); + return queue ? queue->GetCommandQueue() : nullptr; } UINT GetSrvDescriptorSize() const { @@ -124,114 +217,93 @@ public: return kSrvDescriptorCount; } + RHI::RHIDevice* GetRHIDevice() const { + return m_device; + } + + RHI::RHISwapChain* GetSwapChain() const { + return m_swapChain; + } + + Rendering::RenderContext GetRenderContext() const { + Rendering::RenderContext context = {}; + context.device = m_device; + context.commandList = m_commandList; + context.commandQueue = m_commandQueue; + context.backendType = RHI::RHIType::D3D12; + return context; + } + private: - bool CreateDevice() { - HRESULT hr = D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device)); - if (FAILED(hr)) { + RHI::D3D12Device* GetD3D12Device() const { + return m_device ? static_cast(m_device) : nullptr; + } + + RHI::D3D12CommandQueue* GetD3D12CommandQueue() const { + return m_commandQueue ? static_cast(m_commandQueue) : nullptr; + } + + RHI::D3D12CommandList* GetD3D12CommandList() const { + return m_commandList ? static_cast(m_commandList) : nullptr; + } + + RHI::D3D12SwapChain* GetD3D12SwapChain() const { + return m_swapChain ? static_cast(m_swapChain) : nullptr; + } + + void WaitForGpuIdle() { + if (m_commandQueue != nullptr) { + m_commandQueue->WaitForIdle(); + } + } + + void ReleaseBackBufferViews() { + for (RHI::RHIResourceView* view : m_backBufferViews) { + if (view != nullptr) { + view->Shutdown(); + delete view; + } + } + m_backBufferViews.clear(); + } + + bool RecreateBackBufferViews() { + auto* d3d12SwapChain = GetD3D12SwapChain(); + if (m_device == nullptr || d3d12SwapChain == nullptr) { return false; } - D3D12_COMMAND_QUEUE_DESC queueDesc = {}; - queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; - queueDesc.Priority = 0; - queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; - queueDesc.NodeMask = 0; - hr = m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue)); - if (FAILED(hr)) return false; + m_backBufferViews.resize(kSwapChainBufferCount, nullptr); - hr = m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocator)); - if (FAILED(hr)) return false; + RHI::ResourceViewDesc viewDesc = {}; + viewDesc.format = static_cast(RHI::Format::R8G8B8A8_UNorm); + viewDesc.dimension = RHI::ResourceViewDimension::Texture2D; - hr = m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocator, nullptr, IID_PPV_ARGS(&m_commandList)); - if (FAILED(hr)) return false; - m_commandList->Close(); - - hr = m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence)); - if (FAILED(hr)) return false; - - IDXGIFactory4* factory = nullptr; - hr = CreateDXGIFactory1(IID_PPV_ARGS(&factory)); - if (FAILED(hr)) return false; - - DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; - swapChainDesc.BufferCount = 3; - swapChainDesc.Width = m_width; - swapChainDesc.Height = m_height; - swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; - swapChainDesc.SampleDesc.Count = 1; - - IDXGISwapChain1* swapChain1 = nullptr; - hr = factory->CreateSwapChainForHwnd(m_commandQueue, m_hwnd, &swapChainDesc, nullptr, nullptr, &swapChain1); - factory->Release(); - if (FAILED(hr)) return false; - - hr = swapChain1->QueryInterface(IID_PPV_ARGS(&m_swapChain)); - swapChain1->Release(); - if (FAILED(hr)) return false; - - D3D12_DESCRIPTOR_HEAP_DESC rtvDesc = {}; - rtvDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; - rtvDesc.NumDescriptors = 3; - rtvDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; - hr = m_device->CreateDescriptorHeap(&rtvDesc, IID_PPV_ARGS(&m_rtvHeap)); - if (FAILED(hr)) return false; - m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); - - D3D12_DESCRIPTOR_HEAP_DESC srvDesc = {}; - srvDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; - srvDesc.NumDescriptors = kSrvDescriptorCount; - srvDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - hr = m_device->CreateDescriptorHeap(&srvDesc, IID_PPV_ARGS(&m_srvHeap)); - if (FAILED(hr)) return false; - m_srvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - m_srvDescriptorUsage.fill(false); - - return true; - } - - bool CreateRenderTarget() { - if (!m_swapChain || !m_device || !m_rtvHeap) return false; - - for (UINT i = 0; i < 3; ++i) { - HRESULT hr = m_swapChain->GetBuffer(i, IID_PPV_ARGS(&m_renderTargets[i])); - if (FAILED(hr)) return false; - - D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = m_rtvHeap->GetCPUDescriptorHandleForHeapStart(); - rtvHandle.ptr += i * m_rtvDescriptorSize; - m_device->CreateRenderTargetView(m_renderTargets[i], nullptr, rtvHandle); - } - return true; - } - - void CleanupRenderTarget() { - for (UINT i = 0; i < 3; ++i) { - if (m_renderTargets[i]) { - m_renderTargets[i]->Release(); - m_renderTargets[i] = nullptr; + for (uint32_t backBufferIndex = 0; backBufferIndex < kSwapChainBufferCount; ++backBufferIndex) { + m_backBufferViews[backBufferIndex] = m_device->CreateRenderTargetView( + &d3d12SwapChain->GetBackBuffer(backBufferIndex), + viewDesc); + if (m_backBufferViews[backBufferIndex] == nullptr) { + ReleaseBackBufferViews(); + return false; } } + + return true; } HWND m_hwnd = nullptr; - int m_width = 1280; - int m_height = 720; + int m_width = 0; + int m_height = 0; - ID3D12Device* m_device = nullptr; - ID3D12CommandQueue* m_commandQueue = nullptr; - ID3D12CommandAllocator* m_commandAllocator = nullptr; - ID3D12GraphicsCommandList* m_commandList = nullptr; - IDXGISwapChain3* m_swapChain = nullptr; - ID3D12DescriptorHeap* m_rtvHeap = nullptr; - ID3D12DescriptorHeap* m_srvHeap = nullptr; - ID3D12Resource* m_renderTargets[3] = {}; - ID3D12Fence* m_fence = nullptr; - UINT64 m_fenceValue = 0; - UINT m_rtvDescriptorSize = 0; + RHI::RHIDevice* m_device = nullptr; + RHI::RHICommandQueue* m_commandQueue = nullptr; + RHI::RHICommandList* m_commandList = nullptr; + RHI::RHISwapChain* m_swapChain = nullptr; + RHI::RHIDescriptorPool* m_srvPool = nullptr; + RHI::D3D12DescriptorHeap* m_srvHeap = nullptr; + std::vector m_backBufferViews; UINT m_srvDescriptorSize = 0; - UINT m_frameIndex = 0; - std::array m_srvDescriptorUsage = {}; }; } // namespace Platform diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index e438191e..e4c2f11a 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -431,6 +431,7 @@ target_include_directories(XCEngine PUBLIC target_link_libraries(XCEngine PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/third_party/assimp/lib/assimp-vc143-mt.lib + opengl32 Vulkan::Vulkan )