|
|
@@ -9,7 +9,8 @@ using namespace Framework;
|
|
|
Framework::DX12ShaderSignature::DX12ShaderSignature()
|
|
|
: ReferenceCounter(),
|
|
|
signature(0),
|
|
|
- changed(1)
|
|
|
+ changed(1),
|
|
|
+ shaderBindingTableParamCount(0)
|
|
|
{}
|
|
|
|
|
|
Framework::DX12ShaderSignature::~DX12ShaderSignature()
|
|
|
@@ -18,13 +19,50 @@ Framework::DX12ShaderSignature::~DX12ShaderSignature()
|
|
|
{
|
|
|
signature->Release();
|
|
|
}
|
|
|
+ for (DX12ShaderRegisterUsage* usage : descriptorHeapBindings)
|
|
|
+ {
|
|
|
+ delete usage;
|
|
|
+ }
|
|
|
+ for (DX12ShaderRegisterUsage* usage : bindingTableBindings)
|
|
|
+ {
|
|
|
+ delete usage;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-void Framework::DX12ShaderSignature::addRegisterUsageLinkedToShaderBindingTable(
|
|
|
+int* Framework::DX12ShaderSignature::addRegisterUsageLinkedToShaderBindingTable(
|
|
|
DX12ShaderRegister registerType, int registerIndex, int spaceIndex)
|
|
|
{
|
|
|
- addRegisterUsageLinkedToDescriptorHeap(
|
|
|
- -1, registerType, registerIndex, spaceIndex);
|
|
|
+ for (DX12ShaderRegisterUsage* usage : descriptorHeapBindings)
|
|
|
+ {
|
|
|
+ if (usage->registerType == registerType
|
|
|
+ && usage->registerIndex == registerIndex
|
|
|
+ && usage->spaceIndex == spaceIndex)
|
|
|
+ {
|
|
|
+ Logging::error()
|
|
|
+ << "Duplicate register usage in root signature: "
|
|
|
+ << registerType << " " << registerIndex << " " << spaceIndex;
|
|
|
+ throw std::invalid_argument(
|
|
|
+ "Duplicate register usage in root signature");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (DX12ShaderRegisterUsage* usage : bindingTableBindings)
|
|
|
+ {
|
|
|
+ if (usage->registerType == registerType
|
|
|
+ && usage->registerIndex == registerIndex
|
|
|
+ && usage->spaceIndex == spaceIndex)
|
|
|
+ {
|
|
|
+ Logging::error()
|
|
|
+ << "Duplicate register usage in root signature: "
|
|
|
+ << registerType << " " << registerIndex << " " << spaceIndex;
|
|
|
+ throw std::invalid_argument(
|
|
|
+ "Duplicate register usage in root signature");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ DX12ShaderRegisterUsage* usage = new DX12ShaderRegisterUsage{
|
|
|
+ registerType, registerIndex, spaceIndex, -1, 0};
|
|
|
+ bindingTableBindings.add(usage);
|
|
|
+ changed = 1;
|
|
|
+ return &usage->bindingTableIndex;
|
|
|
}
|
|
|
|
|
|
void Framework::DX12ShaderSignature::addRegisterUsageLinkedToDescriptorHeap(
|
|
|
@@ -33,28 +71,45 @@ void Framework::DX12ShaderSignature::addRegisterUsageLinkedToDescriptorHeap(
|
|
|
int registerIndex,
|
|
|
int spaceIndex)
|
|
|
{
|
|
|
- // register usages sould be sorted by registerType -> spaceIndex ->
|
|
|
+ if (descriptorHeapIndex < 0)
|
|
|
+ {
|
|
|
+ Logging::error() << "descriptorHeapIndex can not be below 0";
|
|
|
+ throw std::invalid_argument("descriptorHeapIndex can not be below 0");
|
|
|
+ }
|
|
|
+ for (DX12ShaderRegisterUsage* usage : descriptorHeapBindings)
|
|
|
+ {
|
|
|
+ if (usage->registerType == registerType
|
|
|
+ && usage->registerIndex == registerIndex
|
|
|
+ && usage->spaceIndex == spaceIndex)
|
|
|
+ {
|
|
|
+ Logging::error()
|
|
|
+ << "Duplicate register usage in root signature: "
|
|
|
+ << registerType << " " << registerIndex << " " << spaceIndex;
|
|
|
+ throw std::invalid_argument(
|
|
|
+ "Duplicate register usage in root signature");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // descriptor heap bindings sould be sorted by registerType -> spaceIndex ->
|
|
|
// registerIndex
|
|
|
- ArrayIterator<DX12ShaderRegisterUsage> it = registerUsages.begin();
|
|
|
+ ArrayIterator<DX12ShaderRegisterUsage*> it = descriptorHeapBindings.begin();
|
|
|
bool found = 0;
|
|
|
while (it)
|
|
|
{
|
|
|
- const DX12ShaderRegisterUsage& usage = it.val();
|
|
|
- if (usage.registerType > registerType)
|
|
|
+ if (it->registerType > registerType)
|
|
|
{
|
|
|
found = 1;
|
|
|
break;
|
|
|
}
|
|
|
- if (usage.registerType == registerType)
|
|
|
+ if (it->registerType == registerType)
|
|
|
{
|
|
|
- if (usage.spaceIndex > spaceIndex)
|
|
|
+ if (it->spaceIndex > spaceIndex)
|
|
|
{
|
|
|
found = 1;
|
|
|
break;
|
|
|
}
|
|
|
- if (usage.spaceIndex == spaceIndex)
|
|
|
+ if (it->spaceIndex == spaceIndex)
|
|
|
{
|
|
|
- if (usage.registerIndex >= registerIndex)
|
|
|
+ if (it->registerIndex >= registerIndex)
|
|
|
{
|
|
|
found = 1;
|
|
|
break;
|
|
|
@@ -65,20 +120,21 @@ void Framework::DX12ShaderSignature::addRegisterUsageLinkedToDescriptorHeap(
|
|
|
}
|
|
|
if (found)
|
|
|
{
|
|
|
- if (it.val().registerIndex == registerIndex)
|
|
|
+ if (it->registerIndex == registerIndex)
|
|
|
{
|
|
|
Logging::error()
|
|
|
<< "Duplicate register usage in root signature: "
|
|
|
<< registerType << " " << registerIndex << " " << spaceIndex;
|
|
|
- return;
|
|
|
+ throw std::invalid_argument(
|
|
|
+ "Duplicate register usage in root signature");
|
|
|
}
|
|
|
- it.addBefore(
|
|
|
- {registerType, registerIndex, spaceIndex, descriptorHeapIndex});
|
|
|
+ it.addBefore(new DX12ShaderRegisterUsage{
|
|
|
+ registerType, registerIndex, spaceIndex, descriptorHeapIndex, 0});
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- registerUsages.add(
|
|
|
- {registerType, registerIndex, spaceIndex, descriptorHeapIndex});
|
|
|
+ descriptorHeapBindings.add(new DX12ShaderRegisterUsage{
|
|
|
+ registerType, registerIndex, spaceIndex, descriptorHeapIndex, 0});
|
|
|
}
|
|
|
changed = 1;
|
|
|
}
|
|
|
@@ -96,87 +152,88 @@ void Framework::DX12ShaderSignature::createSignature(ID3D12Device5* zDevice,
|
|
|
signature->Release();
|
|
|
signature = 0;
|
|
|
}
|
|
|
+ int paramCount = (descriptorHeapBindings.getEntryCount() > 0 ? 1 : 0)
|
|
|
+ + bindingTableBindings.getEntryCount();
|
|
|
D3D12_ROOT_PARAMETER* descriptorTable
|
|
|
- = new D3D12_ROOT_PARAMETER[registerUsages.getEntryCount()];
|
|
|
- D3D12_DESCRIPTOR_RANGE* descriptorRanges
|
|
|
- = new D3D12_DESCRIPTOR_RANGE[registerUsages.getEntryCount()];
|
|
|
- ArrayIterator<DX12ShaderRegisterUsage> it = registerUsages.begin();
|
|
|
+ = new D3D12_ROOT_PARAMETER[paramCount];
|
|
|
int index = 0;
|
|
|
- while (it)
|
|
|
+ D3D12_DESCRIPTOR_RANGE* descriptorRanges = 0;
|
|
|
+ if (descriptorHeapBindings.getEntryCount())
|
|
|
{
|
|
|
- const auto& usage = it.val();
|
|
|
- if (usage.descriptorHeapIndex >= 0)
|
|
|
+ descriptorTable[index].ParameterType
|
|
|
+ = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
|
|
+ descriptorTable[index].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
|
+ descriptorRanges = new D3D12_DESCRIPTOR_RANGE[descriptorHeapBindings
|
|
|
+ .getEntryCount()];
|
|
|
+ ArrayIterator<DX12ShaderRegisterUsage*> it
|
|
|
+ = descriptorHeapBindings.begin();
|
|
|
+ while (it)
|
|
|
{
|
|
|
- descriptorTable[index].ParameterType
|
|
|
- = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
|
|
- descriptorTable[index].ShaderVisibility
|
|
|
- = D3D12_SHADER_VISIBILITY_ALL;
|
|
|
- descriptorTable[index].DescriptorTable.NumDescriptorRanges
|
|
|
- = registerUsages.getEntryCount();
|
|
|
- D3D12_DESCRIPTOR_RANGE* range = &descriptorRanges[index];
|
|
|
- switch (usage.registerType)
|
|
|
+ it->bindingTableIndex = 0;
|
|
|
+ D3D12_DESCRIPTOR_RANGE& range = descriptorRanges[index];
|
|
|
+ switch (it->registerType)
|
|
|
{
|
|
|
case DX12_SHADER_REGISTER_B_CONST_BUFFER:
|
|
|
- range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
|
|
|
+ range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
|
|
|
break;
|
|
|
case DX12_SHADER_REGISTER_T_SHADER_RESOURCE:
|
|
|
- range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
|
|
+ range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
|
|
break;
|
|
|
case DX12_SHADER_REGISTER_U_UNORDERED_ACCESS:
|
|
|
- range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
|
|
|
+ range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
|
|
|
break;
|
|
|
- default:
|
|
|
- Logging::error() << "Unknown register type for root signature: "
|
|
|
- << usage.registerType;
|
|
|
- range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
|
|
}
|
|
|
- ArrayIterator<DX12ShaderRegisterUsage> next = it.next();
|
|
|
+ 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
|
|
|
- && next.val().descriptorHeapIndex
|
|
|
- == usage.descriptorHeapIndex + size)
|
|
|
+ while (
|
|
|
+ next && next->registerType == it->registerType
|
|
|
+ && next->spaceIndex == it->spaceIndex
|
|
|
+ && next->registerIndex == it->registerIndex + size
|
|
|
+ && next->descriptorHeapIndex == it->descriptorHeapIndex + size)
|
|
|
{
|
|
|
++size;
|
|
|
it = next;
|
|
|
+ it->bindingTableIndex = 0;
|
|
|
++next;
|
|
|
}
|
|
|
- range->NumDescriptors = size;
|
|
|
- range->BaseShaderRegister = usage.registerIndex;
|
|
|
- range->RegisterSpace = usage.spaceIndex;
|
|
|
- range->OffsetInDescriptorsFromTableStart
|
|
|
- = usage.descriptorHeapIndex;
|
|
|
- descriptorTable[index].DescriptorTable.pDescriptorRanges = range;
|
|
|
+ range.NumDescriptors = size;
|
|
|
+ range.BaseShaderRegister = it->registerIndex;
|
|
|
+ range.RegisterSpace = it->spaceIndex;
|
|
|
+ range.OffsetInDescriptorsFromTableStart = it->descriptorHeapIndex;
|
|
|
+ ++it;
|
|
|
+ ++index;
|
|
|
}
|
|
|
- else
|
|
|
+ descriptorTable[index].DescriptorTable.pDescriptorRanges
|
|
|
+ = descriptorRanges;
|
|
|
+ descriptorTable[index].DescriptorTable.NumDescriptorRanges = index;
|
|
|
+ index = 1;
|
|
|
+ }
|
|
|
+ for (DX12ShaderRegisterUsage* usage : bindingTableBindings)
|
|
|
+ {
|
|
|
+ usage->bindingTableIndex = index;
|
|
|
+ switch (usage->registerType)
|
|
|
{
|
|
|
- switch (usage.registerType)
|
|
|
- {
|
|
|
- case DX12_SHADER_REGISTER_B_CONST_BUFFER:
|
|
|
- descriptorTable[index].ParameterType
|
|
|
- = D3D12_ROOT_PARAMETER_TYPE_CBV;
|
|
|
- break;
|
|
|
- case DX12_SHADER_REGISTER_T_SHADER_RESOURCE:
|
|
|
- descriptorTable[index].ParameterType
|
|
|
- = D3D12_ROOT_PARAMETER_TYPE_SRV;
|
|
|
- break;
|
|
|
- case DX12_SHADER_REGISTER_U_UNORDERED_ACCESS:
|
|
|
- descriptorTable[index].ParameterType
|
|
|
- = D3D12_ROOT_PARAMETER_TYPE_UAV;
|
|
|
- break;
|
|
|
- }
|
|
|
- descriptorTable[index].ShaderVisibility
|
|
|
- = D3D12_SHADER_VISIBILITY_ALL;
|
|
|
- descriptorTable[index].Descriptor.ShaderRegister
|
|
|
- = usage.registerIndex;
|
|
|
- descriptorTable[index].Descriptor.RegisterSpace = usage.spaceIndex;
|
|
|
+ case DX12_SHADER_REGISTER_B_CONST_BUFFER:
|
|
|
+ descriptorTable[index].ParameterType
|
|
|
+ = D3D12_ROOT_PARAMETER_TYPE_CBV;
|
|
|
+ break;
|
|
|
+ case DX12_SHADER_REGISTER_T_SHADER_RESOURCE:
|
|
|
+ descriptorTable[index].ParameterType
|
|
|
+ = D3D12_ROOT_PARAMETER_TYPE_SRV;
|
|
|
+ break;
|
|
|
+ case DX12_SHADER_REGISTER_U_UNORDERED_ACCESS:
|
|
|
+ descriptorTable[index].ParameterType
|
|
|
+ = D3D12_ROOT_PARAMETER_TYPE_UAV;
|
|
|
+ break;
|
|
|
}
|
|
|
- ++it;
|
|
|
+ descriptorTable[index].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
|
+ descriptorTable[index].Descriptor.ShaderRegister = usage->registerIndex;
|
|
|
+ descriptorTable[index].Descriptor.RegisterSpace = usage->spaceIndex;
|
|
|
++index;
|
|
|
}
|
|
|
+ shaderBindingTableParamCount = index;
|
|
|
D3D12_ROOT_SIGNATURE_DESC rootDesc = {};
|
|
|
- rootDesc.NumParameters = index;
|
|
|
+ rootDesc.NumParameters = shaderBindingTableParamCount;
|
|
|
rootDesc.pParameters = descriptorTable;
|
|
|
rootDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_LOCAL_ROOT_SIGNATURE;
|
|
|
ID3DBlob* pSigBlob = 0;
|
|
|
@@ -202,6 +259,7 @@ void Framework::DX12ShaderSignature::createSignature(ID3D12Device5* zDevice,
|
|
|
pErrorBlob->Release();
|
|
|
}
|
|
|
delete[] descriptorRanges;
|
|
|
+ delete[] descriptorTable;
|
|
|
}
|
|
|
|
|
|
ID3D12RootSignature* Framework::DX12ShaderSignature::zSignature() const
|
|
|
@@ -209,17 +267,24 @@ ID3D12RootSignature* Framework::DX12ShaderSignature::zSignature() const
|
|
|
return signature;
|
|
|
}
|
|
|
|
|
|
-const Array<DX12ShaderRegisterUsage>&
|
|
|
-Framework::DX12ShaderSignature::getRegisterUsages() const
|
|
|
+const Array<DX12ShaderRegisterUsage*>&
|
|
|
+Framework::DX12ShaderSignature::getDescriptorHeapBindings() const
|
|
|
{
|
|
|
- return registerUsages;
|
|
|
+ return descriptorHeapBindings;
|
|
|
}
|
|
|
|
|
|
-Framework::DX12ShaderFunction::DX12ShaderFunction(
|
|
|
- const Text& functionName, DX12ShaderSignature* signature)
|
|
|
+int Framework::DX12ShaderSignature::gerShaderBindingTableParamCount() const
|
|
|
+{
|
|
|
+ return shaderBindingTableParamCount;
|
|
|
+}
|
|
|
+
|
|
|
+Framework::DX12ShaderFunction::DX12ShaderFunction(const Text& functionName,
|
|
|
+ DX12ShaderSignature* signature,
|
|
|
+ DX12ShaderFunctionType functionType)
|
|
|
: ReferenceCounter(),
|
|
|
functionName(functionName),
|
|
|
signature(signature),
|
|
|
+ functionType(functionType),
|
|
|
exportDesc(new D3D12_EXPORT_DESC())
|
|
|
{
|
|
|
wchar_t* wc = new wchar_t[functionName.getLength() + 1];
|
|
|
@@ -252,6 +317,11 @@ D3D12_EXPORT_DESC* Framework::DX12ShaderFunction::zExportDesc() const
|
|
|
return exportDesc;
|
|
|
}
|
|
|
|
|
|
+DX12ShaderFunctionType Framework::DX12ShaderFunction::getFunctionType() const
|
|
|
+{
|
|
|
+ return functionType;
|
|
|
+}
|
|
|
+
|
|
|
Framework::DX12Shader::DX12Shader(
|
|
|
const unsigned char* shaderBytes, int shaderBytesSize)
|
|
|
: ReferenceCounter(),
|
|
|
@@ -540,6 +610,23 @@ D3D12_HIT_GROUP_DESC* Framework::DX12ShaderHitGroup::zHitGroupDesc() const
|
|
|
return hitGroupDesc;
|
|
|
}
|
|
|
|
|
|
+DX12ShaderSignature* Framework::DX12ShaderHitGroup::zSignature() const
|
|
|
+{
|
|
|
+ if (closestHitShaderFunction)
|
|
|
+ {
|
|
|
+ return closestHitShaderFunction->zSignature();
|
|
|
+ }
|
|
|
+ if (anyHitShaderFunction)
|
|
|
+ {
|
|
|
+ return anyHitShaderFunction->zSignature();
|
|
|
+ }
|
|
|
+ if (intersectionShaderFunction)
|
|
|
+ {
|
|
|
+ return intersectionShaderFunction->zSignature();
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
Framework::DX12Pipeline::DX12Pipeline()
|
|
|
: ReferenceCounter(),
|
|
|
emptyGlobalRootSignature(0),
|
|
|
@@ -689,9 +776,9 @@ void Framework::DX12Pipeline::createPipelineState(ID3D12Device5* zDevice,
|
|
|
= D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG;
|
|
|
subobjects[index].pDesc = &shaderDesc;
|
|
|
index++;
|
|
|
+ functionsWithoutHitGroups.clear();
|
|
|
// create export list for hole pipeline with all hitgroups and all functions
|
|
|
// that are not part of a hit group
|
|
|
- Array<const DX12ShaderFunction*> functionsWithoutHitGroups;
|
|
|
for (const DX12Shader* shader : shaders)
|
|
|
{
|
|
|
for (const DX12ShaderFunction* function : shader->getFunctions())
|
|
|
@@ -890,6 +977,22 @@ DX12GlobalDescriptorHeap* Framework::DX12Pipeline::createGlobalDescriptorHeap()
|
|
|
return new DX12GlobalDescriptorHeap(dynamic_cast<DX12Pipeline*>(getThis()));
|
|
|
}
|
|
|
|
|
|
+const RCArray<DX12Shader>& Framework::DX12Pipeline::getShaders() const
|
|
|
+{
|
|
|
+ return shaders;
|
|
|
+}
|
|
|
+
|
|
|
+const Array<const DX12ShaderFunction*>&
|
|
|
+Framework::DX12Pipeline::getFunctionsWithoutHitGroups() const
|
|
|
+{
|
|
|
+ return functionsWithoutHitGroups;
|
|
|
+}
|
|
|
+
|
|
|
+const RCArray<DX12ShaderHitGroup>& Framework::DX12Pipeline::getHitGroups() const
|
|
|
+{
|
|
|
+ return hitGroups;
|
|
|
+}
|
|
|
+
|
|
|
Framework::DX12GlobalDescriptorHeap::DX12GlobalDescriptorHeap(
|
|
|
DX12Pipeline* pipeline)
|
|
|
: ReferenceCounter(),
|
|
|
@@ -919,18 +1022,19 @@ void Framework::DX12GlobalDescriptorHeap::addInput(
|
|
|
{
|
|
|
for (DX12ShaderFunction* function : shader->getFunctions())
|
|
|
{
|
|
|
- for (const DX12ShaderRegisterUsage& usage :
|
|
|
- function->zSignature()->getRegisterUsages())
|
|
|
+ for (const DX12ShaderRegisterUsage* usage :
|
|
|
+ function->zSignature()->getDescriptorHeapBindings())
|
|
|
{
|
|
|
- if (usage.descriptorHeapIndex == registerInputs.getEntryCount())
|
|
|
+ if (usage->descriptorHeapIndex
|
|
|
+ == registerInputs.getEntryCount())
|
|
|
{
|
|
|
- if (usage.registerType != type)
|
|
|
+ if (usage->registerType != type)
|
|
|
{
|
|
|
Logging::error()
|
|
|
<< "Register type mismatch for register index "
|
|
|
- << usage.registerIndex << ", space index "
|
|
|
- << usage.spaceIndex << ". Expected register type: "
|
|
|
- << usage.registerType
|
|
|
+ << usage->registerIndex << ", space index "
|
|
|
+ << usage->spaceIndex << ". Expected register type: "
|
|
|
+ << usage->registerType
|
|
|
<< ", given register type: " << type
|
|
|
<< ". The register type is specified in the "
|
|
|
"signature of shader function '"
|
|
|
@@ -1127,5 +1231,372 @@ Framework::DX12GlobalDescriptorHeap::zDescriptorHeap() const
|
|
|
Framework::DX12ShaderBindingTable::DX12ShaderBindingTable(
|
|
|
DX12Pipeline* pipeline)
|
|
|
: ReferenceCounter(),
|
|
|
- pipeline(pipeline)
|
|
|
-{}
|
|
|
+ pipeline(pipeline),
|
|
|
+ shaderBindingTableBuffer(0),
|
|
|
+ globalDescriptorHeap(0),
|
|
|
+ rayGenRecordSize(0),
|
|
|
+ rayGenCount(0),
|
|
|
+ missRecordSize(0),
|
|
|
+ missCount(0),
|
|
|
+ callableRecordSize(0),
|
|
|
+ callableCount(0),
|
|
|
+ hitGroupRecordSize(0),
|
|
|
+ hitGroupCount(0),
|
|
|
+ tableBuffer(0),
|
|
|
+ tableBufferSize(0),
|
|
|
+ nextHitGroupOffset(0),
|
|
|
+ stateObjectProperties(0)
|
|
|
+{
|
|
|
+ pipeline->zPipelineState()->QueryInterface(
|
|
|
+ __uuidof(ID3D12StateObjectProperties), (void**)&stateObjectProperties);
|
|
|
+}
|
|
|
+
|
|
|
+Framework::DX12ShaderBindingTable::~DX12ShaderBindingTable()
|
|
|
+{
|
|
|
+ stateObjectProperties->Release();
|
|
|
+ if (pipeline)
|
|
|
+ {
|
|
|
+ pipeline->release();
|
|
|
+ }
|
|
|
+ if (shaderBindingTableBuffer)
|
|
|
+ {
|
|
|
+ shaderBindingTableBuffer->release();
|
|
|
+ }
|
|
|
+ if (globalDescriptorHeap)
|
|
|
+ {
|
|
|
+ globalDescriptorHeap->release();
|
|
|
+ }
|
|
|
+ for (const char* buffer : tempBuffers)
|
|
|
+ {
|
|
|
+ delete[] buffer;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void Framework::DX12ShaderBindingTable::setGlobalDescriptorHeap(
|
|
|
+ DX12GlobalDescriptorHeap* zGlobalDescriptorHeap)
|
|
|
+{
|
|
|
+ if (this->globalDescriptorHeap)
|
|
|
+ {
|
|
|
+ this->globalDescriptorHeap->release();
|
|
|
+ }
|
|
|
+ this->globalDescriptorHeap = zGlobalDescriptorHeap;
|
|
|
+ if (this->globalDescriptorHeap)
|
|
|
+ {
|
|
|
+ this->globalDescriptorHeap->getThis();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void Framework::DX12ShaderBindingTable::startUpdate()
|
|
|
+{
|
|
|
+ if (shaderBindingTableBuffer)
|
|
|
+ {
|
|
|
+ shaderBindingTableBuffer->zBuffer()->Map(0, 0, (void**)&tableBuffer);
|
|
|
+ tableBufferSize = (int)shaderBindingTableBuffer->getElementCount()
|
|
|
+ * shaderBindingTableBuffer->getElementLength();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ tableBuffer = 0;
|
|
|
+ tableBufferSize = 0;
|
|
|
+ }
|
|
|
+ rayGenRecordSize = 0;
|
|
|
+ rayGenCount = 0;
|
|
|
+ missRecordSize = 0;
|
|
|
+ missCount = 0;
|
|
|
+ callableRecordSize = 0;
|
|
|
+ callableCount = 0;
|
|
|
+ for (const DX12ShaderFunction* function :
|
|
|
+ pipeline->getFunctionsWithoutHitGroups())
|
|
|
+ {
|
|
|
+ DX12ShaderSignature* signature = function->zSignature();
|
|
|
+ if (function->getFunctionType() == DX12_SHADER_FUNCTION_TYPE_RAY_GEN)
|
|
|
+ {
|
|
|
+ if (rayGenRecordSize < signature->gerShaderBindingTableParamCount())
|
|
|
+ {
|
|
|
+ rayGenRecordSize = signature->gerShaderBindingTableParamCount();
|
|
|
+ }
|
|
|
+ rayGenCount++;
|
|
|
+ }
|
|
|
+ else if (function->getFunctionType() == DX12_SHADER_FUNCTION_TYPE_MISS)
|
|
|
+ {
|
|
|
+ if (missRecordSize < signature->gerShaderBindingTableParamCount())
|
|
|
+ {
|
|
|
+ missRecordSize = signature->gerShaderBindingTableParamCount();
|
|
|
+ }
|
|
|
+ missCount++;
|
|
|
+ }
|
|
|
+ else if (function->getFunctionType()
|
|
|
+ == DX12_SHADER_FUNCTION_TYPE_CALLABLE)
|
|
|
+ {
|
|
|
+ if (callableRecordSize
|
|
|
+ < signature->gerShaderBindingTableParamCount())
|
|
|
+ {
|
|
|
+ callableRecordSize
|
|
|
+ = signature->gerShaderBindingTableParamCount();
|
|
|
+ }
|
|
|
+ callableCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ rayGenRecordSize = ROUND_UP_POWER_OF_2(
|
|
|
+ D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT + rayGenRecordSize * 8,
|
|
|
+ D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT);
|
|
|
+ missRecordSize = ROUND_UP_POWER_OF_2(
|
|
|
+ D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT + missRecordSize * 8,
|
|
|
+ D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT);
|
|
|
+ callableRecordSize = ROUND_UP_POWER_OF_2(
|
|
|
+ D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT + callableRecordSize * 8,
|
|
|
+ D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT);
|
|
|
+ hitGroupCount = 0;
|
|
|
+ hitGroupRecordSize = 0;
|
|
|
+ for (DX12ShaderHitGroup* hitGroup : pipeline->getHitGroups())
|
|
|
+ {
|
|
|
+ DX12ShaderSignature* signature = hitGroup->zSignature();
|
|
|
+ if (hitGroupRecordSize < signature->gerShaderBindingTableParamCount())
|
|
|
+ {
|
|
|
+ hitGroupRecordSize = signature->gerShaderBindingTableParamCount();
|
|
|
+ }
|
|
|
+ hitGroupCount++;
|
|
|
+ }
|
|
|
+ hitGroupRecordSize = ROUND_UP_POWER_OF_2(
|
|
|
+ D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT + hitGroupRecordSize * 8,
|
|
|
+ D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT);
|
|
|
+ nextHitGroupOffset
|
|
|
+ = rayGenRecordSize * rayGenCount + missRecordSize * missCount;
|
|
|
+}
|
|
|
+
|
|
|
+void Framework::DX12ShaderBindingTable::set(int index, void* data, int size)
|
|
|
+{
|
|
|
+ if (tableBufferSize >= index + size)
|
|
|
+ {
|
|
|
+ memcpy(tableBuffer + index, data, size);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ index -= tableBufferSize;
|
|
|
+ ArrayIterator<char*> it = tempBuffers.begin();
|
|
|
+ while (it && 2048 >= index + size)
|
|
|
+ {
|
|
|
+ index -= 2048;
|
|
|
+ it++;
|
|
|
+ }
|
|
|
+ while (2048 >= index + size)
|
|
|
+ {
|
|
|
+ char* newBuffer = new char[2048];
|
|
|
+ memset(newBuffer, 0, 2048);
|
|
|
+ tempBuffers.add(newBuffer);
|
|
|
+ index -= 2048;
|
|
|
+ }
|
|
|
+ // because the buffer size is allways rounded up to multiples
|
|
|
+ // of 32 and the size written at once is always 8 or 32 it
|
|
|
+ // should never be possible to have a negative index here
|
|
|
+ assert(index >= 0);
|
|
|
+ if (!it)
|
|
|
+ {
|
|
|
+ char* newBuffer = new char[2048];
|
|
|
+ memset(newBuffer, 0, 2048);
|
|
|
+ tempBuffers.add(newBuffer);
|
|
|
+ memcpy(newBuffer + index, data, size);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ memcpy(it.val() + index, data, size);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void Framework::DX12ShaderBindingTable::setShaderInput(
|
|
|
+ DX12ShaderFunction* zFunction, int* offsetPointer, __int64 gpuAddress)
|
|
|
+{
|
|
|
+ int index = 0;
|
|
|
+ for (const DX12ShaderFunction* pf :
|
|
|
+ pipeline->getFunctionsWithoutHitGroups())
|
|
|
+ {
|
|
|
+ if (pf == zFunction)
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (pf->getFunctionType() == zFunction->getFunctionType())
|
|
|
+ {
|
|
|
+ index++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ int offset = 0;
|
|
|
+ if (zFunction->getFunctionType() == DX12_SHADER_FUNCTION_TYPE_RAY_GEN)
|
|
|
+ {
|
|
|
+ offset = index * rayGenRecordSize;
|
|
|
+ }
|
|
|
+ else if (zFunction->getFunctionType() == DX12_SHADER_FUNCTION_TYPE_MISS)
|
|
|
+ {
|
|
|
+ offset = rayGenRecordSize * rayGenCount + index * missRecordSize;
|
|
|
+ }
|
|
|
+ else if (zFunction->getFunctionType() == DX12_SHADER_FUNCTION_TYPE_CALLABLE)
|
|
|
+ {
|
|
|
+ offset = rayGenRecordSize * rayGenCount + missRecordSize * missCount
|
|
|
+ + index * callableRecordSize;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ throw std::logic_error("setShaderInput can only be used for ray "
|
|
|
+ "generation, miss, and callable "
|
|
|
+ "shader functions");
|
|
|
+ }
|
|
|
+ offset += D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT
|
|
|
+ + sizeof(__int64) * *offsetPointer;
|
|
|
+ set(offset, &gpuAddress, sizeof(__int64));
|
|
|
+}
|
|
|
+
|
|
|
+int Framework::DX12ShaderBindingTable::addHitGroup(
|
|
|
+ DX12ShaderHitGroup* zHitGroup)
|
|
|
+{
|
|
|
+ int index = nextHitGroupOffset;
|
|
|
+ set(index,
|
|
|
+ stateObjectProperties->GetShaderIdentifier(
|
|
|
+ zHitGroup->zHitGroupDesc()->HitGroupExport),
|
|
|
+ D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT);
|
|
|
+ if (zHitGroup->zSignature()->getDescriptorHeapBindings().getEntryCount()
|
|
|
+ > 0)
|
|
|
+ {
|
|
|
+ D3D12_GPU_DESCRIPTOR_HANDLE gpuAddress
|
|
|
+ = globalDescriptorHeap->zDescriptorHeap()
|
|
|
+ ->GetGPUDescriptorHandleForHeapStart();
|
|
|
+ set(index + D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT,
|
|
|
+ &gpuAddress.ptr,
|
|
|
+ sizeof(__int64));
|
|
|
+ }
|
|
|
+ nextHitGroupOffset += hitGroupRecordSize;
|
|
|
+ return index + D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT;
|
|
|
+}
|
|
|
+
|
|
|
+void Framework::DX12ShaderBindingTable::setHitGroupShaderInput(
|
|
|
+ int hitGroupOffset, int* offsetPointer, __int64 gpuAddress)
|
|
|
+{
|
|
|
+ set(hitGroupOffset + sizeof(__int64) * *offsetPointer,
|
|
|
+ &gpuAddress,
|
|
|
+ sizeof(__int64));
|
|
|
+}
|
|
|
+
|
|
|
+void Framework::DX12ShaderBindingTable::endUpdate(ID3D12Device5* zDevice)
|
|
|
+{
|
|
|
+ int rayTracingIndex = 0;
|
|
|
+ int missIndex = 0;
|
|
|
+ int callableIndex = 0;
|
|
|
+ for (const DX12ShaderFunction* function :
|
|
|
+ pipeline->getFunctionsWithoutHitGroups())
|
|
|
+ {
|
|
|
+ int offset = -1;
|
|
|
+ DX12ShaderSignature* signature = function->zSignature();
|
|
|
+ if (function->getFunctionType() == DX12_SHADER_FUNCTION_TYPE_RAY_GEN)
|
|
|
+ {
|
|
|
+ offset = rayTracingIndex * rayGenRecordSize;
|
|
|
+ rayTracingIndex++;
|
|
|
+ }
|
|
|
+ else if (function->getFunctionType() == DX12_SHADER_FUNCTION_TYPE_MISS)
|
|
|
+ {
|
|
|
+ offset
|
|
|
+ = rayGenRecordSize * rayGenCount + missIndex * missRecordSize;
|
|
|
+ missIndex++;
|
|
|
+ }
|
|
|
+ else if (function->getFunctionType()
|
|
|
+ == DX12_SHADER_FUNCTION_TYPE_CALLABLE)
|
|
|
+ {
|
|
|
+ offset = rayGenRecordSize * rayGenCount + missRecordSize * missCount
|
|
|
+ + callableIndex * callableRecordSize;
|
|
|
+ callableIndex++;
|
|
|
+ }
|
|
|
+ if (offset >= 0)
|
|
|
+ {
|
|
|
+ set(offset,
|
|
|
+ stateObjectProperties->GetShaderIdentifier(
|
|
|
+ function->zExportDesc()->Name),
|
|
|
+ D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT);
|
|
|
+ if (function->zSignature()
|
|
|
+ ->getDescriptorHeapBindings()
|
|
|
+ .getEntryCount()
|
|
|
+ > 0)
|
|
|
+ {
|
|
|
+ D3D12_GPU_DESCRIPTOR_HANDLE gpuAddress
|
|
|
+ = globalDescriptorHeap->zDescriptorHeap()
|
|
|
+ ->GetGPUDescriptorHandleForHeapStart();
|
|
|
+ set(offset + D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT,
|
|
|
+ &gpuAddress.ptr,
|
|
|
+ sizeof(__int64));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (nextHitGroupOffset > tableBufferSize)
|
|
|
+ {
|
|
|
+ DX12Buffer* newBuffer
|
|
|
+ = new DX12Buffer(1, zDevice, D3D12_RESOURCE_FLAG_NONE);
|
|
|
+ newBuffer->setLength(ROUND_UP_POWER_OF_2(nextHitGroupOffset, 256));
|
|
|
+ newBuffer->createBufferWithoutData(
|
|
|
+ D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_HEAP_TYPE_UPLOAD);
|
|
|
+ void* newTableBuffer = 0;
|
|
|
+ newBuffer->zBuffer()->Map(0, 0, (void**)&newTableBuffer);
|
|
|
+ int sizeToCopy = nextHitGroupOffset;
|
|
|
+ int index = 0;
|
|
|
+ if (tableBufferSize > 0)
|
|
|
+ {
|
|
|
+ memcpy(newTableBuffer, tableBuffer, tableBufferSize);
|
|
|
+ sizeToCopy -= tableBufferSize;
|
|
|
+ index = tableBufferSize;
|
|
|
+ }
|
|
|
+ for (char* buffer : tempBuffers)
|
|
|
+ {
|
|
|
+ int bytesToCopy = sizeToCopy < 2048 ? sizeToCopy : 2048;
|
|
|
+ memcpy((char*)newTableBuffer + index, buffer, bytesToCopy);
|
|
|
+ sizeToCopy -= bytesToCopy;
|
|
|
+ index += bytesToCopy;
|
|
|
+ if (sizeToCopy == 0)
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ assert(sizeToCopy == 0);
|
|
|
+ newBuffer->zBuffer()->Unmap(0, 0);
|
|
|
+ if (shaderBindingTableBuffer)
|
|
|
+ {
|
|
|
+ shaderBindingTableBuffer->zBuffer()->Unmap(0, 0);
|
|
|
+ shaderBindingTableBuffer->release();
|
|
|
+ }
|
|
|
+ shaderBindingTableBuffer = newBuffer;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ shaderBindingTableBuffer->zBuffer()->Unmap(0, 0);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void Framework::DX12ShaderBindingTable::fillDispatchRaysDesc(
|
|
|
+ D3D12_DISPATCH_RAYS_DESC* dispatchRaysDesc)
|
|
|
+{
|
|
|
+ dispatchRaysDesc->RayGenerationShaderRecord.SizeInBytes
|
|
|
+ = rayGenCount * rayGenRecordSize;
|
|
|
+ dispatchRaysDesc->RayGenerationShaderRecord.StartAddress
|
|
|
+ = shaderBindingTableBuffer->zBuffer()->GetGPUVirtualAddress();
|
|
|
+
|
|
|
+ dispatchRaysDesc->MissShaderTable.SizeInBytes = missCount * missRecordSize;
|
|
|
+ dispatchRaysDesc->MissShaderTable.StartAddress
|
|
|
+ = shaderBindingTableBuffer->zBuffer()->GetGPUVirtualAddress()
|
|
|
+ + rayGenCount * rayGenRecordSize;
|
|
|
+ dispatchRaysDesc->MissShaderTable.StrideInBytes = missRecordSize;
|
|
|
+
|
|
|
+ dispatchRaysDesc->HitGroupTable.SizeInBytes
|
|
|
+ = hitGroupCount * hitGroupRecordSize;
|
|
|
+ dispatchRaysDesc->HitGroupTable.StartAddress
|
|
|
+ = shaderBindingTableBuffer->zBuffer()->GetGPUVirtualAddress()
|
|
|
+ + rayGenCount * rayGenRecordSize + missCount * missRecordSize;
|
|
|
+ dispatchRaysDesc->HitGroupTable.StrideInBytes = hitGroupRecordSize;
|
|
|
+
|
|
|
+ dispatchRaysDesc->CallableShaderTable.SizeInBytes
|
|
|
+ = callableCount * callableRecordSize;
|
|
|
+ dispatchRaysDesc->CallableShaderTable.StartAddress
|
|
|
+ = shaderBindingTableBuffer->zBuffer()->GetGPUVirtualAddress()
|
|
|
+ + rayGenCount * rayGenRecordSize + missCount * missRecordSize
|
|
|
+ + hitGroupCount * hitGroupRecordSize;
|
|
|
+ dispatchRaysDesc->CallableShaderTable.StrideInBytes = callableRecordSize;
|
|
|
+}
|
|
|
+
|
|
|
+DX12Pipeline* Framework::DX12ShaderBindingTable::zPipeline() const
|
|
|
+{
|
|
|
+ return pipeline;
|
|
|
+}
|