Part generated by gemini with antigravity.
Converted to bindless first step
This commit is contained in:
@@ -120,9 +120,10 @@ namespace Juliet
|
||||
extern JULIET_API void SetStencilReference(NonNullPtr<RenderPass> renderPass, uint8 reference);
|
||||
|
||||
extern JULIET_API void BindGraphicsPipeline(NonNullPtr<RenderPass> renderPass, NonNullPtr<GraphicsPipeline> graphicsPipeline);
|
||||
|
||||
extern JULIET_API void DrawPrimitives(NonNullPtr<RenderPass> renderPass, uint32 numVertices, uint32 numInstances,
|
||||
uint32 firstVertex, uint32 firstInstance);
|
||||
extern JULIET_API void SetPushConstants(NonNullPtr<CommandList> commandList, ShaderStage stage,
|
||||
uint32 rootParameterIndex, uint32 numConstants, const void* constants);
|
||||
|
||||
// Fences
|
||||
extern JULIET_API bool WaitUntilGPUIsIdle(NonNullPtr<GraphicsDevice> device);
|
||||
@@ -142,9 +143,16 @@ namespace Juliet
|
||||
#endif
|
||||
|
||||
// Buffers
|
||||
extern GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GraphicsDevice> device, const BufferCreateInfo& createInfo);
|
||||
extern GraphicsTransferBuffer* CreateGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device,
|
||||
const TransferBufferCreateInfo& createInfo);
|
||||
extern void ReleaseGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer);
|
||||
extern void ReleaseGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer);
|
||||
extern JULIET_API GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GraphicsDevice> device, const BufferCreateInfo& createInfo);
|
||||
extern JULIET_API GraphicsTransferBuffer* CreateGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device,
|
||||
const TransferBufferCreateInfo& createInfo);
|
||||
extern JULIET_API void* MapGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer);
|
||||
extern JULIET_API void UnmapGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer);
|
||||
extern JULIET_API void CopyBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> dst,
|
||||
NonNullPtr<GraphicsTransferBuffer> src, size_t size, size_t dstOffset = 0,
|
||||
size_t srcOffset = 0);
|
||||
extern JULIET_API void TransitionBufferToReadable(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer);
|
||||
extern JULIET_API uint32 GetDescriptorIndex(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer);
|
||||
extern JULIET_API void DestroyGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer);
|
||||
extern JULIET_API void DestroyGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer);
|
||||
} // namespace Juliet
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#include <Core/Memory/Allocator.h>
|
||||
#include <Graphics/D3D12/D3D12Buffer.h>
|
||||
|
||||
#include <Core/Logging/LogManager.h>
|
||||
#include <Core/Logging/LogTypes.h>
|
||||
#include <Graphics/D3D12/D3D12CommandList.h>
|
||||
#include <Graphics/D3D12/D3D12DescriptorHeap.h>
|
||||
#include <Graphics/D3D12/D3D12GraphicsDevice.h>
|
||||
#include <Graphics/D3D12/D3D12Utils.h>
|
||||
@@ -10,12 +14,9 @@ namespace Juliet::D3D12
|
||||
{
|
||||
struct D3D12Buffer
|
||||
{
|
||||
ID3D12Resource* Handle;
|
||||
int32 ReferenceCount;
|
||||
|
||||
Internal::D3D12DescriptorHeap CBVDescriptorHeap;
|
||||
Internal::D3D12DescriptorHeap SRVDescriptorHeap;
|
||||
Internal::D3D12DescriptorHeap UAVDescriptorHeap;
|
||||
Internal::D3D12Descriptor Descriptor;
|
||||
ID3D12Resource* Handle;
|
||||
D3D12_RESOURCE_STATES CurrentState;
|
||||
};
|
||||
|
||||
enum class D3D12BufferType : uint8
|
||||
@@ -25,13 +26,18 @@ namespace Juliet::D3D12
|
||||
TransferUpload,
|
||||
};
|
||||
|
||||
void DestroyBuffer(NonNullPtr<D3D12Driver> /*d3d12Driver*/, D3D12Buffer* buffer)
|
||||
void DestroyBuffer(D3D12Buffer* buffer)
|
||||
{
|
||||
if (!buffer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (buffer->Descriptor.Index != UINT32_MAX)
|
||||
{
|
||||
Internal::ReleaseDescriptor(buffer->Descriptor);
|
||||
}
|
||||
|
||||
if (buffer->Handle)
|
||||
{
|
||||
ID3D12Resource_Release(buffer->Handle);
|
||||
@@ -47,6 +53,12 @@ namespace Juliet::D3D12
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Align size for Constant Buffers
|
||||
if (usage == BufferUsage::ConstantBuffer)
|
||||
{
|
||||
size = (size + 255U) & ~255U;
|
||||
}
|
||||
|
||||
D3D12_RESOURCE_STATES initialState = D3D12_RESOURCE_STATE_COMMON;
|
||||
D3D12_HEAP_PROPERTIES heapProperties = {};
|
||||
D3D12_HEAP_FLAGS heapFlags = D3D12_HEAP_FLAG_NONE;
|
||||
@@ -59,8 +71,8 @@ namespace Juliet::D3D12
|
||||
{
|
||||
case BufferUsage::None:
|
||||
{
|
||||
Assert(false , "Creating buffer with invalid usage");
|
||||
DestroyBuffer(d3d12Driver, buffer);
|
||||
Assert(false, "Creating buffer with invalid usage");
|
||||
DestroyBuffer(buffer);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -114,9 +126,7 @@ namespace Juliet::D3D12
|
||||
}
|
||||
}
|
||||
|
||||
// D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc;
|
||||
// D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
// D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc;
|
||||
D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
|
||||
|
||||
D3D12_RESOURCE_DESC desc = {};
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
@@ -138,14 +148,55 @@ namespace Juliet::D3D12
|
||||
if (FAILED(result))
|
||||
{
|
||||
LogError(d3d12Driver->D3D12Device, "Could not create buffer!", result);
|
||||
DestroyBuffer(d3d12Driver, buffer);
|
||||
DestroyBuffer(buffer);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
buffer->ReferenceCount = 0;
|
||||
buffer->Handle = handle;
|
||||
buffer->Handle = handle;
|
||||
buffer->CurrentState = initialState;
|
||||
buffer->Descriptor.Index = UINT32_MAX;
|
||||
|
||||
return nullptr;
|
||||
if (usage == BufferUsage::ConstantBuffer || usage == BufferUsage::StructuredBuffer)
|
||||
{
|
||||
auto& heap = d3d12Driver->BindlessDescriptorHeap;
|
||||
|
||||
Internal::D3D12Descriptor descriptor;
|
||||
if (Internal::AssignDescriptor(heap, descriptor))
|
||||
{
|
||||
buffer->Descriptor = descriptor;
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle = descriptor.CpuHandle;
|
||||
|
||||
if (usage == BufferUsage::ConstantBuffer)
|
||||
{
|
||||
cbvDesc.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(handle);
|
||||
cbvDesc.SizeInBytes = static_cast<uint32>(size);
|
||||
ID3D12Device_CreateConstantBufferView(d3d12Driver->D3D12Device, &cbvDesc, cpuHandle);
|
||||
}
|
||||
else if (usage == BufferUsage::StructuredBuffer)
|
||||
{
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
|
||||
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
srvDesc.Buffer.FirstElement = 0;
|
||||
srvDesc.Buffer.NumElements = static_cast<uint32>(
|
||||
size / 4); // Assuming 4 bytes stride for raw access or similar. Ideally should be provided.
|
||||
srvDesc.Buffer.StructureByteStride = 0; // Raw buffer for simplicity, or 4 if typed?
|
||||
// If it's a Structured Buffer, we typically need stride. For now let's assume raw ByteAddressBuffer (R32_TYPELESS) or similar if stride is 0.
|
||||
// Actually, let's treat it as a ByteAddressBuffer (Raw) for most flexibility in bindless.
|
||||
srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
|
||||
srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW;
|
||||
|
||||
ID3D12Device_CreateShaderResourceView(d3d12Driver->D3D12Device, handle, &srvDesc, cpuHandle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError(LogCategory::Graphics, "Bindless Heap Full or Invalid!");
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -155,6 +206,11 @@ namespace Juliet::D3D12
|
||||
return reinterpret_cast<GraphicsBuffer*>(CreateBuffer(d3d12Driver, size, usage, D3D12BufferType::Base));
|
||||
}
|
||||
|
||||
void DestroyGraphicsBuffer(NonNullPtr<GraphicsBuffer> buffer)
|
||||
{
|
||||
DestroyBuffer(reinterpret_cast<D3D12Buffer*>(buffer.Get()));
|
||||
}
|
||||
|
||||
GraphicsTransferBuffer* CreateGraphicsTransferBuffer(NonNullPtr<GPUDriver> driver, size_t size, TransferBufferUsage usage)
|
||||
{
|
||||
auto d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
|
||||
@@ -163,4 +219,86 @@ namespace Juliet::D3D12
|
||||
usage == TransferBufferUsage::Upload ? D3D12BufferType::TransferUpload : D3D12BufferType::TransferDownload));
|
||||
}
|
||||
|
||||
void DestroyGraphicsTransferBuffer(NonNullPtr<GraphicsTransferBuffer> buffer)
|
||||
{
|
||||
DestroyBuffer(reinterpret_cast<D3D12Buffer*>(buffer.Get()));
|
||||
}
|
||||
|
||||
void* MapBuffer(NonNullPtr<GPUDriver> /*driver*/, NonNullPtr<GraphicsTransferBuffer> buffer)
|
||||
{
|
||||
auto d3d12Buffer = reinterpret_cast<D3D12Buffer*>(buffer.Get());
|
||||
void* ptr = nullptr;
|
||||
// 0-0 range means we don't intend to read anything.
|
||||
D3D12_RANGE readRange = { 0, 0 };
|
||||
if (FAILED(ID3D12Resource_Map(d3d12Buffer->Handle, 0, &readRange, &ptr)))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void UnmapBuffer(NonNullPtr<GPUDriver> /*driver*/, NonNullPtr<GraphicsTransferBuffer> buffer)
|
||||
{
|
||||
auto d3d12Buffer = reinterpret_cast<D3D12Buffer*>(buffer.Get());
|
||||
ID3D12Resource_Unmap(d3d12Buffer->Handle, 0, nullptr);
|
||||
}
|
||||
|
||||
uint32 GetDescriptorIndex(NonNullPtr<GPUDriver> /*driver*/, NonNullPtr<GraphicsBuffer> buffer)
|
||||
{
|
||||
auto d3d12Buffer = reinterpret_cast<D3D12Buffer*>(buffer.Get());
|
||||
return d3d12Buffer->Descriptor.Index;
|
||||
}
|
||||
|
||||
void CopyBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> dst,
|
||||
NonNullPtr<GraphicsTransferBuffer> src, size_t size, size_t dstOffset, size_t srcOffset)
|
||||
{
|
||||
auto d3d12CmdList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
|
||||
auto d3d12Dst = reinterpret_cast<D3D12Buffer*>(dst.Get());
|
||||
auto d3d12Src = reinterpret_cast<D3D12Buffer*>(src.Get());
|
||||
|
||||
// Transition DST to COPY_DEST if needed
|
||||
if (d3d12Dst->CurrentState != D3D12_RESOURCE_STATE_COPY_DEST)
|
||||
{
|
||||
D3D12_RESOURCE_BARRIER barrier = {};
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barrier.Transition.pResource = d3d12Dst->Handle;
|
||||
barrier.Transition.StateBefore = d3d12Dst->CurrentState;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
|
||||
ID3D12GraphicsCommandList_ResourceBarrier(d3d12CmdList->GraphicsCommandList.CommandList, 1, &barrier);
|
||||
d3d12Dst->CurrentState = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
}
|
||||
|
||||
// Src is Upload Buffer, usually effectively GenericRead/Common but for Upload heaps it's simpler.
|
||||
// We assume Upload buffers are always in state GENERIC_READ or similar suitable for CopySrc.
|
||||
// D3D12 Upload heaps start in GENERIC_READ and cannot transition.
|
||||
|
||||
ID3D12GraphicsCommandList_CopyBufferRegion(d3d12CmdList->GraphicsCommandList.CommandList, d3d12Dst->Handle,
|
||||
dstOffset, d3d12Src->Handle, srcOffset, size);
|
||||
}
|
||||
|
||||
void TransitionBufferToReadable(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer)
|
||||
{
|
||||
auto d3d12CmdList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
|
||||
auto d3d12Buffer = reinterpret_cast<D3D12Buffer*>(buffer.Get());
|
||||
|
||||
D3D12_RESOURCE_STATES neededState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
|
||||
|
||||
if (d3d12Buffer->CurrentState != neededState)
|
||||
{
|
||||
D3D12_RESOURCE_BARRIER barrier = {};
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barrier.Transition.pResource = d3d12Buffer->Handle;
|
||||
barrier.Transition.StateBefore = d3d12Buffer->CurrentState;
|
||||
barrier.Transition.StateAfter = neededState;
|
||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
|
||||
ID3D12GraphicsCommandList_ResourceBarrier(d3d12CmdList->GraphicsCommandList.CommandList, 1, &barrier);
|
||||
d3d12Buffer->CurrentState = neededState;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Juliet::D3D12
|
||||
|
||||
@@ -5,10 +5,21 @@
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
struct CommandList;
|
||||
struct GPUDriver;
|
||||
}
|
||||
} // namespace Juliet
|
||||
namespace Juliet::D3D12
|
||||
{
|
||||
extern GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GPUDriver> driver, size_t size, BufferUsage usage);
|
||||
extern void DestroyGraphicsBuffer(NonNullPtr<GraphicsBuffer> buffer);
|
||||
|
||||
extern GraphicsTransferBuffer* CreateGraphicsTransferBuffer(NonNullPtr<GPUDriver> driver, size_t size, TransferBufferUsage usage);
|
||||
}
|
||||
extern void DestroyGraphicsTransferBuffer(NonNullPtr<GraphicsTransferBuffer> buffer);
|
||||
|
||||
extern void* MapBuffer(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsTransferBuffer> buffer);
|
||||
extern void UnmapBuffer(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsTransferBuffer> buffer);
|
||||
extern uint32 GetDescriptorIndex(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsBuffer> buffer);
|
||||
extern void CopyBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> dst,
|
||||
NonNullPtr<GraphicsTransferBuffer> src, size_t size, size_t dstOffset, size_t srcOffset);
|
||||
extern void TransitionBufferToReadable(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer);
|
||||
} // namespace Juliet::D3D12
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Juliet::D3D12
|
||||
reinterpret_cast<void**>(&baseData->Allocator));
|
||||
if (FAILED(result))
|
||||
{
|
||||
Assert(false, "Error not implemented: cannot create ID3D12CommandAllocator");
|
||||
AssertHR(result, "Cannot create ID3D12CommandAllocator");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace Juliet::D3D12
|
||||
|
||||
if (FAILED(result))
|
||||
{
|
||||
AssertHR(result, "Error not implemented: cannot create ID3D12GraphicsCommandList (copy command list)");
|
||||
AssertHR(result, "cannot create ID3D12GraphicsCommandList (copy command list)");
|
||||
return false;
|
||||
}
|
||||
commandList->CopyCommandList.CommandList = d3d12CopyCommandList;
|
||||
@@ -369,6 +369,15 @@ namespace Juliet::D3D12
|
||||
ID3D12GraphicsCommandList_OMSetStencilRef(d3d12CommandList->GraphicsCommandList.CommandList, reference);
|
||||
}
|
||||
|
||||
void SetPushConstants(NonNullPtr<CommandList> commandList, ShaderStage /*stage*/, uint32 rootParameterIndex,
|
||||
uint32 numConstants, const void* constants)
|
||||
{
|
||||
auto d3d12CommandList = reinterpret_cast<D3D12CommandList*>(commandList.Get());
|
||||
// For now we assume Graphics Root Signature. Compute support would need a check or separate function.
|
||||
ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(d3d12CommandList->GraphicsCommandList.CommandList,
|
||||
rootParameterIndex, numConstants, constants, 0);
|
||||
}
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
void SetDescriptorHeaps(NonNullPtr<D3D12CommandList> commandList)
|
||||
@@ -377,7 +386,8 @@ namespace Juliet::D3D12
|
||||
D3D12DescriptorHeap* viewHeap = nullptr;
|
||||
D3D12DescriptorHeap* samplerHeap = nullptr;
|
||||
|
||||
viewHeap = AcquireDescriptorHeapFromPool(commandList->Driver, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
viewHeap = commandList->Driver->BindlessDescriptorHeap;
|
||||
|
||||
samplerHeap = AcquireDescriptorHeapFromPool(commandList->Driver, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
|
||||
|
||||
commandList->CRB_SRV_UAV_Heap = viewHeap;
|
||||
@@ -426,7 +436,7 @@ namespace Juliet::D3D12
|
||||
}
|
||||
|
||||
// Return heap descriptor to pool
|
||||
ReturnDescriptorHeapToPool(driver, commandList->CRB_SRV_UAV_Heap);
|
||||
// CRB_SRV_UAV_Heap is global bindless, do not return it.
|
||||
ReturnDescriptorHeapToPool(driver, commandList->RTV_Heap);
|
||||
commandList->CRB_SRV_UAV_Heap = nullptr;
|
||||
commandList->RTV_Heap = nullptr;
|
||||
|
||||
@@ -93,7 +93,9 @@ namespace Juliet::D3D12
|
||||
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 SetBlendConstants(NonNullPtr<CommandList> commandList, FColor blendConstants);
|
||||
extern void SetStencilReference(NonNullPtr<CommandList> commandList, uint8 reference);
|
||||
extern void SetPushConstants(NonNullPtr<CommandList> commandList, ShaderStage stage, uint32 rootParameterIndex, uint32 numConstants, const void* constants);
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
|
||||
@@ -16,6 +16,9 @@ namespace Juliet::D3D12::Internal
|
||||
}
|
||||
|
||||
heap->CurrentDescriptorIndex = 0;
|
||||
heap->FreeIndicesCapacity = 16;
|
||||
heap->FreeIndicesCount = 0;
|
||||
heap->FreeIndices = static_cast<uint32*>(Calloc(heap->FreeIndicesCapacity, sizeof(uint32)));
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC heapDesc;
|
||||
heapDesc.NumDescriptors = count;
|
||||
@@ -52,9 +55,56 @@ namespace Juliet::D3D12::Internal
|
||||
{
|
||||
ID3D12DescriptorHeap_Release(heap->Handle);
|
||||
}
|
||||
SafeFree(heap->FreeIndices);
|
||||
Free(heap.Get());
|
||||
}
|
||||
|
||||
bool AssignDescriptor(D3D12DescriptorHeap* heap, D3D12Descriptor& outDescriptor)
|
||||
{
|
||||
uint32 index = UINT32_MAX;
|
||||
|
||||
if (heap->FreeIndicesCount > 0)
|
||||
{
|
||||
heap->FreeIndicesCount -= 1;
|
||||
index = heap->FreeIndices[heap->FreeIndicesCount];
|
||||
}
|
||||
else if (heap->CurrentDescriptorIndex < heap->MaxDescriptors)
|
||||
{
|
||||
index = heap->CurrentDescriptorIndex;
|
||||
heap->CurrentDescriptorIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert(false, "Descriptor Heap Full!");
|
||||
return false;
|
||||
}
|
||||
|
||||
outDescriptor.Heap = heap;
|
||||
outDescriptor.Index = index;
|
||||
outDescriptor.CpuHandle = heap->DescriptorHeapCPUStart;
|
||||
outDescriptor.CpuHandle.ptr += heap->DescriptorSize * index;
|
||||
outDescriptor.GpuHandle = heap->DescriptorHeapGPUStart;
|
||||
outDescriptor.GpuHandle.ptr += heap->DescriptorSize * index;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ReleaseDescriptor(const D3D12Descriptor& descriptor)
|
||||
{
|
||||
if (descriptor.Index == UINT32_MAX || descriptor.Heap == nullptr) return;
|
||||
|
||||
D3D12DescriptorHeap* heap = descriptor.Heap;
|
||||
|
||||
if (heap->FreeIndicesCount >= heap->FreeIndicesCapacity)
|
||||
{
|
||||
heap->FreeIndicesCapacity *= 2;
|
||||
heap->FreeIndices = static_cast<uint32*>(Realloc(heap->FreeIndices, heap->FreeIndicesCapacity * sizeof(uint32)));
|
||||
}
|
||||
|
||||
heap->FreeIndices[heap->FreeIndicesCount] = descriptor.Index;
|
||||
heap->FreeIndicesCount++;
|
||||
}
|
||||
|
||||
D3D12DescriptorHeap* AcquireDescriptorHeapFromPool(NonNullPtr<D3D12Driver> d3d12Driver, D3D12_DESCRIPTOR_HEAP_TYPE type)
|
||||
{
|
||||
D3D12DescriptorHeapPool* pool = nullptr;
|
||||
|
||||
@@ -21,9 +21,22 @@ namespace Juliet::D3D12::Internal
|
||||
uint32 MaxDescriptors;
|
||||
uint32 DescriptorSize;
|
||||
uint32 CurrentDescriptorIndex; // only used by GPU heaps
|
||||
|
||||
uint32* FreeIndices;
|
||||
uint32 FreeIndicesCapacity;
|
||||
uint32 FreeIndicesCount;
|
||||
|
||||
bool Staging : 1;
|
||||
};
|
||||
|
||||
struct D3D12Descriptor
|
||||
{
|
||||
D3D12DescriptorHeap* Heap;
|
||||
uint32 Index;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE CpuHandle;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE GpuHandle;
|
||||
};
|
||||
|
||||
struct D3D12DescriptorHeapPool
|
||||
{
|
||||
D3D12DescriptorHeap** Heaps;
|
||||
@@ -38,4 +51,7 @@ namespace Juliet::D3D12::Internal
|
||||
extern D3D12DescriptorHeap* AcquireDescriptorHeapFromPool(NonNullPtr<D3D12Driver> commandList,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE type);
|
||||
extern void ReturnDescriptorHeapToPool(NonNullPtr<D3D12Driver> d3d12Driver, D3D12DescriptorHeap* heap);
|
||||
|
||||
extern bool AssignDescriptor(D3D12DescriptorHeap* heap, D3D12Descriptor& outDescriptor);
|
||||
extern void ReleaseDescriptor(const D3D12Descriptor& descriptor);
|
||||
} // namespace Juliet::D3D12
|
||||
|
||||
@@ -461,7 +461,8 @@ namespace Juliet::D3D12
|
||||
return;
|
||||
}
|
||||
|
||||
ID3D12InfoQueue1_RegisterMessageCallback(infoQueue, OnD3D12DebugInfoMsg, D3D12_MESSAGE_CALLBACK_FLAG_NONE, nullptr, nullptr);
|
||||
ID3D12InfoQueue1_RegisterMessageCallback(infoQueue, OnD3D12DebugInfoMsg, D3D12_MESSAGE_CALLBACK_FLAG_NONE,
|
||||
nullptr, nullptr);
|
||||
ID3D12InfoQueue1_Release(infoQueue);
|
||||
}
|
||||
#endif
|
||||
@@ -520,6 +521,8 @@ namespace Juliet::D3D12
|
||||
|
||||
DestroyGraphicsRootSignature(driver->BindlessRootSignature);
|
||||
|
||||
Internal::DestroyDescriptorHeap(driver->BindlessDescriptorHeap);
|
||||
|
||||
// Clean allocations
|
||||
SafeFree(driver->AvailableCommandLists);
|
||||
SafeFree(driver->SubmittedCommandLists);
|
||||
@@ -999,6 +1002,7 @@ namespace Juliet::D3D12
|
||||
device->BindGraphicsPipeline = BindGraphicsPipeline;
|
||||
device->DrawPrimitives = DrawPrimitives;
|
||||
device->WaitUntilGPUIsIdle = WaitUntilGPUIsIdle;
|
||||
device->SetPushConstants = SetPushConstants;
|
||||
device->QueryFence = QueryFence;
|
||||
device->ReleaseFence = ReleaseFence;
|
||||
device->CreateShader = CreateShader;
|
||||
@@ -1006,7 +1010,14 @@ namespace Juliet::D3D12
|
||||
device->CreateGraphicsPipeline = CreateGraphicsPipeline;
|
||||
device->DestroyGraphicsPipeline = DestroyGraphicsPipeline;
|
||||
device->CreateGraphicsBuffer = CreateGraphicsBuffer;
|
||||
device->DestroyGraphicsBuffer = DestroyGraphicsBuffer;
|
||||
device->CreateGraphicsTransferBuffer = CreateGraphicsTransferBuffer;
|
||||
device->DestroyGraphicsTransferBuffer = DestroyGraphicsTransferBuffer;
|
||||
device->MapGraphicsTransferBuffer = MapBuffer;
|
||||
device->UnmapGraphicsTransferBuffer = UnmapBuffer;
|
||||
device->CopyBuffer = CopyBuffer;
|
||||
device->TransitionBufferToReadable = TransitionBufferToReadable;
|
||||
device->GetDescriptorIndex = GetDescriptorIndex;
|
||||
|
||||
#if ALLOW_SHADER_HOT_RELOAD
|
||||
device->UpdateGraphicsPipelineShaders = UpdateGraphicsPipelineShaders;
|
||||
@@ -1017,6 +1028,9 @@ namespace Juliet::D3D12
|
||||
|
||||
driver->GraphicsDevice = device;
|
||||
|
||||
// Create Global Bindless Heap that stays alive for the driver whole lifetime
|
||||
driver->BindlessDescriptorHeap = Internal::AcquireDescriptorHeapFromPool(driver, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
|
||||
return device;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -98,6 +98,7 @@ namespace Juliet::D3D12
|
||||
D3D12GraphicsRootSignature* BindlessRootSignature;
|
||||
|
||||
D3D12StagingDescriptorPool* StagingDescriptorPools[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES];
|
||||
Internal::D3D12DescriptorHeap* BindlessDescriptorHeap;
|
||||
Internal::D3D12DescriptorHeapPool CRB_SRV_UAV_HeapPool;
|
||||
Internal::D3D12DescriptorHeapPool RTV_HeapPool;
|
||||
|
||||
|
||||
@@ -264,6 +264,13 @@ namespace Juliet
|
||||
commandListHeader->Device->DrawPrimitives(commandList, numVertices, numInstances, firstVertex, firstInstance);
|
||||
}
|
||||
|
||||
void SetPushConstants(NonNullPtr<CommandList> commandList, ShaderStage stage, uint32 rootParameterIndex,
|
||||
uint32 numConstants, const void* constants)
|
||||
{
|
||||
auto* header = reinterpret_cast<CommandListHeader*>(commandList.Get());
|
||||
header->Device->SetPushConstants(commandList, stage, rootParameterIndex, numConstants, constants);
|
||||
}
|
||||
|
||||
// Fences
|
||||
bool WaitUntilGPUIsIdle(NonNullPtr<GraphicsDevice> device)
|
||||
{
|
||||
@@ -335,15 +342,41 @@ namespace Juliet
|
||||
return device->CreateGraphicsTransferBuffer(device->Driver, createInfo.Size, createInfo.Usage);
|
||||
}
|
||||
|
||||
void ReleaseGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer)
|
||||
void* MapGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer)
|
||||
{
|
||||
(void)device;
|
||||
(void)buffer;
|
||||
return device->MapGraphicsTransferBuffer(device->Driver, buffer);
|
||||
}
|
||||
|
||||
void ReleaseGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer)
|
||||
void UnmapGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer)
|
||||
{
|
||||
(void)device;
|
||||
(void)buffer;
|
||||
device->UnmapGraphicsTransferBuffer(device->Driver, buffer);
|
||||
}
|
||||
|
||||
void CopyBuffer(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> dst,
|
||||
NonNullPtr<GraphicsTransferBuffer> src, size_t size, size_t dstOffset, size_t srcOffset)
|
||||
{
|
||||
auto* header = reinterpret_cast<CommandListHeader*>(commandList.Get());
|
||||
header->Device->CopyBuffer(commandList, dst, src, size, dstOffset, srcOffset);
|
||||
}
|
||||
|
||||
void TransitionBufferToReadable(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer)
|
||||
{
|
||||
auto* header = reinterpret_cast<CommandListHeader*>(commandList.Get());
|
||||
header->Device->TransitionBufferToReadable(commandList, buffer);
|
||||
}
|
||||
|
||||
uint32 GetDescriptorIndex(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer)
|
||||
{
|
||||
return device->GetDescriptorIndex(device->Driver, buffer);
|
||||
}
|
||||
|
||||
void DestroyGraphicsBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsBuffer> buffer)
|
||||
{
|
||||
device->DestroyGraphicsBuffer(buffer);
|
||||
}
|
||||
|
||||
void DestroyGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsTransferBuffer> buffer)
|
||||
{
|
||||
device->DestroyGraphicsTransferBuffer(buffer);
|
||||
}
|
||||
} // namespace Juliet
|
||||
|
||||
@@ -71,6 +71,9 @@ namespace Juliet
|
||||
void (*DrawPrimitives)(NonNullPtr<CommandList> commandList, uint32 numVertices, uint32 numInstances,
|
||||
uint32 firstVertex, uint32 firstInstance);
|
||||
|
||||
void (*SetPushConstants)(NonNullPtr<CommandList> commandList, ShaderStage stage, uint32 rootParameterIndex,
|
||||
uint32 numConstants, const void* constants);
|
||||
|
||||
// Fences
|
||||
bool (*WaitUntilGPUIsIdle)(NonNullPtr<GPUDriver> driver);
|
||||
bool (*QueryFence)(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
|
||||
@@ -88,7 +91,17 @@ namespace Juliet
|
||||
|
||||
// Buffers
|
||||
GraphicsBuffer* (*CreateGraphicsBuffer)(NonNullPtr<GPUDriver> driver, size_t size, BufferUsage usage);
|
||||
void (*DestroyGraphicsBuffer)(NonNullPtr<GraphicsBuffer> buffer);
|
||||
|
||||
GraphicsTransferBuffer* (*CreateGraphicsTransferBuffer)(NonNullPtr<GPUDriver> driver, size_t size, TransferBufferUsage usage);
|
||||
void (*DestroyGraphicsTransferBuffer)(NonNullPtr<GraphicsTransferBuffer> buffer);
|
||||
|
||||
void* (*MapGraphicsTransferBuffer)(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsTransferBuffer> buffer);
|
||||
void (*UnmapGraphicsTransferBuffer)(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsTransferBuffer> buffer);
|
||||
void (*CopyBuffer)(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> dst,
|
||||
NonNullPtr<GraphicsTransferBuffer> src, size_t size, size_t dstOffset, size_t srcOffset);
|
||||
void (*TransitionBufferToReadable)(NonNullPtr<CommandList> commandList, NonNullPtr<GraphicsBuffer> buffer);
|
||||
uint32 (*GetDescriptorIndex)(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsBuffer> buffer);
|
||||
|
||||
const char* Name = "Unknown";
|
||||
GPUDriver* Driver = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user