Files
2025-01-29 10:55:49 +01:00

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