Fences first pass

This commit is contained in:
2025-02-18 22:26:50 -05:00
parent 857f8c4e69
commit cc9bbf0ef5
6 changed files with 167 additions and 13 deletions

View File

@@ -1,7 +1,10 @@
#include <pch.h>
#include <Core/Memory/Allocator.h>
#include <Graphics/D3D12/D3D12Synchronization.h>
#include <Graphics/D3D12/DX12CommandList.h>
#include <Graphics/D3D12/DX12GraphicsDevice.h>
#include <Graphics/D3D12/DX12Utils.h>
namespace Juliet::D3D12
{
@@ -38,4 +41,58 @@ namespace Juliet::D3D12
ID3D12GraphicsCommandList_ResourceBarrier(commandList->GraphicsCommandList.CommandList, numBarriers, barrierDesc);
}
}
D3D12Fence* AcquireFence(NonNullPtr<D3D12Driver> driver)
{
D3D12Fence* fence;
ID3D12Fence* handle;
// TODO :Thread safe (lock + atomic)
if (driver->AvailableFenceCount == 0)
{
HRESULT result = ID3D12Device_CreateFence(driver->D3D12Device, D3D12_FENCE_UNSIGNALED_VALUE, D3D12_FENCE_FLAG_NONE,
IID_ID3D12Fence, reinterpret_cast<void**>(&handle));
if (FAILED(result))
{
LogError(driver, "Failed to create fence!", result);
return nullptr;
}
fence = static_cast<D3D12Fence*>(Calloc(1, sizeof(D3D12Fence)));
if (!fence)
{
ID3D12Fence_Release(handle);
return nullptr;
}
fence->Handle = handle;
fence->Event = CreateEvent(nullptr, false, false, nullptr);
fence->ReferenceCount = 0;
}
else
{
fence = driver->AvailableFences[driver->AvailableFenceCount - 1];
driver->AvailableFenceCount -= 1;
ID3D12Fence_Signal(fence->Handle, D3D12_FENCE_UNSIGNALED_VALUE);
}
fence->ReferenceCount += 1;
return fence;
}
void DestroyFence(NonNullPtr<D3D12Fence> fence)
{
if (fence->Handle)
{
ID3D12Fence_Release(fence->Handle);
}
if (fence->Event)
{
CloseHandle(fence->Event);
}
Free(fence.Get());
}
} // namespace Juliet::D3D12

View File

@@ -5,10 +5,23 @@
namespace Juliet::D3D12
{
#define D3D12_FENCE_UNSIGNALED_VALUE 0
#define D3D12_FENCE_SIGNAL_VALUE 1
// Forward Declare
struct D3D12CommandList;
extern void ResourceBarrier(NonNullPtr<D3D12CommandList> commandList, D3D12_RESOURCE_STATES sourceState, D3D12_RESOURCE_STATES destinationState,
ID3D12Resource* resource, uint32 subresourceIndex, bool needsUavBarrier);
}
struct D3D12Fence
{
ID3D12Fence* Handle;
HANDLE Event; // used for blocking
int32 ReferenceCount; // TODO : Atomic
};
extern void ResourceBarrier(NonNullPtr<D3D12CommandList> commandList, D3D12_RESOURCE_STATES sourceState,
D3D12_RESOURCE_STATES destinationState, ID3D12Resource* resource,
uint32 subresourceIndex, bool needsUavBarrier);
extern D3D12Fence* AcquireFence(NonNullPtr<D3D12Driver> driver);
extern void DestroyFence(NonNullPtr<D3D12Fence> fence);
} // namespace Juliet::D3D12

View File

