Finishing fences

+ moved some functions to an internal namespace to tidy stuff a bit
This commit is contained in:
2025-02-19 22:01:39 -05:00
parent cc9bbf0ef5
commit 8326772558
14 changed files with 683 additions and 485 deletions

View File

@@ -26,7 +26,7 @@ namespace Juliet::D3D12
bool ExtendStagingDescriptorPool(NonNullPtr<D3D12Driver> driver, D3D12StagingDescriptorPool& pool)
{
D3D12DescriptorHeap* heap =
CreateDescriptorHeap(driver, pool.Heaps[0]->HeapType, kStagingHeapDescriptorExpectedCount, true);
Internal::CreateDescriptorHeap(driver, pool.Heaps[0]->HeapType, kStagingHeapDescriptorExpectedCount, true);
if (!heap)
{
return false;
@@ -47,7 +47,10 @@ namespace Juliet::D3D12
}
} // namespace
D3D12DescriptorHeap* CreateDescriptorHeap(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 count, bool isStaging)
namespace Internal
{
D3D12DescriptorHeap* CreateDescriptorHeap(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type,
uint32 count, bool isStaging)
{
ID3D12DescriptorHeap* handle;
@@ -114,8 +117,8 @@ namespace Juliet::D3D12
pool->FreeDescriptorCapacity = kStagingHeapDescriptorExpectedCount;
pool->FreeDescriptorCount = kStagingHeapDescriptorExpectedCount;
pool->FreeDescriptors =
static_cast<D3D12StagingDescriptor*>(Malloc(kStagingHeapDescriptorExpectedCount * sizeof(D3D12StagingDescriptor)));
pool->FreeDescriptors = static_cast<D3D12StagingDescriptor*>(
Malloc(kStagingHeapDescriptorExpectedCount * sizeof(D3D12StagingDescriptor)));
InitStagingDescriptorPool(heap, pool);
@@ -165,4 +168,5 @@ namespace Juliet::D3D12
Free(pool->FreeDescriptors);
Free(pool.Get());
}
} // namespace Internal
} // namespace Juliet::D3D12

View File

@@ -51,8 +51,10 @@ namespace Juliet::D3D12
uint32 CpuHandleIndex;
};
extern D3D12DescriptorHeap* CreateDescriptorHeap(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type,
uint32 count, bool isStaging);
namespace Internal
{
extern D3D12DescriptorHeap* CreateDescriptorHeap(NonNullPtr<D3D12Driver> driver,
D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 count, bool isStaging);
extern void DestroyDescriptorHeap(NonNullPtr<D3D12DescriptorHeap> heap);
extern D3D12StagingDescriptorPool* CreateStagingDescriptorPool(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type);
@@ -60,4 +62,5 @@ namespace Juliet::D3D12
D3D12StagingDescriptor& outDescriptor);
extern void ReleaseStagingDescriptor(NonNullPtr<D3D12Driver> driver, D3D12StagingDescriptor& cpuDescriptor);
extern void DestroyStagingDescriptorPool(NonNullPtr<D3D12StagingDescriptorPool> pool);
} // namespace Internal
} // namespace Juliet::D3D12

View File

