|
|
@@ -1,5 +1,7 @@
|
|
|
#include "DX12Shader.h"
|
|
|
|
|
|
+#include "DX12Texture.h"
|
|
|
+#include "DX12TLAS.h"
|
|
|
#include "Logging.h"
|
|
|
|
|
|
using namespace Framework;
|
|
|
@@ -18,16 +20,47 @@ Framework::DX12ShaderSignature::~DX12ShaderSignature()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void Framework::DX12ShaderSignature::addRegisterUsage(
|
|
|
- DX12ShaderRegister registerType, int registerIndex)
|
|
|
-{
|
|
|
- addRegisterUsage(registerType, registerIndex, 0);
|
|
|
-}
|
|
|
-
|
|
|
void Framework::DX12ShaderSignature::addRegisterUsage(
|
|
|
DX12ShaderRegister registerType, int registerIndex, int spaceIndex)
|
|
|
{
|
|
|
- registerUsages.add({registerType, registerIndex, spaceIndex});
|
|
|
+ // register usages sould be sorted by registerType -> spaceIndex ->
|
|
|
+ // registerIndex
|
|
|
+ ArrayIterator<DX12ShaderRegisterUsage> it = registerUsages.begin();
|
|
|
+ bool found = 0;
|
|
|
+ while (it)
|
|
|
+ {
|
|
|
+ const DX12ShaderRegisterUsage& usage = it.val();
|
|
|
+ if (usage.registerType > registerType)
|
|
|
+ {
|
|
|
+ found = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (usage.registerType == registerType)
|
|
|
+ {
|
|
|
+ if (usage.spaceIndex > spaceIndex)
|
|
|
+ {
|
|
|
+ found = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (usage.spaceIndex == spaceIndex)
|
|
|
+ {
|
|
|
+ if (usage.registerIndex >= registerIndex)
|
|
|
+ {
|
|
|
+ found = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ++it;
|
|
|
+ }
|
|
|
+ if (found)
|
|
|
+ {
|
|
|
+ it.addBefore({registerType, registerIndex, spaceIndex});
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ registerUsages.add({registerType, registerIndex, spaceIndex});
|
|
|
+ }
|
|
|
changed = 1;
|
|
|
}
|
|
|
|
|
|
@@ -52,8 +85,10 @@ void Framework::DX12ShaderSignature::createSignature(ID3D12Device5* zDevice,
|
|
|
D3D12_DESCRIPTOR_RANGE* descriptorRanges
|
|
|
= new D3D12_DESCRIPTOR_RANGE[registerUsages.getEntryCount()];
|
|
|
int index = 0;
|
|
|
- for (const auto& usage : registerUsages)
|
|
|
+ ArrayIterator<DX12ShaderRegisterUsage> it = registerUsages.begin();
|
|
|
+ while (it)
|
|
|
{
|
|
|
+ const auto& usage = it.val();
|
|
|
D3D12_DESCRIPTOR_RANGE* range = &descriptorRanges[index];
|
|
|
switch (usage.registerType)
|
|
|
{
|
|
|
@@ -71,13 +106,21 @@ void Framework::DX12ShaderSignature::createSignature(ID3D12Device5* zDevice,
|
|
|
<< usage.registerType;
|
|
|
range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
|
|
}
|
|
|
- range->NumDescriptors
|
|
|
- = 1; // TODO: optimize when multiple descriptors are used in a row
|
|
|
- // e.g. u0, u1, u2 with the same range then NumDescriptors can
|
|
|
- // be 3 for u0 and u1 and u2 would not be needed in this array
|
|
|
+ ArrayIterator<DX12ShaderRegisterUsage> next = it.next();
|
|
|
+ int size = 1;
|
|
|
+ while (next && next.val().registerType == usage.registerType
|
|
|
+ && next.val().spaceIndex == usage.spaceIndex
|
|
|
+ && next.val().registerIndex == usage.registerIndex + size)
|
|
|
+ {
|
|
|
+ ++size;
|
|
|
+ it = next;
|
|
|
+ ++next;
|
|
|
+ }
|
|
|
+ range->NumDescriptors = size;
|
|
|
range->BaseShaderRegister = usage.registerIndex;
|
|
|
range->RegisterSpace = usage.spaceIndex;
|
|
|
range->OffsetInDescriptorsFromTableStart = index;
|
|
|
+ ++it;
|
|
|
index++;
|
|
|
}
|
|
|
descriptorTable.DescriptorTable.pDescriptorRanges = descriptorRanges;
|
|
|
@@ -115,6 +158,17 @@ ID3D12RootSignature* Framework::DX12ShaderSignature::zSignature() const
|
|
|
return signature;
|
|
|
}
|
|
|
|
|
|
+const Array<DX12ShaderRegisterUsage>&
|
|
|
+Framework::DX12ShaderSignature::getRegisterUsagesOrder() const
|
|
|
+{
|
|
|
+ return registerUsages;
|
|
|
+}
|
|
|
+
|
|
|
+ShaderHeap* Framework::DX12ShaderSignature::createShaderHeap()
|
|
|
+{
|
|
|
+ return new ShaderHeap(dynamic_cast<DX12ShaderSignature*>(getThis()));
|
|
|
+}
|
|
|
+
|
|
|
Framework::DX12ShaderFunction::DX12ShaderFunction(
|
|
|
const Text& functionName, DX12ShaderSignature* signature)
|
|
|
: ReferenceCounter(),
|
|
|
@@ -611,9 +665,9 @@ void Framework::DX12Pipeline::createPipelineState(ID3D12Device5* zDevice,
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- wchar_t** functionAndHitGroupNames
|
|
|
- = new wchar_t*[functionsWithoutHitGroups.getEntryCount()
|
|
|
- + hitGroups.getEntryCount()];
|
|
|
+ const wchar_t** functionAndHitGroupNames
|
|
|
+ = new const wchar_t*[functionsWithoutHitGroups.getEntryCount()
|
|
|
+ + hitGroups.getEntryCount()];
|
|
|
int nameIndex = 0;
|
|
|
for (const DX12ShaderFunction* function : functionsWithoutHitGroups)
|
|
|
{
|
|
|
@@ -776,4 +830,205 @@ void Framework::DX12Pipeline::createPipelineState(ID3D12Device5* zDevice,
|
|
|
ID3D12StateObject* Framework::DX12Pipeline::zPipelineState() const
|
|
|
{
|
|
|
return pipelineState;
|
|
|
-}
|
|
|
+}
|
|
|
+
|
|
|
+Framework::ShaderHeap::ShaderHeap(DX12ShaderSignature* signature)
|
|
|
+ : ReferenceCounter(),
|
|
|
+ signature(signature),
|
|
|
+ descriptorHeap(0),
|
|
|
+ lastDescriptorHeapSize(0)
|
|
|
+{}
|
|
|
+
|
|
|
+Framework::ShaderHeap::~ShaderHeap()
|
|
|
+{
|
|
|
+ signature->release();
|
|
|
+ if (descriptorHeap)
|
|
|
+ {
|
|
|
+ descriptorHeap->Release();
|
|
|
+ }
|
|
|
+ for (const DX12ShaderRegisterInput* input : registerInputs)
|
|
|
+ {
|
|
|
+ input->inputResource->release();
|
|
|
+ delete input;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void Framework::ShaderHeap::setRegisterInput(DX12ShaderRegister registerType,
|
|
|
+ int registerIndex,
|
|
|
+ int spaceIndex,
|
|
|
+ ReferenceCounter* inputResource)
|
|
|
+{
|
|
|
+ for (DX12ShaderRegisterInput* input : registerInputs)
|
|
|
+ {
|
|
|
+ if (input->registerIndex == registerIndex
|
|
|
+ && input->spaceIndex == spaceIndex
|
|
|
+ && input->registerType == registerType)
|
|
|
+ {
|
|
|
+ input->inputResource->release();
|
|
|
+ input->inputResource = inputResource->getThis();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ bool found = 0;
|
|
|
+ for (const DX12ShaderRegisterUsage& usage :
|
|
|
+ signature->getRegisterUsagesOrder())
|
|
|
+ {
|
|
|
+ if (usage.registerIndex == registerIndex
|
|
|
+ && usage.spaceIndex == spaceIndex
|
|
|
+ && usage.registerType == registerType)
|
|
|
+ {
|
|
|
+ found = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (found)
|
|
|
+ {
|
|
|
+ registerInputs.add(new DX12ShaderRegisterInput{
|
|
|
+ registerType, registerIndex, spaceIndex, inputResource->getThis()});
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Logging::error() << "Register type " << registerType
|
|
|
+ << ", register index " << registerIndex
|
|
|
+ << ", space index " << spaceIndex
|
|
|
+ << " is not used in the shader signature. The given "
|
|
|
+ "input will be ignored.";
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void Framework::ShaderHeap::setRegisterInput(
|
|
|
+ Texture* zTexture, int registerIndex, int spaceIndex)
|
|
|
+{
|
|
|
+ setRegisterInput(DX12_SHADER_REGISTER_U_UNORDERED_ACCESS,
|
|
|
+ registerIndex,
|
|
|
+ spaceIndex,
|
|
|
+ zTexture);
|
|
|
+}
|
|
|
+
|
|
|
+void Framework::ShaderHeap::setRegisterInput(
|
|
|
+ DXBuffer* zBuffer, int registerIndex, int spaceIndex)
|
|
|
+{
|
|
|
+ setRegisterInput(DX12_SHADER_REGISTER_B_CONST_BUFFER,
|
|
|
+ registerIndex,
|
|
|
+ spaceIndex,
|
|
|
+ zBuffer);
|
|
|
+}
|
|
|
+
|
|
|
+void Framework::ShaderHeap::setRegisterInput(
|
|
|
+ DX12TLAS* zTLAS, int registerIndex, int spaceIndex)
|
|
|
+{
|
|
|
+ setRegisterInput(DX12_SHADER_REGISTER_T_SHADER_RESOURCE,
|
|
|
+ registerIndex,
|
|
|
+ spaceIndex,
|
|
|
+ zTLAS);
|
|
|
+}
|
|
|
+
|
|
|
+void Framework::ShaderHeap::updateDescriptorHeap(ID3D12Device5* zDevice)
|
|
|
+{
|
|
|
+ const Array<DX12ShaderRegisterUsage>& registerUsages
|
|
|
+ = signature->getRegisterUsagesOrder();
|
|
|
+ if (!descriptorHeap
|
|
|
+ || lastDescriptorHeapSize
|
|
|
+ != signature->getRegisterUsagesOrder().getEntryCount())
|
|
|
+ {
|
|
|
+ if (descriptorHeap)
|
|
|
+ {
|
|
|
+ descriptorHeap->Release();
|
|
|
+ }
|
|
|
+ D3D12_DESCRIPTOR_HEAP_DESC desc = {};
|
|
|
+ desc.NumDescriptors = registerUsages.getEntryCount();
|
|
|
+ desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
|
|
+ desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
|
|
+ desc.NodeMask = 0;
|
|
|
+
|
|
|
+ HRESULT r = zDevice->CreateDescriptorHeap(
|
|
|
+ &desc, __uuidof(ID3D12DescriptorHeap), (void**)&descriptorHeap);
|
|
|
+ lastDescriptorHeapSize = registerUsages.getEntryCount();
|
|
|
+ }
|
|
|
+
|
|
|
+ D3D12_CPU_DESCRIPTOR_HANDLE descriptorHeapHandle
|
|
|
+ = descriptorHeap->GetCPUDescriptorHandleForHeapStart();
|
|
|
+ ArrayIterator<DX12ShaderRegisterUsage> it = registerUsages.begin();
|
|
|
+ while (it)
|
|
|
+ {
|
|
|
+ const DX12ShaderRegisterUsage& usage = it.val();
|
|
|
+ ArrayIterator<DX12ShaderRegisterInput*> inputIt
|
|
|
+ = registerInputs.begin();
|
|
|
+ bool found = 0;
|
|
|
+ while (inputIt)
|
|
|
+ {
|
|
|
+ if (inputIt->registerType == usage.registerType
|
|
|
+ && inputIt->registerIndex == usage.registerIndex
|
|
|
+ && inputIt->spaceIndex == usage.spaceIndex)
|
|
|
+ {
|
|
|
+ switch (inputIt->registerType)
|
|
|
+ {
|
|
|
+ case DX12_SHADER_REGISTER_B_CONST_BUFFER:
|
|
|
+ D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
|
|
|
+ DX12Buffer* buffer
|
|
|
+ = dynamic_cast<DX12Buffer*>(inputIt->inputResource);
|
|
|
+ cbvDesc.BufferLocation
|
|
|
+ = buffer->zBuffer()->GetGPUVirtualAddress();
|
|
|
+ cbvDesc.SizeInBytes = buffer->getElementCount()
|
|
|
+ * buffer->getElementLength();
|
|
|
+ zDevice->CreateConstantBufferView(
|
|
|
+ &cbvDesc, descriptorHeapHandle);
|
|
|
+ break;
|
|
|
+ case DX12_SHADER_REGISTER_T_SHADER_RESOURCE:
|
|
|
+ D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
|
|
+ srvDesc.Format = DXGI_FORMAT_UNKNOWN;
|
|
|
+ srvDesc.ViewDimension
|
|
|
+ = D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE;
|
|
|
+ srvDesc.Shader4ComponentMapping
|
|
|
+ = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
|
|
+ srvDesc.RaytracingAccelerationStructure.Location
|
|
|
+ = dynamic_cast<DX12TLAS*>(inputIt->inputResource)
|
|
|
+ ->zResultBuffer()
|
|
|
+ ->zBuffer()
|
|
|
+ ->GetGPUVirtualAddress();
|
|
|
+ zDevice->CreateShaderResourceView(
|
|
|
+ 0, &srvDesc, descriptorHeapHandle);
|
|
|
+ break;
|
|
|
+ case DX12_SHADER_REGISTER_U_UNORDERED_ACCESS:
|
|
|
+ D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
|
|
|
+ uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
|
|
|
+ uavDesc.Format = DXGI_FORMAT_UNKNOWN;
|
|
|
+ uavDesc.Texture2D.MipSlice = 0;
|
|
|
+ uavDesc.Texture2D.PlaneSlice = 0;
|
|
|
+ zDevice->CreateUnorderedAccessView(
|
|
|
+ dynamic_cast<DX12Texture*>(inputIt->inputResource)
|
|
|
+ ->zResource(),
|
|
|
+ 0,
|
|
|
+ &uavDesc,
|
|
|
+ descriptorHeapHandle);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ Logging::error()
|
|
|
+ << "Unknown register type for descriptor heap: "
|
|
|
+ << inputIt->registerType;
|
|
|
+ }
|
|
|
+ found = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ ++inputIt;
|
|
|
+ }
|
|
|
+ if (!found)
|
|
|
+ {
|
|
|
+ Logging::error()
|
|
|
+ << "No input resource found for register type "
|
|
|
+ << usage.registerType << ", register index "
|
|
|
+ << usage.registerIndex << ", space index " << usage.spaceIndex
|
|
|
+ << ". This will result in an uninitialized descriptor in the "
|
|
|
+ "descriptor heap. Access to the register in the shader "
|
|
|
+ "might lead to undefined behaviour.";
|
|
|
+ }
|
|
|
+ descriptorHeapHandle.ptr += zDevice->GetDescriptorHandleIncrementSize(
|
|
|
+ D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
|
|
+ ++it;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+ID3D12DescriptorHeap* Framework::ShaderHeap::zDescriptorHeap() const
|
|
|
+{
|
|
|
+ return descriptorHeap;
|
|
|
+}
|