From 7e8aaaa891c35fae826d0e332db1a9542bb69686 Mon Sep 17 00:00:00 2001 From: Patedam Date: Sun, 16 Feb 2025 11:54:04 -0500 Subject: [PATCH] Command to acquire swap chain texture --- Juliet/Juliet.vcxproj | 1 + Juliet/include/Graphics/Graphics.h | 5 ++ Juliet/include/Graphics/Texture.h | 2 +- Juliet/src/Graphics/D3D12/DX12CommandList.cpp | 15 ++++- Juliet/src/Graphics/D3D12/DX12CommandList.h | 18 +++++- .../src/Graphics/D3D12/DX12GraphicsDevice.cpp | 2 + Juliet/src/Graphics/D3D12/DX12SwapChain.cpp | 59 +++++++++++++++++++ Juliet/src/Graphics/D3D12/DX12SwapChain.h | 1 + Juliet/src/Graphics/Graphics.cpp | 22 +++++++ Juliet/src/Graphics/GraphicsDevice.h | 9 +++ Juliet/src/TODO.txt | 1 + JulietApp/Editor/EditorMain_win32.cpp | 14 +++++ 12 files changed, 145 insertions(+), 4 deletions(-) create mode 100644 Juliet/src/TODO.txt diff --git a/Juliet/Juliet.vcxproj b/Juliet/Juliet.vcxproj index 58320fa..7a94569 100644 --- a/Juliet/Juliet.vcxproj +++ b/Juliet/Juliet.vcxproj @@ -302,6 +302,7 @@ + diff --git a/Juliet/include/Graphics/Graphics.h b/Juliet/include/Graphics/Graphics.h index 8389115..e13bc56 100644 --- a/Juliet/include/Graphics/Graphics.h +++ b/Juliet/include/Graphics/Graphics.h @@ -2,6 +2,7 @@ #include #include +#include #include // Graphics Interface @@ -74,6 +75,10 @@ namespace Juliet extern JULIET_API bool AttachToWindow(NonNullPtr device, NonNullPtr window); extern JULIET_API void DetachFromWindow(NonNullPtr device, NonNullPtr window); + // SwapChain + extern JULIET_API bool AcquireSwapChainTexture(NonNullPtr commandList, NonNullPtr window, + Texture** swapChainTexture); + // Command List extern JULIET_API CommandList* AcquireCommandList(NonNullPtr device, QueueType queueType = QueueType::Graphics); extern JULIET_API void SubmitCommandLists(NonNullPtr device); diff --git a/Juliet/include/Graphics/Texture.h b/Juliet/include/Graphics/Texture.h index 1e724e5..628e8ae 100644 --- a/Juliet/include/Graphics/Texture.h +++ b/Juliet/include/Graphics/Texture.h @@ -1,5 +1,4 @@ #pragma once -#include namespace Juliet { @@ -177,4 +176,5 @@ namespace Juliet uint32 MipLevelCount; }; + struct Texture; } // namespace Juliet diff --git a/Juliet/src/Graphics/D3D12/DX12CommandList.cpp b/Juliet/src/Graphics/D3D12/DX12CommandList.cpp index 4d117cf..1c725c8 100644 --- a/Juliet/src/Graphics/D3D12/DX12CommandList.cpp +++ b/Juliet/src/Graphics/D3D12/DX12CommandList.cpp @@ -87,13 +87,26 @@ namespace Juliet::D3D12 driver->AvailableCommandLists = resizedArray; driver->AvailableCommandLists[driver->AvailableCommandListCapacity] = commandList; - commandList->ID = driver->AvailableCommandListCapacity; + + commandList->ID = driver->AvailableCommandListCapacity; + commandList->Driver = driver; + + commandList->PresentDataCapacity = 1; + commandList->PresentDataCount = 0; + commandList->PresentDatas = + static_cast(Calloc(commandList->PresentDataCapacity, sizeof(D3D12PresentData))); + driver->AvailableCommandListCapacity += 1; return true; } } // namespace + ID3D12GraphicsCommandList6* GetGraphicsCommandList(NonNullPtr commandList) + { + return reinterpret_cast(commandList->CommandLists[ToUnderlying(QueueType::Graphics)]); + } + CommandList* AcquireCommandList(NonNullPtr driver, QueueType queueType) { auto* d3d12Driver = static_cast(driver.Get()); diff --git a/Juliet/src/Graphics/D3D12/DX12CommandList.h b/Juliet/src/Graphics/D3D12/DX12CommandList.h index fb13f31..f794c00 100644 --- a/Juliet/src/Graphics/D3D12/DX12CommandList.h +++ b/Juliet/src/Graphics/D3D12/DX12CommandList.h @@ -8,18 +8,32 @@ namespace Juliet::D3D12 { struct D3D12Driver; + struct D3D12WindowData; + + struct D3D12PresentData + { + D3D12WindowData* WindowData; + uint32 SwapChainImageIndex; + }; struct D3D12CommandList { - D3D12Driver* Driver; - uint64 ID; + CommandListHeader Common; + D3D12Driver* Driver; + + D3D12PresentData* PresentDatas; + uint32 PresentDataCapacity; + uint32 PresentDataCount; + // We create kResourceBufferCount allocator per queue to allow reusing the command list every N frames ID3D12CommandAllocator* CommandAllocator[GPUDriver::kResourceBufferCount][ToUnderlying(QueueType::Count)]; ID3D12CommandList* CommandLists[ToUnderlying(QueueType::Count)]; }; + ID3D12GraphicsCommandList6* GetGraphicsCommandList(NonNullPtr commandList); + extern CommandList* AcquireCommandList(NonNullPtr driver, QueueType queueType); extern bool SubmitCommandLists(NonNullPtr driver); } // namespace Juliet::D3D12 diff --git a/Juliet/src/Graphics/D3D12/DX12GraphicsDevice.cpp b/Juliet/src/Graphics/D3D12/DX12GraphicsDevice.cpp index 9172af6..63bdcf0 100644 --- a/Juliet/src/Graphics/D3D12/DX12GraphicsDevice.cpp +++ b/Juliet/src/Graphics/D3D12/DX12GraphicsDevice.cpp @@ -544,6 +544,8 @@ namespace Juliet::D3D12 device->AttachToWindow = AttachToWindow; device->DetachFromWindow = DetachFromWindow; + device->AcquireSwapChainTexture = AcquireSwapChainTexture; + device->AcquireCommandList = AcquireCommandList; device->SubmitCommandLists = SubmitCommandLists; diff --git a/Juliet/src/Graphics/D3D12/DX12SwapChain.cpp b/Juliet/src/Graphics/D3D12/DX12SwapChain.cpp index 3898a97..255f604 100644 --- a/Juliet/src/Graphics/D3D12/DX12SwapChain.cpp +++ b/Juliet/src/Graphics/D3D12/DX12SwapChain.cpp @@ -9,6 +9,7 @@ #include #include +#include namespace Juliet::D3D12 { namespace @@ -131,6 +132,59 @@ namespace Juliet::D3D12 return true; } + + bool AcquireSwapChainTexture(bool block, NonNullPtr commandList, NonNullPtr window, Texture** swapchainTexture) + { + auto d3d12CommandList = reinterpret_cast(commandList.Get()); + + auto* driver = d3d12CommandList->Driver; + Assert(driver->WindowData); + + // TODO: Find a way to fetch window data more smoothly from the window ptr + auto* windowData = driver->WindowData; + Assert(windowData->Window == window.Get()); + + // TODO : FENCES + Assert(!block); + + uint32 swapchainIndex = IDXGISwapChain3_GetCurrentBackBufferIndex(windowData->SwapChain); + HRESULT result = + IDXGISwapChain_GetBuffer(windowData->SwapChain, swapchainIndex, IID_ID3D12Resource, + reinterpret_cast( + &windowData->SwapChainTextureContainers[swapchainIndex].ActiveTexture->Resource)); + if (FAILED(result)) + { + LogError(driver, "Could not acquire swapchain", result); + return false; + } + + // When the swap chain texture is acquired its time to present + if (d3d12CommandList->PresentDataCount == d3d12CommandList->PresentDataCapacity) + { + d3d12CommandList->PresentDataCapacity += 1; + d3d12CommandList->PresentDatas = + static_cast(Realloc(d3d12CommandList->PresentDatas, + d3d12CommandList->PresentDataCapacity * sizeof(D3D12PresentData))); + } + d3d12CommandList->PresentDatas[d3d12CommandList->PresentDataCount].WindowData = windowData; + d3d12CommandList->PresentDatas[d3d12CommandList->PresentDataCount].SwapChainImageIndex = swapchainIndex; + d3d12CommandList->PresentDataCount += 1; + + // Create the presentation barrier. + D3D12_RESOURCE_BARRIER barrierDesc; + barrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrierDesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrierDesc.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; + barrierDesc.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; + barrierDesc.Transition.pResource = windowData->SwapChainTextureContainers[swapchainIndex].ActiveTexture->Resource; + barrierDesc.Transition.Subresource = 0; + + ID3D12GraphicsCommandList_ResourceBarrier(GetGraphicsCommandList(d3d12CommandList), 1, &barrierDesc); + + *swapchainTexture = reinterpret_cast(&windowData->SwapChainTextureContainers[swapchainIndex]); + + return true; + } } // namespace bool CreateSwapChain(NonNullPtr driver, NonNullPtr windowData, @@ -244,6 +298,11 @@ namespace Juliet::D3D12 return true; } + bool AcquireSwapChainTexture(NonNullPtr commandList, NonNullPtr window, Texture** swapChainTexture) + { + return AcquireSwapChainTexture(false, commandList, window, swapChainTexture); + } + void DestroySwapChain(NonNullPtr driver, NonNullPtr windowData) { for (uint32 idx = 0; idx < windowData->SwapChainTextureCount; ++idx) diff --git a/Juliet/src/Graphics/D3D12/DX12SwapChain.h b/Juliet/src/Graphics/D3D12/DX12SwapChain.h index 478ead4..de08684 100644 --- a/Juliet/src/Graphics/D3D12/DX12SwapChain.h +++ b/Juliet/src/Graphics/D3D12/DX12SwapChain.h @@ -8,5 +8,6 @@ namespace Juliet::D3D12 extern bool CreateSwapChain(NonNullPtr driver, NonNullPtr windowData, SwapChainComposition composition, PresentMode presentMode); + extern bool AcquireSwapChainTexture(NonNullPtr commandList, NonNullPtr window, Texture** swapChainTexture); extern void DestroySwapChain(NonNullPtr driver, NonNullPtr windowData); } // namespace Juliet::D3D12 diff --git a/Juliet/src/Graphics/Graphics.cpp b/Juliet/src/Graphics/Graphics.cpp index 91b083e..ee8bcbc 100644 --- a/Juliet/src/Graphics/Graphics.cpp +++ b/Juliet/src/Graphics/Graphics.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -75,11 +76,32 @@ namespace Juliet device->DetachFromWindow(driver, window); } + bool AcquireSwapChainTexture(NonNullPtr commandList, NonNullPtr window, Texture** swapChainTexture) + { + auto header = reinterpret_cast(commandList.Get()); + + header->Device->AcquireSwapChainTexture(commandList, window, swapChainTexture); + if (swapChainTexture) + { + header->AcquiredSwapChain = true; + } + + return true; + } + CommandList* AcquireCommandList(NonNullPtr device, QueueType queueType /* = QueueType::Graphics */) { GPUDriver* driver = device->Driver; CommandList* cmdList = device->AcquireCommandList(driver, queueType); + if (!cmdList) + { + return nullptr; + } + + auto header = reinterpret_cast(cmdList); + header->Device = device.Get(); + driver->CommandListCount += 1; return cmdList; diff --git a/Juliet/src/Graphics/GraphicsDevice.h b/Juliet/src/Graphics/GraphicsDevice.h index 7339b2b..ab04c05 100644 --- a/Juliet/src/Graphics/GraphicsDevice.h +++ b/Juliet/src/Graphics/GraphicsDevice.h @@ -14,6 +14,12 @@ namespace Juliet TextureCreateInfo CreateInfo; }; + struct CommandListHeader + { + GraphicsDevice* Device = nullptr; + bool AcquiredSwapChain = false; + }; + struct GPUDriver { uint8 CommandListCount; @@ -30,6 +36,9 @@ namespace Juliet bool (*AttachToWindow)(NonNullPtr driver, NonNullPtr window); void (*DetachFromWindow)(NonNullPtr driver, NonNullPtr window); + // SwapChain + bool (*AcquireSwapChainTexture)(NonNullPtr commandList, NonNullPtr window, Texture** swapChainTexture); + // CommandLists CommandList* (*AcquireCommandList)(NonNullPtr driver, QueueType queueType); bool (*SubmitCommandLists)(NonNullPtr driver); diff --git a/Juliet/src/TODO.txt b/Juliet/src/TODO.txt new file mode 100644 index 0000000..f585166 --- /dev/null +++ b/Juliet/src/TODO.txt @@ -0,0 +1 @@ +- Create Simple vector class to make the vector stuff a bit more easier than writing Capacity and Count \ No newline at end of file diff --git a/JulietApp/Editor/EditorMain_win32.cpp b/JulietApp/Editor/EditorMain_win32.cpp index f31cb36..e332fd5 100644 --- a/JulietApp/Editor/EditorMain_win32.cpp +++ b/JulietApp/Editor/EditorMain_win32.cpp @@ -82,6 +82,20 @@ void Win32EditorApplication::Update() // Draw here for now // 1) Acquire a Command Buffer CommandList* cmdList = AcquireCommandList(GraphicsDevice, QueueType::Graphics); + if (cmdList == nullptr) + { + Log(LogLevel::Error, LogCategory::Editor, "Failed to acquire command list."); + Running = false; + return; + } + + Texture* swapChainTexture = nullptr; + if (!AcquireSwapChainTexture(cmdList, MainWindow, &swapChainTexture)) + { + Log(LogLevel::Error, LogCategory::Editor, "Failed to acquire swapchain texture."); + Running = false; + return; + } // Submit Commands SubmitCommandLists(GraphicsDevice);