@@ -31,7 +31,7 @@ namespace Juliet::D3D12
for (uint32 idx = 0; idx < colorTargetInfoCount; ++idx)
{
auto* container = reinterpret_cast<D3D12TextureContainer*>(colorTargetInfos[idx].TargetTexture);
D3D12TextureSubresource* subresource = PrepareTextureSubresourceForWrite(
D3D12TextureSubresource* subresource = Internal::PrepareTextureSubresourceForWrite(
d3d12CommandList, container,
container->Header.CreateInfo.Type == TextureType::Texture_3D ? 0 : colorTargetInfos[idx].LayerIndex,
colorTargetInfos[idx].MipLevel, colorTargetInfos[idx].CycleTexture, D3D12_RESOURCE_STATE_RENDER_TARGET);
@@ -61,8 +61,10 @@ namespace Juliet::D3D12
{
auto resolveContainer = reinterpret_cast<D3D12TextureContainer*>(colorTargetInfos[idx].ResolveTexture);
D3D12TextureSubresource* resolveSubresource =
PrepareTextureSubresourceForWrite(d3d12CommandList, resolveContainer, colorTargetInfos[idx].ResolveLayerIndex,
colorTargetInfos[idx].ResolveMipLevel, colorTargetInfos[idx].CycleResolveTexture,
Internal::PrepareTextureSubresourceForWrite(d3d12CommandList, resolveContainer,
colorTargetInfos[idx].ResolveLayerIndex,
colorTargetInfos[idx].ResolveMipLevel,
colorTargetInfos[idx].CycleResolveTexture,
D3D12_RESOURCE_STATE_RESOLVE_DEST);
d3d12CommandList->ColorResolveSubresources[idx] = resolveSubresource;
@@ -114,7 +116,8 @@ namespace Juliet::D3D12
{
if (d3d12CommandList->ColorResolveSubresources[idx])
{
TextureSubresourceBarrier(d3d12CommandList, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_RESOLVE_SOURCE,
Internal::TextureSubresourceBarrier(d3d12CommandList, D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_RESOLVE_SOURCE,
d3d12CommandList->ColorTargetSubresources[idx]);
ID3D12GraphicsCommandList_ResolveSubresource(
d3d12CommandList->GraphicsCommandList.CommandList,
@@ -122,18 +125,21 @@ namespace Juliet::D3D12
d3d12CommandList->ColorResolveSubresources[idx]->Index,
d3d12CommandList->ColorTargetSubresources[idx]->Parent->Resource,
d3d12CommandList->ColorTargetSubresources[idx]->Index,
ConvertToD3D12TextureFormat(
Internal::ConvertToD3D12TextureFormat(
d3d12CommandList->ColorTargetSubresources[idx]->Parent->Container->Header.CreateInfo.Format));
TextureSubresourceTransitionToDefaultUsage(d3d12CommandList, d3d12CommandList->ColorTargetSubresources[idx],
Internal::TextureSubresourceTransitionToDefaultUsage(d3d12CommandList,
d3d12CommandList->ColorTargetSubresources[idx],
D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
TextureSubresourceTransitionToDefaultUsage(d3d12CommandList, d3d12CommandList->ColorResolveSubresources[idx],
Internal::TextureSubresourceTransitionToDefaultUsage(d3d12CommandList,
d3d12CommandList->ColorResolveSubresources[idx],
D3D12_RESOURCE_STATE_RESOLVE_DEST);
}
else
{
TextureSubresourceTransitionToDefaultUsage(d3d12CommandList, d3d12CommandList->ColorTargetSubresources[idx],
Internal::TextureSubresourceTransitionToDefaultUsage(d3d12CommandList,
d3d12CommandList->ColorTargetSubresources[idx],
D3D12_RESOURCE_STATE_RENDER_TARGET);
}
}

View File

@@ -8,8 +8,88 @@
namespace Juliet::D3D12
{
namespace
{
void ReleaseFenceToPool(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12Fence> fence)
{
if (driver->AvailableFenceCount + 1 >= driver->AvailableFenceCapacity)
{
driver->AvailableFenceCapacity = driver->AvailableFenceCapacity * 2;
driver->AvailableFences = static_cast<D3D12Fence**>(
Realloc(driver->AvailableFences, sizeof(D3D12Fence*) * driver->AvailableFenceCapacity));
}
driver->AvailableFences[driver->AvailableFenceCount] = fence;
driver->AvailableFenceCount += 1;
}
} // namespace
bool Wait(NonNullPtr<GPUDriver> driver)
{
auto d3d12driver = static_cast<D3D12Driver*>(driver.Get());
D3D12Fence* fence = Internal::AcquireFence(d3d12driver);
if (!fence)
{
return false;
}
if (d3d12driver->GraphicsQueue)
{
// Insert a signal into the end of the command queue...
ID3D12CommandQueue_Signal(d3d12driver->GraphicsQueue, fence->Handle, D3D12_FENCE_SIGNAL_VALUE);
// ...and then block on it.
if (ID3D12Fence_GetCompletedValue(fence->Handle) != D3D12_FENCE_SIGNAL_VALUE)
{
HRESULT result = ID3D12Fence_SetEventOnCompletion(fence->Handle, D3D12_FENCE_SIGNAL_VALUE, fence->Event);
if (FAILED(result))
{
LogError(d3d12driver, "Setting fence event failed!", result);
return false;
}
DWORD waitResult = WaitForSingleObject(fence->Event, INFINITE);
if (waitResult == WAIT_FAILED)
{
LogError(d3d12driver, "Wait failed!", result);
return false;
}
}
}
ReleaseFence(driver, reinterpret_cast<Fence*>(fence));
bool result = true;
// Clean up
for (int32 idx = d3d12driver->SubmittedCommandListCount - 1; idx >= 0; idx -= 1)
{
result &= Internal::CleanCommandList(d3d12driver, d3d12driver->SubmittedCommandLists[idx], false);
}
return result;
}
bool QueryFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence)
{
return true;
}
void ReleaseFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence)
{
auto d3d12driver = static_cast<D3D12Driver*>(driver.Get());
auto d3d12Fence = reinterpret_cast<D3D12Fence*>(fence.Get());
if (--d3d12Fence->ReferenceCount == 0)
{
ReleaseFenceToPool(d3d12driver, d3d12Fence);
}
}
namespace Internal
{
void ResourceBarrier(NonNullPtr<D3D12CommandList> commandList, D3D12_RESOURCE_STATES sourceState,
D3D12_RESOURCE_STATES destinationState, ID3D12Resource* resource, uint32 subresourceIndex, bool needsUavBarrier)
D3D12_RESOURCE_STATES destinationState, ID3D12Resource* resource, uint32 subresourceIndex,
bool needsUavBarrier)
{
D3D12_RESOURCE_BARRIER barrierDesc[2];
uint32 numBarriers = 0;
@@ -94,5 +174,5 @@ namespace Juliet::D3D12
}
Free(fence.Get());
}
} // namespace Internal
} // namespace Juliet::D3D12

View File

@@ -2,6 +2,13 @@
#include <Core/Common/NonNullPtr.h>
#include <Graphics/D3D12/D3D12Common.h>
#include <Graphics/GraphicsDevice.h>
namespace Juliet
{
struct Fence;
struct GPUDriver;
} // namespace Juliet
namespace Juliet::D3D12
{
@@ -18,10 +25,17 @@ namespace Juliet::D3D12
int32 ReferenceCount; // TODO : Atomic
};
extern bool Wait(NonNullPtr<GPUDriver> driver);
extern bool QueryFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
extern void ReleaseFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
namespace Internal
{
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 Internal
} // namespace Juliet::D3D12

View File

@@ -157,20 +157,23 @@ namespace Juliet::D3D12
}
} // namespace
D3D12TextureSubresource* PrepareTextureSubresourceForWrite(NonNullPtr<D3D12CommandList> commandList,
NonNullPtr<D3D12TextureContainer> container, uint32 layer,
uint32 level, bool shouldCycle, D3D12_RESOURCE_STATES newTextureUsage)
namespace Internal
{
D3D12TextureSubresource* subresource = FetchTextureSubresource(container, layer, level);
D3D12TextureSubresource* PrepareTextureSubresourceForWrite(NonNullPtr<D3D12CommandList> commandList,
NonNullPtr<D3D12TextureContainer> container,
uint32 layer, uint32 level, bool shouldCycle,
D3D12_RESOURCE_STATES newTextureUsage)
{
D3D12TextureSubresource* subresource = Internal::FetchTextureSubresource(container, layer, level);
if (shouldCycle and container->CanBeCycled and subresource->Parent->RefCount > 0)
{
// TODO: Cycle the active texture to an available one. Not needed for swap chain (current objective)
// CycleActiveTexture(commandList->Driver, container);
subresource = FetchTextureSubresource(container, layer, level);
subresource = Internal::FetchTextureSubresource(container, layer, level);
}
TextureSubresourceTransitionFromDefaultUsage(commandList, subresource, newTextureUsage);
Internal::TextureSubresourceTransitionFromDefaultUsage(commandList, subresource, newTextureUsage);
return subresource;
}
@@ -185,9 +188,10 @@ namespace Juliet::D3D12
D3D12_RESOURCE_STATES destinationState, NonNullPtr<D3D12TextureSubresource> textureSubresource)
{
TextureUsageFlag currentFlag = textureSubresource->Parent->Container->Header.CreateInfo.Flags;
bool needsUAVBarrier = ((currentFlag & TextureUsageFlag::ComputeStorageWrite) != TextureUsageFlag::None) ||
bool needsUAVBarrier =
((currentFlag & TextureUsageFlag::ComputeStorageWrite) != TextureUsageFlag::None) ||
((currentFlag & TextureUsageFlag::ComputeStorageSimultaneousReadWrite) != TextureUsageFlag::None);
ResourceBarrier(commandList, sourceState, destinationState, textureSubresource->Parent->Resource,
Internal::ResourceBarrier(commandList, sourceState, destinationState, textureSubresource->Parent->Resource,
textureSubresource->Index, needsUAVBarrier);
}
@@ -200,8 +204,8 @@ namespace Juliet::D3D12
TextureSubresourceBarrier(commandList, defaultUsage, toTextureUsage, subresource);
}
void TextureTransitionFromDefaultUsage(NonNullPtr<D3D12CommandList> commandList, NonNullPtr<D3D12Texture> texture,
D3D12_RESOURCE_STATES toTextureUsage)
void TextureTransitionFromDefaultUsage(NonNullPtr<D3D12CommandList> commandList,
NonNullPtr<D3D12Texture> texture, D3D12_RESOURCE_STATES toTextureUsage)
{
for (uint32 i = 0; i < texture->SubresourceCount; ++i)
{
@@ -210,7 +214,8 @@ namespace Juliet::D3D12
}
void TextureSubresourceTransitionToDefaultUsage(NonNullPtr<D3D12CommandList> commandList,
NonNullPtr<D3D12TextureSubresource> subresource, D3D12_RESOURCE_STATES fromTextureUsage)
NonNullPtr<D3D12TextureSubresource> subresource,
D3D12_RESOURCE_STATES fromTextureUsage)
{
D3D12_RESOURCE_STATES defaultUsage =
GetDefaultTextureResourceState(subresource->Parent->Container->Header.CreateInfo.Flags);
@@ -231,5 +236,5 @@ namespace Juliet::D3D12
{
return JulietToD3D12_TextureFormat[ToUnderlying(format)];
}
} // namespace Internal
} // namespace Juliet::D3D12

View File

@@ -62,13 +62,16 @@ namespace Juliet::D3D12
int32 RefCount;
};
namespace Internal
{
extern D3D12TextureSubresource* PrepareTextureSubresourceForWrite(NonNullPtr<D3D12CommandList>,
NonNullPtr<D3D12TextureContainer> container,
uint32 layer, uint32 level, bool shouldCycle,
D3D12_RESOURCE_STATES newTextureUsage);
extern D3D12TextureSubresource* FetchTextureSubresource(NonNullPtr<D3D12TextureContainer> container, uint32 layer, uint32 level);
extern void TextureSubresourceBarrier(NonNullPtr<D3D12CommandList> commandList, D3D12_RESOURCE_STATES sourceState,
D3D12_RESOURCE_STATES destinationState,
extern D3D12TextureSubresource* FetchTextureSubresource(NonNullPtr<D3D12TextureContainer> container,
uint32 layer, uint32 level);
extern void TextureSubresourceBarrier(NonNullPtr<D3D12CommandList> commandList,
D3D12_RESOURCE_STATES sourceState, D3D12_RESOURCE_STATES destinationState,
NonNullPtr<D3D12TextureSubresource> textureSubresource);
// Texture usage transition
@@ -80,9 +83,10 @@ namespace Juliet::D3D12
extern void TextureSubresourceTransitionToDefaultUsage(NonNullPtr<D3D12CommandList> commandList,
NonNullPtr<D3D12TextureSubresource> subresource,
D3D12_RESOURCE_STATES fromTextureUsage);
extern void TextureTransitionToDefaultUsage(NonNullPtr<D3D12CommandList> commandList,
NonNullPtr<D3D12Texture> texture, D3D12_RESOURCE_STATES fromTextureUsage);
extern void TextureTransitionToDefaultUsage(NonNullPtr<D3D12CommandList> commandList, NonNullPtr<D3D12Texture> texture,
D3D12_RESOURCE_STATES fromTextureUsage);
// Utils
extern DXGI_FORMAT ConvertToD3D12TextureFormat(TextureFormat format);
} // namespace Internal
} // namespace Juliet::D3D12

View File

@@ -10,7 +10,7 @@ namespace Juliet::D3D12
{
namespace
{
bool HasD3D12CommandList(NonNullPtr<D3D12CommandList> commandList, QueueType queueType)
bool HasD3D12CommandListForQueueType(NonNullPtr<D3D12CommandList> commandList, QueueType queueType)
{
switch (queueType)
{
@@ -37,7 +37,7 @@ namespace Juliet::D3D12
return true;
}
bool CreateD3D12CommandList(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12CommandList> commandList, QueueType queueType)
bool CreateD3D12CommandListForQueueType(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12CommandList> commandList, QueueType queueType)
{
// TODO: String library
std::wstring wide_str = L"CommandList ID:" + std::to_wstring(commandList->ID);
@@ -111,7 +111,7 @@ namespace Juliet::D3D12
if (!commandList)
{
Log(LogLevel::Error, LogCategory::Graphics, "Cannot allocate D3D12CommandList: Out of memory");
DestroyCommandList(commandList);
Internal::DestroyCommandList(commandList);
return false;
}
@@ -122,14 +122,18 @@ namespace Juliet::D3D12
{
Log(LogLevel::Error, LogCategory::Graphics,
"Error not implemented, out of memory, handle that by deallocating stuff and returning false");
DestroyCommandList(commandList);
Internal::DestroyCommandList(commandList);
return false;
}
uint32 id = driver->AvailableCommandListCapacity;
driver->AvailableCommandListCapacity += 1;
driver->AvailableCommandLists = resizedArray;
driver->AvailableCommandLists[driver->AvailableCommandListCapacity] = commandList;
commandList->ID = driver->AvailableCommandListCapacity;
driver->AvailableCommandLists[driver->AvailableCommandListCount] = commandList;
driver->AvailableCommandListCount += 1;
commandList->ID = id;
commandList->Driver = driver;
commandList->PresentDataCapacity = 1;
@@ -137,35 +141,42 @@ namespace Juliet::D3D12
commandList->PresentDatas =
static_cast<D3D12PresentData*>(Calloc(commandList->PresentDataCapacity, sizeof(D3D12PresentData)));
driver->AvailableCommandListCapacity += 1;
// TODO : Simplify this
if (!HasD3D12CommandListForQueueType(commandList, queueType))
{
if (!CreateD3D12CommandListForQueueType(driver, commandList, queueType))
{
Log(LogLevel::Error, LogCategory::Graphics, "Cannot Create D3D12 command list");
Internal::DestroyCommandList(commandList);
return false;
}
}
return true;
}
D3D12CommandList* AcquireCommandListFromPool(NonNullPtr<D3D12Driver> driver, QueueType queueType)
{
if (driver->AvailableCommandListCount == 0)
{
if (!AllocateCommandList(driver, queueType))
{
return nullptr;
}
}
D3D12CommandList* commandList = driver->AvailableCommandLists[driver->AvailableCommandListCount - 1];
driver->AvailableCommandListCount -= 1;
return commandList;
}
} // namespace
CommandList* AcquireCommandList(NonNullPtr<GPUDriver> driver, QueueType queueType)
{
auto* d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
uint8 currentCommandListIndex = d3d12Driver->AvailableCommandListCount;
if (currentCommandListIndex >= d3d12Driver->AvailableCommandListCapacity)
{
if (!AllocateCommandList(d3d12Driver, queueType))
{
return nullptr;
}
}
D3D12CommandList* commandList = d3d12Driver->AvailableCommandLists[currentCommandListIndex];
if (!HasD3D12CommandList(commandList, queueType))
{
if (!CreateD3D12CommandList(d3d12Driver, commandList, queueType))
{
Log(LogLevel::Error, LogCategory::Graphics, "Cannot Create D3D12 command list");
DestroyCommandList(commandList);
return nullptr;
}
}
D3D12CommandList* commandList = AcquireCommandListFromPool(d3d12Driver, queueType);
// Get Proper allocator for the frame and reset both it and the requested queue
uint8 bufferIndex = d3d12Driver->FrameCounter % GPUDriver::kResourceBufferCount;
@@ -195,7 +206,8 @@ namespace Juliet::D3D12
default: Assert(false && "Unsupported QueueType"); return nullptr;
}
d3d12Driver->AvailableCommandListCount += 1;
commandList->AutoReleaseFence = true;
return reinterpret_cast<CommandList*>(commandList);
}
@@ -212,7 +224,7 @@ namespace Juliet::D3D12
uint32 swapchainIndex = d3d12CommandList->PresentDatas[i].SwapChainImageIndex;
D3D12TextureContainer* container =
&d3d12CommandList->PresentDatas[i].WindowData->SwapChainTextureContainers[swapchainIndex];
D3D12TextureSubresource* subresource = FetchTextureSubresource(container, 0, 0);
D3D12TextureSubresource* subresource = Internal::FetchTextureSubresource(container, 0, 0);
D3D12_RESOURCE_BARRIER barrierDesc;
barrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
@@ -248,7 +260,7 @@ namespace Juliet::D3D12
ID3D12CommandList_Release(commandLists[0]);
// Acquire a fence and set it to the in-flight fence
d3d12CommandList->InFlightFence = AcquireFence(d3d12Driver);
d3d12CommandList->InFlightFence = Internal::AcquireFence(d3d12Driver);
if (!d3d12CommandList->InFlightFence)
{
return false;
@@ -263,16 +275,15 @@ namespace Juliet::D3D12
}
// Mark the command list as submitted
if (d3d12Driver->SubmittedCommandBufferCount + 1 >= d3d12Driver->SubmittedCommandListCapacity)
if (d3d12Driver->SubmittedCommandListCount + 1 >= d3d12Driver->SubmittedCommandListCapacity)
{
d3d12Driver->SubmittedCommandListCapacity = d3d12Driver->SubmittedCommandBufferCount + 1;
d3d12Driver->SubmittedCommandListCapacity = d3d12Driver->SubmittedCommandListCount + 1;
d3d12Driver->SubmittedCommandLists = static_cast<D3D12CommandList**>(
Realloc(d3d12Driver->SubmittedCommandLists, sizeof(D3D12CommandList*) * d3d12Driver->SubmittedCommandListCapacity));
}
d3d12Driver->SubmittedCommandLists[d3d12Driver->SubmittedCommandBufferCount] = d3d12CommandList;
d3d12Driver->SubmittedCommandBufferCount += 1;
d3d12Driver->SubmittedCommandLists[d3d12Driver->SubmittedCommandListCount] = d3d12CommandList;
d3d12Driver->SubmittedCommandListCount += 1;
bool success = true;
for (uint32 i = 0; i < d3d12CommandList->PresentDataCount; i += 1)
@@ -308,19 +319,15 @@ namespace Juliet::D3D12
}
// TODO : Correctly clean up and destroy
d3d12Driver->AvailableCommandListCount = 0;
// Check for cleanups
// for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
// Uint64 fenceValue = ID3D12Fence_GetCompletedValue(
// renderer->submittedCommandBuffers[i]->inFlightFence->handle);
//
// if (fenceValue == D3D12_FENCE_SIGNAL_VALUE) {
// result &= D3D12_INTERNAL_CleanCommandBuffer(
// renderer,
// renderer->submittedCommandBuffers[i],
// false);
// }
// }
for (int32 i = d3d12Driver->SubmittedCommandListCount - 1; i >= 0; i -= 1)
{
uint64 fenceValue = ID3D12Fence_GetCompletedValue(d3d12Driver->SubmittedCommandLists[i]->InFlightFence->Handle);
if (fenceValue == D3D12_FENCE_SIGNAL_VALUE)
{
result &= Internal::CleanCommandList(d3d12Driver, d3d12Driver->SubmittedCommandLists[i], false);
}
}
// TODO Destroy anything (buffer, texture, etc...)
@@ -329,26 +336,6 @@ 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());
@@ -386,4 +373,66 @@ namespace Juliet::D3D12
auto* d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
ID3D12GraphicsCommandList_OMSetStencilRef(d3d12CommandList->GraphicsCommandList.CommandList, reference);
}
namespace Internal
{
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());
}
bool CleanCommandList(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12CommandList> commandList, bool cancel)
{
// No more presentation data
commandList->PresentDataCount = 0;
// Release Fence if needed
if (commandList->AutoReleaseFence)
{
ReleaseFence(driver.Get(), reinterpret_cast<Fence*>(commandList->InFlightFence));
commandList->InFlightFence = nullptr;
}
// Return the command list to the pool
if (driver->AvailableCommandListCount == driver->AvailableCommandListCapacity)
{
driver->AvailableCommandListCapacity += 1;
driver->AvailableCommandLists = static_cast<D3D12CommandList**>(
Realloc(driver->AvailableCommandLists, driver->AvailableCommandListCapacity * sizeof(D3D12CommandList*)));
}
driver->AvailableCommandLists[driver->AvailableCommandListCount] = commandList;
driver->AvailableCommandListCount += 1;
// Remove this command list from the submitted list
if (!cancel)
{
for (uint32 idx = 0; idx < driver->SubmittedCommandListCount; idx += 1)
{
if (driver->SubmittedCommandLists[idx] == commandList)
{
driver->SubmittedCommandLists[idx] = driver->SubmittedCommandLists[driver->SubmittedCommandListCount - 1];
driver->SubmittedCommandListCount -= 1;
}
}
}
return true;
}
} // namespace Internal
} // namespace Juliet::D3D12

