Part generated by gemini with antigravity.

Converted to bindless first step
This commit is contained in:
2026-01-11 17:54:57 -05:00
parent bd45cacc6c
commit 8a23ae72fe
18 changed files with 481 additions and 122 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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
{

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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;