Finishing fences
+ moved some functions to an internal namespace to tidy stuff a bit
This commit is contained in:
@@ -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,122 +47,126 @@ namespace Juliet::D3D12
|
||||
}
|
||||
} // namespace
|
||||
|
||||
D3D12DescriptorHeap* CreateDescriptorHeap(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 count, bool isStaging)
|
||||
namespace Internal
|
||||
{
|
||||
ID3D12DescriptorHeap* handle;
|
||||
|
||||
auto heap = static_cast<D3D12DescriptorHeap*>(Calloc(1, sizeof(D3D12DescriptorHeap)));
|
||||
if (!heap)
|
||||
D3D12DescriptorHeap* CreateDescriptorHeap(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type,
|
||||
uint32 count, bool isStaging)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
ID3D12DescriptorHeap* handle;
|
||||
|
||||
heap->CurrentDescriptorIndex = 0;
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC heapDesc;
|
||||
heapDesc.NumDescriptors = count;
|
||||
heapDesc.Type = type;
|
||||
heapDesc.Flags = isStaging ? D3D12_DESCRIPTOR_HEAP_FLAG_NONE : D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
heapDesc.NodeMask = 0;
|
||||
|
||||
HRESULT result =
|
||||
ID3D12Device_CreateDescriptorHeap(driver->D3D12Device, &heapDesc, IID_ID3D12DescriptorHeap, (void**)&handle);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(driver, "Failed to create descriptor heap!", result);
|
||||
DestroyDescriptorHeap(heap);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
heap->Handle = handle;
|
||||
heap->HeapType = type;
|
||||
heap->MaxDescriptors = count;
|
||||
heap->Staging = isStaging;
|
||||
heap->DescriptorSize = ID3D12Device_GetDescriptorHandleIncrementSize(driver->D3D12Device, type);
|
||||
ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(handle, &heap->DescriptorHeapCPUStart);
|
||||
if (!isStaging)
|
||||
{
|
||||
ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(handle, &heap->DescriptorHeapGPUStart);
|
||||
}
|
||||
|
||||
return heap;
|
||||
}
|
||||
|
||||
void DestroyDescriptorHeap(NonNullPtr<D3D12DescriptorHeap> heap)
|
||||
{
|
||||
if (heap->Handle)
|
||||
{
|
||||
ID3D12DescriptorHeap_Release(heap->Handle);
|
||||
}
|
||||
Free(heap.Get());
|
||||
}
|
||||
|
||||
D3D12StagingDescriptorPool* CreateStagingDescriptorPool(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type)
|
||||
{
|
||||
D3D12DescriptorHeap* heap = CreateDescriptorHeap(driver, type, kStagingHeapDescriptorExpectedCount, true);
|
||||
if (!heap)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto pool = static_cast<D3D12StagingDescriptorPool*>(Calloc(1, sizeof(D3D12StagingDescriptorPool)));
|
||||
|
||||
// First create the heaps
|
||||
pool->HeapCount = 1;
|
||||
pool->Heaps = static_cast<D3D12DescriptorHeap**>(Malloc(sizeof(D3D12DescriptorHeap*)));
|
||||
pool->Heaps[0] = heap;
|
||||
|
||||
pool->FreeDescriptorCapacity = kStagingHeapDescriptorExpectedCount;
|
||||
pool->FreeDescriptorCount = kStagingHeapDescriptorExpectedCount;
|
||||
pool->FreeDescriptors =
|
||||
static_cast<D3D12StagingDescriptor*>(Malloc(kStagingHeapDescriptorExpectedCount * sizeof(D3D12StagingDescriptor)));
|
||||
|
||||
InitStagingDescriptorPool(heap, pool);
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
bool AssignStagingDescriptor(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type, D3D12StagingDescriptor& outDescriptor)
|
||||
{
|
||||
// TODO: Make it thread safe
|
||||
D3D12StagingDescriptor* descriptor = nullptr;
|
||||
D3D12StagingDescriptorPool* pool = driver->StagingDescriptorPools[type];
|
||||
|
||||
if (pool->FreeDescriptorCount == 0)
|
||||
{
|
||||
if (!ExtendStagingDescriptorPool(driver, *pool))
|
||||
auto heap = static_cast<D3D12DescriptorHeap*>(Calloc(1, sizeof(D3D12DescriptorHeap)));
|
||||
if (!heap)
|
||||
{
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
heap->CurrentDescriptorIndex = 0;
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC heapDesc;
|
||||
heapDesc.NumDescriptors = count;
|
||||
heapDesc.Type = type;
|
||||
heapDesc.Flags = isStaging ? D3D12_DESCRIPTOR_HEAP_FLAG_NONE : D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
heapDesc.NodeMask = 0;
|
||||
|
||||
HRESULT result =
|
||||
ID3D12Device_CreateDescriptorHeap(driver->D3D12Device, &heapDesc, IID_ID3D12DescriptorHeap, (void**)&handle);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(driver, "Failed to create descriptor heap!", result);
|
||||
DestroyDescriptorHeap(heap);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
heap->Handle = handle;
|
||||
heap->HeapType = type;
|
||||
heap->MaxDescriptors = count;
|
||||
heap->Staging = isStaging;
|
||||
heap->DescriptorSize = ID3D12Device_GetDescriptorHandleIncrementSize(driver->D3D12Device, type);
|
||||
ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(handle, &heap->DescriptorHeapCPUStart);
|
||||
if (!isStaging)
|
||||
{
|
||||
ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(handle, &heap->DescriptorHeapGPUStart);
|
||||
}
|
||||
|
||||
return heap;
|
||||
}
|
||||
|
||||
void DestroyDescriptorHeap(NonNullPtr<D3D12DescriptorHeap> heap)
|
||||
{
|
||||
if (heap->Handle)
|
||||
{
|
||||
ID3D12DescriptorHeap_Release(heap->Handle);
|
||||
}
|
||||
Free(heap.Get());
|
||||
}
|
||||
|
||||
D3D12StagingDescriptorPool* CreateStagingDescriptorPool(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type)
|
||||
{
|
||||
D3D12DescriptorHeap* heap = CreateDescriptorHeap(driver, type, kStagingHeapDescriptorExpectedCount, true);
|
||||
if (!heap)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto pool = static_cast<D3D12StagingDescriptorPool*>(Calloc(1, sizeof(D3D12StagingDescriptorPool)));
|
||||
|
||||
// First create the heaps
|
||||
pool->HeapCount = 1;
|
||||
pool->Heaps = static_cast<D3D12DescriptorHeap**>(Malloc(sizeof(D3D12DescriptorHeap*)));
|
||||
pool->Heaps[0] = heap;
|
||||
|
||||
pool->FreeDescriptorCapacity = kStagingHeapDescriptorExpectedCount;
|
||||
pool->FreeDescriptorCount = kStagingHeapDescriptorExpectedCount;
|
||||
pool->FreeDescriptors = static_cast<D3D12StagingDescriptor*>(
|
||||
Malloc(kStagingHeapDescriptorExpectedCount * sizeof(D3D12StagingDescriptor)));
|
||||
|
||||
InitStagingDescriptorPool(heap, pool);
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
bool AssignStagingDescriptor(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type, D3D12StagingDescriptor& outDescriptor)
|
||||
{
|
||||
// TODO: Make it thread safe
|
||||
D3D12StagingDescriptor* descriptor = nullptr;
|
||||
D3D12StagingDescriptorPool* pool = driver->StagingDescriptorPools[type];
|
||||
|
||||
if (pool->FreeDescriptorCount == 0)
|
||||
{
|
||||
if (!ExtendStagingDescriptorPool(driver, *pool))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
descriptor = &pool->FreeDescriptors[pool->FreeDescriptorCount - 1];
|
||||
MemCopy(&outDescriptor, descriptor, sizeof(D3D12StagingDescriptor));
|
||||
pool->FreeDescriptorCount -= 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ReleaseStagingDescriptor(NonNullPtr<D3D12Driver> driver, D3D12StagingDescriptor& cpuDescriptor)
|
||||
{
|
||||
D3D12StagingDescriptorPool* pool = cpuDescriptor.Pool;
|
||||
|
||||
if (pool != nullptr)
|
||||
{
|
||||
MemCopy(&pool->FreeDescriptors[pool->FreeDescriptorCount], &cpuDescriptor, sizeof(D3D12StagingDescriptor));
|
||||
pool->FreeDescriptorCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
descriptor = &pool->FreeDescriptors[pool->FreeDescriptorCount - 1];
|
||||
MemCopy(&outDescriptor, descriptor, sizeof(D3D12StagingDescriptor));
|
||||
pool->FreeDescriptorCount -= 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ReleaseStagingDescriptor(NonNullPtr<D3D12Driver> driver, D3D12StagingDescriptor& cpuDescriptor)
|
||||
{
|
||||
D3D12StagingDescriptorPool* pool = cpuDescriptor.Pool;
|
||||
|
||||
if (pool != nullptr)
|
||||
void DestroyStagingDescriptorPool(NonNullPtr<D3D12StagingDescriptorPool> pool)
|
||||
{
|
||||
MemCopy(&pool->FreeDescriptors[pool->FreeDescriptorCount], &cpuDescriptor, sizeof(D3D12StagingDescriptor));
|
||||
pool->FreeDescriptorCount += 1;
|
||||
}
|
||||
}
|
||||
for (uint32 i = 0; i < pool->HeapCount; i += 1)
|
||||
{
|
||||
DestroyDescriptorHeap(pool->Heaps[i]);
|
||||
}
|
||||
|
||||
void DestroyStagingDescriptorPool(NonNullPtr<D3D12StagingDescriptorPool> pool)
|
||||
{
|
||||
for (uint32 i = 0; i < pool->HeapCount; i += 1)
|
||||
{
|
||||
DestroyDescriptorHeap(pool->Heaps[i]);
|
||||
Free(pool->Heaps);
|
||||
Free(pool->FreeDescriptors);
|
||||
Free(pool.Get());
|
||||
}
|
||||
|
||||
Free(pool->Heaps);
|
||||
Free(pool->FreeDescriptors);
|
||||
Free(pool.Get());
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace Juliet::D3D12
|
||||
|
||||
@@ -51,13 +51,16 @@ namespace Juliet::D3D12
|
||||
uint32 CpuHandleIndex;
|
||||
};
|
||||
|
||||
extern D3D12DescriptorHeap* CreateDescriptorHeap(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type,
|
||||
uint32 count, bool isStaging);
|
||||
extern void DestroyDescriptorHeap(NonNullPtr<D3D12DescriptorHeap> heap);
|
||||
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);
|
||||
extern bool AssignStagingDescriptor(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type,
|
||||
D3D12StagingDescriptor& outDescriptor);
|
||||
extern void ReleaseStagingDescriptor(NonNullPtr<D3D12Driver> driver, D3D12StagingDescriptor& cpuDescriptor);
|
||||
extern void DestroyStagingDescriptorPool(NonNullPtr<D3D12StagingDescriptorPool> pool);
|
||||
extern D3D12StagingDescriptorPool* CreateStagingDescriptorPool(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type);
|
||||
extern bool AssignStagingDescriptor(NonNullPtr<D3D12Driver> driver, D3D12_DESCRIPTOR_HEAP_TYPE type,
|
||||
D3D12StagingDescriptor& outDescriptor);
|
||||
extern void ReleaseStagingDescriptor(NonNullPtr<D3D12Driver> driver, D3D12StagingDescriptor& cpuDescriptor);
|
||||
extern void DestroyStagingDescriptorPool(NonNullPtr<D3D12StagingDescriptorPool> pool);
|
||||
} // namespace Internal
|
||||
} // namespace Juliet::D3D12
|
||||
|
||||
@@ -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,9 +61,11 @@ 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,
|
||||
D3D12_RESOURCE_STATE_RESOLVE_DEST);
|
||||
Internal::PrepareTextureSubresourceForWrite(d3d12CommandList, resolveContainer,
|
||||
colorTargetInfos[idx].ResolveLayerIndex,
|
||||
colorTargetInfos[idx].ResolveMipLevel,
|
||||
colorTargetInfos[idx].CycleResolveTexture,
|
||||
D3D12_RESOURCE_STATE_RESOLVE_DEST);
|
||||
|
||||
d3d12CommandList->ColorResolveSubresources[idx] = resolveSubresource;
|
||||
|
||||
@@ -114,27 +116,31 @@ namespace Juliet::D3D12
|
||||
{
|
||||
if (d3d12CommandList->ColorResolveSubresources[idx])
|
||||
{
|
||||
TextureSubresourceBarrier(d3d12CommandList, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_RESOLVE_SOURCE,
|
||||
d3d12CommandList->ColorTargetSubresources[idx]);
|
||||
Internal::TextureSubresourceBarrier(d3d12CommandList, D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||
D3D12_RESOURCE_STATE_RESOLVE_SOURCE,
|
||||
d3d12CommandList->ColorTargetSubresources[idx]);
|
||||
ID3D12GraphicsCommandList_ResolveSubresource(
|
||||
d3d12CommandList->GraphicsCommandList.CommandList,
|
||||
d3d12CommandList->ColorResolveSubresources[idx]->Parent->Resource,
|
||||
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],
|
||||
D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
|
||||
Internal::TextureSubresourceTransitionToDefaultUsage(d3d12CommandList,
|
||||
d3d12CommandList->ColorTargetSubresources[idx],
|
||||
D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
|
||||
|
||||
TextureSubresourceTransitionToDefaultUsage(d3d12CommandList, d3d12CommandList->ColorResolveSubresources[idx],
|
||||
D3D12_RESOURCE_STATE_RESOLVE_DEST);
|
||||
Internal::TextureSubresourceTransitionToDefaultUsage(d3d12CommandList,
|
||||
d3d12CommandList->ColorResolveSubresources[idx],
|
||||
D3D12_RESOURCE_STATE_RESOLVE_DEST);
|
||||
}
|
||||
else
|
||||
{
|
||||
TextureSubresourceTransitionToDefaultUsage(d3d12CommandList, d3d12CommandList->ColorTargetSubresources[idx],
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||
Internal::TextureSubresourceTransitionToDefaultUsage(d3d12CommandList,
|
||||
d3d12CommandList->ColorTargetSubresources[idx],
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,91 +8,171 @@
|
||||
|
||||
namespace Juliet::D3D12
|
||||
{
|
||||
void ResourceBarrier(NonNullPtr<D3D12CommandList> commandList, D3D12_RESOURCE_STATES sourceState,
|
||||
D3D12_RESOURCE_STATES destinationState, ID3D12Resource* resource, uint32 subresourceIndex, bool needsUavBarrier)
|
||||
namespace
|
||||
{
|
||||
D3D12_RESOURCE_BARRIER barrierDesc[2];
|
||||
uint32 numBarriers = 0;
|
||||
|
||||
// No transition barrier is needed if the state is not changing.
|
||||
if (sourceState != destinationState)
|
||||
void ReleaseFenceToPool(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12Fence> fence)
|
||||
{
|
||||
barrierDesc[numBarriers].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrierDesc[numBarriers].Flags = static_cast<D3D12_RESOURCE_BARRIER_FLAGS>(0);
|
||||
barrierDesc[numBarriers].Transition.StateBefore = sourceState;
|
||||
barrierDesc[numBarriers].Transition.StateAfter = destinationState;
|
||||
barrierDesc[numBarriers].Transition.pResource = resource;
|
||||
barrierDesc[numBarriers].Transition.Subresource = subresourceIndex;
|
||||
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
|
||||
|
||||
numBarriers += 1;
|
||||
bool Wait(NonNullPtr<GPUDriver> driver)
|
||||
{
|
||||
auto d3d12driver = static_cast<D3D12Driver*>(driver.Get());
|
||||
D3D12Fence* fence = Internal::AcquireFence(d3d12driver);
|
||||
if (!fence)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (needsUavBarrier)
|
||||
if (d3d12driver->GraphicsQueue)
|
||||
{
|
||||
barrierDesc[numBarriers].Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
|
||||
barrierDesc[numBarriers].Flags = static_cast<D3D12_RESOURCE_BARRIER_FLAGS>(0);
|
||||
barrierDesc[numBarriers].UAV.pResource = resource;
|
||||
// Insert a signal into the end of the command queue...
|
||||
ID3D12CommandQueue_Signal(d3d12driver->GraphicsQueue, fence->Handle, D3D12_FENCE_SIGNAL_VALUE);
|
||||
|
||||
numBarriers += 1;
|
||||
// ...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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numBarriers > 0)
|
||||
ReleaseFence(driver, reinterpret_cast<Fence*>(fence));
|
||||
|
||||
bool result = true;
|
||||
|
||||
// Clean up
|
||||
for (int32 idx = d3d12driver->SubmittedCommandListCount - 1; idx >= 0; idx -= 1)
|
||||
{
|
||||
ID3D12GraphicsCommandList_ResourceBarrier(commandList->GraphicsCommandList.CommandList, numBarriers, barrierDesc);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
D3D12Fence* AcquireFence(NonNullPtr<D3D12Driver> driver)
|
||||
namespace Internal
|
||||
{
|
||||
D3D12Fence* fence;
|
||||
ID3D12Fence* handle;
|
||||
|
||||
// TODO :Thread safe (lock + atomic)
|
||||
|
||||
if (driver->AvailableFenceCount == 0)
|
||||
void ResourceBarrier(NonNullPtr<D3D12CommandList> commandList, D3D12_RESOURCE_STATES sourceState,
|
||||
D3D12_RESOURCE_STATES destinationState, ID3D12Resource* resource, uint32 subresourceIndex,
|
||||
bool needsUavBarrier)
|
||||
{
|
||||
HRESULT result = ID3D12Device_CreateFence(driver->D3D12Device, D3D12_FENCE_UNSIGNALED_VALUE, D3D12_FENCE_FLAG_NONE,
|
||||
IID_ID3D12Fence, reinterpret_cast<void**>(&handle));
|
||||
if (FAILED(result))
|
||||
D3D12_RESOURCE_BARRIER barrierDesc[2];
|
||||
uint32 numBarriers = 0;
|
||||
|
||||
// No transition barrier is needed if the state is not changing.
|
||||
if (sourceState != destinationState)
|
||||
{
|
||||
LogError(driver, "Failed to create fence!", result);
|
||||
return nullptr;
|
||||
barrierDesc[numBarriers].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrierDesc[numBarriers].Flags = static_cast<D3D12_RESOURCE_BARRIER_FLAGS>(0);
|
||||
barrierDesc[numBarriers].Transition.StateBefore = sourceState;
|
||||
barrierDesc[numBarriers].Transition.StateAfter = destinationState;
|
||||
barrierDesc[numBarriers].Transition.pResource = resource;
|
||||
barrierDesc[numBarriers].Transition.Subresource = subresourceIndex;
|
||||
|
||||
numBarriers += 1;
|
||||
}
|
||||
|
||||
fence = static_cast<D3D12Fence*>(Calloc(1, sizeof(D3D12Fence)));
|
||||
if (!fence)
|
||||
if (needsUavBarrier)
|
||||
{
|
||||
ID3D12Fence_Release(handle);
|
||||
barrierDesc[numBarriers].Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
|
||||
barrierDesc[numBarriers].Flags = static_cast<D3D12_RESOURCE_BARRIER_FLAGS>(0);
|
||||
barrierDesc[numBarriers].UAV.pResource = resource;
|
||||
|
||||
return nullptr;
|
||||
numBarriers += 1;
|
||||
}
|
||||
|
||||
if (numBarriers > 0)
|
||||
{
|
||||
ID3D12GraphicsCommandList_ResourceBarrier(commandList->GraphicsCommandList.CommandList, numBarriers, barrierDesc);
|
||||
}
|
||||
fence->Handle = handle;
|
||||
fence->Event = CreateEvent(nullptr, false, false, nullptr);
|
||||
fence->ReferenceCount = 0;
|
||||
}
|
||||
else
|
||||
|
||||
D3D12Fence* AcquireFence(NonNullPtr<D3D12Driver> driver)
|
||||
{
|
||||
fence = driver->AvailableFences[driver->AvailableFenceCount - 1];
|
||||
driver->AvailableFenceCount -= 1;
|
||||
ID3D12Fence_Signal(fence->Handle, D3D12_FENCE_UNSIGNALED_VALUE);
|
||||
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;
|
||||
}
|
||||
|
||||
fence->ReferenceCount += 1;
|
||||
return fence;
|
||||
}
|
||||
|
||||
void DestroyFence(NonNullPtr<D3D12Fence> fence)
|
||||
{
|
||||
if (fence->Handle)
|
||||
void DestroyFence(NonNullPtr<D3D12Fence> fence)
|
||||
{
|
||||
ID3D12Fence_Release(fence->Handle);
|
||||
}
|
||||
if (fence->Handle)
|
||||
{
|
||||
ID3D12Fence_Release(fence->Handle);
|
||||
}
|
||||
|
||||
if (fence->Event)
|
||||
{
|
||||
CloseHandle(fence->Event);
|
||||
if (fence->Event)
|
||||
{
|
||||
CloseHandle(fence->Event);
|
||||
}
|
||||
Free(fence.Get());
|
||||
}
|
||||
Free(fence.Get());
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Juliet::D3D12
|
||||
|
||||
@@ -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 void ResourceBarrier(NonNullPtr<D3D12CommandList> commandList, D3D12_RESOURCE_STATES sourceState,
|
||||
D3D12_RESOURCE_STATES destinationState, ID3D12Resource* resource,
|
||||
uint32 subresourceIndex, bool needsUavBarrier);
|
||||
extern bool Wait(NonNullPtr<GPUDriver> driver);
|
||||
extern bool QueryFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
|
||||
extern void ReleaseFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
|
||||
|
||||
extern D3D12Fence* AcquireFence(NonNullPtr<D3D12Driver> driver);
|
||||
extern void DestroyFence(NonNullPtr<D3D12Fence> 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
|
||||
|
||||
@@ -157,79 +157,84 @@ 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);
|
||||
if (shouldCycle and container->CanBeCycled and subresource->Parent->RefCount > 0)
|
||||
D3D12TextureSubresource* PrepareTextureSubresourceForWrite(NonNullPtr<D3D12CommandList> commandList,
|
||||
NonNullPtr<D3D12TextureContainer> container,
|
||||
uint32 layer, uint32 level, bool shouldCycle,
|
||||
D3D12_RESOURCE_STATES newTextureUsage)
|
||||
{
|
||||
// TODO: Cycle the active texture to an available one. Not needed for swap chain (current objective)
|
||||
// CycleActiveTexture(commandList->Driver, container);
|
||||
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);
|
||||
}
|
||||
|
||||
Internal::TextureSubresourceTransitionFromDefaultUsage(commandList, subresource, newTextureUsage);
|
||||
|
||||
return subresource;
|
||||
}
|
||||
|
||||
TextureSubresourceTransitionFromDefaultUsage(commandList, subresource, newTextureUsage);
|
||||
|
||||
return subresource;
|
||||
}
|
||||
|
||||
D3D12TextureSubresource* FetchTextureSubresource(NonNullPtr<D3D12TextureContainer> container, uint32 layer, uint32 level)
|
||||
{
|
||||
uint32 index = ComputeSubresourceIndex(level, layer, container->Header.CreateInfo.MipLevelCount);
|
||||
return &container->ActiveTexture->Subresources[index];
|
||||
}
|
||||
|
||||
void TextureSubresourceBarrier(NonNullPtr<D3D12CommandList> commandList, D3D12_RESOURCE_STATES sourceState,
|
||||
D3D12_RESOURCE_STATES destinationState, NonNullPtr<D3D12TextureSubresource> textureSubresource)
|
||||
{
|
||||
TextureUsageFlag currentFlag = textureSubresource->Parent->Container->Header.CreateInfo.Flags;
|
||||
bool needsUAVBarrier = ((currentFlag & TextureUsageFlag::ComputeStorageWrite) != TextureUsageFlag::None) ||
|
||||
((currentFlag & TextureUsageFlag::ComputeStorageSimultaneousReadWrite) != TextureUsageFlag::None);
|
||||
ResourceBarrier(commandList, sourceState, destinationState, textureSubresource->Parent->Resource,
|
||||
textureSubresource->Index, needsUAVBarrier);
|
||||
}
|
||||
|
||||
void TextureSubresourceTransitionFromDefaultUsage(NonNullPtr<D3D12CommandList> commandList,
|
||||
NonNullPtr<D3D12TextureSubresource> subresource,
|
||||
D3D12_RESOURCE_STATES toTextureUsage)
|
||||
{
|
||||
D3D12_RESOURCE_STATES defaultUsage =
|
||||
GetDefaultTextureResourceState(subresource->Parent->Container->Header.CreateInfo.Flags);
|
||||
TextureSubresourceBarrier(commandList, defaultUsage, toTextureUsage, subresource);
|
||||
}
|
||||
|
||||
void TextureTransitionFromDefaultUsage(NonNullPtr<D3D12CommandList> commandList, NonNullPtr<D3D12Texture> texture,
|
||||
D3D12_RESOURCE_STATES toTextureUsage)
|
||||
{
|
||||
for (uint32 i = 0; i < texture->SubresourceCount; ++i)
|
||||
D3D12TextureSubresource* FetchTextureSubresource(NonNullPtr<D3D12TextureContainer> container, uint32 layer, uint32 level)
|
||||
{
|
||||
TextureSubresourceTransitionFromDefaultUsage(commandList, &texture->Subresources[i], toTextureUsage);
|
||||
uint32 index = ComputeSubresourceIndex(level, layer, container->Header.CreateInfo.MipLevelCount);
|
||||
return &container->ActiveTexture->Subresources[index];
|
||||
}
|
||||
}
|
||||
|
||||
void TextureSubresourceTransitionToDefaultUsage(NonNullPtr<D3D12CommandList> commandList,
|
||||
NonNullPtr<D3D12TextureSubresource> subresource, D3D12_RESOURCE_STATES fromTextureUsage)
|
||||
{
|
||||
D3D12_RESOURCE_STATES defaultUsage =
|
||||
GetDefaultTextureResourceState(subresource->Parent->Container->Header.CreateInfo.Flags);
|
||||
TextureSubresourceBarrier(commandList, fromTextureUsage, defaultUsage, subresource);
|
||||
}
|
||||
|
||||
void TextureTransitionToDefaultUsage(NonNullPtr<D3D12CommandList> commandList, NonNullPtr<D3D12Texture> texture,
|
||||
D3D12_RESOURCE_STATES fromTextureUsage)
|
||||
{
|
||||
for (uint32 i = 0; i < texture->SubresourceCount; ++i)
|
||||
void TextureSubresourceBarrier(NonNullPtr<D3D12CommandList> commandList, D3D12_RESOURCE_STATES sourceState,
|
||||
D3D12_RESOURCE_STATES destinationState, NonNullPtr<D3D12TextureSubresource> textureSubresource)
|
||||
{
|
||||
TextureSubresourceTransitionToDefaultUsage(commandList, &texture->Subresources[i], fromTextureUsage);
|
||||
TextureUsageFlag currentFlag = textureSubresource->Parent->Container->Header.CreateInfo.Flags;
|
||||
bool needsUAVBarrier =
|
||||
((currentFlag & TextureUsageFlag::ComputeStorageWrite) != TextureUsageFlag::None) ||
|
||||
((currentFlag & TextureUsageFlag::ComputeStorageSimultaneousReadWrite) != TextureUsageFlag::None);
|
||||
Internal::ResourceBarrier(commandList, sourceState, destinationState, textureSubresource->Parent->Resource,
|
||||
textureSubresource->Index, needsUAVBarrier);
|
||||
}
|
||||
}
|
||||
|
||||
// Utils
|
||||
DXGI_FORMAT ConvertToD3D12TextureFormat(TextureFormat format)
|
||||
{
|
||||
return JulietToD3D12_TextureFormat[ToUnderlying(format)];
|
||||
}
|
||||
void TextureSubresourceTransitionFromDefaultUsage(NonNullPtr<D3D12CommandList> commandList,
|
||||
NonNullPtr<D3D12TextureSubresource> subresource,
|
||||
D3D12_RESOURCE_STATES toTextureUsage)
|
||||
{
|
||||
D3D12_RESOURCE_STATES defaultUsage =
|
||||
GetDefaultTextureResourceState(subresource->Parent->Container->Header.CreateInfo.Flags);
|
||||
TextureSubresourceBarrier(commandList, defaultUsage, toTextureUsage, subresource);
|
||||
}
|
||||
|
||||
void TextureTransitionFromDefaultUsage(NonNullPtr<D3D12CommandList> commandList,
|
||||
NonNullPtr<D3D12Texture> texture, D3D12_RESOURCE_STATES toTextureUsage)
|
||||
{
|
||||
for (uint32 i = 0; i < texture->SubresourceCount; ++i)
|
||||
{
|
||||
TextureSubresourceTransitionFromDefaultUsage(commandList, &texture->Subresources[i], toTextureUsage);
|
||||
}
|
||||
}
|
||||
|
||||
void TextureSubresourceTransitionToDefaultUsage(NonNullPtr<D3D12CommandList> commandList,
|
||||
NonNullPtr<D3D12TextureSubresource> subresource,
|
||||
D3D12_RESOURCE_STATES fromTextureUsage)
|
||||
{
|
||||
D3D12_RESOURCE_STATES defaultUsage =
|
||||
GetDefaultTextureResourceState(subresource->Parent->Container->Header.CreateInfo.Flags);
|
||||
TextureSubresourceBarrier(commandList, fromTextureUsage, defaultUsage, subresource);
|
||||
}
|
||||
|
||||
void TextureTransitionToDefaultUsage(NonNullPtr<D3D12CommandList> commandList, NonNullPtr<D3D12Texture> texture,
|
||||
D3D12_RESOURCE_STATES fromTextureUsage)
|
||||
{
|
||||
for (uint32 i = 0; i < texture->SubresourceCount; ++i)
|
||||
{
|
||||
TextureSubresourceTransitionToDefaultUsage(commandList, &texture->Subresources[i], fromTextureUsage);
|
||||
}
|
||||
}
|
||||
|
||||
// Utils
|
||||
DXGI_FORMAT ConvertToD3D12TextureFormat(TextureFormat format)
|
||||
{
|
||||
return JulietToD3D12_TextureFormat[ToUnderlying(format)];
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace Juliet::D3D12
|
||||
|
||||
@@ -62,27 +62,31 @@ namespace Juliet::D3D12
|
||||
int32 RefCount;
|
||||
};
|
||||
|
||||
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,
|
||||
NonNullPtr<D3D12TextureSubresource> textureSubresource);
|
||||
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,
|
||||
NonNullPtr<D3D12TextureSubresource> textureSubresource);
|
||||
|
||||
// Texture usage transition
|
||||
extern void TextureSubresourceTransitionFromDefaultUsage(NonNullPtr<D3D12CommandList> commandList,
|
||||
NonNullPtr<D3D12TextureSubresource> subresource,
|
||||
D3D12_RESOURCE_STATES toTextureUsage);
|
||||
extern void TextureTransitionFromDefaultUsage(NonNullPtr<D3D12CommandList> commandList,
|
||||
NonNullPtr<D3D12Texture> texture, D3D12_RESOURCE_STATES toTextureUsage);
|
||||
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);
|
||||
// Texture usage transition
|
||||
extern void TextureSubresourceTransitionFromDefaultUsage(NonNullPtr<D3D12CommandList> commandList,
|
||||
NonNullPtr<D3D12TextureSubresource> subresource,
|
||||
D3D12_RESOURCE_STATES toTextureUsage);
|
||||
extern void TextureTransitionFromDefaultUsage(NonNullPtr<D3D12CommandList> commandList,
|
||||
NonNullPtr<D3D12Texture> texture, D3D12_RESOURCE_STATES toTextureUsage);
|
||||
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);
|
||||
|
||||
// Utils
|
||||
extern DXGI_FORMAT ConvertToD3D12TextureFormat(TextureFormat format);
|
||||
// Utils
|
||||
extern DXGI_FORMAT ConvertToD3D12TextureFormat(TextureFormat format);
|
||||
} // namespace Internal
|
||||
} // namespace Juliet::D3D12
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
driver->AvailableCommandLists = resizedArray;
|
||||
driver->AvailableCommandLists[driver->AvailableCommandListCapacity] = commandList;
|
||||
uint32 id = driver->AvailableCommandListCapacity;
|
||||
driver->AvailableCommandListCapacity += 1;
|
||||
driver->AvailableCommandLists = resizedArray;
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace Juliet::D3D12
|
||||
|
||||
D3D12CommandList** SubmittedCommandLists;
|
||||
uint8 SubmittedCommandListCapacity;
|
||||
uint8 SubmittedCommandBufferCount;
|
||||
uint8 SubmittedCommandListCount;
|
||||
|
||||
D3D12Fence** AvailableFences;
|
||||
uint32 AvailableFenceCount;
|
||||
|
||||
@@ -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,136 +187,140 @@ namespace Juliet::D3D12
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool CreateSwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData,
|
||||
SwapChainComposition composition, PresentMode presentMode)
|
||||
{
|
||||
auto windowWin32State = static_cast<Win32::Window32State*>(windowData->Window->State);
|
||||
HWND windowHandle = windowWin32State->Handle;
|
||||
if (!IsWindow(windowHandle))
|
||||
{
|
||||
Assert(false && "windowWin32State->Handle is not a window handle ???");
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: I have no way to test HDR easily except the steamdeck
|
||||
DXGI_FORMAT swapChainFormat = SwapchainCompositionToTextureFormat[ToUnderlying(composition)];
|
||||
|
||||
windowData->SwapChainTextureCount = std::clamp<uint8>(driver->FramesInFlight, 2, 3);
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
|
||||
swapChainDesc.Width = 0; // Use the whole width
|
||||
swapChainDesc.Height = 0; // Use the whole height
|
||||
swapChainDesc.Format = swapChainFormat;
|
||||
swapChainDesc.Stereo = 0;
|
||||
swapChainDesc.SampleDesc.Count = 1;
|
||||
swapChainDesc.SampleDesc.Quality = 0;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.BufferCount = windowData->SwapChainTextureCount;
|
||||
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
|
||||
if (driver->IsTearingSupported)
|
||||
{
|
||||
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
|
||||
}
|
||||
else
|
||||
{
|
||||
swapChainDesc.Flags = 0;
|
||||
}
|
||||
|
||||
DXGI_SWAP_CHAIN_FULLSCREEN_DESC swapChainFullscreenDesc = {};
|
||||
swapChainFullscreenDesc.RefreshRate.Numerator = 0;
|
||||
swapChainFullscreenDesc.RefreshRate.Denominator = 0;
|
||||
swapChainFullscreenDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
||||
swapChainFullscreenDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
||||
swapChainFullscreenDesc.Windowed = true;
|
||||
|
||||
IDXGISwapChain1* swapChain = nullptr;
|
||||
HRESULT result =
|
||||
IDXGIFactory4_CreateSwapChainForHwnd(driver->DXGIFactory, reinterpret_cast<IUnknown*>(driver->GraphicsQueue),
|
||||
windowHandle, &swapChainDesc, &swapChainFullscreenDesc, nullptr, &swapChain);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(driver, "Failed to create SwapChain", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
IDXGISwapChain3* swapChain3 = nullptr;
|
||||
result = IDXGISwapChain1_QueryInterface(swapChain, IID_IDXGISwapChain3, reinterpret_cast<void**>(&swapChain3));
|
||||
IDXGISwapChain1_Release(swapChain);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(driver, "Could not query IDXGISwapChain3 interface", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (composition != SwapChainComposition::SDR)
|
||||
{
|
||||
IDXGISwapChain3_SetColorSpace1(swapChain3, SwapchainCompositionToColorSpace[ToUnderlying(composition)]);
|
||||
}
|
||||
|
||||
IDXGIFactory1* parentFactory = nullptr;
|
||||
result = IDXGISwapChain3_GetParent(swapChain3, IID_IDXGIFactory1, reinterpret_cast<void**>(&parentFactory));
|
||||
if (FAILED(result))
|
||||
{
|
||||
Log(LogLevel::Warning, LogCategory::Graphics, "Cannot get SwapChain Parent! Error Code: " HRESULT_FMT, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Disable DXGI window crap
|
||||
result = IDXGIFactory1_MakeWindowAssociation(parentFactory, windowHandle, DXGI_MWA_NO_WINDOW_CHANGES);
|
||||
if (FAILED(result))
|
||||
{
|
||||
Log(LogLevel::Warning, LogCategory::Graphics, "MakeWindowAssociation failed! Error Code: " HRESULT_FMT, result);
|
||||
}
|
||||
IDXGIFactory1_Release(parentFactory);
|
||||
}
|
||||
|
||||
IDXGISwapChain3_GetDesc1(swapChain3, &swapChainDesc);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(driver, "Failed to retrieve SwapChain descriptor", result);
|
||||
return false;
|
||||
}
|
||||
windowData->SwapChain = swapChain3;
|
||||
windowData->SwapChainColorSpace = SwapchainCompositionToColorSpace[ToUnderlying(composition)];
|
||||
windowData->SwapChainComposition = composition;
|
||||
windowData->WindowFrameCounter = 0;
|
||||
windowData->Width = swapChainDesc.Width;
|
||||
windowData->Height = swapChainDesc.Height;
|
||||
windowData->PresentMode = presentMode;
|
||||
|
||||
for (uint8 idx = 0; idx < windowData->SwapChainTextureCount; ++idx)
|
||||
{
|
||||
if (!CreateSwapChainTexture(driver, swapChain3, composition, &windowData->SwapChainTextureContainers[idx], idx))
|
||||
{
|
||||
IDXGISwapChain3_Release(swapChain3);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
namespace Internal
|
||||
{
|
||||
for (uint32 idx = 0; idx < windowData->SwapChainTextureCount; ++idx)
|
||||
bool CreateSwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData,
|
||||
SwapChainComposition composition, PresentMode presentMode)
|
||||
{
|
||||
ReleaseStagingDescriptor(driver, windowData->SwapChainTextureContainers[idx].ActiveTexture->SRVHandle);
|
||||
ReleaseStagingDescriptor(driver, windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources[0].RTVHandles[0]);
|
||||
auto windowWin32State = static_cast<Win32::Window32State*>(windowData->Window->State);
|
||||
HWND windowHandle = windowWin32State->Handle;
|
||||
if (!IsWindow(windowHandle))
|
||||
{
|
||||
Assert(false && "windowWin32State->Handle is not a window handle ???");
|
||||
return false;
|
||||
}
|
||||
|
||||
Free(windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources[0].RTVHandles);
|
||||
Free(windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources);
|
||||
Free(windowData->SwapChainTextureContainers[idx].ActiveTexture);
|
||||
Free(windowData->SwapChainTextureContainers[idx].Textures);
|
||||
// TODO: I have no way to test HDR easily except the steamdeck
|
||||
DXGI_FORMAT swapChainFormat = SwapchainCompositionToTextureFormat[ToUnderlying(composition)];
|
||||
|
||||
windowData->SwapChainTextureCount = std::clamp<uint8>(driver->FramesInFlight, 2, 3);
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
|
||||
swapChainDesc.Width = 0; // Use the whole width
|
||||
swapChainDesc.Height = 0; // Use the whole height
|
||||
swapChainDesc.Format = swapChainFormat;
|
||||
swapChainDesc.Stereo = 0;
|
||||
swapChainDesc.SampleDesc.Count = 1;
|
||||
swapChainDesc.SampleDesc.Quality = 0;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.BufferCount = windowData->SwapChainTextureCount;
|
||||
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
|
||||
if (driver->IsTearingSupported)
|
||||
{
|
||||
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
|
||||
}
|
||||
else
|
||||
{
|
||||
swapChainDesc.Flags = 0;
|
||||
}
|
||||
|
||||
DXGI_SWAP_CHAIN_FULLSCREEN_DESC swapChainFullscreenDesc = {};
|
||||
swapChainFullscreenDesc.RefreshRate.Numerator = 0;
|
||||
swapChainFullscreenDesc.RefreshRate.Denominator = 0;
|
||||
swapChainFullscreenDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
||||
swapChainFullscreenDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
||||
swapChainFullscreenDesc.Windowed = true;
|
||||
|
||||
IDXGISwapChain1* swapChain = nullptr;
|
||||
HRESULT result =
|
||||
IDXGIFactory4_CreateSwapChainForHwnd(driver->DXGIFactory, reinterpret_cast<IUnknown*>(driver->GraphicsQueue),
|
||||
windowHandle, &swapChainDesc, &swapChainFullscreenDesc, nullptr, &swapChain);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(driver, "Failed to create SwapChain", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
IDXGISwapChain3* swapChain3 = nullptr;
|
||||
result = IDXGISwapChain1_QueryInterface(swapChain, IID_IDXGISwapChain3, reinterpret_cast<void**>(&swapChain3));
|
||||
IDXGISwapChain1_Release(swapChain);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(driver, "Could not query IDXGISwapChain3 interface", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (composition != SwapChainComposition::SDR)
|
||||
{
|
||||
IDXGISwapChain3_SetColorSpace1(swapChain3, SwapchainCompositionToColorSpace[ToUnderlying(composition)]);
|
||||
}
|
||||
|
||||
IDXGIFactory1* parentFactory = nullptr;
|
||||
result = IDXGISwapChain3_GetParent(swapChain3, IID_IDXGIFactory1, reinterpret_cast<void**>(&parentFactory));
|
||||
if (FAILED(result))
|
||||
{
|
||||
Log(LogLevel::Warning, LogCategory::Graphics, "Cannot get SwapChain Parent! Error Code: " HRESULT_FMT, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Disable DXGI window crap
|
||||
result = IDXGIFactory1_MakeWindowAssociation(parentFactory, windowHandle, DXGI_MWA_NO_WINDOW_CHANGES);
|
||||
if (FAILED(result))
|
||||
{
|
||||
Log(LogLevel::Warning, LogCategory::Graphics, "MakeWindowAssociation failed! Error Code: " HRESULT_FMT, result);
|
||||
}
|
||||
IDXGIFactory1_Release(parentFactory);
|
||||
}
|
||||
|
||||
IDXGISwapChain3_GetDesc1(swapChain3, &swapChainDesc);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(driver, "Failed to retrieve SwapChain descriptor", result);
|
||||
return false;
|
||||
}
|
||||
windowData->SwapChain = swapChain3;
|
||||
windowData->SwapChainColorSpace = SwapchainCompositionToColorSpace[ToUnderlying(composition)];
|
||||
windowData->SwapChainComposition = composition;
|
||||
windowData->WindowFrameCounter = 0;
|
||||
windowData->Width = swapChainDesc.Width;
|
||||
windowData->Height = swapChainDesc.Height;
|
||||
windowData->PresentMode = presentMode;
|
||||
|
||||
for (uint8 idx = 0; idx < windowData->SwapChainTextureCount; ++idx)
|
||||
{
|
||||
if (!CreateSwapChainTexture(driver, swapChain3, composition, &windowData->SwapChainTextureContainers[idx], idx))
|
||||
{
|
||||
IDXGISwapChain3_Release(swapChain3);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
IDXGISwapChain_Release(windowData->SwapChain);
|
||||
windowData->SwapChain = nullptr;
|
||||
}
|
||||
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]);
|
||||
|
||||
Free(windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources[0].RTVHandles);
|
||||
Free(windowData->SwapChainTextureContainers[idx].ActiveTexture->Subresources);
|
||||
Free(windowData->SwapChainTextureContainers[idx].ActiveTexture);
|
||||
Free(windowData->SwapChainTextureContainers[idx].Textures);
|
||||
}
|
||||
|
||||
IDXGISwapChain_Release(windowData->SwapChain);
|
||||
windowData->SwapChain = nullptr;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace Juliet::D3D12
|
||||
|
||||
@@ -7,8 +7,12 @@ namespace Juliet::D3D12
|
||||
struct D3D12Driver;
|
||||
struct D3D12WindowData;
|
||||
|
||||
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
|
||||
{
|
||||
extern bool CreateSwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData,
|
||||
SwapChainComposition composition, PresentMode presentMode);
|
||||
extern void DestroySwapChain(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12WindowData> windowData);
|
||||
} // namespace Internal
|
||||
} // namespace Juliet::D3D12
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user