View File

@@ -46,6 +46,7 @@ namespace Juliet::D3D12
uint32 PresentDataCount;
D3D12Fence* InFlightFence;
bool AutoReleaseFence;
D3D12GraphicsCommandListData GraphicsCommandList;
D3D12GraphicsCommandListData ComputeCommandList;
@@ -57,9 +58,14 @@ 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);
extern void SetStencilReference(NonNullPtr<CommandList> commandList, uint8 reference);
namespace Internal
{
extern void DestroyCommandList(NonNullPtr<D3D12CommandList> commandList);
extern bool CleanCommandList(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12CommandList> commandList, bool cancel);
} // namespace Internal
} // namespace Juliet::D3D12

View File

@@ -174,7 +174,7 @@ namespace Juliet::D3D12
{
if (driver->StagingDescriptorPools[i])
{
DestroyStagingDescriptorPool(driver->StagingDescriptorPools[i]);
Internal::DestroyStagingDescriptorPool(driver->StagingDescriptorPools[i]);
driver->StagingDescriptorPools[i] = nullptr;
}
}
@@ -184,7 +184,7 @@ namespace Juliet::D3D12
{
if (driver->AvailableCommandLists[i])
{
DestroyCommandList(driver->AvailableCommandLists[i]);
Internal::DestroyCommandList(driver->AvailableCommandLists[i]);
driver->AvailableCommandLists[i] = nullptr;
}
}
@@ -194,7 +194,7 @@ namespace Juliet::D3D12
{
if (driver->AvailableFences[i])
{
DestroyFence(driver->AvailableFences[i]);
Internal::DestroyFence(driver->AvailableFences[i]);
driver->AvailableFences[i] = nullptr;
}
}
@@ -202,7 +202,7 @@ namespace Juliet::D3D12
// Clean allocations
Free(driver->AvailableCommandLists);
Free(driver->SubmittedCommandLists);
Free(driver->WindowData);
//Free(driver->WindowData); // TODO Should free the vector of WindowData, but we have only one for now
Free(driver->AvailableFences);
if (driver->IndirectDrawCommandSignature)
@@ -278,7 +278,7 @@ namespace Juliet::D3D12
windowData->Window = window;
if (!CreateSwapChain(d3d12Driver, windowData, SwapChainComposition::SDR, PresentMode::VSync))
if (!Internal::CreateSwapChain(d3d12Driver, windowData, SwapChainComposition::SDR, PresentMode::VSync))
{
Log(LogLevel::Error, LogCategory::Graphics, "AttachToWindow failure: Cannot create Swap Chain.");
Free(windowData);
@@ -294,12 +294,21 @@ namespace Juliet::D3D12
void DetachFromWindow(NonNullPtr<GPUDriver> driver, NonNullPtr<Window> window)
{
auto* d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
auto* windowData = d3d12Driver->WindowData;
Assert(windowData && "Trying to destroy a swapchain but no Window Data exists");
Assert(d3d12Driver->WindowData && "Trying to destroy a swapchain but no Window Data exists");
Wait(driver);
// TODO : Wait for any remaining work and release the fences.
for (uint32 idx = 0; idx < GPUDriver::kMaxFramesInFlight; idx += 1)
{
if (windowData->InFlightFences[idx] != nullptr)
{
ReleaseFence(driver, windowData->InFlightFences[idx]);
windowData->InFlightFences[idx] = nullptr;
}
}
DestroySwapChain(d3d12Driver, d3d12Driver->WindowData);
Internal::DestroySwapChain(d3d12Driver, d3d12Driver->WindowData);
Free(d3d12Driver->WindowData);
d3d12Driver->WindowData = nullptr;
@@ -548,7 +557,7 @@ namespace Juliet::D3D12
// Create Pools
driver->SubmittedCommandListCapacity = 4;
driver->SubmittedCommandBufferCount = 0;
driver->SubmittedCommandListCount = 0;
driver->SubmittedCommandLists =
static_cast<D3D12CommandList**>(Calloc(driver->SubmittedCommandListCapacity, sizeof(D3D12CommandList*)));
if (!driver->SubmittedCommandLists)
@@ -570,7 +579,7 @@ namespace Juliet::D3D12
for (uint32 i = 0; i < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; i += 1)
{
driver->StagingDescriptorPools[i] =
CreateStagingDescriptorPool(driver, static_cast<D3D12_DESCRIPTOR_HEAP_TYPE>(i));
Internal::CreateStagingDescriptorPool(driver, static_cast<D3D12_DESCRIPTOR_HEAP_TYPE>(i));
if (driver->StagingDescriptorPools[i] == nullptr)
{
@@ -605,6 +614,10 @@ namespace Juliet::D3D12
device->SetBlendConstants = SetBlendConstants;
device->SetStencilReference = SetStencilReference;
device->Wait = Wait;
device->QueryFence = QueryFence;
device->ReleaseFence = ReleaseFence;
device->Driver = driver;
driver->GraphicsDevice = device;

View File

@@ -71,7 +71,7 @@ namespace Juliet::D3D12
D3D12CommandList** SubmittedCommandLists;
uint8 SubmittedCommandListCapacity;
uint8 SubmittedCommandBufferCount;
uint8 SubmittedCommandListCount;
D3D12Fence** AvailableFences;
uint32 AvailableFenceCount;

View File

@@ -3,13 +3,14 @@
#include <Core/HAL/Display/Win32/Win32Window.h>
#include <Core/Memory/Allocator.h>
#include <Graphics/D3D12/D3D12Texture.h>
#include <Graphics/D3D12/DX12CommandList.h>
#include <Graphics/D3D12/DX12GraphicsDevice.h>
#include <Graphics/D3D12/DX12Includes.h>
#include <Graphics/D3D12/DX12SwapChain.h>
#include <Graphics/D3D12/DX12Utils.h>
#include <algorithm>
#include <DX12CommandList.h>
namespace Juliet::D3D12
{
namespace
@@ -105,7 +106,7 @@ namespace Juliet::D3D12
texture->IndexInContainer = 0;
// Assign SRV to the swapchain texture
AssignStagingDescriptor(driver, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, texture->SRVHandle);
Internal::AssignStagingDescriptor(driver, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, texture->SRVHandle);
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format = SwapchainCompositionToTextureFormat[ToUnderlying(composition)];
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
@@ -118,7 +119,7 @@ namespace Juliet::D3D12
// Assign RTV to the swapchain texture
DXGI_FORMAT swapchainFormat = SwapchainCompositionToTextureFormat[ToUnderlying(composition)];
AssignStagingDescriptor(driver, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, texture->Subresources[0].RTVHandles[0]);
Internal::AssignStagingDescriptor(driver, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, texture->Subresources[0].RTVHandles[0]);
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc;
rtvDesc.Format = (composition == SwapChainComposition::SDR_LINEAR) ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : swapchainFormat;
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
@@ -186,6 +187,13 @@ namespace Juliet::D3D12
}
} // namespace
bool AcquireSwapChainTexture(NonNullPtr<CommandList> commandList, NonNullPtr<Window> window, Texture** swapChainTexture)
{
return AcquireSwapChainTexture(false, commandList, window, swapChainTexture);
}
namespace Internal
{
bool CreateSwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData,
SwapChainComposition composition, PresentMode presentMode)
{
@@ -297,17 +305,13 @@ namespace Juliet::D3D12
return true;
}
bool AcquireSwapChainTexture(NonNullPtr<CommandList> commandList, NonNullPtr<Window> window, Texture** swapChainTexture)
{
return AcquireSwapChainTexture(false, commandList, window, swapChainTexture);
}
void DestroySwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData)
{
for (uint32 idx = 0; idx < windowData->SwapChainTextureCount; ++idx)
{
ReleaseStagingDescriptor(driver, windowData->SwapChainTextureContainers[idx].ActiveTexture->SRVHandle);
ReleaseStagingDescriptor(driver, windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources[0].RTVHandles[0]);
ReleaseStagingDescriptor(driver,
windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources[0].RTVHandles[0]);
Free(windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources[0].RTVHandles);
Free(windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources);
@@ -318,4 +322,5 @@ namespace Juliet::D3D12
IDXGISwapChain_Release(windowData->SwapChain);
windowData->SwapChain = nullptr;
}
} // namespace Internal
} // namespace Juliet::D3D12

View File

@@ -7,8 +7,12 @@ namespace Juliet::D3D12
struct D3D12Driver;
struct D3D12WindowData;
extern bool AcquireSwapChainTexture(NonNullPtr<CommandList> commandList, NonNullPtr<Window> window, Texture** swapChainTexture);
namespace Internal
{
extern bool CreateSwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData,
SwapChainComposition composition, PresentMode presentMode);
extern bool AcquireSwapChainTexture(NonNullPtr<CommandList> commandList, NonNullPtr<Window> window, Texture** swapChainTexture);
extern void DestroySwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData);
} // namespace Internal
} // namespace Juliet::D3D12

View File

@@ -59,6 +59,11 @@ namespace Juliet
void (*SetBlendConstants)(NonNullPtr<CommandList> commandList, FColor blendConstants);
void (*SetStencilReference)(NonNullPtr<CommandList> commandList, uint8 reference);
// Fences
bool (*Wait)(NonNullPtr<GPUDriver> driver);
bool (*QueryFence)(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
void (*ReleaseFence)(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
const char* Name = "Unknown";
GPUDriver* Driver = nullptr;
};