Bindless resource first step
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -32,6 +32,13 @@ namespace Juliet::D3D12
|
||||
bool Staging : 1;
|
||||
};
|
||||
|
||||
struct D3D12DescriptorHeapPool
|
||||
{
|
||||
D3D12DescriptorHeap** Heaps;
|
||||
size_t Capacity;
|
||||
size_t Count;
|
||||
};
|
||||
|
||||
struct D3D12StagingDescriptorPool
|
||||
{
|
||||
D3D12DescriptorHeap** Heaps;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user