@@ -1,6 +1,7 @@
#include <pch.h>
#include <Core/Memory/Allocator.h>
#include <Graphics/D3D12/D3D12Synchronization.h>
#include <Graphics/D3D12/DX12CommandList.h>
#include <Graphics/D3D12/DX12GraphicsDevice.h>
#include <Graphics/D3D12/DX12Utils.h>
@@ -110,6 +111,7 @@ namespace Juliet::D3D12
if (!commandList)
{
Log(LogLevel::Error, LogCategory::Graphics, "Cannot allocate D3D12CommandList: Out of memory");
DestroyCommandList(commandList);
return false;
}
@@ -118,8 +120,9 @@ namespace Juliet::D3D12
if (!resizedArray)
{
Assert(false &&
"Error not implemented, out of memory, handle that by deallocating stuff and returning false");
Log(LogLevel::Error, LogCategory::Graphics,
"Error not implemented, out of memory, handle that by deallocating stuff and returning false");
DestroyCommandList(commandList);
return false;
}
@@ -158,7 +161,8 @@ namespace Juliet::D3D12
{
if (!CreateD3D12CommandList(d3d12Driver, commandList, queueType))
{
// TODO Shoud destroy the command list here
Log(LogLevel::Error, LogCategory::Graphics, "Cannot Create D3D12 command list");
DestroyCommandList(commandList);
return nullptr;
}
}
@@ -243,10 +247,24 @@ namespace Juliet::D3D12
ID3D12CommandList_Release(commandLists[0]);
// TODO Fences
// Acquire a fence and set it to the in-flight fence
d3d12CommandList->InFlightFence = AcquireFence(d3d12Driver);
if (!d3d12CommandList->InFlightFence)
{
return false;
}
// Mark that a fence should be signaled after command list execution
result = ID3D12CommandQueue_Signal(d3d12Driver->GraphicsQueue, d3d12CommandList->InFlightFence->Handle, D3D12_FENCE_SIGNAL_VALUE);
if (FAILED(result))
{
LogError(d3d12Driver, "Failed to enqueue fence signal!", result);
return false;
}
// Mark the command list as submitted
if (d3d12Driver->SubmittedCommandBufferCount + 1 >= d3d12Driver->SubmittedCommandListCapacity) {
if (d3d12Driver->SubmittedCommandBufferCount + 1 >= d3d12Driver->SubmittedCommandListCapacity)
{
d3d12Driver->SubmittedCommandListCapacity = d3d12Driver->SubmittedCommandBufferCount + 1;
d3d12Driver->SubmittedCommandLists = static_cast<D3D12CommandList**>(
@@ -281,10 +299,11 @@ namespace Juliet::D3D12
result = false;
}
ID3D12Resource_Release(windowData->SwapChainTextureContainers[presentData->SwapChainImageIndex].ActiveTexture->Resource);
ID3D12Resource_Release(
windowData->SwapChainTextureContainers[presentData->SwapChainImageIndex].ActiveTexture->Resource);
//windowData->inFlightFences[windowData->frameCounter] = (SDL_GPUFence*)d3d12CommandBuffer->inFlightFence;
//(void)SDL_AtomicIncRef(&d3d12CommandBuffer->inFlightFence->referenceCount);
windowData->InFlightFences[windowData->WindowFrameCounter] = reinterpret_cast<Fence*>(d3d12CommandList->InFlightFence);
d3d12CommandList->InFlightFence->ReferenceCount += 1;
windowData->WindowFrameCounter = (windowData->WindowFrameCounter + 1) % d3d12Driver->FramesInFlight;
}
@@ -310,6 +329,26 @@ namespace Juliet::D3D12
return success;
}
void DestroyCommandList(NonNullPtr<D3D12CommandList> commandList)
{
// TODO : Handle other kind of command list (copy compute)
if (commandList->GraphicsCommandList.CommandList)
{
ID3D12GraphicsCommandList_Release(commandList->GraphicsCommandList.CommandList);
}
for (auto* allocator : commandList->GraphicsCommandList.Allocator)
{
if (allocator)
{
ID3D12CommandAllocator_Release(allocator);
}
}
Free(commandList->PresentDatas);
Free(commandList.Get());
}
void SetViewPort(NonNullPtr<CommandList> commandList, const GraphicsViewPort& viewPort)
{
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
@@ -347,5 +386,4 @@ namespace Juliet::D3D12
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
ID3D12GraphicsCommandList_OMSetStencilRef(d3d12CommandList->GraphicsCommandList.CommandList, reference);
}
} // namespace Juliet::D3D12

View File

@@ -9,8 +9,9 @@ namespace Juliet::D3D12
{
// Forward Declare
struct D3D12Driver;
struct D3D12WindowData;
struct D3D12Fence;
struct D3D12TextureSubresource;
struct D3D12WindowData;
struct D3D12CommandListBaseData
{
@@ -44,6 +45,8 @@ namespace Juliet::D3D12
uint32 PresentDataCapacity;
uint32 PresentDataCount;
D3D12Fence* InFlightFence;
D3D12GraphicsCommandListData GraphicsCommandList;
D3D12GraphicsCommandListData ComputeCommandList;
D3D12CopyCommandListData CopyCommandList;
@@ -54,6 +57,7 @@ namespace Juliet::D3D12
extern CommandList* AcquireCommandList(NonNullPtr<GPUDriver> driver, QueueType queueType);
extern bool SubmitCommandLists(NonNullPtr<CommandList> commandList);
extern void DestroyCommandList(NonNullPtr<D3D12CommandList> commandList);
extern void SetViewPort(NonNullPtr<CommandList> commandList, const GraphicsViewPort& viewPort);
extern void SetScissorRect(NonNullPtr<CommandList> commandList, const Rectangle& rectangle);
extern void SetBlendConstants(NonNullPtr<CommandList> commandList, FColor blendConstants);

View File

@@ -4,6 +4,7 @@
#include <Core/DynLib/DynamicLibrary.h>
#include <Core/Memory/Allocator.h>
#include <Graphics/D3D12/D3D12RenderPass.h>
#include <Graphics/D3D12/D3D12Synchronization.h>
#include <Graphics/D3D12/DX12CommandList.h>
#include <Graphics/D3D12/DX12GraphicsDevice.h>
#include <Graphics/D3D12/DX12Includes.h>
@@ -168,6 +169,7 @@ namespace Juliet::D3D12
void DestroyDriver_Internal(NonNullPtr<D3D12Driver> driver)
{
// Destroy pools
for (uint32 i = 0; i < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; i += 1)
{
if (driver->StagingDescriptorPools[i])
@@ -177,6 +179,32 @@ namespace Juliet::D3D12
}
}
// Release command buffers
for (uint32 i = 0; i < driver->AvailableCommandListCount; i += 1)
{
if (driver->AvailableCommandLists[i])
{
DestroyCommandList(driver->AvailableCommandLists[i]);
driver->AvailableCommandLists[i] = nullptr;
}
}
// Release fences
for (uint32 i = 0; i < driver->AvailableFenceCount; i += 1)
{
if (driver->AvailableFences[i])
{
DestroyFence(driver->AvailableFences[i]);
driver->AvailableFences[i] = nullptr;
}
}
// Clean allocations
Free(driver->AvailableCommandLists);
Free(driver->SubmittedCommandLists);
Free(driver->WindowData);
Free(driver->AvailableFences);
if (driver->IndirectDrawCommandSignature)
{
ID3D12CommandSignature_Release(driver->IndirectDrawCommandSignature);
@@ -529,6 +557,15 @@ namespace Juliet::D3D12
return nullptr;
}
driver->AvailableFenceCapacity = 4;
driver->AvailableFenceCount = 0;
driver->AvailableFences = static_cast<D3D12Fence**>(Calloc(driver->AvailableFenceCapacity, sizeof(D3D12Fence*)));
if (!driver->AvailableFences)
{
DestroyDriver_Internal(driver);
return nullptr;
}
// Staging descriptor pools
for (uint32 i = 0; i < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; i += 1)
{

View File

@@ -14,6 +14,7 @@ namespace Juliet::D3D12
{
// Forward Declare
struct D3D12CommandList;
struct D3D12Fence;
struct D3D12WindowData
{
@@ -72,6 +73,10 @@ namespace Juliet::D3D12
uint8 SubmittedCommandListCapacity;
uint8 SubmittedCommandBufferCount;
D3D12Fence** AvailableFences;
uint32 AvailableFenceCount;
uint32 AvailableFenceCapacity;
D3D12StagingDescriptorPool* StagingDescriptorPools[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES];
uint8 FramesInFlight;