476 lines
22 KiB
C
476 lines
22 KiB
C
#ifndef KORE_XBOX_ONE
|
|
|
|
#include <kinc/backend/graphics5/raytrace.h>
|
|
|
|
#include <kinc/graphics5/commandlist.h>
|
|
#include <kinc/graphics5/constantbuffer.h>
|
|
#include <kinc/graphics5/graphics.h>
|
|
#include <kinc/graphics5/indexbuffer.h>
|
|
#include <kinc/graphics5/raytrace.h>
|
|
#include <kinc/graphics5/vertexbuffer.h>
|
|
|
|
static const wchar_t *hit_group_name = L"hitgroup";
|
|
static const wchar_t *raygen_shader_name = L"raygeneration";
|
|
static const wchar_t *closesthit_shader_name = L"closesthit";
|
|
static const wchar_t *miss_shader_name = L"miss";
|
|
|
|
static ID3D12Device5 *dxrDevice;
|
|
static ID3D12GraphicsCommandList4 *dxrCommandList;
|
|
static ID3D12RootSignature *dxrRootSignature;
|
|
static ID3D12DescriptorHeap *descriptorHeap;
|
|
static kinc_raytrace_acceleration_structure_t *accel;
|
|
static kinc_raytrace_pipeline_t *pipeline;
|
|
static kinc_g5_texture_t *output = NULL;
|
|
|
|
void kinc_raytrace_pipeline_init(kinc_raytrace_pipeline_t *pipeline, kinc_g5_command_list_t *command_list, void *ray_shader, int ray_shader_size,
|
|
kinc_g5_constant_buffer_t *constant_buffer) {
|
|
pipeline->_constant_buffer = constant_buffer;
|
|
// Descriptor heap
|
|
D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc = {0};
|
|
// Allocate a heap for 3 descriptors:
|
|
// 2 - bottom and top level acceleration structure
|
|
// 1 - raytracing output texture SRV
|
|
descriptorHeapDesc.NumDescriptors = 3;
|
|
descriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
|
descriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
|
descriptorHeapDesc.NodeMask = 0;
|
|
device->CreateDescriptorHeap(&descriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(&descriptorHeap));
|
|
|
|
// Device
|
|
device->QueryInterface(IID_GRAPHICS_PPV_ARGS(&dxrDevice));
|
|
command_list->impl._commandList->QueryInterface(IID_GRAPHICS_PPV_ARGS(&dxrCommandList));
|
|
|
|
// Root signatures
|
|
// This is a root signature that is shared across all raytracing shaders invoked during a DispatchRays() call.
|
|
D3D12_DESCRIPTOR_RANGE UAVDescriptor = {};
|
|
UAVDescriptor.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
|
|
UAVDescriptor.NumDescriptors = 1;
|
|
UAVDescriptor.BaseShaderRegister = 0;
|
|
UAVDescriptor.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
|
|
|
|
D3D12_ROOT_PARAMETER rootParameters[3] = {};
|
|
// Output view
|
|
rootParameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
|
rootParameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
rootParameters[0].DescriptorTable.NumDescriptorRanges = 1;
|
|
rootParameters[0].DescriptorTable.pDescriptorRanges = &UAVDescriptor;
|
|
// Acceleration structure
|
|
rootParameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;
|
|
rootParameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
rootParameters[1].Descriptor.ShaderRegister = 0;
|
|
// Constant buffer
|
|
rootParameters[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
|
|
rootParameters[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
rootParameters[2].Descriptor.ShaderRegister = 0;
|
|
|
|
D3D12_ROOT_SIGNATURE_DESC dxrRootSignatureDesc = {0};
|
|
dxrRootSignatureDesc.NumParameters = ARRAYSIZE(rootParameters);
|
|
dxrRootSignatureDesc.pParameters = rootParameters;
|
|
ID3DBlob *blob = NULL;
|
|
ID3DBlob *error = NULL;
|
|
D3D12SerializeRootSignature(&dxrRootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, &error);
|
|
device->CreateRootSignature(1, blob->GetBufferPointer(), blob->GetBufferSize(), IID_GRAPHICS_PPV_ARGS(&dxrRootSignature));
|
|
|
|
// Pipeline
|
|
D3D12_STATE_OBJECT_DESC raytracingPipeline = {0};
|
|
raytracingPipeline.Type = D3D12_STATE_OBJECT_TYPE_RAYTRACING_PIPELINE;
|
|
|
|
D3D12_SHADER_BYTECODE shaderBytecode = {0};
|
|
shaderBytecode.pShaderBytecode = ray_shader;
|
|
shaderBytecode.BytecodeLength = ray_shader_size;
|
|
|
|
D3D12_DXIL_LIBRARY_DESC dxilLibrary = {0};
|
|
dxilLibrary.DXILLibrary = shaderBytecode;
|
|
D3D12_EXPORT_DESC exports[3] = {0};
|
|
exports[0].Name = raygen_shader_name;
|
|
exports[1].Name = closesthit_shader_name;
|
|
exports[2].Name = miss_shader_name;
|
|
dxilLibrary.pExports = exports;
|
|
dxilLibrary.NumExports = 3;
|
|
|
|
D3D12_HIT_GROUP_DESC hitGroup = {0};
|
|
hitGroup.ClosestHitShaderImport = closesthit_shader_name;
|
|
hitGroup.HitGroupExport = hit_group_name;
|
|
hitGroup.Type = D3D12_HIT_GROUP_TYPE_TRIANGLES;
|
|
|
|
D3D12_RAYTRACING_SHADER_CONFIG shaderConfig = {0};
|
|
shaderConfig.MaxPayloadSizeInBytes = 4 * sizeof(float); // float4 color
|
|
shaderConfig.MaxAttributeSizeInBytes = 2 * sizeof(float); // float2 barycentrics
|
|
|
|
D3D12_RAYTRACING_PIPELINE_CONFIG pipelineConfig = {0};
|
|
pipelineConfig.MaxTraceRecursionDepth = 1; // ~ primary rays only
|
|
|
|
D3D12_STATE_SUBOBJECT subobjects[5] = {};
|
|
subobjects[0].Type = D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY;
|
|
subobjects[0].pDesc = &dxilLibrary;
|
|
subobjects[1].Type = D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP;
|
|
subobjects[1].pDesc = &hitGroup;
|
|
subobjects[2].Type = D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG;
|
|
subobjects[2].pDesc = &shaderConfig;
|
|
subobjects[3].Type = D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE;
|
|
subobjects[3].pDesc = &dxrRootSignature;
|
|
subobjects[4].Type = D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG;
|
|
subobjects[4].pDesc = &pipelineConfig;
|
|
raytracingPipeline.NumSubobjects = 5;
|
|
raytracingPipeline.pSubobjects = subobjects;
|
|
|
|
dxrDevice->CreateStateObject(&raytracingPipeline, IID_GRAPHICS_PPV_ARGS(&pipeline->impl.dxr_state));
|
|
|
|
// Shader tables
|
|
// Get shader identifiers
|
|
ID3D12StateObjectProperties *stateObjectProps = NULL;
|
|
pipeline->impl.dxr_state->QueryInterface(IID_GRAPHICS_PPV_ARGS(&stateObjectProps));
|
|
const void *rayGenShaderId = stateObjectProps->GetShaderIdentifier(raygen_shader_name);
|
|
const void *missShaderId = stateObjectProps->GetShaderIdentifier(miss_shader_name);
|
|
const void *hitGroupShaderId = stateObjectProps->GetShaderIdentifier(hit_group_name);
|
|
UINT shaderIdSize = D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES;
|
|
int align = D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT;
|
|
|
|
// Ray gen shader table
|
|
{
|
|
UINT size = shaderIdSize + constant_buffer->impl.mySize;
|
|
UINT shaderRecordSize = (size + (align - 1)) & ~(align - 1);
|
|
D3D12_RESOURCE_DESC bufferDesc = {0};
|
|
bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
|
bufferDesc.Width = shaderRecordSize;
|
|
bufferDesc.Height = 1;
|
|
bufferDesc.DepthOrArraySize = 1;
|
|
bufferDesc.MipLevels = 1;
|
|
bufferDesc.Format = DXGI_FORMAT_UNKNOWN;
|
|
bufferDesc.SampleDesc.Count = 1;
|
|
bufferDesc.SampleDesc.Quality = 0;
|
|
bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
|
D3D12_HEAP_PROPERTIES uploadHeapProperties = {0};
|
|
uploadHeapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
|
uploadHeapProperties.CreationNodeMask = 1;
|
|
uploadHeapProperties.VisibleNodeMask = 1;
|
|
|
|
device->CreateCommittedResource(&uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
|
|
IID_GRAPHICS_PPV_ARGS(&pipeline->impl.raygen_shader_table));
|
|
|
|
D3D12_RANGE rstRange = {0};
|
|
rstRange.Begin = 0;
|
|
rstRange.End = 0;
|
|
uint8_t *byteDest;
|
|
pipeline->impl.raygen_shader_table->Map(0, &rstRange, (void **)(&byteDest));
|
|
|
|
D3D12_RANGE cbRange = {0};
|
|
cbRange.Begin = 0;
|
|
cbRange.End = constant_buffer->impl.mySize;
|
|
void *constantBufferData;
|
|
constant_buffer->impl.constant_buffer->Map(0, &cbRange, (void **)&constantBufferData);
|
|
memcpy(byteDest, rayGenShaderId, size);
|
|
memcpy(byteDest + size, constantBufferData, constant_buffer->impl.mySize);
|
|
pipeline->impl.raygen_shader_table->Unmap(0, NULL);
|
|
}
|
|
|
|
// Miss shader table
|
|
{
|
|
UINT size = shaderIdSize;
|
|
UINT shaderRecordSize = (size + (align - 1)) & ~(align - 1);
|
|
D3D12_RESOURCE_DESC bufferDesc = {0};
|
|
bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
|
bufferDesc.Width = shaderRecordSize;
|
|
bufferDesc.Height = 1;
|
|
bufferDesc.DepthOrArraySize = 1;
|
|
bufferDesc.MipLevels = 1;
|
|
bufferDesc.Format = DXGI_FORMAT_UNKNOWN;
|
|
bufferDesc.SampleDesc.Count = 1;
|
|
bufferDesc.SampleDesc.Quality = 0;
|
|
bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
|
D3D12_HEAP_PROPERTIES uploadHeapProperties = {0};
|
|
uploadHeapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
|
uploadHeapProperties.CreationNodeMask = 1;
|
|
uploadHeapProperties.VisibleNodeMask = 1;
|
|
|
|
device->CreateCommittedResource(&uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
|
|
IID_GRAPHICS_PPV_ARGS(&pipeline->impl.miss_shader_table));
|
|
|
|
D3D12_RANGE mstRange = {0};
|
|
mstRange.Begin = 0;
|
|
mstRange.End = 0;
|
|
uint8_t *byteDest;
|
|
pipeline->impl.miss_shader_table->Map(0, &mstRange, (void **)(&byteDest));
|
|
memcpy(byteDest, missShaderId, size);
|
|
pipeline->impl.miss_shader_table->Unmap(0, NULL);
|
|
}
|
|
|
|
// Hit group shader table
|
|
{
|
|
UINT size = shaderIdSize;
|
|
UINT shaderRecordSize = (size + (align - 1)) & ~(align - 1);
|
|
D3D12_RESOURCE_DESC bufferDesc = {0};
|
|
bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
|
bufferDesc.Width = shaderRecordSize;
|
|
bufferDesc.Height = 1;
|
|
bufferDesc.DepthOrArraySize = 1;
|
|
bufferDesc.MipLevels = 1;
|
|
bufferDesc.Format = DXGI_FORMAT_UNKNOWN;
|
|
bufferDesc.SampleDesc.Count = 1;
|
|
bufferDesc.SampleDesc.Quality = 0;
|
|
bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
|
D3D12_HEAP_PROPERTIES uploadHeapProperties = {0};
|
|
uploadHeapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
|
uploadHeapProperties.CreationNodeMask = 1;
|
|
uploadHeapProperties.VisibleNodeMask = 1;
|
|
|
|
device->CreateCommittedResource(&uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
|
|
IID_GRAPHICS_PPV_ARGS(&pipeline->impl.hitgroup_shader_table));
|
|
|
|
D3D12_RANGE hstRange = {0};
|
|
hstRange.Begin = 0;
|
|
hstRange.End = 0;
|
|
uint8_t *byteDest;
|
|
pipeline->impl.hitgroup_shader_table->Map(0, &hstRange, (void **)(&byteDest));
|
|
memcpy(byteDest, hitGroupShaderId, size);
|
|
pipeline->impl.hitgroup_shader_table->Unmap(0, NULL);
|
|
}
|
|
}
|
|
|
|
void kinc_raytrace_pipeline_destroy(kinc_raytrace_pipeline_t *pipeline) {
|
|
pipeline->impl.dxr_state->Release();
|
|
pipeline->impl.raygen_shader_table->Release();
|
|
pipeline->impl.miss_shader_table->Release();
|
|
pipeline->impl.hitgroup_shader_table->Release();
|
|
}
|
|
|
|
void kinc_raytrace_acceleration_structure_init(kinc_raytrace_acceleration_structure_t *accel, kinc_g5_command_list_t *command_list, kinc_g5_vertex_buffer_t *vb,
|
|
kinc_g5_index_buffer_t *ib) {
|
|
// Reset the command list for the acceleration structure construction
|
|
command_list->impl._commandList->Reset(command_list->impl._commandAllocator, NULL);
|
|
|
|
D3D12_RAYTRACING_GEOMETRY_DESC geometryDesc = {};
|
|
geometryDesc.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES;
|
|
geometryDesc.Triangles.IndexBuffer = ib->impl.upload_buffer->GetGPUVirtualAddress();
|
|
geometryDesc.Triangles.IndexCount = ib->impl.count;
|
|
geometryDesc.Triangles.IndexFormat = ib->impl.format == KINC_G5_INDEX_BUFFER_FORMAT_16BIT ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;
|
|
geometryDesc.Triangles.Transform3x4 = 0;
|
|
geometryDesc.Triangles.VertexFormat = DXGI_FORMAT_R32G32B32_FLOAT;
|
|
geometryDesc.Triangles.VertexCount = vb->impl.myCount;
|
|
geometryDesc.Triangles.VertexBuffer.StartAddress = vb->impl.uploadBuffer->GetGPUVirtualAddress();
|
|
geometryDesc.Triangles.VertexBuffer.StrideInBytes = vb->impl.uploadBuffer->GetDesc().Width / vb->impl.myCount;
|
|
geometryDesc.Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_OPAQUE;
|
|
|
|
// Get required sizes for an acceleration structure
|
|
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS topLevelInputs = {};
|
|
topLevelInputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY;
|
|
topLevelInputs.Flags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE;
|
|
topLevelInputs.NumDescs = 1;
|
|
topLevelInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL;
|
|
|
|
D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO topLevelPrebuildInfo = {0};
|
|
dxrDevice->GetRaytracingAccelerationStructurePrebuildInfo(&topLevelInputs, &topLevelPrebuildInfo);
|
|
|
|
D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO bottomLevelPrebuildInfo = {0};
|
|
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS bottomLevelInputs = topLevelInputs;
|
|
bottomLevelInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL;
|
|
bottomLevelInputs.pGeometryDescs = &geometryDesc;
|
|
bottomLevelInputs.Flags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE;
|
|
dxrDevice->GetRaytracingAccelerationStructurePrebuildInfo(&bottomLevelInputs, &bottomLevelPrebuildInfo);
|
|
|
|
ID3D12Resource *scratchResource;
|
|
{
|
|
UINT64 tlSize = topLevelPrebuildInfo.ScratchDataSizeInBytes;
|
|
UINT64 blSize = bottomLevelPrebuildInfo.ScratchDataSizeInBytes;
|
|
D3D12_RESOURCE_DESC bufferDesc = {0};
|
|
bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
|
bufferDesc.Width = tlSize > blSize ? tlSize : blSize;
|
|
bufferDesc.Height = 1;
|
|
bufferDesc.DepthOrArraySize = 1;
|
|
bufferDesc.MipLevels = 1;
|
|
bufferDesc.Format = DXGI_FORMAT_UNKNOWN;
|
|
bufferDesc.SampleDesc.Count = 1;
|
|
bufferDesc.SampleDesc.Quality = 0;
|
|
bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
|
bufferDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
|
D3D12_HEAP_PROPERTIES uploadHeapProperties = {0};
|
|
uploadHeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
|
uploadHeapProperties.CreationNodeMask = 1;
|
|
uploadHeapProperties.VisibleNodeMask = 1;
|
|
|
|
device->CreateCommittedResource(&uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, NULL,
|
|
IID_GRAPHICS_PPV_ARGS(&scratchResource));
|
|
}
|
|
|
|
// Allocate resources for acceleration structures
|
|
// The resources that will contain acceleration structures must be created in the state D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE,
|
|
// and must have resource flag D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS.
|
|
{
|
|
D3D12_RESOURCE_DESC bufferDesc = {};
|
|
bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
|
bufferDesc.Width = bottomLevelPrebuildInfo.ResultDataMaxSizeInBytes;
|
|
bufferDesc.Height = 1;
|
|
bufferDesc.DepthOrArraySize = 1;
|
|
bufferDesc.MipLevels = 1;
|
|
bufferDesc.Format = DXGI_FORMAT_UNKNOWN;
|
|
bufferDesc.SampleDesc.Count = 1;
|
|
bufferDesc.SampleDesc.Quality = 0;
|
|
bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
|
bufferDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
|
D3D12_HEAP_PROPERTIES uploadHeapProperties = {};
|
|
uploadHeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
|
uploadHeapProperties.CreationNodeMask = 1;
|
|
uploadHeapProperties.VisibleNodeMask = 1;
|
|
|
|
device->CreateCommittedResource(&uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE, NULL,
|
|
IID_GRAPHICS_PPV_ARGS(&accel->impl.bottom_level_accel));
|
|
}
|
|
{
|
|
D3D12_RESOURCE_DESC bufferDesc = {};
|
|
bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
|
bufferDesc.Width = topLevelPrebuildInfo.ResultDataMaxSizeInBytes;
|
|
bufferDesc.Height = 1;
|
|
bufferDesc.DepthOrArraySize = 1;
|
|
bufferDesc.MipLevels = 1;
|
|
bufferDesc.Format = DXGI_FORMAT_UNKNOWN;
|
|
bufferDesc.SampleDesc.Count = 1;
|
|
bufferDesc.SampleDesc.Quality = 0;
|
|
bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
|
bufferDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
|
D3D12_HEAP_PROPERTIES uploadHeapProperties = {};
|
|
uploadHeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
|
uploadHeapProperties.CreationNodeMask = 1;
|
|
uploadHeapProperties.VisibleNodeMask = 1;
|
|
|
|
device->CreateCommittedResource(&uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE, NULL,
|
|
IID_GRAPHICS_PPV_ARGS(&accel->impl.top_level_accel));
|
|
}
|
|
|
|
// Create an instance desc for the bottom-level acceleration structure
|
|
ID3D12Resource *instanceDescs;
|
|
D3D12_RAYTRACING_INSTANCE_DESC instanceDesc = {0};
|
|
instanceDesc.Transform[0][0] = instanceDesc.Transform[1][1] = instanceDesc.Transform[2][2] = 1;
|
|
instanceDesc.InstanceMask = 1;
|
|
instanceDesc.AccelerationStructure = accel->impl.bottom_level_accel->GetGPUVirtualAddress();
|
|
|
|
D3D12_RESOURCE_DESC bufferDesc = {0};
|
|
bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
|
bufferDesc.Width = sizeof(instanceDesc);
|
|
bufferDesc.Height = 1;
|
|
bufferDesc.DepthOrArraySize = 1;
|
|
bufferDesc.MipLevels = 1;
|
|
bufferDesc.Format = DXGI_FORMAT_UNKNOWN;
|
|
bufferDesc.SampleDesc.Count = 1;
|
|
bufferDesc.SampleDesc.Quality = 0;
|
|
bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
|
D3D12_HEAP_PROPERTIES uploadHeapProperties = {};
|
|
uploadHeapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
|
uploadHeapProperties.CreationNodeMask = 1;
|
|
uploadHeapProperties.VisibleNodeMask = 1;
|
|
|
|
device->CreateCommittedResource(&uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
|
|
IID_GRAPHICS_PPV_ARGS(&instanceDescs));
|
|
void *mappedData;
|
|
instanceDescs->Map(0, NULL, &mappedData);
|
|
memcpy(mappedData, &instanceDesc, sizeof(instanceDesc));
|
|
instanceDescs->Unmap(0, NULL);
|
|
|
|
// Bottom Level Acceleration Structure desc
|
|
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC bottomLevelBuildDesc = {0};
|
|
bottomLevelBuildDesc.Inputs = bottomLevelInputs;
|
|
bottomLevelBuildDesc.ScratchAccelerationStructureData = scratchResource->GetGPUVirtualAddress();
|
|
bottomLevelBuildDesc.DestAccelerationStructureData = accel->impl.bottom_level_accel->GetGPUVirtualAddress();
|
|
|
|
// Top Level Acceleration Structure desc
|
|
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC topLevelBuildDesc = bottomLevelBuildDesc;
|
|
topLevelInputs.InstanceDescs = instanceDescs->GetGPUVirtualAddress();
|
|
topLevelBuildDesc.Inputs = topLevelInputs;
|
|
topLevelBuildDesc.DestAccelerationStructureData = accel->impl.top_level_accel->GetGPUVirtualAddress();
|
|
topLevelBuildDesc.ScratchAccelerationStructureData = scratchResource->GetGPUVirtualAddress();
|
|
|
|
// Build acceleration structure
|
|
dxrCommandList->BuildRaytracingAccelerationStructure(&bottomLevelBuildDesc, 0, NULL);
|
|
D3D12_RESOURCE_BARRIER barrier = {};
|
|
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
|
|
barrier.UAV.pResource = accel->impl.bottom_level_accel;
|
|
command_list->impl._commandList->ResourceBarrier(1, &barrier);
|
|
dxrCommandList->BuildRaytracingAccelerationStructure(&topLevelBuildDesc, 0, NULL);
|
|
|
|
kinc_g5_command_list_end(command_list);
|
|
kinc_g5_command_list_execute(command_list);
|
|
kinc_g5_command_list_wait_for_execution_to_finish(command_list);
|
|
kinc_g5_command_list_begin(command_list);
|
|
}
|
|
|
|
void kinc_raytrace_acceleration_structure_destroy(kinc_raytrace_acceleration_structure_t *accel) {
|
|
accel->impl.bottom_level_accel->Release();
|
|
accel->impl.top_level_accel->Release();
|
|
}
|
|
|
|
void kinc_raytrace_set_acceleration_structure(kinc_raytrace_acceleration_structure_t *_accel) {
|
|
accel = _accel;
|
|
}
|
|
|
|
void kinc_raytrace_set_pipeline(kinc_raytrace_pipeline_t *_pipeline) {
|
|
pipeline = _pipeline;
|
|
}
|
|
|
|
void kinc_raytrace_set_target(kinc_g5_texture_t *_output) {
|
|
if (_output != output) {
|
|
output = _output;
|
|
|
|
D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
|
|
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
|
|
device->CreateUnorderedAccessView(output->impl.image, NULL, &uavDesc, descriptorHeap->GetCPUDescriptorHandleForHeapStart());
|
|
}
|
|
}
|
|
|
|
void kinc_raytrace_dispatch_rays(kinc_g5_command_list_t *command_list) {
|
|
command_list->impl._commandList->SetComputeRootSignature(dxrRootSignature);
|
|
|
|
// Bind the heaps, acceleration structure and dispatch rays
|
|
command_list->impl._commandList->SetDescriptorHeaps(1, &descriptorHeap);
|
|
command_list->impl._commandList->SetComputeRootDescriptorTable(0, descriptorHeap->GetGPUDescriptorHandleForHeapStart());
|
|
command_list->impl._commandList->SetComputeRootShaderResourceView(1, accel->impl.top_level_accel->GetGPUVirtualAddress());
|
|
D3D12_GPU_VIRTUAL_ADDRESS cbGpuAddress = pipeline->_constant_buffer->impl.constant_buffer->GetGPUVirtualAddress();
|
|
command_list->impl._commandList->SetComputeRootConstantBufferView(2, cbGpuAddress);
|
|
|
|
// Since each shader table has only one shader record, the stride is same as the size.
|
|
D3D12_DISPATCH_RAYS_DESC dispatchDesc = {0};
|
|
dispatchDesc.HitGroupTable.StartAddress = pipeline->impl.hitgroup_shader_table->GetGPUVirtualAddress();
|
|
dispatchDesc.HitGroupTable.SizeInBytes = pipeline->impl.hitgroup_shader_table->GetDesc().Width;
|
|
dispatchDesc.HitGroupTable.StrideInBytes = dispatchDesc.HitGroupTable.SizeInBytes;
|
|
dispatchDesc.MissShaderTable.StartAddress = pipeline->impl.miss_shader_table->GetGPUVirtualAddress();
|
|
dispatchDesc.MissShaderTable.SizeInBytes = pipeline->impl.miss_shader_table->GetDesc().Width;
|
|
dispatchDesc.MissShaderTable.StrideInBytes = dispatchDesc.MissShaderTable.SizeInBytes;
|
|
dispatchDesc.RayGenerationShaderRecord.StartAddress = pipeline->impl.raygen_shader_table->GetGPUVirtualAddress();
|
|
dispatchDesc.RayGenerationShaderRecord.SizeInBytes = pipeline->impl.raygen_shader_table->GetDesc().Width;
|
|
dispatchDesc.Width = output->texWidth;
|
|
dispatchDesc.Height = output->texHeight;
|
|
dispatchDesc.Depth = 1;
|
|
dxrCommandList->SetPipelineState1(pipeline->impl.dxr_state);
|
|
dxrCommandList->DispatchRays(&dispatchDesc);
|
|
}
|
|
|
|
void kinc_raytrace_copy(kinc_g5_command_list_t *command_list, kinc_g5_render_target_t *target, kinc_g5_texture_t *source) {
|
|
D3D12_RESOURCE_BARRIER preCopyBarriers[2] = {};
|
|
preCopyBarriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
|
preCopyBarriers[0].Transition.pResource = target->impl.renderTarget;
|
|
preCopyBarriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
|
|
preCopyBarriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
|
|
preCopyBarriers[0].Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
|
preCopyBarriers[1].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
|
preCopyBarriers[1].Transition.pResource = source->impl.image;
|
|
preCopyBarriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
|
|
preCopyBarriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
|
preCopyBarriers[1].Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
|
command_list->impl._commandList->ResourceBarrier(ARRAYSIZE(preCopyBarriers), preCopyBarriers);
|
|
|
|
command_list->impl._commandList->CopyResource(target->impl.renderTarget, source->impl.image);
|
|
|
|
D3D12_RESOURCE_BARRIER postCopyBarriers[2] = {};
|
|
postCopyBarriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
|
postCopyBarriers[0].Transition.pResource = target->impl.renderTarget;
|
|
postCopyBarriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
|
postCopyBarriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
|
|
postCopyBarriers[0].Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
|
postCopyBarriers[1].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
|
postCopyBarriers[1].Transition.pResource = source->impl.image;
|
|
postCopyBarriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
|
postCopyBarriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
|
|
postCopyBarriers[1].Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
|
command_list->impl._commandList->ResourceBarrier(ARRAYSIZE(postCopyBarriers), postCopyBarriers);
|
|
}
|
|
|
|
#endif
|