From 2d3a075eb61f20654b54ae83bbe397f643a0499c Mon Sep 17 00:00:00 2001 From: Patedam Date: Mon, 24 Mar 2025 22:19:52 -0400 Subject: [PATCH] Bindless resource first step --- .../src/Graphics/D3D12/D3D12CommandList.cpp | 90 ++++++ Juliet/src/Graphics/D3D12/D3D12CommandList.h | 6 + Juliet/src/Graphics/D3D12/D3D12Common.h | 7 + .../Graphics/D3D12/D3D12GraphicsDevice.cpp | 190 ++++++++++- .../src/Graphics/D3D12/D3D12GraphicsDevice.h | 23 +- .../Graphics/D3D12/D3D12GraphicsPipeline.cpp | 304 +----------------- .../Graphics/D3D12/D3D12GraphicsPipeline.h | 14 - Juliet/src/Graphics/D3D12/D3D12RenderPass.cpp | 3 + Juliet/src/Graphics/GraphicsDevice.h | 3 + JulietShaderCompiler/ShaderCompiler.cpp | 6 +- 10 files changed, 316 insertions(+), 330 deletions(-) diff --git a/Juliet/src/Graphics/D3D12/D3D12CommandList.cpp b/Juliet/src/Graphics/D3D12/D3D12CommandList.cpp index b82c6c0..c6ff77e 100644 --- a/Juliet/src/Graphics/D3D12/D3D12CommandList.cpp +++ b/Juliet/src/Graphics/D3D12/D3D12CommandList.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -367,6 +368,89 @@ namespace Juliet::D3D12 namespace Internal { + namespace + { + D3D12DescriptorHeap* AcquireDescriptorHeapFromPool(NonNullPtr commandList, D3D12_DESCRIPTOR_HEAP_TYPE type) + { + D3D12Driver* d3d12Driver = commandList->Driver; + + D3D12DescriptorHeapPool* pool = nullptr; + uint32 count = 0; + if (type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) + { + pool = &d3d12Driver->CRB_SRV_UAV_HeapPool; + count = GPUDriver::kCBV_SRV_UAV_HeapDescriptorCount; + } + else if (type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) + { + pool = &d3d12Driver->RTV_HeapPool; + count = GPUDriver::kSampler_HeapDescriptorCount; + } + Assert(pool != nullptr); + + D3D12DescriptorHeap* result = nullptr; + if (pool->Count > 0) + { + result = pool->Heaps[pool->Count - 1]; + pool->Count -= 1; + } + else + { + result = CreateDescriptorHeap(d3d12Driver, type, count, false); + } + + return result; + } + + void ReturnDescriptorHeapToPool(NonNullPtr d3d12Driver, D3D12DescriptorHeap* heap) + { + if (heap == nullptr) + { + return; + } + + D3D12DescriptorHeapPool* pool = nullptr; + if (heap->HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) + { + pool = &d3d12Driver->CRB_SRV_UAV_HeapPool; + } + else if (heap->HeapType == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) + { + pool = &d3d12Driver->RTV_HeapPool; + } + Assert(pool != nullptr); + heap->CurrentDescriptorIndex = 0; + + if (pool->Count >= pool->Capacity) + { + pool->Capacity *= 2; + pool->Heaps = + static_cast(Realloc(pool->Heaps, pool->Capacity * sizeof(D3D12DescriptorHeap*))); + } + + pool->Heaps[pool->Count] = heap; + pool->Count += 1; + } + } // namespace + + void SetDescriptorHeaps(NonNullPtr commandList) + { + ID3D12DescriptorHeap* heaps[2]; + D3D12DescriptorHeap* viewHeap = nullptr; + D3D12DescriptorHeap* samplerHeap = nullptr; + + viewHeap = AcquireDescriptorHeapFromPool(commandList, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + samplerHeap = AcquireDescriptorHeapFromPool(commandList, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); + + commandList->CRB_SRV_UAV_Heap = viewHeap; + commandList->RTV_Heap = samplerHeap; + + heaps[0] = viewHeap->Handle; + heaps[1] = samplerHeap->Handle; + + ID3D12GraphicsCommandList_SetDescriptorHeaps(commandList->GraphicsCommandList.CommandList, 2, heaps); + } + void DestroyCommandList(NonNullPtr commandList) { // TODO : Handle other kind of command list (copy compute) @@ -403,6 +487,12 @@ namespace Juliet::D3D12 return false; } + // Return heap descriptor to pool + ReturnDescriptorHeapToPool(driver, commandList->CRB_SRV_UAV_Heap); + ReturnDescriptorHeapToPool(driver, commandList->RTV_Heap); + commandList->CRB_SRV_UAV_Heap = nullptr; + commandList->RTV_Heap = nullptr; + // Clean up resource tracking for (uint32 idx = 0; idx < commandList->UsedTextureCount; ++idx) { diff --git a/Juliet/src/Graphics/D3D12/D3D12CommandList.h b/Juliet/src/Graphics/D3D12/D3D12CommandList.h index 06dfd71..6705ba7 100644 --- a/Juliet/src/Graphics/D3D12/D3D12CommandList.h +++ b/Juliet/src/Graphics/D3D12/D3D12CommandList.h @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -74,6 +75,9 @@ namespace Juliet::D3D12 // D3D12UniformBuffer *vertexUniformBuffers[GPUDriver::kMaxUniformBuffersPerStage]; // D3D12UniformBuffer *fragmentUniformBuffers[GPUDriver::kMaxUniformBuffersPerStage]; + D3D12DescriptorHeap* CRB_SRV_UAV_Heap; + D3D12DescriptorHeap* RTV_Heap; + // Resource Tracking D3D12Texture** UsedTextures; uint32 UsedTextureCount; @@ -93,6 +97,8 @@ namespace Juliet::D3D12 namespace Internal { + extern void SetDescriptorHeaps(NonNullPtr commandList); + extern void DestroyCommandList(NonNullPtr commandList); extern bool CleanCommandList(NonNullPtr driver, NonNullPtr commandList, bool cancel); diff --git a/Juliet/src/Graphics/D3D12/D3D12Common.h b/Juliet/src/Graphics/D3D12/D3D12Common.h index c6ef10e..4584787 100644 --- a/Juliet/src/Graphics/D3D12/D3D12Common.h +++ b/Juliet/src/Graphics/D3D12/D3D12Common.h @@ -32,6 +32,13 @@ namespace Juliet::D3D12 bool Staging : 1; }; + struct D3D12DescriptorHeapPool + { + D3D12DescriptorHeap** Heaps; + size_t Capacity; + size_t Count; + }; + struct D3D12StagingDescriptorPool { D3D12DescriptorHeap** Heaps; diff --git a/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.cpp b/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.cpp index 14ed6ea..f5b9401 100644 --- a/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.cpp +++ b/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.cpp @@ -17,7 +17,7 @@ #define D3D12_DLL "d3d12.dll" #define D3D12_CREATEDEVICE_FUNC "D3D12CreateDevice" -#define D3D12_SERIALIZE_ROOT_SIGNATURE_FUNC "D3D12SerializeRootSignature" +#define D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE_FUNC "D3D12SerializeVersionedRootSignature" #define DXGIDEBUG_DLL "dxgidebug.dll" #define DXGI_GET_DEBUG_INTERFACE_FUNC "DXGIGetDebugInterface" #define D3D12_GET_DEBUG_INTERFACE_FUNC "D3D12GetDebugInterface" @@ -196,6 +196,127 @@ namespace Juliet::D3D12 return driverIsValid; } + void DestroyGraphicsRootSignature(D3D12GraphicsRootSignature* rootSignature) + { + if (!rootSignature) + { + return; + } + if (rootSignature->Handle) + { + ID3D12RootSignature_Release(rootSignature->Handle); + } + Free(rootSignature); + } + + D3D12GraphicsRootSignature* CreateGraphicsRootSignature(NonNullPtr d3d12Driver) + { + auto d3d12GraphicsRootSignature = + static_cast(Calloc(1, sizeof(D3D12GraphicsRootSignature))); + if (!d3d12GraphicsRootSignature) + { + return nullptr; + } + + D3D12_ROOT_PARAMETER1 parameters[ToUnderlying(RootParameters::Count)] = {}; + parameters[ToUnderlying(RootParameters::Constants32Bits)] = { + .ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS, + .Constants = { + .ShaderRegister = 0, + .RegisterSpace = 0, + .Num32BitValues = 58, // 58 because each root cbv takes 2 uints, and the max is 64 + }, + }; + + parameters[ToUnderlying(RootParameters::PassCBV)] = { + .ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV, + .Descriptor = { + .ShaderRegister = 1, + .Flags = D3D12_ROOT_DESCRIPTOR_FLAG_DATA_VOLATILE, + }, + }; + + parameters[ToUnderlying(RootParameters::ViewCBV)] = { + .ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV, + .Descriptor = { + .ShaderRegister = 2, + .Flags = D3D12_ROOT_DESCRIPTOR_FLAG_DATA_VOLATILE, + }, + }; + + parameters[ToUnderlying(RootParameters::GlobalCBV)] = { + .ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV, + .Descriptor = { + .ShaderRegister = 3, + .Flags = D3D12_ROOT_DESCRIPTOR_FLAG_DATA_VOLATILE, + }, + }; + + D3D12_STATIC_SAMPLER_DESC samplers[] = { + { + // s_nearest + .Filter = D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR, + .AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + .AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + .AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP, + .MipLODBias = 0.0f, + .MinLOD = 0.0f, + .MaxLOD = D3D12_FLOAT32_MAX, + .ShaderRegister = 0, + .RegisterSpace = 0, + .ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL, + }, + }; + + D3D12_VERSIONED_ROOT_SIGNATURE_DESC rootSignatureDesc = { + .Version = D3D_ROOT_SIGNATURE_VERSION_1_1, + .Desc_1_1 = { + .NumParameters = ArraySize(parameters), + .pParameters = parameters, + .NumStaticSamplers = ArraySize(samplers), + .pStaticSamplers = samplers, + .Flags = D3D12_ROOT_SIGNATURE_FLAG_CBV_SRV_UAV_HEAP_DIRECTLY_INDEXED, + }, + }; + + // Serialize the root signature + ID3DBlob* serializedRootSignature; + ID3DBlob* errorBlob; + HRESULT res = + d3d12Driver->D3D12SerializeVersionedRootSignatureFct(&rootSignatureDesc, &serializedRootSignature, &errorBlob); + if (FAILED(res)) + { + if (errorBlob) + { + auto errorBuffer = ID3D10Blob_GetBufferPointer(errorBlob); + LogError(LogCategory::Graphics, "Failed to serialize RootSignature: %s", errorBuffer); + ID3D10Blob_Release(errorBlob); + } + DestroyGraphicsRootSignature(d3d12GraphicsRootSignature); + return nullptr; + } + + // Create the root signature + ID3D12RootSignature* rootSignature; + res = ID3D12Device_CreateRootSignature(d3d12Driver->D3D12Device, 0, ID3D10Blob_GetBufferPointer(serializedRootSignature), + ID3D10Blob_GetBufferSize(serializedRootSignature), + IID_ID3D12RootSignature, reinterpret_cast(&rootSignature)); + if (FAILED(res)) + { + if (errorBlob) + { + LogError(LogCategory::Graphics, "Failed to create RootSignature: %s", + (const char*)ID3D10Blob_GetBufferPointer(errorBlob)); + ID3D10Blob_Release(errorBlob); + } + DestroyGraphicsRootSignature(d3d12GraphicsRootSignature); + return nullptr; + } + + d3d12GraphicsRootSignature->Handle = rootSignature; + return d3d12GraphicsRootSignature; + } + #ifdef IDXGIINFOQUEUE_SUPPORTED void InitializeDXGIDebug(NonNullPtr driver) { @@ -355,7 +476,7 @@ namespace Juliet::D3D12 void DestroyDriver_Internal(NonNullPtr driver) { - // Destroy pools + // Destroy Descriptor pools for (uint32 i = 0; i < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; i += 1) { if (driver->StagingDescriptorPools[i]) @@ -365,6 +486,24 @@ namespace Juliet::D3D12 } } + auto DestroyDescriptorHeapPool = [](D3D12DescriptorHeapPool& heapPool) + { + if (heapPool.Heaps) + { + for (uint32 i = 0; i < heapPool.Count; ++i) + { + if (heapPool.Heaps[i]) + { + Internal::DestroyDescriptorHeap(heapPool.Heaps[i]); + heapPool.Heaps[i] = nullptr; + } + } + SafeFree(heapPool.Heaps); + } + }; + DestroyDescriptorHeapPool(driver->CRB_SRV_UAV_HeapPool); + DestroyDescriptorHeapPool(driver->RTV_HeapPool); + // Release command buffers for (uint32 i = 0; i < driver->AvailableCommandListCount; i += 1) { @@ -385,6 +524,8 @@ namespace Juliet::D3D12 } } + DestroyGraphicsRootSignature(driver->BindlessRootSignature); + // Clean allocations SafeFree(driver->AvailableCommandLists); SafeFree(driver->SubmittedCommandLists); @@ -440,7 +581,7 @@ namespace Juliet::D3D12 driver->D3D12DLL = nullptr; } - driver->D3D12SerializeRootSignatureFct = nullptr; + driver->D3D12SerializeVersionedRootSignatureFct = nullptr; Free(driver.Get()); } @@ -624,12 +765,12 @@ namespace Juliet::D3D12 return nullptr; } - driver->D3D12SerializeRootSignatureFct = reinterpret_cast( - LoadFunction(driver->D3D12DLL, D3D12_SERIALIZE_ROOT_SIGNATURE_FUNC)); - if (driver->D3D12SerializeRootSignatureFct == nullptr) + driver->D3D12SerializeVersionedRootSignatureFct = reinterpret_cast( + LoadFunction(driver->D3D12DLL, D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE_FUNC)); + if (driver->D3D12SerializeVersionedRootSignatureFct == nullptr) { Log(LogLevel::Error, LogCategory::Graphics, - "DX12: Couldn't Load function " D3D12_SERIALIZE_ROOT_SIGNATURE_FUNC " in " D3D12_DLL); + "DX12: Couldn't Load function " D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE_FUNC " in " D3D12_DLL); DestroyDriver_Internal(driver); return nullptr; } @@ -687,6 +828,9 @@ namespace Juliet::D3D12 driver->GPUUploadHeapSupported = options16.GPUUploadHeapSupported; } + // Create bindless root signature + driver->BindlessRootSignature = CreateGraphicsRootSignature(driver); + // Command Queues // Graphics Queue only for now D3D12_COMMAND_QUEUE_DESC queueDesc = {}; @@ -784,6 +928,38 @@ namespace Juliet::D3D12 } } + // Other Descriptor pools + auto CreateDescriptorPool = [&](D3D12DescriptorHeapPool& heapPool, D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 count) -> bool + { + heapPool.Capacity = 4; + heapPool.Count = 4; + heapPool.Heaps = static_cast(Calloc(heapPool.Capacity, sizeof(D3D12DescriptorHeap*))); + + for (uint32 i = 0; i < heapPool.Capacity; ++i) + { + heapPool.Heaps[i] = Internal::CreateDescriptorHeap(driver, type, count, false); + + if (heapPool.Heaps[i] == nullptr) + { + return false; + } + } + return true; + }; + + if (!CreateDescriptorPool(driver->CRB_SRV_UAV_HeapPool, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, + GPUDriver::kCBV_SRV_UAV_HeapDescriptorCount)) + { + DestroyDriver_Internal(driver); + return nullptr; + } + + if (!CreateDescriptorPool(driver->RTV_HeapPool, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, GPUDriver::kSampler_HeapDescriptorCount)) + { + DestroyDriver_Internal(driver); + return nullptr; + } + // Deferred dispose vectors driver->GraphicsPipelinesToDisposeCapacity = 4; driver->GraphicsPipelinesToDisposeCount = 0; diff --git a/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.h b/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.h index 96bf435..f74d032 100644 --- a/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.h +++ b/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.h @@ -17,6 +17,15 @@ namespace Juliet::D3D12 struct D3D12CommandList; struct D3D12Fence; + enum class RootParameters : uint8 + { + Constants32Bits, + PassCBV, + ViewCBV, + GlobalCBV, + Count, + }; + struct D3D12WindowData { Window* Window; @@ -41,11 +50,11 @@ namespace Juliet::D3D12 GraphicsDevice* GraphicsDevice; // D3D12 - DynamicLibrary* D3D12DLL; - ID3D12Device5* D3D12Device; - PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignatureFct; - ID3D12CommandQueue* GraphicsQueue; - D3D12_COMMAND_QUEUE_DESC QueueDesc[ToUnderlying(QueueType::Copy)]; + DynamicLibrary* D3D12DLL; + ID3D12Device5* D3D12Device; + PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE D3D12SerializeVersionedRootSignatureFct; + ID3D12CommandQueue* GraphicsQueue; + D3D12_COMMAND_QUEUE_DESC QueueDesc[ToUnderlying(QueueType::Copy)]; #ifdef JULIET_DEBUG ID3D12Debug1* D3D12Debug; #endif @@ -85,7 +94,11 @@ namespace Juliet::D3D12 uint32 GraphicsPipelinesToDisposeCount; uint32 GraphicsPipelinesToDisposeCapacity; + D3D12GraphicsRootSignature* BindlessRootSignature; + D3D12StagingDescriptorPool* StagingDescriptorPools[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES]; + D3D12DescriptorHeapPool CRB_SRV_UAV_HeapPool; + D3D12DescriptorHeapPool RTV_HeapPool; String Semantic; diff --git a/Juliet/src/Graphics/D3D12/D3D12GraphicsPipeline.cpp b/Juliet/src/Graphics/D3D12/D3D12GraphicsPipeline.cpp index 41412bf..4403380 100644 --- a/Juliet/src/Graphics/D3D12/D3D12GraphicsPipeline.cpp +++ b/Juliet/src/Graphics/D3D12/D3D12GraphicsPipeline.cpp @@ -319,284 +319,6 @@ namespace Juliet::D3D12 return true; } - void DestroyGraphicsRootSignature(NonNullPtr rootSignature); - - constexpr size_t kMaxRootSignatureParameters = 64; - D3D12GraphicsRootSignature* CreateGraphicsRootSignature(NonNullPtr d3d12Driver, - NonNullPtr vertexShader, - NonNullPtr fragmentShader) - { - // TODO: Investigate bindless resources - D3D12_ROOT_PARAMETER rootParameters[kMaxRootSignatureParameters]; - D3D12_DESCRIPTOR_RANGE descriptorRanges[kMaxRootSignatureParameters]; - ZeroArray(rootParameters); - ZeroArray(descriptorRanges); - - uint32 parameterCount = 0; - uint32 rangeCount = 0; - D3D12_DESCRIPTOR_RANGE descriptorRange = {}; - D3D12_ROOT_PARAMETER rootParameter = {}; - auto d3d12GraphicsRootSignature = - static_cast(Calloc(1, sizeof(D3D12GraphicsRootSignature))); - if (!d3d12GraphicsRootSignature) - { - return nullptr; - } - - d3d12GraphicsRootSignature->VertexSamplerRootIndex = -1; - d3d12GraphicsRootSignature->VertexSamplerTextureRootIndex = -1; - d3d12GraphicsRootSignature->VertexStorageTextureRootIndex = -1; - d3d12GraphicsRootSignature->VertexStorageBufferRootIndex = -1; - - d3d12GraphicsRootSignature->FragmentSamplerRootIndex = -1; - d3d12GraphicsRootSignature->FragmentSamplerTextureRootIndex = -1; - d3d12GraphicsRootSignature->FragmentStorageTextureRootIndex = -1; - d3d12GraphicsRootSignature->FragmentStorageBufferRootIndex = -1; - - for (uint32 i = 0; i < GPUDriver::kMaxUniformBuffersPerStage; ++i) - { - d3d12GraphicsRootSignature->VertexUniformBufferRootIndex[i] = -1; - d3d12GraphicsRootSignature->FragmentUniformBufferRootIndex[i] = -1; - } - - if (vertexShader->NumSamplers > 0) - { - // Vertex Samplers - descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER; - descriptorRange.NumDescriptors = vertexShader->NumSamplers; - descriptorRange.BaseShaderRegister = 0; - descriptorRange.RegisterSpace = 0; - descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; - descriptorRanges[rangeCount] = descriptorRange; - - rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - rootParameter.DescriptorTable.NumDescriptorRanges = 1; - rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount]; - rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX; - rootParameters[parameterCount] = rootParameter; - d3d12GraphicsRootSignature->VertexSamplerRootIndex = parameterCount; - rangeCount += 1; - parameterCount += 1; - - descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - descriptorRange.NumDescriptors = vertexShader->NumSamplers; - descriptorRange.BaseShaderRegister = 0; - descriptorRange.RegisterSpace = 0; - descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; - descriptorRanges[rangeCount] = descriptorRange; - - rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - rootParameter.DescriptorTable.NumDescriptorRanges = 1; - rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount]; - rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX; - rootParameters[parameterCount] = rootParameter; - d3d12GraphicsRootSignature->VertexSamplerTextureRootIndex = parameterCount; - rangeCount += 1; - parameterCount += 1; - } - - if (vertexShader->NumStorageTextures) - { - // Vertex storage textures - descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - descriptorRange.NumDescriptors = vertexShader->NumStorageTextures; - descriptorRange.BaseShaderRegister = vertexShader->NumSamplers; - descriptorRange.RegisterSpace = 0; - descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; - descriptorRanges[rangeCount] = descriptorRange; - - rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - rootParameter.DescriptorTable.NumDescriptorRanges = 1; - rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount]; - rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX; - rootParameters[parameterCount] = rootParameter; - d3d12GraphicsRootSignature->VertexStorageTextureRootIndex = parameterCount; - rangeCount += 1; - parameterCount += 1; - } - - if (vertexShader->NumStorageBuffers) - { - // Vertex storage buffers - descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - descriptorRange.NumDescriptors = vertexShader->NumStorageBuffers; - descriptorRange.BaseShaderRegister = vertexShader->NumSamplers + vertexShader->NumStorageBuffers; - descriptorRange.RegisterSpace = 0; - descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; - descriptorRanges[rangeCount] = descriptorRange; - - rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - rootParameter.DescriptorTable.NumDescriptorRanges = 1; - rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount]; - rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX; - rootParameters[parameterCount] = rootParameter; - d3d12GraphicsRootSignature->VertexStorageBufferRootIndex = parameterCount; - rangeCount += 1; - parameterCount += 1; - } - - // Vertex Uniforms - for (uint32 i = 0; i < vertexShader->NumUniformBuffers; ++i) - { - rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; - rootParameter.Descriptor.ShaderRegister = i; - rootParameter.Descriptor.RegisterSpace = 1; - rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX; - rootParameters[parameterCount] = rootParameter; - d3d12GraphicsRootSignature->VertexUniformBufferRootIndex[i] = parameterCount; - parameterCount += 1; - } - - if (fragmentShader->NumSamplers) - { - // Fragment Samplers - descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER; - descriptorRange.NumDescriptors = fragmentShader->NumSamplers; - descriptorRange.BaseShaderRegister = 0; - descriptorRange.RegisterSpace = 2; - descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; - descriptorRanges[rangeCount] = descriptorRange; - - rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - rootParameter.DescriptorTable.NumDescriptorRanges = 1; - rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount]; - rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; - rootParameters[parameterCount] = rootParameter; - d3d12GraphicsRootSignature->FragmentSamplerRootIndex = parameterCount; - rangeCount += 1; - parameterCount += 1; - - descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - descriptorRange.NumDescriptors = fragmentShader->NumSamplers; - descriptorRange.BaseShaderRegister = 0; - descriptorRange.RegisterSpace = 2; - descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; - descriptorRanges[rangeCount] = descriptorRange; - - rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - rootParameter.DescriptorTable.NumDescriptorRanges = 1; - rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount]; - rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; - rootParameters[parameterCount] = rootParameter; - d3d12GraphicsRootSignature->FragmentSamplerTextureRootIndex = parameterCount; - rangeCount += 1; - parameterCount += 1; - } - - if (fragmentShader->NumStorageTextures) - { - // Fragment Storage Textures - descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - descriptorRange.NumDescriptors = fragmentShader->NumStorageTextures; - descriptorRange.BaseShaderRegister = fragmentShader->NumSamplers; - descriptorRange.RegisterSpace = 2; - descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; - descriptorRanges[rangeCount] = descriptorRange; - - rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - rootParameter.DescriptorTable.NumDescriptorRanges = 1; - rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount]; - rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; - rootParameters[parameterCount] = rootParameter; - d3d12GraphicsRootSignature->FragmentStorageTextureRootIndex = parameterCount; - rangeCount += 1; - parameterCount += 1; - } - - if (fragmentShader->NumStorageBuffers) - { - // Fragment Storage Buffers - descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - descriptorRange.NumDescriptors = fragmentShader->NumStorageBuffers; - descriptorRange.BaseShaderRegister = fragmentShader->NumSamplers + fragmentShader->NumStorageTextures; - descriptorRange.RegisterSpace = 2; - descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; - descriptorRanges[rangeCount] = descriptorRange; - - rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - rootParameter.DescriptorTable.NumDescriptorRanges = 1; - rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount]; - rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; - rootParameters[parameterCount] = rootParameter; - d3d12GraphicsRootSignature->FragmentStorageBufferRootIndex = parameterCount; - rangeCount += 1; - parameterCount += 1; - } - - // Fragment Uniforms - for (uint32 i = 0; i < fragmentShader->NumUniformBuffers; ++i) - { - rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; - rootParameter.Descriptor.ShaderRegister = i; - rootParameter.Descriptor.RegisterSpace = 3; - rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; - rootParameters[parameterCount] = rootParameter; - d3d12GraphicsRootSignature->FragmentUniformBufferRootIndex[i] = parameterCount; - parameterCount += 1; - } - - Assert(parameterCount <= kMaxRootSignatureParameters); - Assert(rangeCount <= kMaxRootSignatureParameters); - - // Create the root signature description - D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc; - rootSignatureDesc.NumParameters = parameterCount; - rootSignatureDesc.pParameters = rootParameters; - rootSignatureDesc.NumStaticSamplers = 0; - rootSignatureDesc.pStaticSamplers = nullptr; - rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; - - // Serialize the root signature - ID3DBlob* serializedRootSignature; - ID3DBlob* errorBlob; - HRESULT res = d3d12Driver->D3D12SerializeRootSignatureFct(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1_0, - &serializedRootSignature, &errorBlob); - if (FAILED(res)) - { - if (errorBlob) - { - auto errorBuffer = ID3D10Blob_GetBufferPointer(errorBlob); - LogError(LogCategory::Graphics, "Failed to serialize RootSignature: %s", errorBuffer); - ID3D10Blob_Release(errorBlob); - } - DestroyGraphicsRootSignature(d3d12GraphicsRootSignature); - return NULL; - } - - // Create the root signature - ID3D12RootSignature* rootSignature; - res = ID3D12Device_CreateRootSignature(d3d12Driver->D3D12Device, 0, ID3D10Blob_GetBufferPointer(serializedRootSignature), - ID3D10Blob_GetBufferSize(serializedRootSignature), - IID_ID3D12RootSignature, reinterpret_cast(&rootSignature)); - if (FAILED(res)) - { - if (errorBlob) - { - LogError(LogCategory::Graphics, "Failed to create RootSignature: %s", - (const char*)ID3D10Blob_GetBufferPointer(errorBlob)); - ID3D10Blob_Release(errorBlob); - } - DestroyGraphicsRootSignature(d3d12GraphicsRootSignature); - return nullptr; - } - - d3d12GraphicsRootSignature->Handle = rootSignature; - return d3d12GraphicsRootSignature; - } - - void DestroyGraphicsRootSignature(NonNullPtr rootSignature) - { - if (!rootSignature) - { - return; - } - if (rootSignature->Handle) - { - ID3D12RootSignature_Release(rootSignature->Handle); - } - Free(rootSignature.Get()); - } - void CopyShader(NonNullPtr destination, NonNullPtr source) { D3D12Shader* src = source.Get(); @@ -680,14 +402,8 @@ namespace Juliet::D3D12 psoDesc.NodeMask = 0; - D3D12GraphicsRootSignature* rootSignature = CreateGraphicsRootSignature(d3d12Driver, vertexShader, fragmentShader); - if (rootSignature == nullptr) - { - Internal::ReleaseGraphicsPipeline(pipeline); - return nullptr; - } - pipeline->RootSignature = rootSignature; - psoDesc.pRootSignature = rootSignature->Handle; + pipeline->RootSignature = d3d12Driver->BindlessRootSignature; + psoDesc.pRootSignature = d3d12Driver->BindlessRootSignature->Handle; ID3D12PipelineState* pipelineState; HRESULT res = ID3D12Device_CreateGraphicsPipelineState(d3d12Driver->D3D12Device, &psoDesc, IID_ID3D12PipelineState, @@ -774,20 +490,13 @@ namespace Juliet::D3D12 fragmentShader = d3d12GraphicsPipeline->FragmentShaderCache; } - // Recreate a new root signature and pipeline state - D3D12GraphicsRootSignature* rootSignature = CreateGraphicsRootSignature(d3d12Driver, vertexShader, fragmentShader); - if (rootSignature == nullptr) - { - return false; - } - auto psoDesc = d3d12GraphicsPipeline->PSODescTemplate; psoDesc.VS.pShaderBytecode = vertexShader->ByteCode.Data; psoDesc.VS.BytecodeLength = vertexShader->ByteCode.Size; psoDesc.PS.pShaderBytecode = fragmentShader->ByteCode.Data; psoDesc.PS.BytecodeLength = fragmentShader->ByteCode.Size; - psoDesc.pRootSignature = rootSignature->Handle; + psoDesc.pRootSignature = d3d12Driver->BindlessRootSignature->Handle; ID3D12PipelineState* pipelineState; HRESULT res = ID3D12Device_CreateGraphicsPipelineState(d3d12Driver->D3D12Device, &psoDesc, IID_ID3D12PipelineState, @@ -815,12 +524,6 @@ namespace Juliet::D3D12 } d3d12GraphicsPipeline->PipelineState = pipelineState; - if (d3d12GraphicsPipeline->RootSignature) - { - DestroyGraphicsRootSignature(d3d12GraphicsPipeline->RootSignature); - } - d3d12GraphicsPipeline->RootSignature = rootSignature; - if (vertexShader != d3d12GraphicsPipeline->VertexShaderCache) { CopyShader(d3d12GraphicsPipeline->VertexShaderCache, vertexShader); @@ -842,7 +545,6 @@ namespace Juliet::D3D12 { ID3D12PipelineState_Release(d3d12GraphicsPipeline->PipelineState); } - DestroyGraphicsRootSignature(d3d12GraphicsPipeline->RootSignature); #if ALLOW_SHADER_HOT_RELOAD SafeFree(d3d12GraphicsPipeline->VertexShaderCache); diff --git a/Juliet/src/Graphics/D3D12/D3D12GraphicsPipeline.h b/Juliet/src/Graphics/D3D12/D3D12GraphicsPipeline.h index b9749ab..23993ba 100644 --- a/Juliet/src/Graphics/D3D12/D3D12GraphicsPipeline.h +++ b/Juliet/src/Graphics/D3D12/D3D12GraphicsPipeline.h @@ -18,20 +18,6 @@ namespace Juliet::D3D12 struct D3D12GraphicsRootSignature { ID3D12RootSignature* Handle; - - int32 VertexSamplerRootIndex; - int32 VertexSamplerTextureRootIndex; - int32 VertexStorageTextureRootIndex; - int32 VertexStorageBufferRootIndex; - - int32 VertexUniformBufferRootIndex[GPUDriver::kMaxUniformBuffersPerStage]; - - int32 FragmentSamplerRootIndex; - int32 FragmentSamplerTextureRootIndex; - int32 FragmentStorageTextureRootIndex; - int32 FragmentStorageBufferRootIndex; - - int32 FragmentUniformBufferRootIndex[GPUDriver::kMaxUniformBuffersPerStage]; }; struct D3D12GraphicsPipeline diff --git a/Juliet/src/Graphics/D3D12/D3D12RenderPass.cpp b/Juliet/src/Graphics/D3D12/D3D12RenderPass.cpp index 26bc840..1b1f14b 100644 --- a/Juliet/src/Graphics/D3D12/D3D12RenderPass.cpp +++ b/Juliet/src/Graphics/D3D12/D3D12RenderPass.cpp @@ -197,6 +197,9 @@ namespace Juliet::D3D12 d3d12CommandList->CurrentGraphicsPipeline = pipeline; + // Set the Descriptor heap + Internal::SetDescriptorHeaps(d3d12CommandList); + // Set the pipeline state ID3D12GraphicsCommandList_SetPipelineState(d3d12CommandList->GraphicsCommandList.CommandList, pipeline->PipelineState); ID3D12GraphicsCommandList_SetGraphicsRootSignature(d3d12CommandList->GraphicsCommandList.CommandList, diff --git a/Juliet/src/Graphics/GraphicsDevice.h b/Juliet/src/Graphics/GraphicsDevice.h index 1ea27d4..91bbca3 100644 --- a/Juliet/src/Graphics/GraphicsDevice.h +++ b/Juliet/src/Graphics/GraphicsDevice.h @@ -34,6 +34,9 @@ namespace Juliet static constexpr uint8 kMaxColorTargetInfo = 4; static constexpr uint8 kMaxUniformBuffersPerStage = 4; static constexpr uint8 kMaxVertexBuffers = 16; + + static constexpr uint32 kCBV_SRV_UAV_HeapDescriptorCount = 65536; + static constexpr uint32 kSampler_HeapDescriptorCount = 2048; }; struct GraphicsDevice diff --git a/JulietShaderCompiler/ShaderCompiler.cpp b/JulietShaderCompiler/ShaderCompiler.cpp index 3fd8aed..b7e11cf 100644 --- a/JulietShaderCompiler/ShaderCompiler.cpp +++ b/JulietShaderCompiler/ShaderCompiler.cpp @@ -96,19 +96,19 @@ namespace case ShaderStage::Vertex: { args[argCount++] = const_cast(L"-T"); - args[argCount++] = const_cast(L"vs_6_0"); + args[argCount++] = const_cast(L"vs_6_6"); break; } case ShaderStage::Fragment: { args[argCount++] = const_cast(L"-T"); - args[argCount++] = const_cast(L"ps_6_0"); + args[argCount++] = const_cast(L"ps_6_6"); break; } case ShaderStage::Compute: { args[argCount++] = const_cast(L"-T"); - args[argCount++] = const_cast(L"cs_6_0"); + args[argCount++] = const_cast(L"cs_6_6"); break; } case ShaderStage::Invalid: