Bindless resource first step

This commit is contained in:
2025-03-24 22:19:52 -04:00
parent d8c36b7715
commit 2d3a075eb6
10 changed files with 316 additions and 330 deletions

View File

@@ -1,3 +1,4 @@
#include <D3D12CommandList.h>
#include <pch.h>
#include <Core/Memory/Allocator.h>
@@ -367,6 +368,89 @@ namespace Juliet::D3D12
namespace Internal
{
namespace
{
D3D12DescriptorHeap* AcquireDescriptorHeapFromPool(NonNullPtr<D3D12CommandList> 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> 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<D3D12DescriptorHeap**>(Realloc(pool->Heaps, pool->Capacity * sizeof(D3D12DescriptorHeap*)));
}
pool->Heaps[pool->Count] = heap;
pool->Count += 1;
}
} // namespace
void SetDescriptorHeaps(NonNullPtr<D3D12CommandList> 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<D3D12CommandList> 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)
{

View File

@@ -2,6 +2,7 @@
#include <Core/Common/NonNullPtr.h>
#include <Core/Math/Shape.h>
#include <D3D12Common.h>
#include <D3D12GraphicsPipeline.h>
#include <Graphics/D3D12/D3D12Includes.h>
#include <Graphics/GraphicsDevice.h>
@@ -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<D3D12CommandList> commandList);
extern void DestroyCommandList(NonNullPtr<D3D12CommandList> commandList);
extern bool CleanCommandList(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12CommandList> commandList, bool cancel);

View File

@@ -32,6 +32,13 @@ namespace Juliet::D3D12
bool Staging : 1;
};
struct D3D12DescriptorHeapPool
{
D3D12DescriptorHeap** Heaps;
size_t Capacity;
size_t Count;
};
struct D3D12StagingDescriptorPool
{
D3D12DescriptorHeap** Heaps;

View File

@@ -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> d3d12Driver)
{
auto d3d12GraphicsRootSignature =
static_cast<D3D12GraphicsRootSignature*>(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<void**>(&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<D3D12Driver> driver)
{
@@ -355,7 +476,7 @@ namespace Juliet::D3D12
void DestroyDriver_Internal(NonNullPtr<D3D12Driver> 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<PFN_D3D12_SERIALIZE_ROOT_SIGNATURE>(
LoadFunction(driver->D3D12DLL, D3D12_SERIALIZE_ROOT_SIGNATURE_FUNC));
if (driver->D3D12SerializeRootSignatureFct == nullptr)
driver->D3D12SerializeVersionedRootSignatureFct = reinterpret_cast<PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE>(
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<D3D12DescriptorHeap**>(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;

View File

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

View File

@@ -319,284 +319,6 @@ namespace Juliet::D3D12
return true;
}
void DestroyGraphicsRootSignature(NonNullPtr<D3D12GraphicsRootSignature> rootSignature);
constexpr size_t kMaxRootSignatureParameters = 64;
D3D12GraphicsRootSignature* CreateGraphicsRootSignature(NonNullPtr<D3D12Driver> d3d12Driver,
NonNullPtr<D3D12Shader> vertexShader,
NonNullPtr<D3D12Shader> 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<D3D12GraphicsRootSignature*>(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<void**>(&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<D3D12GraphicsRootSignature> rootSignature)
{
if (!rootSignature)
{
return;
}
if (rootSignature->Handle)
{
ID3D12RootSignature_Release(rootSignature->Handle);
}
Free(rootSignature.Get());
}
void CopyShader(NonNullPtr<D3D12Shader> destination, NonNullPtr<D3D12Shader> 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);

View File

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

View File

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

View File

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

View File

@@ -96,19 +96,19 @@ namespace
case ShaderStage::Vertex:
{
args[argCount++] = const_cast<LPCWSTR>(L"-T");
args[argCount++] = const_cast<LPCWSTR>(L"vs_6_0");
args[argCount++] = const_cast<LPCWSTR>(L"vs_6_6");
break;
}
case ShaderStage::Fragment:
{
args[argCount++] = const_cast<LPCWSTR>(L"-T");
args[argCount++] = const_cast<LPCWSTR>(L"ps_6_0");
args[argCount++] = const_cast<LPCWSTR>(L"ps_6_6");
break;
}
case ShaderStage::Compute:
{
args[argCount++] = const_cast<LPCWSTR>(L"-T");
args[argCount++] = const_cast<LPCWSTR>(L"cs_6_0");
args[argCount++] = const_cast<LPCWSTR>(L"cs_6_6");
break;
}
case ShaderStage::Invalid: