Fences first pass
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user