Updated ray tracing samples to final ray tracing extensions
This commit is contained in:
parent
02a9be4c62
commit
08be260685
16 changed files with 1168 additions and 1351 deletions
|
|
@ -612,5 +612,48 @@ namespace vks
|
|||
return specializationInfo;
|
||||
}
|
||||
|
||||
// Ray tracing related
|
||||
inline VkAccelerationStructureGeometryKHR accelerationStructureGeometryKHR()
|
||||
{
|
||||
VkAccelerationStructureGeometryKHR accelerationStructureGeometryKHR{};
|
||||
accelerationStructureGeometryKHR.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
|
||||
return accelerationStructureGeometryKHR;
|
||||
}
|
||||
|
||||
inline VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfoKHR()
|
||||
{
|
||||
VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfoKHR{};
|
||||
accelerationStructureBuildGeometryInfoKHR.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
|
||||
return accelerationStructureBuildGeometryInfoKHR;
|
||||
}
|
||||
|
||||
inline VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfoKHR()
|
||||
{
|
||||
VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfoKHR{};
|
||||
accelerationStructureBuildSizesInfoKHR.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR;
|
||||
return accelerationStructureBuildSizesInfoKHR;
|
||||
}
|
||||
|
||||
inline VkRayTracingShaderGroupCreateInfoKHR rayTracingShaderGroupCreateInfoKHR()
|
||||
{
|
||||
VkRayTracingShaderGroupCreateInfoKHR rayTracingShaderGroupCreateInfoKHR{};
|
||||
rayTracingShaderGroupCreateInfoKHR.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
|
||||
return rayTracingShaderGroupCreateInfoKHR;
|
||||
}
|
||||
|
||||
inline VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCreateInfoKHR()
|
||||
{
|
||||
VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCreateInfoKHR{};
|
||||
rayTracingPipelineCreateInfoKHR.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR;
|
||||
return rayTracingPipelineCreateInfoKHR;
|
||||
}
|
||||
|
||||
inline VkWriteDescriptorSetAccelerationStructureKHR writeDescriptorSetAccelerationStructureKHR()
|
||||
{
|
||||
VkWriteDescriptorSetAccelerationStructureKHR writeDescriptorSetAccelerationStructureKHR{};
|
||||
writeDescriptorSetAccelerationStructureKHR.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR;
|
||||
return writeDescriptorSetAccelerationStructureKHR;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
227
base/VulkanRaytracingSample.cpp
Normal file
227
base/VulkanRaytracingSample.cpp
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
* Extended sample base class for ray tracing based samples
|
||||
*
|
||||
* Copyright (C) 2020 by Sascha Willems - www.saschawillems.de
|
||||
*
|
||||
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "VulkanRaytracingSample.h"
|
||||
|
||||
void VulkanRaytracingSample::enableExtensions()
|
||||
{
|
||||
// Require Vulkan 1.1
|
||||
apiVersion = VK_API_VERSION_1_1;
|
||||
|
||||
// Ray tracing related extensions required by this sample
|
||||
enabledDeviceExtensions.push_back(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME);
|
||||
|
||||
// Required by VK_KHR_acceleration_structure
|
||||
enabledDeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
|
||||
|
||||
// Required for VK_KHR_ray_tracing_pipeline
|
||||
enabledDeviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME);
|
||||
|
||||
// Required by VK_KHR_spirv_1_4
|
||||
enabledDeviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
VulkanRaytracingSample::ScratchBuffer VulkanRaytracingSample::createScratchBuffer(VkDeviceSize size)
|
||||
{
|
||||
ScratchBuffer scratchBuffer{};
|
||||
// Buffer and memory
|
||||
VkBufferCreateInfo bufferCreateInfo{};
|
||||
bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
bufferCreateInfo.size = size;
|
||||
bufferCreateInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
|
||||
VK_CHECK_RESULT(vkCreateBuffer(vulkanDevice->logicalDevice, &bufferCreateInfo, nullptr, &scratchBuffer.handle));
|
||||
VkMemoryRequirements memoryRequirements{};
|
||||
vkGetBufferMemoryRequirements(vulkanDevice->logicalDevice, scratchBuffer.handle, &memoryRequirements);
|
||||
VkMemoryAllocateFlagsInfo memoryAllocateFlagsInfo{};
|
||||
memoryAllocateFlagsInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO;
|
||||
memoryAllocateFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR;
|
||||
VkMemoryAllocateInfo memoryAllocateInfo = {};
|
||||
memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
memoryAllocateInfo.pNext = &memoryAllocateFlagsInfo;
|
||||
memoryAllocateInfo.allocationSize = memoryRequirements.size;
|
||||
memoryAllocateInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
VK_CHECK_RESULT(vkAllocateMemory(vulkanDevice->logicalDevice, &memoryAllocateInfo, nullptr, &scratchBuffer.memory));
|
||||
VK_CHECK_RESULT(vkBindBufferMemory(vulkanDevice->logicalDevice, scratchBuffer.handle, scratchBuffer.memory, 0));
|
||||
// Buffer device address
|
||||
VkBufferDeviceAddressInfoKHR bufferDeviceAddresInfo{};
|
||||
bufferDeviceAddresInfo.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
|
||||
bufferDeviceAddresInfo.buffer = scratchBuffer.handle;
|
||||
scratchBuffer.deviceAddress = vkGetBufferDeviceAddressKHR(vulkanDevice->logicalDevice, &bufferDeviceAddresInfo);
|
||||
return scratchBuffer;
|
||||
}
|
||||
|
||||
void VulkanRaytracingSample::deleteScratchBuffer(ScratchBuffer& scratchBuffer)
|
||||
{
|
||||
if (scratchBuffer.memory != VK_NULL_HANDLE) {
|
||||
vkFreeMemory(vulkanDevice->logicalDevice, scratchBuffer.memory, nullptr);
|
||||
}
|
||||
if (scratchBuffer.handle != VK_NULL_HANDLE) {
|
||||
vkDestroyBuffer(vulkanDevice->logicalDevice, scratchBuffer.handle, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanRaytracingSample::createAccelerationStructure(AccelerationStructure& accelerationStructure, VkAccelerationStructureTypeKHR type, VkAccelerationStructureBuildSizesInfoKHR buildSizeInfo)
|
||||
{
|
||||
// Buffer and memory
|
||||
VkBufferCreateInfo bufferCreateInfo{};
|
||||
bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
bufferCreateInfo.size = buildSizeInfo.accelerationStructureSize;
|
||||
bufferCreateInfo.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
|
||||
VK_CHECK_RESULT(vkCreateBuffer(vulkanDevice->logicalDevice, &bufferCreateInfo, nullptr, &accelerationStructure.buffer));
|
||||
VkMemoryRequirements memoryRequirements{};
|
||||
vkGetBufferMemoryRequirements(vulkanDevice->logicalDevice, accelerationStructure.buffer, &memoryRequirements);
|
||||
VkMemoryAllocateFlagsInfo memoryAllocateFlagsInfo{};
|
||||
memoryAllocateFlagsInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO;
|
||||
memoryAllocateFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR;
|
||||
VkMemoryAllocateInfo memoryAllocateInfo{};
|
||||
memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
memoryAllocateInfo.pNext = &memoryAllocateFlagsInfo;
|
||||
memoryAllocateInfo.allocationSize = memoryRequirements.size;
|
||||
memoryAllocateInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
VK_CHECK_RESULT(vkAllocateMemory(vulkanDevice->logicalDevice, &memoryAllocateInfo, nullptr, &accelerationStructure.memory));
|
||||
VK_CHECK_RESULT(vkBindBufferMemory(vulkanDevice->logicalDevice, accelerationStructure.buffer, accelerationStructure.memory, 0));
|
||||
// Acceleration structure
|
||||
VkAccelerationStructureCreateInfoKHR accelerationStructureCreate_info{};
|
||||
accelerationStructureCreate_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR;
|
||||
accelerationStructureCreate_info.buffer = accelerationStructure.buffer;
|
||||
accelerationStructureCreate_info.size = buildSizeInfo.accelerationStructureSize;
|
||||
accelerationStructureCreate_info.type = type;
|
||||
vkCreateAccelerationStructureKHR(vulkanDevice->logicalDevice, &accelerationStructureCreate_info, nullptr, &accelerationStructure.handle);
|
||||
// AS device address
|
||||
VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{};
|
||||
accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
|
||||
accelerationDeviceAddressInfo.accelerationStructure = accelerationStructure.handle;
|
||||
accelerationStructure.deviceAddress = vkGetAccelerationStructureDeviceAddressKHR(vulkanDevice->logicalDevice, &accelerationDeviceAddressInfo);
|
||||
}
|
||||
|
||||
void VulkanRaytracingSample::deleteAccelerationStructure(AccelerationStructure& accelerationStructure)
|
||||
{
|
||||
vkFreeMemory(device, accelerationStructure.memory, nullptr);
|
||||
vkDestroyBuffer(device, accelerationStructure.buffer, nullptr);
|
||||
vkDestroyAccelerationStructureKHR(device, accelerationStructure.handle, nullptr);
|
||||
}
|
||||
|
||||
uint64_t VulkanRaytracingSample::getBufferDeviceAddress(VkBuffer buffer)
|
||||
{
|
||||
VkBufferDeviceAddressInfoKHR bufferDeviceAI{};
|
||||
bufferDeviceAI.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
|
||||
bufferDeviceAI.buffer = buffer;
|
||||
return vkGetBufferDeviceAddressKHR(vulkanDevice->logicalDevice, &bufferDeviceAI);
|
||||
}
|
||||
|
||||
void VulkanRaytracingSample::createStorageImage(VkFormat format, VkExtent3D extent)
|
||||
{
|
||||
// Release ressources if image is to be recreated
|
||||
if (storageImage.image != VK_NULL_HANDLE) {
|
||||
vkDestroyImageView(device, storageImage.view, nullptr);
|
||||
vkDestroyImage(device, storageImage.image, nullptr);
|
||||
vkFreeMemory(device, storageImage.memory, nullptr);
|
||||
storageImage = {};
|
||||
}
|
||||
|
||||
VkImageCreateInfo image = vks::initializers::imageCreateInfo();
|
||||
image.imageType = VK_IMAGE_TYPE_2D;
|
||||
image.format = format;
|
||||
image.extent = extent;
|
||||
image.mipLevels = 1;
|
||||
image.arrayLayers = 1;
|
||||
image.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
image.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
image.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
|
||||
image.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VK_CHECK_RESULT(vkCreateImage(vulkanDevice->logicalDevice, &image, nullptr, &storageImage.image));
|
||||
|
||||
VkMemoryRequirements memReqs;
|
||||
vkGetImageMemoryRequirements(vulkanDevice->logicalDevice, storageImage.image, &memReqs);
|
||||
VkMemoryAllocateInfo memoryAllocateInfo = vks::initializers::memoryAllocateInfo();
|
||||
memoryAllocateInfo.allocationSize = memReqs.size;
|
||||
memoryAllocateInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
VK_CHECK_RESULT(vkAllocateMemory(vulkanDevice->logicalDevice, &memoryAllocateInfo, nullptr, &storageImage.memory));
|
||||
VK_CHECK_RESULT(vkBindImageMemory(vulkanDevice->logicalDevice, storageImage.image, storageImage.memory, 0));
|
||||
|
||||
VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo();
|
||||
colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
colorImageView.format = format;
|
||||
colorImageView.subresourceRange = {};
|
||||
colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
colorImageView.subresourceRange.baseMipLevel = 0;
|
||||
colorImageView.subresourceRange.levelCount = 1;
|
||||
colorImageView.subresourceRange.baseArrayLayer = 0;
|
||||
colorImageView.subresourceRange.layerCount = 1;
|
||||
colorImageView.image = storageImage.image;
|
||||
VK_CHECK_RESULT(vkCreateImageView(vulkanDevice->logicalDevice, &colorImageView, nullptr, &storageImage.view));
|
||||
|
||||
VkCommandBuffer cmdBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||
vks::tools::setImageLayout(cmdBuffer, storageImage.image,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_GENERAL,
|
||||
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
|
||||
vulkanDevice->flushCommandBuffer(cmdBuffer, queue);
|
||||
}
|
||||
|
||||
void VulkanRaytracingSample::deleteStorageImage()
|
||||
{
|
||||
vkDestroyImageView(vulkanDevice->logicalDevice, storageImage.view, nullptr);
|
||||
vkDestroyImage(vulkanDevice->logicalDevice, storageImage.image, nullptr);
|
||||
vkFreeMemory(vulkanDevice->logicalDevice, storageImage.memory, nullptr);
|
||||
}
|
||||
|
||||
void VulkanRaytracingSample::prepare()
|
||||
{
|
||||
VulkanExampleBase::prepare();
|
||||
// Get properties and features
|
||||
rayTracingPipelineProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;
|
||||
VkPhysicalDeviceProperties2 deviceProperties2{};
|
||||
deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
|
||||
deviceProperties2.pNext = &rayTracingPipelineProperties;
|
||||
vkGetPhysicalDeviceProperties2(physicalDevice, &deviceProperties2);
|
||||
accelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR;
|
||||
VkPhysicalDeviceFeatures2 deviceFeatures2{};
|
||||
deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
|
||||
deviceFeatures2.pNext = &accelerationStructureFeatures;
|
||||
vkGetPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures2);
|
||||
// Get the function pointers required for ray tracing
|
||||
vkGetBufferDeviceAddressKHR = reinterpret_cast<PFN_vkGetBufferDeviceAddressKHR>(vkGetDeviceProcAddr(device, "vkGetBufferDeviceAddressKHR"));
|
||||
vkCmdBuildAccelerationStructuresKHR = reinterpret_cast<PFN_vkCmdBuildAccelerationStructuresKHR>(vkGetDeviceProcAddr(device, "vkCmdBuildAccelerationStructuresKHR"));
|
||||
vkBuildAccelerationStructuresKHR = reinterpret_cast<PFN_vkBuildAccelerationStructuresKHR>(vkGetDeviceProcAddr(device, "vkBuildAccelerationStructuresKHR"));
|
||||
vkCreateAccelerationStructureKHR = reinterpret_cast<PFN_vkCreateAccelerationStructureKHR>(vkGetDeviceProcAddr(device, "vkCreateAccelerationStructureKHR"));
|
||||
vkDestroyAccelerationStructureKHR = reinterpret_cast<PFN_vkDestroyAccelerationStructureKHR>(vkGetDeviceProcAddr(device, "vkDestroyAccelerationStructureKHR"));
|
||||
vkGetAccelerationStructureBuildSizesKHR = reinterpret_cast<PFN_vkGetAccelerationStructureBuildSizesKHR>(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureBuildSizesKHR"));
|
||||
vkGetAccelerationStructureDeviceAddressKHR = reinterpret_cast<PFN_vkGetAccelerationStructureDeviceAddressKHR>(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureDeviceAddressKHR"));
|
||||
vkCmdTraceRaysKHR = reinterpret_cast<PFN_vkCmdTraceRaysKHR>(vkGetDeviceProcAddr(device, "vkCmdTraceRaysKHR"));
|
||||
vkGetRayTracingShaderGroupHandlesKHR = reinterpret_cast<PFN_vkGetRayTracingShaderGroupHandlesKHR>(vkGetDeviceProcAddr(device, "vkGetRayTracingShaderGroupHandlesKHR"));
|
||||
vkCreateRayTracingPipelinesKHR = reinterpret_cast<PFN_vkCreateRayTracingPipelinesKHR>(vkGetDeviceProcAddr(device, "vkCreateRayTracingPipelinesKHR"));
|
||||
}
|
||||
|
||||
VkStridedDeviceAddressRegionKHR VulkanRaytracingSample::getSbtEntryStridedDeviceAddressRegion(VkBuffer buffer, uint32_t handleCount)
|
||||
{
|
||||
VkStridedDeviceAddressRegionKHR stridedDeviceAddressRegionKHR{};
|
||||
stridedDeviceAddressRegionKHR.deviceAddress = getBufferDeviceAddress(buffer);
|
||||
stridedDeviceAddressRegionKHR.stride = rayTracingPipelineProperties.shaderGroupHandleSize;
|
||||
stridedDeviceAddressRegionKHR.size = rayTracingPipelineProperties.shaderGroupHandleSize * handleCount;
|
||||
return stridedDeviceAddressRegionKHR;
|
||||
}
|
||||
|
||||
void VulkanRaytracingSample::createShaderBindingTable(ShaderBindingTable& shaderBindingTable, uint32_t handleCount)
|
||||
{
|
||||
// Create buffer to hold all shader handles for the SBT
|
||||
VK_CHECK_RESULT(vulkanDevice->createBuffer(
|
||||
VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
&shaderBindingTable,
|
||||
rayTracingPipelineProperties.shaderGroupHandleSize * handleCount));
|
||||
// Get the strided address to be used when dispatching the rays
|
||||
shaderBindingTable.stridedDeviceAddressRegion = getSbtEntryStridedDeviceAddressRegion(shaderBindingTable.buffer, handleCount);
|
||||
// Map persistent
|
||||
shaderBindingTable.map();
|
||||
}
|
||||
82
base/VulkanRaytracingSample.h
Normal file
82
base/VulkanRaytracingSample.h
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Extended sample base class for ray tracing based samples
|
||||
*
|
||||
* Copyright (C) 2020 by Sascha Willems - www.saschawillems.de
|
||||
*
|
||||
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "vulkan/vulkan.h"
|
||||
#include "vulkanexamplebase.h"
|
||||
#include "VulkanTools.h"
|
||||
#include "VulkanDevice.h"
|
||||
|
||||
class VulkanRaytracingSample : public VulkanExampleBase
|
||||
{
|
||||
public:
|
||||
// Function pointers for ray tracing related stuff
|
||||
PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR;
|
||||
PFN_vkCreateAccelerationStructureKHR vkCreateAccelerationStructureKHR;
|
||||
PFN_vkDestroyAccelerationStructureKHR vkDestroyAccelerationStructureKHR;
|
||||
PFN_vkGetAccelerationStructureBuildSizesKHR vkGetAccelerationStructureBuildSizesKHR;
|
||||
PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR;
|
||||
PFN_vkBuildAccelerationStructuresKHR vkBuildAccelerationStructuresKHR;
|
||||
PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR;
|
||||
PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR;
|
||||
PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR;
|
||||
PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR;
|
||||
|
||||
// Available features and properties
|
||||
VkPhysicalDeviceRayTracingPipelinePropertiesKHR rayTracingPipelineProperties{};
|
||||
VkPhysicalDeviceAccelerationStructureFeaturesKHR accelerationStructureFeatures{};
|
||||
|
||||
// Enabled features and properties
|
||||
VkPhysicalDeviceBufferDeviceAddressFeatures enabledBufferDeviceAddresFeatures{};
|
||||
VkPhysicalDeviceRayTracingPipelineFeaturesKHR enabledRayTracingPipelineFeatures{};
|
||||
VkPhysicalDeviceAccelerationStructureFeaturesKHR enabledAccelerationStructureFeatures{};
|
||||
|
||||
// Holds information for a ray tracing scratch buffer that is used as a temporary storage
|
||||
struct ScratchBuffer
|
||||
{
|
||||
uint64_t deviceAddress = 0;
|
||||
VkBuffer handle = VK_NULL_HANDLE;
|
||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
// Holds information for a ray tracing tracing acceleration structure
|
||||
struct AccelerationStructure {
|
||||
VkAccelerationStructureKHR handle;
|
||||
uint64_t deviceAddress = 0;
|
||||
VkDeviceMemory memory;
|
||||
VkBuffer buffer;
|
||||
};
|
||||
|
||||
// Holds information for a storage image that the ray tracing shaders output to
|
||||
struct StorageImage {
|
||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
VkImage image = VK_NULL_HANDLE;
|
||||
VkImageView view = VK_NULL_HANDLE;
|
||||
VkFormat format;
|
||||
} storageImage;
|
||||
|
||||
// Extends the buffer class and holds information for a shader binding table
|
||||
class ShaderBindingTable : public vks::Buffer {
|
||||
public:
|
||||
VkStridedDeviceAddressRegionKHR stridedDeviceAddressRegion{};
|
||||
};
|
||||
|
||||
void enableExtensions();
|
||||
ScratchBuffer createScratchBuffer(VkDeviceSize size);
|
||||
void deleteScratchBuffer(ScratchBuffer& scratchBuffer);
|
||||
void createAccelerationStructure(AccelerationStructure& accelerationStructure, VkAccelerationStructureTypeKHR type, VkAccelerationStructureBuildSizesInfoKHR buildSizeInfo);
|
||||
void deleteAccelerationStructure(AccelerationStructure& accelerationStructure);
|
||||
uint64_t getBufferDeviceAddress(VkBuffer buffer);
|
||||
void createStorageImage(VkFormat format, VkExtent3D extent);
|
||||
void deleteStorageImage();
|
||||
VkStridedDeviceAddressRegionKHR getSbtEntryStridedDeviceAddressRegion(VkBuffer buffer, uint32_t handleCount);
|
||||
void createShaderBindingTable(ShaderBindingTable& shaderBindingTable, uint32_t handleCount);
|
||||
|
||||
virtual void prepare();
|
||||
};
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,71 +1,61 @@
|
|||
/*
|
||||
* Vulkan Example - Basic hardware accelerated ray tracing example using VK_KHR_ray_traying
|
||||
* Vulkan Example - Basic hardware accelerated ray tracing example
|
||||
*
|
||||
* Copyright (C) 2019-2020 by Sascha Willems - www.saschawillems.de
|
||||
*
|
||||
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
||||
*/
|
||||
|
||||
#define VK_ENABLE_BETA_EXTENSIONS
|
||||
|
||||
#include "vulkanexamplebase.h"
|
||||
|
||||
// Holds data for a ray tracing scratch buffer that is used as a temporary storage
|
||||
struct RayTracingScratchBuffer
|
||||
{
|
||||
uint64_t deviceAddress = 0;
|
||||
VkBuffer buffer = VK_NULL_HANDLE;
|
||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
// Holds data for a memory object bound to an acceleration structure
|
||||
struct RayTracingObjectMemory
|
||||
{
|
||||
uint64_t deviceAddress = 0;
|
||||
VkBuffer handle = VK_NULL_HANDLE;
|
||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
// Ray tracing acceleration structure
|
||||
struct AccelerationStructure {
|
||||
VkAccelerationStructureKHR accelerationStructure;
|
||||
uint64_t handle;
|
||||
RayTracingObjectMemory objectMemory;
|
||||
VkAccelerationStructureKHR handle;
|
||||
uint64_t deviceAddress = 0;
|
||||
VkDeviceMemory memory;
|
||||
VkBuffer buffer;
|
||||
};
|
||||
|
||||
// Indices for the different ray tracing shader types used in this example
|
||||
#define INDEX_RAYGEN_GROUP 0
|
||||
#define INDEX_MISS_GROUP 1
|
||||
#define INDEX_CLOSEST_HIT_GROUP 2
|
||||
|
||||
class VulkanExample : public VulkanExampleBase
|
||||
{
|
||||
public:
|
||||
PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR;
|
||||
PFN_vkBindAccelerationStructureMemoryKHR vkBindAccelerationStructureMemoryKHR;
|
||||
PFN_vkCreateAccelerationStructureKHR vkCreateAccelerationStructureKHR;
|
||||
PFN_vkDestroyAccelerationStructureKHR vkDestroyAccelerationStructureKHR;
|
||||
PFN_vkGetAccelerationStructureMemoryRequirementsKHR vkGetAccelerationStructureMemoryRequirementsKHR;
|
||||
PFN_vkCmdBuildAccelerationStructureKHR vkCmdBuildAccelerationStructureKHR;
|
||||
PFN_vkBuildAccelerationStructureKHR vkBuildAccelerationStructureKHR;
|
||||
PFN_vkGetAccelerationStructureBuildSizesKHR vkGetAccelerationStructureBuildSizesKHR;
|
||||
PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR;
|
||||
PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR;
|
||||
PFN_vkBuildAccelerationStructuresKHR vkBuildAccelerationStructuresKHR;
|
||||
PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR;
|
||||
PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR;
|
||||
PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR;
|
||||
|
||||
VkPhysicalDeviceRayTracingPropertiesKHR rayTracingProperties{};
|
||||
VkPhysicalDeviceRayTracingFeaturesKHR rayTracingFeatures{};
|
||||
VkPhysicalDeviceRayTracingPipelinePropertiesKHR rayTracingPipelineProperties{};
|
||||
VkPhysicalDeviceAccelerationStructureFeaturesKHR accelerationStructureFeatures{};
|
||||
|
||||
VkPhysicalDeviceBufferDeviceAddressFeatures enabledBufferDeviceAddresFeatures{};
|
||||
VkPhysicalDeviceRayTracingFeaturesKHR enabledRayTracingFeatures{};
|
||||
VkPhysicalDeviceRayTracingPipelineFeaturesKHR enabledRayTracingPipelineFeatures{};
|
||||
VkPhysicalDeviceAccelerationStructureFeaturesKHR enabledAccelerationStructureFeatures{};
|
||||
|
||||
AccelerationStructure bottomLevelAS;
|
||||
AccelerationStructure topLevelAS;
|
||||
AccelerationStructure bottomLevelAS{};
|
||||
AccelerationStructure topLevelAS{};
|
||||
|
||||
vks::Buffer vertexBuffer;
|
||||
vks::Buffer indexBuffer;
|
||||
uint32_t indexCount;
|
||||
vks::Buffer transformBuffer;
|
||||
std::vector<VkRayTracingShaderGroupCreateInfoKHR> shaderGroups{};
|
||||
vks::Buffer shaderBindingTable;
|
||||
vks::Buffer raygenShaderBindingTable;
|
||||
vks::Buffer missShaderBindingTable;
|
||||
vks::Buffer hitShaderBindingTable;
|
||||
|
||||
struct StorageImage {
|
||||
VkDeviceMemory memory;
|
||||
|
|
@ -88,22 +78,29 @@ public:
|
|||
VulkanExample() : VulkanExampleBase()
|
||||
{
|
||||
title = "Ray tracing basic";
|
||||
settings.overlay = true;
|
||||
settings.overlay = false;
|
||||
camera.type = Camera::CameraType::lookat;
|
||||
camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f);
|
||||
camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f));
|
||||
camera.setTranslation(glm::vec3(0.0f, 0.0f, -2.5f));
|
||||
// Enable instance and device extensions required to use VK_KHR_ray_tracing
|
||||
enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_RAY_TRACING_EXTENSION_NAME);
|
||||
|
||||
// Require Vulkan 1.1
|
||||
apiVersion = VK_API_VERSION_1_1;
|
||||
|
||||
// Ray tracing related extensions required by this sample
|
||||
enabledDeviceExtensions.push_back(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME);
|
||||
|
||||
// Required by VK_KHR_acceleration_structure
|
||||
enabledDeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME);
|
||||
// We require Vulkan 1.2 for ray tracing
|
||||
apiVersion = VK_API_VERSION_1_2;
|
||||
|
||||
// Required for VK_KHR_ray_tracing_pipeline
|
||||
enabledDeviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME);
|
||||
|
||||
// Required by VK_KHR_spirv_1_4
|
||||
enabledDeviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
~VulkanExample()
|
||||
|
|
@ -114,59 +111,53 @@ public:
|
|||
vkDestroyImageView(device, storageImage.view, nullptr);
|
||||
vkDestroyImage(device, storageImage.image, nullptr);
|
||||
vkFreeMemory(device, storageImage.memory, nullptr);
|
||||
vkDestroyAccelerationStructureKHR(device, bottomLevelAS.accelerationStructure, nullptr);
|
||||
vkDestroyAccelerationStructureKHR(device, topLevelAS.accelerationStructure, nullptr);
|
||||
vkFreeMemory(device, bottomLevelAS.memory, nullptr);
|
||||
vkDestroyBuffer(device, bottomLevelAS.buffer, nullptr);
|
||||
vkDestroyAccelerationStructureKHR(device, bottomLevelAS.handle, nullptr);
|
||||
vkFreeMemory(device, topLevelAS.memory, nullptr);
|
||||
vkDestroyBuffer(device, topLevelAS.buffer, nullptr);
|
||||
vkDestroyAccelerationStructureKHR(device, topLevelAS.handle, nullptr);
|
||||
vertexBuffer.destroy();
|
||||
indexBuffer.destroy();
|
||||
shaderBindingTable.destroy();
|
||||
transformBuffer.destroy();
|
||||
raygenShaderBindingTable.destroy();
|
||||
missShaderBindingTable.destroy();
|
||||
hitShaderBindingTable.destroy();
|
||||
ubo.destroy();
|
||||
deleteObjectMemory(bottomLevelAS.objectMemory);
|
||||
deleteObjectMemory(topLevelAS.objectMemory);
|
||||
}
|
||||
|
||||
/*
|
||||
Create a scratch buffer to hold temporary data for a ray tracing acceleration structure
|
||||
*/
|
||||
RayTracingScratchBuffer createScratchBuffer(VkAccelerationStructureKHR accelerationStructure)
|
||||
RayTracingScratchBuffer createScratchBuffer(VkDeviceSize size)
|
||||
{
|
||||
RayTracingScratchBuffer scratchBuffer{};
|
||||
|
||||
VkMemoryRequirements2 memoryRequirements2{};
|
||||
memoryRequirements2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
|
||||
|
||||
VkAccelerationStructureMemoryRequirementsInfoKHR accelerationStructureMemoryRequirements{};
|
||||
accelerationStructureMemoryRequirements.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR;
|
||||
accelerationStructureMemoryRequirements.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR;
|
||||
accelerationStructureMemoryRequirements.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR;
|
||||
accelerationStructureMemoryRequirements.accelerationStructure = accelerationStructure;
|
||||
vkGetAccelerationStructureMemoryRequirementsKHR(device, &accelerationStructureMemoryRequirements, &memoryRequirements2);
|
||||
|
||||
VkBufferCreateInfo bufferCI{};
|
||||
bufferCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
bufferCI.size = memoryRequirements2.memoryRequirements.size;
|
||||
bufferCI.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
|
||||
bufferCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCI, nullptr, &scratchBuffer.buffer));
|
||||
VkBufferCreateInfo bufferCreateInfo{};
|
||||
bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
bufferCreateInfo.size = size;
|
||||
bufferCreateInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
|
||||
VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &scratchBuffer.handle));
|
||||
|
||||
VkMemoryRequirements memoryRequirements{};
|
||||
vkGetBufferMemoryRequirements(device, scratchBuffer.buffer, &memoryRequirements);
|
||||
vkGetBufferMemoryRequirements(device, scratchBuffer.handle, &memoryRequirements);
|
||||
|
||||
VkMemoryAllocateFlagsInfo memoryAllocateFI{};
|
||||
memoryAllocateFI.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO;
|
||||
memoryAllocateFI.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR;
|
||||
VkMemoryAllocateFlagsInfo memoryAllocateFlagsInfo{};
|
||||
memoryAllocateFlagsInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO;
|
||||
memoryAllocateFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR;
|
||||
|
||||
VkMemoryAllocateInfo memoryAI{};
|
||||
memoryAI.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
memoryAI.pNext = &memoryAllocateFI;
|
||||
memoryAI.allocationSize = memoryRequirements.size;
|
||||
memoryAI.memoryTypeIndex = vulkanDevice->getMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
VK_CHECK_RESULT(vkAllocateMemory(device, &memoryAI, nullptr, &scratchBuffer.memory));
|
||||
VK_CHECK_RESULT(vkBindBufferMemory(device, scratchBuffer.buffer, scratchBuffer.memory, 0));
|
||||
VkMemoryAllocateInfo memoryAllocateInfo = {};
|
||||
memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
memoryAllocateInfo.pNext = &memoryAllocateFlagsInfo;
|
||||
memoryAllocateInfo.allocationSize = memoryRequirements.size;
|
||||
memoryAllocateInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
VK_CHECK_RESULT(vkAllocateMemory(device, &memoryAllocateInfo, nullptr, &scratchBuffer.memory));
|
||||
VK_CHECK_RESULT(vkBindBufferMemory(device, scratchBuffer.handle, scratchBuffer.memory, 0));
|
||||
|
||||
VkBufferDeviceAddressInfoKHR buffer_device_address_info{};
|
||||
buffer_device_address_info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
|
||||
buffer_device_address_info.buffer = scratchBuffer.buffer;
|
||||
scratchBuffer.deviceAddress = vkGetBufferDeviceAddressKHR(device, &buffer_device_address_info);
|
||||
VkBufferDeviceAddressInfoKHR bufferDeviceAddressInfo{};
|
||||
bufferDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
|
||||
bufferDeviceAddressInfo.buffer = scratchBuffer.handle;
|
||||
scratchBuffer.deviceAddress = vkGetBufferDeviceAddressKHR(device, &bufferDeviceAddressInfo);
|
||||
|
||||
return scratchBuffer;
|
||||
}
|
||||
|
|
@ -176,45 +167,32 @@ public:
|
|||
if (scratchBuffer.memory != VK_NULL_HANDLE) {
|
||||
vkFreeMemory(device, scratchBuffer.memory, nullptr);
|
||||
}
|
||||
if (scratchBuffer.buffer != VK_NULL_HANDLE) {
|
||||
vkDestroyBuffer(device, scratchBuffer.buffer, nullptr);
|
||||
if (scratchBuffer.handle != VK_NULL_HANDLE) {
|
||||
vkDestroyBuffer(device, scratchBuffer.handle, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate memory that will be attached to a ray tracing acceleration structure
|
||||
*/
|
||||
RayTracingObjectMemory createObjectMemory(VkAccelerationStructureKHR acceleration_structure)
|
||||
void createAccelerationStructureBuffer(AccelerationStructure &accelerationStructure, VkAccelerationStructureBuildSizesInfoKHR buildSizeInfo)
|
||||
{
|
||||
RayTracingObjectMemory objectMemory{};
|
||||
|
||||
VkMemoryRequirements2 memoryRequirements2{};
|
||||
memoryRequirements2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
|
||||
|
||||
VkAccelerationStructureMemoryRequirementsInfoKHR accelerationStructureMemoryRequirements{};
|
||||
accelerationStructureMemoryRequirements.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR;
|
||||
accelerationStructureMemoryRequirements.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR;
|
||||
accelerationStructureMemoryRequirements.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR;
|
||||
accelerationStructureMemoryRequirements.accelerationStructure = acceleration_structure;
|
||||
vkGetAccelerationStructureMemoryRequirementsKHR(device, &accelerationStructureMemoryRequirements, &memoryRequirements2);
|
||||
|
||||
VkMemoryRequirements memoryRequirements = memoryRequirements2.memoryRequirements;
|
||||
|
||||
VkMemoryAllocateInfo memoryAI{};
|
||||
memoryAI.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
memoryAI.allocationSize = memoryRequirements.size;
|
||||
memoryAI.memoryTypeIndex = vulkanDevice->getMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
VK_CHECK_RESULT(vkAllocateMemory(device, &memoryAI, nullptr, &objectMemory.memory));
|
||||
|
||||
return objectMemory;
|
||||
VkBufferCreateInfo bufferCreateInfo{};
|
||||
bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
bufferCreateInfo.size = buildSizeInfo.accelerationStructureSize;
|
||||
bufferCreateInfo.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
|
||||
VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &accelerationStructure.buffer));
|
||||
VkMemoryRequirements memoryRequirements{};
|
||||
vkGetBufferMemoryRequirements(device, accelerationStructure.buffer, &memoryRequirements);
|
||||
VkMemoryAllocateFlagsInfo memoryAllocateFlagsInfo{};
|
||||
memoryAllocateFlagsInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO;
|
||||
memoryAllocateFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR;
|
||||
VkMemoryAllocateInfo memoryAllocateInfo{};
|
||||
memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
memoryAllocateInfo.pNext = &memoryAllocateFlagsInfo;
|
||||
memoryAllocateInfo.allocationSize = memoryRequirements.size;
|
||||
memoryAllocateInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
VK_CHECK_RESULT(vkAllocateMemory(device, &memoryAllocateInfo, nullptr, &accelerationStructure.memory));
|
||||
VK_CHECK_RESULT(vkBindBufferMemory(device, accelerationStructure.buffer, accelerationStructure.memory, 0));
|
||||
}
|
||||
|
||||
void deleteObjectMemory(RayTracingObjectMemory& objectMemory)
|
||||
{
|
||||
if (objectMemory.memory != VK_NULL_HANDLE) {
|
||||
vkFreeMemory(device, objectMemory.memory, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Gets the device address from a buffer that's required for some of the buffers used for ray tracing
|
||||
|
|
@ -293,109 +271,134 @@ public:
|
|||
std::vector<uint32_t> indices = { 0, 1, 2 };
|
||||
indexCount = static_cast<uint32_t>(indices.size());
|
||||
|
||||
// Setup identity transform matrix
|
||||
VkTransformMatrixKHR transformMatrix = {
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f
|
||||
};
|
||||
|
||||
// Create buffers
|
||||
// For the sake of simplicity we won't stage the vertex data to the GPU memory
|
||||
// Vertex buffer
|
||||
VK_CHECK_RESULT(vulkanDevice->createBuffer(
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
|
||||
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
&vertexBuffer,
|
||||
vertices.size() * sizeof(Vertex),
|
||||
vertices.data()));
|
||||
// Index buffer
|
||||
VK_CHECK_RESULT(vulkanDevice->createBuffer(
|
||||
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
|
||||
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
&indexBuffer,
|
||||
indices.size() * sizeof(uint32_t),
|
||||
indices.data()));
|
||||
// Transform buffer
|
||||
VK_CHECK_RESULT(vulkanDevice->createBuffer(
|
||||
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
&transformBuffer,
|
||||
sizeof(VkTransformMatrixKHR),
|
||||
&transformMatrix));
|
||||
|
||||
VkDeviceOrHostAddressConstKHR vertexBufferDeviceAddress{};
|
||||
VkDeviceOrHostAddressConstKHR indexBufferDeviceAddress{};
|
||||
|
||||
VkDeviceOrHostAddressConstKHR transformBufferDeviceAddress{};
|
||||
|
||||
vertexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(vertexBuffer.buffer);
|
||||
indexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(indexBuffer.buffer);
|
||||
transformBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(transformBuffer.buffer);
|
||||
|
||||
VkAccelerationStructureCreateGeometryTypeInfoKHR accelerationCreateGeometryInfo{};
|
||||
accelerationCreateGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR;
|
||||
accelerationCreateGeometryInfo.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
|
||||
accelerationCreateGeometryInfo.maxPrimitiveCount = 1;
|
||||
accelerationCreateGeometryInfo.indexType = VK_INDEX_TYPE_UINT32;
|
||||
accelerationCreateGeometryInfo.maxVertexCount = static_cast<uint32_t>(vertices.size());
|
||||
accelerationCreateGeometryInfo.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
|
||||
accelerationCreateGeometryInfo.allowsTransforms = VK_FALSE;
|
||||
|
||||
VkAccelerationStructureCreateInfoKHR accelerationCI{};
|
||||
accelerationCI.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR;
|
||||
accelerationCI.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
|
||||
accelerationCI.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
accelerationCI.maxGeometryCount = 1;
|
||||
accelerationCI.pGeometryInfos = &accelerationCreateGeometryInfo;
|
||||
VK_CHECK_RESULT(vkCreateAccelerationStructureKHR(device, &accelerationCI, nullptr, &bottomLevelAS.accelerationStructure));
|
||||
|
||||
// Bind object memory to the top level acceleration structure
|
||||
bottomLevelAS.objectMemory = createObjectMemory(bottomLevelAS.accelerationStructure);
|
||||
|
||||
VkBindAccelerationStructureMemoryInfoKHR bindAccelerationMemoryInfo{};
|
||||
bindAccelerationMemoryInfo.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR;
|
||||
bindAccelerationMemoryInfo.accelerationStructure = bottomLevelAS.accelerationStructure;
|
||||
bindAccelerationMemoryInfo.memory = bottomLevelAS.objectMemory.memory;
|
||||
VK_CHECK_RESULT(vkBindAccelerationStructureMemoryKHR(device, 1, &bindAccelerationMemoryInfo));
|
||||
|
||||
// Build
|
||||
VkAccelerationStructureGeometryKHR accelerationStructureGeometry{};
|
||||
accelerationStructureGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
|
||||
accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
|
||||
accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
|
||||
accelerationStructureGeometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
|
||||
accelerationStructureGeometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
|
||||
accelerationStructureGeometry.geometry.triangles.vertexData.deviceAddress = vertexBufferDeviceAddress.deviceAddress;
|
||||
accelerationStructureGeometry.geometry.triangles.vertexData = vertexBufferDeviceAddress;
|
||||
accelerationStructureGeometry.geometry.triangles.maxVertex = 3;
|
||||
accelerationStructureGeometry.geometry.triangles.vertexStride = sizeof(Vertex);
|
||||
accelerationStructureGeometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
|
||||
accelerationStructureGeometry.geometry.triangles.indexData.deviceAddress = indexBufferDeviceAddress.deviceAddress;
|
||||
accelerationStructureGeometry.geometry.triangles.indexData = indexBufferDeviceAddress;
|
||||
accelerationStructureGeometry.geometry.triangles.transformData.deviceAddress = 0;
|
||||
accelerationStructureGeometry.geometry.triangles.transformData.hostAddress = nullptr;
|
||||
accelerationStructureGeometry.geometry.triangles.transformData = transformBufferDeviceAddress;
|
||||
|
||||
// Get size info
|
||||
VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo{};
|
||||
accelerationStructureBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
|
||||
accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
|
||||
accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
accelerationStructureBuildGeometryInfo.geometryCount = 1;
|
||||
accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry;
|
||||
|
||||
const uint32_t numTriangles = 1;
|
||||
VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo{};
|
||||
accelerationStructureBuildSizesInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR;
|
||||
vkGetAccelerationStructureBuildSizesKHR(
|
||||
device,
|
||||
VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
|
||||
&accelerationStructureBuildGeometryInfo,
|
||||
&numTriangles,
|
||||
&accelerationStructureBuildSizesInfo);
|
||||
|
||||
std::vector<VkAccelerationStructureGeometryKHR> acceleration_geometries = { accelerationStructureGeometry };
|
||||
VkAccelerationStructureGeometryKHR* acceleration_structure_geometries = acceleration_geometries.data();
|
||||
createAccelerationStructureBuffer(bottomLevelAS, accelerationStructureBuildSizesInfo);
|
||||
|
||||
VkAccelerationStructureCreateInfoKHR accelerationStructureCreateInfo{};
|
||||
accelerationStructureCreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR;
|
||||
accelerationStructureCreateInfo.buffer = bottomLevelAS.buffer;
|
||||
accelerationStructureCreateInfo.size = accelerationStructureBuildSizesInfo.accelerationStructureSize;
|
||||
accelerationStructureCreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
|
||||
vkCreateAccelerationStructureKHR(device, &accelerationStructureCreateInfo, nullptr, &bottomLevelAS.handle);
|
||||
|
||||
// Create a small scratch buffer used during build of the bottom level acceleration structure
|
||||
RayTracingScratchBuffer scratchBuffer = createScratchBuffer(bottomLevelAS.accelerationStructure);
|
||||
RayTracingScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize);
|
||||
|
||||
VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo{};
|
||||
accelerationBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
|
||||
accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
|
||||
accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
accelerationBuildGeometryInfo.update = VK_FALSE;
|
||||
accelerationBuildGeometryInfo.dstAccelerationStructure = bottomLevelAS.accelerationStructure;
|
||||
accelerationBuildGeometryInfo.geometryArrayOfPointers = VK_FALSE;
|
||||
accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
|
||||
accelerationBuildGeometryInfo.dstAccelerationStructure = bottomLevelAS.handle;
|
||||
accelerationBuildGeometryInfo.geometryCount = 1;
|
||||
accelerationBuildGeometryInfo.ppGeometries = &acceleration_structure_geometries;
|
||||
accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry;
|
||||
accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress;
|
||||
|
||||
VkAccelerationStructureBuildOffsetInfoKHR accelerationBuildOffsetInfo{};
|
||||
accelerationBuildOffsetInfo.primitiveCount = 1;
|
||||
accelerationBuildOffsetInfo.primitiveOffset = 0x0;
|
||||
accelerationBuildOffsetInfo.firstVertex = 0;
|
||||
accelerationBuildOffsetInfo.transformOffset = 0x0;
|
||||
VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{};
|
||||
accelerationStructureBuildRangeInfo.primitiveCount = numTriangles;
|
||||
accelerationStructureBuildRangeInfo.primitiveOffset = 0;
|
||||
accelerationStructureBuildRangeInfo.firstVertex = 0;
|
||||
accelerationStructureBuildRangeInfo.transformOffset = 0;
|
||||
std::vector<VkAccelerationStructureBuildRangeInfoKHR*> accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo };
|
||||
|
||||
std::vector<VkAccelerationStructureBuildOffsetInfoKHR*> accelerationBuildOffsets = { &accelerationBuildOffsetInfo };
|
||||
|
||||
if (rayTracingFeatures.rayTracingHostAccelerationStructureCommands)
|
||||
if (accelerationStructureFeatures.accelerationStructureHostCommands)
|
||||
{
|
||||
// Implementation supports building acceleration structure building on host
|
||||
VK_CHECK_RESULT(vkBuildAccelerationStructureKHR(device, 1, &accelerationBuildGeometryInfo, accelerationBuildOffsets.data()));
|
||||
vkBuildAccelerationStructuresKHR(
|
||||
device,
|
||||
VK_NULL_HANDLE,
|
||||
1,
|
||||
&accelerationBuildGeometryInfo,
|
||||
accelerationBuildStructureRangeInfos.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Acceleration structure needs to be build on the device
|
||||
VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||
vkCmdBuildAccelerationStructureKHR(commandBuffer, 1, &accelerationBuildGeometryInfo, accelerationBuildOffsets.data());
|
||||
vkCmdBuildAccelerationStructuresKHR(
|
||||
commandBuffer,
|
||||
1,
|
||||
&accelerationBuildGeometryInfo,
|
||||
accelerationBuildStructureRangeInfos.data());
|
||||
vulkanDevice->flushCommandBuffer(commandBuffer, queue);
|
||||
}
|
||||
|
||||
VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{};
|
||||
accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
|
||||
accelerationDeviceAddressInfo.accelerationStructure = bottomLevelAS.accelerationStructure;
|
||||
|
||||
bottomLevelAS.handle = vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
|
||||
accelerationDeviceAddressInfo.accelerationStructure = bottomLevelAS.handle;
|
||||
bottomLevelAS.deviceAddress = vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
|
||||
|
||||
deleteScratchBuffer(scratchBuffer);
|
||||
}
|
||||
|
|
@ -405,132 +408,157 @@ public:
|
|||
*/
|
||||
void createTopLevelAccelerationStructure()
|
||||
{
|
||||
VkAccelerationStructureCreateGeometryTypeInfoKHR accelerationCreateGeometryInfo{};
|
||||
accelerationCreateGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR;
|
||||
accelerationCreateGeometryInfo.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
|
||||
accelerationCreateGeometryInfo.maxPrimitiveCount = 1;
|
||||
accelerationCreateGeometryInfo.allowsTransforms = VK_FALSE;
|
||||
|
||||
VkAccelerationStructureCreateInfoKHR accelerationCI{};
|
||||
accelerationCI.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR;
|
||||
accelerationCI.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
|
||||
accelerationCI.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
accelerationCI.maxGeometryCount = 1;
|
||||
accelerationCI.pGeometryInfos = &accelerationCreateGeometryInfo;
|
||||
VK_CHECK_RESULT(vkCreateAccelerationStructureKHR(device, &accelerationCI, nullptr, &topLevelAS.accelerationStructure));
|
||||
|
||||
// Bind object memory to the top level acceleration structure
|
||||
topLevelAS.objectMemory = createObjectMemory(topLevelAS.accelerationStructure);
|
||||
|
||||
VkBindAccelerationStructureMemoryInfoKHR bindAccelerationMemoryInfo{};
|
||||
bindAccelerationMemoryInfo.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR;
|
||||
bindAccelerationMemoryInfo.accelerationStructure = topLevelAS.accelerationStructure;
|
||||
bindAccelerationMemoryInfo.memory = topLevelAS.objectMemory.memory;
|
||||
VK_CHECK_RESULT(vkBindAccelerationStructureMemoryKHR(device, 1, &bindAccelerationMemoryInfo));
|
||||
|
||||
VkTransformMatrixKHR transform_matrix = {
|
||||
VkTransformMatrixKHR transformMatrix = {
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f };
|
||||
|
||||
VkAccelerationStructureInstanceKHR instance{};
|
||||
instance.transform = transform_matrix;
|
||||
instance.transform = transformMatrix;
|
||||
instance.instanceCustomIndex = 0;
|
||||
instance.mask = 0xFF;
|
||||
instance.instanceShaderBindingTableRecordOffset = 0;
|
||||
instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||
instance.accelerationStructureReference = bottomLevelAS.handle;
|
||||
instance.accelerationStructureReference = bottomLevelAS.deviceAddress;
|
||||
|
||||
// Buffer for instance data
|
||||
vks::Buffer instancesBuffer;
|
||||
VK_CHECK_RESULT(vulkanDevice->createBuffer(
|
||||
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
|
||||
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
&instancesBuffer,
|
||||
sizeof(instance),
|
||||
sizeof(VkAccelerationStructureInstanceKHR),
|
||||
&instance));
|
||||
|
||||
VkDeviceOrHostAddressConstKHR instance_data_device_address{};
|
||||
instance_data_device_address.deviceAddress = getBufferDeviceAddress(instancesBuffer.buffer);
|
||||
VkDeviceOrHostAddressConstKHR instanceDataDeviceAddress{};
|
||||
instanceDataDeviceAddress.deviceAddress = getBufferDeviceAddress(instancesBuffer.buffer);
|
||||
|
||||
VkAccelerationStructureGeometryKHR accelerationStructureGeometry{};
|
||||
accelerationStructureGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
|
||||
accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
|
||||
accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
|
||||
accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
|
||||
accelerationStructureGeometry.geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR;
|
||||
accelerationStructureGeometry.geometry.instances.arrayOfPointers = VK_FALSE;
|
||||
accelerationStructureGeometry.geometry.instances.data.deviceAddress = instance_data_device_address.deviceAddress;
|
||||
accelerationStructureGeometry.geometry.instances.data = instanceDataDeviceAddress;
|
||||
|
||||
std::vector<VkAccelerationStructureGeometryKHR> acceleration_geometries = { accelerationStructureGeometry };
|
||||
VkAccelerationStructureGeometryKHR* acceleration_structure_geometries = acceleration_geometries.data();
|
||||
// Get size info
|
||||
/*
|
||||
The pSrcAccelerationStructure, dstAccelerationStructure, and mode members of pBuildInfo are ignored. Any VkDeviceOrHostAddressKHR members of pBuildInfo are ignored by this command, except that the hostAddress member of VkAccelerationStructureGeometryTrianglesDataKHR::transformData will be examined to check if it is NULL.*
|
||||
*/
|
||||
VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo{};
|
||||
accelerationStructureBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
|
||||
accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
|
||||
accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
accelerationStructureBuildGeometryInfo.geometryCount = 1;
|
||||
accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry;
|
||||
|
||||
uint32_t primitive_count = 1;
|
||||
|
||||
VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo{};
|
||||
accelerationStructureBuildSizesInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR;
|
||||
vkGetAccelerationStructureBuildSizesKHR(
|
||||
device,
|
||||
VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
|
||||
&accelerationStructureBuildGeometryInfo,
|
||||
&primitive_count,
|
||||
&accelerationStructureBuildSizesInfo);
|
||||
|
||||
createAccelerationStructureBuffer(topLevelAS, accelerationStructureBuildSizesInfo);
|
||||
|
||||
VkAccelerationStructureCreateInfoKHR accelerationStructureCreateInfo{};
|
||||
accelerationStructureCreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR;
|
||||
accelerationStructureCreateInfo.buffer = topLevelAS.buffer;
|
||||
accelerationStructureCreateInfo.size = accelerationStructureBuildSizesInfo.accelerationStructureSize;
|
||||
accelerationStructureCreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
|
||||
vkCreateAccelerationStructureKHR(device, &accelerationStructureCreateInfo, nullptr, &topLevelAS.handle);
|
||||
|
||||
// Create a small scratch buffer used during build of the top level acceleration structure
|
||||
RayTracingScratchBuffer scratchBuffer = createScratchBuffer(topLevelAS.accelerationStructure);
|
||||
RayTracingScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize);
|
||||
|
||||
VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo{};
|
||||
accelerationBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
|
||||
accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
|
||||
accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
accelerationBuildGeometryInfo.update = VK_FALSE;
|
||||
accelerationBuildGeometryInfo.srcAccelerationStructure = VK_NULL_HANDLE;
|
||||
accelerationBuildGeometryInfo.dstAccelerationStructure = topLevelAS.accelerationStructure;
|
||||
accelerationBuildGeometryInfo.geometryArrayOfPointers = VK_FALSE;
|
||||
accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
|
||||
accelerationBuildGeometryInfo.dstAccelerationStructure = topLevelAS.handle;
|
||||
accelerationBuildGeometryInfo.geometryCount = 1;
|
||||
accelerationBuildGeometryInfo.ppGeometries = &acceleration_structure_geometries;
|
||||
accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry;
|
||||
accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress;
|
||||
|
||||
VkAccelerationStructureBuildOffsetInfoKHR accelerationBuildOffsetInfo{};
|
||||
accelerationBuildOffsetInfo.primitiveCount = 1;
|
||||
accelerationBuildOffsetInfo.primitiveOffset = 0x0;
|
||||
accelerationBuildOffsetInfo.firstVertex = 0;
|
||||
accelerationBuildOffsetInfo.transformOffset = 0x0;
|
||||
std::vector<VkAccelerationStructureBuildOffsetInfoKHR*> accelerationBuildOffsets = { &accelerationBuildOffsetInfo };
|
||||
VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{};
|
||||
accelerationStructureBuildRangeInfo.primitiveCount = 1;
|
||||
accelerationStructureBuildRangeInfo.primitiveOffset = 0;
|
||||
accelerationStructureBuildRangeInfo.firstVertex = 0;
|
||||
accelerationStructureBuildRangeInfo.transformOffset = 0;
|
||||
std::vector<VkAccelerationStructureBuildRangeInfoKHR*> accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo };
|
||||
|
||||
if (rayTracingFeatures.rayTracingHostAccelerationStructureCommands)
|
||||
if (accelerationStructureFeatures.accelerationStructureHostCommands)
|
||||
{
|
||||
// Implementation supports building acceleration structure building on host
|
||||
VK_CHECK_RESULT(vkBuildAccelerationStructureKHR(device, 1, &accelerationBuildGeometryInfo, accelerationBuildOffsets.data()));
|
||||
vkBuildAccelerationStructuresKHR(
|
||||
device,
|
||||
VK_NULL_HANDLE,
|
||||
1,
|
||||
&accelerationBuildGeometryInfo,
|
||||
accelerationBuildStructureRangeInfos.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Acceleration structure needs to be build on the device
|
||||
VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||
vkCmdBuildAccelerationStructureKHR(commandBuffer, 1, &accelerationBuildGeometryInfo, accelerationBuildOffsets.data());
|
||||
vkCmdBuildAccelerationStructuresKHR(
|
||||
commandBuffer,
|
||||
1,
|
||||
&accelerationBuildGeometryInfo,
|
||||
accelerationBuildStructureRangeInfos.data());
|
||||
vulkanDevice->flushCommandBuffer(commandBuffer, queue);
|
||||
}
|
||||
|
||||
VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{};
|
||||
accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
|
||||
accelerationDeviceAddressInfo.accelerationStructure = topLevelAS.accelerationStructure;
|
||||
|
||||
topLevelAS.handle = vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
|
||||
accelerationDeviceAddressInfo.accelerationStructure = topLevelAS.handle;
|
||||
topLevelAS.deviceAddress = vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
|
||||
|
||||
deleteScratchBuffer(scratchBuffer);
|
||||
instancesBuffer.destroy();
|
||||
}
|
||||
|
||||
/*
|
||||
Create the Shader Binding Table that binds the programs and top-level acceleration structure
|
||||
Create the Shader Binding Tables that binds the programs and top-level acceleration structure
|
||||
|
||||
SBT Layout used in this sample:
|
||||
|
||||
/-----------\
|
||||
| raygen |
|
||||
|-----------|
|
||||
| miss |
|
||||
|-----------|
|
||||
| hit |
|
||||
\-----------/
|
||||
|
||||
*/
|
||||
void createShaderBindingTable() {
|
||||
const uint32_t handleSize = rayTracingPipelineProperties.shaderGroupHandleSize;
|
||||
const uint32_t handleAlignment = rayTracingPipelineProperties.shaderGroupHandleAlignment;
|
||||
const uint32_t groupCount = static_cast<uint32_t>(shaderGroups.size());
|
||||
const uint32_t sbtSize = handleSize * groupCount;
|
||||
|
||||
const uint32_t sbtSize = rayTracingProperties.shaderGroupBaseAlignment * groupCount;
|
||||
VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &shaderBindingTable, sbtSize));
|
||||
shaderBindingTable.map();
|
||||
|
||||
// Write the shader handles to the shader binding table
|
||||
std::vector<uint8_t> shaderHandleStorage(sbtSize);
|
||||
VK_CHECK_RESULT(vkGetRayTracingShaderGroupHandlesKHR(device, pipeline, 0, groupCount, sbtSize, shaderHandleStorage.data()));
|
||||
|
||||
auto* data = static_cast<uint8_t*>(shaderBindingTable.mapped);
|
||||
// This part is required, as the alignment and handle size may differ
|
||||
for (uint32_t i = 0; i < groupCount; i++)
|
||||
{
|
||||
memcpy(data, shaderHandleStorage.data() + i * rayTracingProperties.shaderGroupHandleSize, rayTracingProperties.shaderGroupHandleSize);
|
||||
data += rayTracingProperties.shaderGroupBaseAlignment;
|
||||
}
|
||||
shaderBindingTable.unmap();
|
||||
const VkBufferUsageFlags bufferUsageFlags = VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
|
||||
const VkMemoryPropertyFlags memoryUsageFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
||||
VK_CHECK_RESULT(vulkanDevice->createBuffer(bufferUsageFlags, memoryUsageFlags, &raygenShaderBindingTable, handleSize));
|
||||
VK_CHECK_RESULT(vulkanDevice->createBuffer(bufferUsageFlags, memoryUsageFlags, &missShaderBindingTable, handleSize));
|
||||
VK_CHECK_RESULT(vulkanDevice->createBuffer(bufferUsageFlags, memoryUsageFlags, &hitShaderBindingTable, handleSize));
|
||||
|
||||
// Copy handles
|
||||
raygenShaderBindingTable.map();
|
||||
missShaderBindingTable.map();
|
||||
hitShaderBindingTable.map();
|
||||
memcpy(raygenShaderBindingTable.mapped, shaderHandleStorage.data(), handleSize);
|
||||
memcpy(missShaderBindingTable.mapped, shaderHandleStorage.data() + handleAlignment, handleSize);
|
||||
memcpy(hitShaderBindingTable.mapped, shaderHandleStorage.data() + handleAlignment * 2, handleSize);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -552,7 +580,7 @@ public:
|
|||
VkWriteDescriptorSetAccelerationStructureKHR descriptorAccelerationStructureInfo{};
|
||||
descriptorAccelerationStructureInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR;
|
||||
descriptorAccelerationStructureInfo.accelerationStructureCount = 1;
|
||||
descriptorAccelerationStructureInfo.pAccelerationStructures = &topLevelAS.accelerationStructure;
|
||||
descriptorAccelerationStructureInfo.pAccelerationStructures = &topLevelAS.handle;
|
||||
|
||||
VkWriteDescriptorSet accelerationStructureWrite{};
|
||||
accelerationStructureWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
|
|
@ -619,55 +647,62 @@ public:
|
|||
pipelineLayoutCI.pSetLayouts = &descriptorSetLayout;
|
||||
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout));
|
||||
|
||||
const uint32_t shaderIndexRaygen = 0;
|
||||
const uint32_t shaderIndexMiss = 1;
|
||||
const uint32_t shaderIndexClosestHit = 2;
|
||||
|
||||
std::array<VkPipelineShaderStageCreateInfo, 3> shaderStages;
|
||||
shaderStages[shaderIndexRaygen] = loadShader(getShadersPath() + "raytracingbasic/raygen.rgen.spv", VK_SHADER_STAGE_RAYGEN_BIT_KHR);
|
||||
shaderStages[shaderIndexMiss] = loadShader(getShadersPath() + "raytracingbasic/miss.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR);
|
||||
shaderStages[shaderIndexClosestHit] = loadShader(getShadersPath() + "raytracingbasic/closesthit.rchit.spv", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
||||
|
||||
/*
|
||||
Setup ray tracing shader groups
|
||||
*/
|
||||
VkRayTracingShaderGroupCreateInfoKHR raygenGroupCI{};
|
||||
raygenGroupCI.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
|
||||
raygenGroupCI.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
|
||||
raygenGroupCI.generalShader = shaderIndexRaygen;
|
||||
raygenGroupCI.closestHitShader = VK_SHADER_UNUSED_KHR;
|
||||
raygenGroupCI.anyHitShader = VK_SHADER_UNUSED_KHR;
|
||||
raygenGroupCI.intersectionShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroups.push_back(raygenGroupCI);
|
||||
std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
|
||||
|
||||
VkRayTracingShaderGroupCreateInfoKHR missGroupCI{};
|
||||
missGroupCI.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
|
||||
missGroupCI.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
|
||||
missGroupCI.generalShader = shaderIndexMiss;
|
||||
missGroupCI.closestHitShader = VK_SHADER_UNUSED_KHR;
|
||||
missGroupCI.anyHitShader = VK_SHADER_UNUSED_KHR;
|
||||
missGroupCI.intersectionShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroups.push_back(missGroupCI);
|
||||
// Ray generation group
|
||||
{
|
||||
shaderStages.push_back(loadShader(getShadersPath() + "raytracingbasic/raygen.rgen.spv", VK_SHADER_STAGE_RAYGEN_BIT_KHR));
|
||||
VkRayTracingShaderGroupCreateInfoKHR shaderGroup{};
|
||||
shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
|
||||
shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
|
||||
shaderGroup.generalShader = static_cast<uint32_t>(shaderStages.size()) - 1;
|
||||
shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroups.push_back(shaderGroup);
|
||||
}
|
||||
|
||||
VkRayTracingShaderGroupCreateInfoKHR closesHitGroupCI{};
|
||||
closesHitGroupCI.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
|
||||
closesHitGroupCI.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR;
|
||||
closesHitGroupCI.generalShader = VK_SHADER_UNUSED_KHR;
|
||||
closesHitGroupCI.closestHitShader = shaderIndexClosestHit;
|
||||
closesHitGroupCI.anyHitShader = VK_SHADER_UNUSED_KHR;
|
||||
closesHitGroupCI.intersectionShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroups.push_back(closesHitGroupCI);
|
||||
// Miss group
|
||||
{
|
||||
shaderStages.push_back(loadShader(getShadersPath() + "raytracingbasic/miss.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR));
|
||||
VkRayTracingShaderGroupCreateInfoKHR shaderGroup{};
|
||||
shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
|
||||
shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
|
||||
shaderGroup.generalShader = static_cast<uint32_t>(shaderStages.size()) - 1;
|
||||
shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroups.push_back(shaderGroup);
|
||||
}
|
||||
|
||||
// Closest hit group
|
||||
{
|
||||
shaderStages.push_back(loadShader(getShadersPath() + "raytracingbasic/closesthit.rchit.spv", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR));
|
||||
VkRayTracingShaderGroupCreateInfoKHR shaderGroup{};
|
||||
shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
|
||||
shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR;
|
||||
shaderGroup.generalShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroup.closestHitShader = static_cast<uint32_t>(shaderStages.size()) - 1;
|
||||
shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroups.push_back(shaderGroup);
|
||||
}
|
||||
|
||||
/*
|
||||
Create the ray tracing pipeline
|
||||
*/
|
||||
VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCI{};
|
||||
rayTracingPipelineCI.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR;
|
||||
rayTracingPipelineCI.stageCount = static_cast<uint32_t>(shaderStages.size());
|
||||
rayTracingPipelineCI.pStages = shaderStages.data();
|
||||
rayTracingPipelineCI.groupCount = static_cast<uint32_t>(shaderGroups.size());
|
||||
rayTracingPipelineCI.pGroups = shaderGroups.data();
|
||||
rayTracingPipelineCI.maxRecursionDepth = 1;
|
||||
rayTracingPipelineCI.maxPipelineRayRecursionDepth = 1;
|
||||
rayTracingPipelineCI.layout = pipelineLayout;
|
||||
rayTracingPipelineCI.libraries.sType = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR;
|
||||
VK_CHECK_RESULT(vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &pipeline));
|
||||
VK_CHECK_RESULT(vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &pipeline));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -721,37 +756,26 @@ public:
|
|||
{
|
||||
VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo));
|
||||
|
||||
/*
|
||||
Dispatch the ray tracing commands
|
||||
*/
|
||||
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline);
|
||||
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout, 0, 1, &descriptorSet, 0, 0);
|
||||
|
||||
|
||||
/*
|
||||
Setup the buffer regions pointing to the shaders in our shader binding table
|
||||
*/
|
||||
const VkDeviceSize sbtSize = rayTracingProperties.shaderGroupBaseAlignment * (VkDeviceSize)shaderGroups.size();
|
||||
|
||||
VkStridedBufferRegionKHR raygenShaderSBTEntry{};
|
||||
raygenShaderSBTEntry.buffer = shaderBindingTable.buffer;
|
||||
raygenShaderSBTEntry.offset = static_cast<VkDeviceSize>(rayTracingProperties.shaderGroupBaseAlignment * INDEX_RAYGEN_GROUP);
|
||||
raygenShaderSBTEntry.stride = rayTracingProperties.shaderGroupBaseAlignment;
|
||||
raygenShaderSBTEntry.size = sbtSize;
|
||||
VkStridedDeviceAddressRegionKHR raygenShaderSbtEntry{};
|
||||
raygenShaderSbtEntry.deviceAddress = getBufferDeviceAddress(raygenShaderBindingTable.buffer);
|
||||
raygenShaderSbtEntry.stride = rayTracingPipelineProperties.shaderGroupHandleSize;
|
||||
raygenShaderSbtEntry.size = rayTracingPipelineProperties.shaderGroupHandleSize;
|
||||
|
||||
VkStridedBufferRegionKHR missShaderSBTEntry{};
|
||||
missShaderSBTEntry.buffer = shaderBindingTable.buffer;
|
||||
missShaderSBTEntry.offset = static_cast<VkDeviceSize>(rayTracingProperties.shaderGroupBaseAlignment * INDEX_MISS_GROUP);
|
||||
missShaderSBTEntry.stride = rayTracingProperties.shaderGroupBaseAlignment;
|
||||
missShaderSBTEntry.size = sbtSize;
|
||||
VkStridedDeviceAddressRegionKHR missShaderSbtEntry{};
|
||||
missShaderSbtEntry.deviceAddress = getBufferDeviceAddress(missShaderBindingTable.buffer);
|
||||
missShaderSbtEntry.stride = rayTracingPipelineProperties.shaderGroupHandleSize;
|
||||
missShaderSbtEntry.size = rayTracingPipelineProperties.shaderGroupHandleSize;
|
||||
|
||||
VkStridedBufferRegionKHR hitShaderSBTEntry{};
|
||||
hitShaderSBTEntry.buffer = shaderBindingTable.buffer;
|
||||
hitShaderSBTEntry.offset = static_cast<VkDeviceSize>(rayTracingProperties.shaderGroupBaseAlignment * INDEX_CLOSEST_HIT_GROUP);
|
||||
hitShaderSBTEntry.stride = rayTracingProperties.shaderGroupBaseAlignment;
|
||||
hitShaderSBTEntry.size = sbtSize;
|
||||
VkStridedDeviceAddressRegionKHR hitShaderSbtEntry{};
|
||||
hitShaderSbtEntry.deviceAddress = getBufferDeviceAddress(hitShaderBindingTable.buffer);
|
||||
hitShaderSbtEntry.stride = rayTracingPipelineProperties.shaderGroupHandleSize;
|
||||
hitShaderSbtEntry.size = rayTracingPipelineProperties.shaderGroupHandleSize;
|
||||
|
||||
VkStridedBufferRegionKHR callableShaderSBTEntry{};
|
||||
VkStridedDeviceAddressRegionKHR callableShaderSbtEntry{};
|
||||
|
||||
/*
|
||||
Dispatch the ray tracing commands
|
||||
|
|
@ -761,10 +785,10 @@ public:
|
|||
|
||||
vkCmdTraceRaysKHR(
|
||||
drawCmdBuffers[i],
|
||||
&raygenShaderSBTEntry,
|
||||
&missShaderSBTEntry,
|
||||
&hitShaderSBTEntry,
|
||||
&callableShaderSBTEntry,
|
||||
&raygenShaderSbtEntry,
|
||||
&missShaderSbtEntry,
|
||||
&hitShaderSbtEntry,
|
||||
&callableShaderSbtEntry,
|
||||
width,
|
||||
height,
|
||||
1);
|
||||
|
|
@ -829,40 +853,43 @@ public:
|
|||
// Enable features required for ray tracing using feature chaining via pNext
|
||||
enabledBufferDeviceAddresFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES;
|
||||
enabledBufferDeviceAddresFeatures.bufferDeviceAddress = VK_TRUE;
|
||||
|
||||
enabledRayTracingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR;
|
||||
enabledRayTracingFeatures.rayTracing = VK_TRUE;
|
||||
enabledRayTracingFeatures.pNext = &enabledBufferDeviceAddresFeatures;
|
||||
|
||||
deviceCreatepNextChain = &enabledRayTracingFeatures;
|
||||
enabledRayTracingPipelineFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR;
|
||||
enabledRayTracingPipelineFeatures.rayTracingPipeline = VK_TRUE;
|
||||
enabledRayTracingPipelineFeatures.pNext = &enabledBufferDeviceAddresFeatures;
|
||||
|
||||
enabledAccelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR;
|
||||
enabledAccelerationStructureFeatures.accelerationStructure = VK_TRUE;
|
||||
enabledAccelerationStructureFeatures.pNext = &enabledRayTracingPipelineFeatures;
|
||||
|
||||
deviceCreatepNextChain = &enabledAccelerationStructureFeatures;
|
||||
}
|
||||
|
||||
void prepare()
|
||||
{
|
||||
VulkanExampleBase::prepare();
|
||||
|
||||
// Query the ray tracing properties of the current implementation, we will need them later on
|
||||
rayTracingProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR;
|
||||
VkPhysicalDeviceProperties2 deviceProps2{};
|
||||
deviceProps2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
|
||||
deviceProps2.pNext = &rayTracingProperties;
|
||||
vkGetPhysicalDeviceProperties2(physicalDevice, &deviceProps2);
|
||||
// Get ray tracing pipeline properties, which will be used later on in the sample
|
||||
rayTracingPipelineProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;
|
||||
VkPhysicalDeviceProperties2 deviceProperties2{};
|
||||
deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
|
||||
deviceProperties2.pNext = &rayTracingPipelineProperties;
|
||||
vkGetPhysicalDeviceProperties2(physicalDevice, &deviceProperties2);
|
||||
|
||||
// Query the ray tracing properties of the current implementation, we will need them later on
|
||||
rayTracingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR;
|
||||
// Get acceleration structure properties, which will be used later on in the sample
|
||||
accelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR;
|
||||
VkPhysicalDeviceFeatures2 deviceFeatures2{};
|
||||
deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
|
||||
deviceFeatures2.pNext = &rayTracingFeatures;
|
||||
deviceFeatures2.pNext = &accelerationStructureFeatures;
|
||||
vkGetPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures2);
|
||||
|
||||
// Get the function pointers required for ray tracing
|
||||
// Get the ray tracing and accelertion structure related function pointers required by this sample
|
||||
vkGetBufferDeviceAddressKHR = reinterpret_cast<PFN_vkGetBufferDeviceAddressKHR>(vkGetDeviceProcAddr(device, "vkGetBufferDeviceAddressKHR"));
|
||||
vkBindAccelerationStructureMemoryKHR = reinterpret_cast<PFN_vkBindAccelerationStructureMemoryKHR>(vkGetDeviceProcAddr(device, "vkBindAccelerationStructureMemoryKHR"));
|
||||
vkCmdBuildAccelerationStructuresKHR = reinterpret_cast<PFN_vkCmdBuildAccelerationStructuresKHR>(vkGetDeviceProcAddr(device, "vkCmdBuildAccelerationStructuresKHR"));
|
||||
vkBuildAccelerationStructuresKHR = reinterpret_cast<PFN_vkBuildAccelerationStructuresKHR>(vkGetDeviceProcAddr(device, "vkBuildAccelerationStructuresKHR"));
|
||||
vkCreateAccelerationStructureKHR = reinterpret_cast<PFN_vkCreateAccelerationStructureKHR>(vkGetDeviceProcAddr(device, "vkCreateAccelerationStructureKHR"));
|
||||
vkDestroyAccelerationStructureKHR = reinterpret_cast<PFN_vkDestroyAccelerationStructureKHR>(vkGetDeviceProcAddr(device, "vkDestroyAccelerationStructureKHR"));
|
||||
vkGetAccelerationStructureMemoryRequirementsKHR = reinterpret_cast<PFN_vkGetAccelerationStructureMemoryRequirementsKHR>(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureMemoryRequirementsKHR"));
|
||||
vkCmdBuildAccelerationStructureKHR = reinterpret_cast<PFN_vkCmdBuildAccelerationStructureKHR>(vkGetDeviceProcAddr(device, "vkCmdBuildAccelerationStructureKHR"));
|
||||
vkBuildAccelerationStructureKHR = reinterpret_cast<PFN_vkBuildAccelerationStructureKHR>(vkGetDeviceProcAddr(device, "vkBuildAccelerationStructureKHR"));
|
||||
vkGetAccelerationStructureBuildSizesKHR = reinterpret_cast<PFN_vkGetAccelerationStructureBuildSizesKHR>(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureBuildSizesKHR"));
|
||||
vkGetAccelerationStructureDeviceAddressKHR = reinterpret_cast<PFN_vkGetAccelerationStructureDeviceAddressKHR>(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureDeviceAddressKHR"));
|
||||
vkCmdTraceRaysKHR = reinterpret_cast<PFN_vkCmdTraceRaysKHR>(vkGetDeviceProcAddr(device, "vkCmdTraceRaysKHR"));
|
||||
vkGetRayTracingShaderGroupHandlesKHR = reinterpret_cast<PFN_vkGetRayTracingShaderGroupHandlesKHR>(vkGetDeviceProcAddr(device, "vkGetRayTracingShaderGroupHandlesKHR"));
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Vulkan Example - Hardware accelerated ray tracing example for doing reflections using VK_KHR_ray_traying
|
||||
* Vulkan Example - Hardware accelerated ray tracing example for doing reflections
|
||||
*
|
||||
* Renders a complex scene doing recursion inside the shaders for creating reflections
|
||||
*
|
||||
|
|
@ -8,69 +8,21 @@
|
|||
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
||||
*/
|
||||
|
||||
#define VK_ENABLE_BETA_EXTENSIONS
|
||||
|
||||
#include "vulkanexamplebase.h"
|
||||
#include "VulkanRaytracingSample.h"
|
||||
#include "VulkanglTFModel.h"
|
||||
|
||||
// Ray tracing utility structures, see ray tracing basic sample for details
|
||||
struct RayTracingScratchBuffer
|
||||
{
|
||||
uint64_t deviceAddress = 0;
|
||||
VkBuffer buffer = VK_NULL_HANDLE;
|
||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
struct RayTracingObjectMemory
|
||||
{
|
||||
uint64_t deviceAddress = 0;
|
||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
struct AccelerationStructure {
|
||||
VkAccelerationStructureKHR accelerationStructure;
|
||||
uint64_t handle;
|
||||
RayTracingObjectMemory objectMemory;
|
||||
};
|
||||
|
||||
// Indices for the different ray tracing groups used in this example
|
||||
#define INDEX_RAYGEN_GROUP 0
|
||||
#define INDEX_MISS_GROUP 1
|
||||
#define INDEX_CLOSEST_HIT_GROUP 2
|
||||
|
||||
class VulkanExample : public VulkanExampleBase
|
||||
class VulkanExample : public VulkanRaytracingSample
|
||||
{
|
||||
public:
|
||||
PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR;
|
||||
PFN_vkBindAccelerationStructureMemoryKHR vkBindAccelerationStructureMemoryKHR;
|
||||
PFN_vkCreateAccelerationStructureKHR vkCreateAccelerationStructureKHR;
|
||||
PFN_vkDestroyAccelerationStructureKHR vkDestroyAccelerationStructureKHR;
|
||||
PFN_vkGetAccelerationStructureMemoryRequirementsKHR vkGetAccelerationStructureMemoryRequirementsKHR;
|
||||
PFN_vkCmdBuildAccelerationStructureKHR vkCmdBuildAccelerationStructureKHR;
|
||||
PFN_vkBuildAccelerationStructureKHR vkBuildAccelerationStructureKHR;
|
||||
PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR;
|
||||
PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR;
|
||||
PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR;
|
||||
PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR;
|
||||
|
||||
VkPhysicalDeviceRayTracingPropertiesKHR rayTracingProperties{};
|
||||
VkPhysicalDeviceRayTracingFeaturesKHR rayTracingFeatures{};
|
||||
|
||||
VkPhysicalDeviceBufferDeviceAddressFeatures enabledBufferDeviceAddresFeatures{};
|
||||
VkPhysicalDeviceRayTracingFeaturesKHR enabledRayTracingFeatures{};
|
||||
|
||||
AccelerationStructure bottomLevelAS;
|
||||
AccelerationStructure topLevelAS;
|
||||
AccelerationStructure bottomLevelAS{};
|
||||
AccelerationStructure topLevelAS{};
|
||||
|
||||
std::vector<VkRayTracingShaderGroupCreateInfoKHR> shaderGroups{};
|
||||
vks::Buffer shaderBindingTable;
|
||||
|
||||
struct StorageImage {
|
||||
VkDeviceMemory memory;
|
||||
VkImage image;
|
||||
VkImageView view;
|
||||
VkFormat format;
|
||||
} storageImage;
|
||||
struct ShaderBindingTables {
|
||||
ShaderBindingTable raygen;
|
||||
ShaderBindingTable miss;
|
||||
ShaderBindingTable hit;
|
||||
} shaderBindingTables;
|
||||
|
||||
struct UniformData {
|
||||
glm::mat4 viewInverse;
|
||||
|
|
@ -87,7 +39,8 @@ public:
|
|||
|
||||
vkglTF::Model scene;
|
||||
|
||||
VulkanExample() : VulkanExampleBase()
|
||||
// This sample is derived from an extended base class that saves most of the ray tracing setup boiler plate
|
||||
VulkanExample() : VulkanRaytracingSample()
|
||||
{
|
||||
title = "Ray tracing reflections";
|
||||
settings.overlay = false;
|
||||
|
|
@ -97,17 +50,7 @@ public:
|
|||
camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f);
|
||||
camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f));
|
||||
camera.setTranslation(glm::vec3(0.0f, 0.5f, -2.0f));
|
||||
// Enable instance and device extensions required to use VK_KHR_ray_tracing
|
||||
enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_RAY_TRACING_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME);
|
||||
// We require Vulkan 1.2 for ray tracing
|
||||
apiVersion = VK_API_VERSION_1_2;
|
||||
enableExtensions();
|
||||
}
|
||||
|
||||
~VulkanExample()
|
||||
|
|
@ -115,248 +58,107 @@ public:
|
|||
vkDestroyPipeline(device, pipeline, nullptr);
|
||||
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
|
||||
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
|
||||
vkDestroyImageView(device, storageImage.view, nullptr);
|
||||
vkDestroyImage(device, storageImage.image, nullptr);
|
||||
vkFreeMemory(device, storageImage.memory, nullptr);
|
||||
vkDestroyAccelerationStructureKHR(device, bottomLevelAS.accelerationStructure, nullptr);
|
||||
vkDestroyAccelerationStructureKHR(device, topLevelAS.accelerationStructure, nullptr);
|
||||
shaderBindingTable.destroy();
|
||||
deleteStorageImage();
|
||||
deleteAccelerationStructure(bottomLevelAS);
|
||||
deleteAccelerationStructure(topLevelAS);
|
||||
shaderBindingTables.raygen.destroy();
|
||||
shaderBindingTables.miss.destroy();
|
||||
shaderBindingTables.hit.destroy();
|
||||
ubo.destroy();
|
||||
deleteObjectMemory(bottomLevelAS.objectMemory);
|
||||
deleteObjectMemory(topLevelAS.objectMemory);
|
||||
}
|
||||
|
||||
/*
|
||||
Ray tracing utility functions, see ray tracing basic sample for details
|
||||
*/
|
||||
RayTracingScratchBuffer createScratchBuffer(VkAccelerationStructureKHR accelerationStructure)
|
||||
{
|
||||
RayTracingScratchBuffer scratchBuffer{};
|
||||
VkMemoryRequirements2 memoryRequirements2{};
|
||||
memoryRequirements2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
|
||||
VkAccelerationStructureMemoryRequirementsInfoKHR accelerationStructureMemoryRequirements{};
|
||||
accelerationStructureMemoryRequirements.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR;
|
||||
accelerationStructureMemoryRequirements.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR;
|
||||
accelerationStructureMemoryRequirements.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR;
|
||||
accelerationStructureMemoryRequirements.accelerationStructure = accelerationStructure;
|
||||
vkGetAccelerationStructureMemoryRequirementsKHR(device, &accelerationStructureMemoryRequirements, &memoryRequirements2);
|
||||
VkBufferCreateInfo bufferCI{};
|
||||
bufferCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
bufferCI.size = memoryRequirements2.memoryRequirements.size;
|
||||
bufferCI.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
|
||||
bufferCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCI, nullptr, &scratchBuffer.buffer));
|
||||
VkMemoryRequirements memoryRequirements{};
|
||||
vkGetBufferMemoryRequirements(device, scratchBuffer.buffer, &memoryRequirements);
|
||||
VkMemoryAllocateFlagsInfo memoryAllocateFI{};
|
||||
memoryAllocateFI.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO;
|
||||
memoryAllocateFI.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR;
|
||||
VkMemoryAllocateInfo memoryAI{};
|
||||
memoryAI.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
memoryAI.pNext = &memoryAllocateFI;
|
||||
memoryAI.allocationSize = memoryRequirements.size;
|
||||
memoryAI.memoryTypeIndex = vulkanDevice->getMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
VK_CHECK_RESULT(vkAllocateMemory(device, &memoryAI, nullptr, &scratchBuffer.memory));
|
||||
VK_CHECK_RESULT(vkBindBufferMemory(device, scratchBuffer.buffer, scratchBuffer.memory, 0));
|
||||
VkBufferDeviceAddressInfoKHR buffer_device_address_info{};
|
||||
buffer_device_address_info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
|
||||
buffer_device_address_info.buffer = scratchBuffer.buffer;
|
||||
scratchBuffer.deviceAddress = vkGetBufferDeviceAddressKHR(device, &buffer_device_address_info);
|
||||
return scratchBuffer;
|
||||
}
|
||||
|
||||
void deleteScratchBuffer(RayTracingScratchBuffer& scratchBuffer)
|
||||
{
|
||||
if (scratchBuffer.memory != VK_NULL_HANDLE) {
|
||||
vkFreeMemory(device, scratchBuffer.memory, nullptr);
|
||||
}
|
||||
if (scratchBuffer.buffer != VK_NULL_HANDLE) {
|
||||
vkDestroyBuffer(device, scratchBuffer.buffer, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
RayTracingObjectMemory createObjectMemory(VkAccelerationStructureKHR acceleration_structure)
|
||||
{
|
||||
RayTracingObjectMemory objectMemory{};
|
||||
VkMemoryRequirements2 memoryRequirements2{};
|
||||
memoryRequirements2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
|
||||
VkAccelerationStructureMemoryRequirementsInfoKHR accelerationStructureMemoryRequirements{};
|
||||
accelerationStructureMemoryRequirements.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR;
|
||||
accelerationStructureMemoryRequirements.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR;
|
||||
accelerationStructureMemoryRequirements.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR;
|
||||
accelerationStructureMemoryRequirements.accelerationStructure = acceleration_structure;
|
||||
vkGetAccelerationStructureMemoryRequirementsKHR(device, &accelerationStructureMemoryRequirements, &memoryRequirements2);
|
||||
VkMemoryRequirements memoryRequirements = memoryRequirements2.memoryRequirements;
|
||||
VkMemoryAllocateInfo memoryAI{};
|
||||
memoryAI.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
memoryAI.allocationSize = memoryRequirements.size;
|
||||
memoryAI.memoryTypeIndex = vulkanDevice->getMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
VK_CHECK_RESULT(vkAllocateMemory(device, &memoryAI, nullptr, &objectMemory.memory));
|
||||
return objectMemory;
|
||||
}
|
||||
|
||||
void deleteObjectMemory(RayTracingObjectMemory& objectMemory)
|
||||
{
|
||||
if (objectMemory.memory != VK_NULL_HANDLE) {
|
||||
vkFreeMemory(device, objectMemory.memory, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t getBufferDeviceAddress(VkBuffer buffer)
|
||||
{
|
||||
VkBufferDeviceAddressInfoKHR bufferDeviceAI{};
|
||||
bufferDeviceAI.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
|
||||
bufferDeviceAI.buffer = buffer;
|
||||
return vkGetBufferDeviceAddressKHR(device, &bufferDeviceAI);
|
||||
}
|
||||
|
||||
/*
|
||||
Set up a storage image that the ray generation shader will be writing to
|
||||
Create the bottom level acceleration structure contains the scene's actual geometry (vertices, triangles)
|
||||
*/
|
||||
void createStorageImage()
|
||||
{
|
||||
VkImageCreateInfo image = vks::initializers::imageCreateInfo();
|
||||
image.imageType = VK_IMAGE_TYPE_2D;
|
||||
image.format = swapChain.colorFormat;
|
||||
image.extent.width = width;
|
||||
image.extent.height = height;
|
||||
image.extent.depth = 1;
|
||||
image.mipLevels = 1;
|
||||
image.arrayLayers = 1;
|
||||
image.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
image.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
image.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
|
||||
image.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &storageImage.image));
|
||||
|
||||
VkMemoryRequirements memReqs;
|
||||
vkGetImageMemoryRequirements(device, storageImage.image, &memReqs);
|
||||
VkMemoryAllocateInfo memoryAllocateInfo = vks::initializers::memoryAllocateInfo();
|
||||
memoryAllocateInfo.allocationSize = memReqs.size;
|
||||
memoryAllocateInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
VK_CHECK_RESULT(vkAllocateMemory(device, &memoryAllocateInfo, nullptr, &storageImage.memory));
|
||||
VK_CHECK_RESULT(vkBindImageMemory(device, storageImage.image, storageImage.memory, 0));
|
||||
|
||||
VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo();
|
||||
colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
colorImageView.format = swapChain.colorFormat;
|
||||
colorImageView.subresourceRange = {};
|
||||
colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
colorImageView.subresourceRange.baseMipLevel = 0;
|
||||
colorImageView.subresourceRange.levelCount = 1;
|
||||
colorImageView.subresourceRange.baseArrayLayer = 0;
|
||||
colorImageView.subresourceRange.layerCount = 1;
|
||||
colorImageView.image = storageImage.image;
|
||||
VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &storageImage.view));
|
||||
|
||||
VkCommandBuffer cmdBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||
vks::tools::setImageLayout(cmdBuffer, storageImage.image,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_GENERAL,
|
||||
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
|
||||
vulkanDevice->flushCommandBuffer(cmdBuffer, queue);
|
||||
}
|
||||
|
||||
/*
|
||||
Create the bottom level acceleration structure contains the scene's actual geometry (vertices, triangles)
|
||||
*/
|
||||
void createBottomLevelAccelerationStructure()
|
||||
{
|
||||
// Instead of a simple triangle, we'll be loading a more complex scene for this example
|
||||
// The shaders are accessing the vertex and index buffers of the scene, so the proper usage flag has to be set on the vertex and index buffers for the scene
|
||||
vkglTF::memoryPropertyFlags = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
|
||||
vkglTF::memoryPropertyFlags = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY;
|
||||
scene.loadFromFile(getAssetPath() + "models/reflection_scene.gltf", vulkanDevice, queue, glTFLoadingFlags);
|
||||
|
||||
const uint32_t numTriangles = static_cast<uint32_t>(scene.indices.count) / 3;
|
||||
|
||||
VkDeviceOrHostAddressConstKHR vertexBufferDeviceAddress{};
|
||||
VkDeviceOrHostAddressConstKHR indexBufferDeviceAddress{};
|
||||
|
||||
vertexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(scene.vertices.buffer);
|
||||
indexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(scene.indices.buffer);
|
||||
|
||||
VkAccelerationStructureCreateGeometryTypeInfoKHR accelerationCreateGeometryInfo{};
|
||||
accelerationCreateGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR;
|
||||
accelerationCreateGeometryInfo.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
|
||||
accelerationCreateGeometryInfo.maxPrimitiveCount = numTriangles;
|
||||
accelerationCreateGeometryInfo.indexType = VK_INDEX_TYPE_UINT32;
|
||||
accelerationCreateGeometryInfo.maxVertexCount = static_cast<uint32_t>(scene.vertices.count);
|
||||
accelerationCreateGeometryInfo.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
|
||||
accelerationCreateGeometryInfo.allowsTransforms = VK_FALSE;
|
||||
uint32_t numTriangles = static_cast<uint32_t>(scene.indices.count) / 3;
|
||||
uint32_t maxVertex = scene.vertices.count;
|
||||
|
||||
VkAccelerationStructureCreateInfoKHR accelerationCI{};
|
||||
accelerationCI.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR;
|
||||
accelerationCI.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
|
||||
accelerationCI.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
accelerationCI.maxGeometryCount = 1;
|
||||
accelerationCI.pGeometryInfos = &accelerationCreateGeometryInfo;
|
||||
VK_CHECK_RESULT(vkCreateAccelerationStructureKHR(device, &accelerationCI, nullptr, &bottomLevelAS.accelerationStructure));
|
||||
|
||||
// Bind object memory to the top level acceleration structure
|
||||
bottomLevelAS.objectMemory = createObjectMemory(bottomLevelAS.accelerationStructure);
|
||||
|
||||
VkBindAccelerationStructureMemoryInfoKHR bindAccelerationMemoryInfo{};
|
||||
bindAccelerationMemoryInfo.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR;
|
||||
bindAccelerationMemoryInfo.accelerationStructure = bottomLevelAS.accelerationStructure;
|
||||
bindAccelerationMemoryInfo.memory = bottomLevelAS.objectMemory.memory;
|
||||
VK_CHECK_RESULT(vkBindAccelerationStructureMemoryKHR(device, 1, &bindAccelerationMemoryInfo));
|
||||
|
||||
VkAccelerationStructureGeometryKHR accelerationStructureGeometry{};
|
||||
accelerationStructureGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
|
||||
// Build
|
||||
VkAccelerationStructureGeometryKHR accelerationStructureGeometry = vks::initializers::accelerationStructureGeometryKHR();
|
||||
accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
|
||||
accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
|
||||
accelerationStructureGeometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
|
||||
accelerationStructureGeometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
|
||||
accelerationStructureGeometry.geometry.triangles.vertexData.deviceAddress = vertexBufferDeviceAddress.deviceAddress;
|
||||
accelerationStructureGeometry.geometry.triangles.vertexData = vertexBufferDeviceAddress;
|
||||
accelerationStructureGeometry.geometry.triangles.maxVertex = maxVertex;
|
||||
accelerationStructureGeometry.geometry.triangles.vertexStride = sizeof(vkglTF::Vertex);
|
||||
accelerationStructureGeometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
|
||||
accelerationStructureGeometry.geometry.triangles.indexData.deviceAddress = indexBufferDeviceAddress.deviceAddress;
|
||||
accelerationStructureGeometry.geometry.triangles.indexData = indexBufferDeviceAddress;
|
||||
accelerationStructureGeometry.geometry.triangles.transformData.deviceAddress = 0;
|
||||
accelerationStructureGeometry.geometry.triangles.transformData.hostAddress = nullptr;
|
||||
|
||||
std::vector<VkAccelerationStructureGeometryKHR> acceleration_geometries = { accelerationStructureGeometry };
|
||||
VkAccelerationStructureGeometryKHR* acceleration_structure_geometries = acceleration_geometries.data();
|
||||
// Get size info
|
||||
VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR();
|
||||
accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
|
||||
accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
accelerationStructureBuildGeometryInfo.geometryCount = 1;
|
||||
accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry;
|
||||
|
||||
VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo = vks::initializers::accelerationStructureBuildSizesInfoKHR();
|
||||
vkGetAccelerationStructureBuildSizesKHR(
|
||||
device,
|
||||
VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
|
||||
&accelerationStructureBuildGeometryInfo,
|
||||
&numTriangles,
|
||||
&accelerationStructureBuildSizesInfo);
|
||||
|
||||
createAccelerationStructure(bottomLevelAS, VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, accelerationStructureBuildSizesInfo);
|
||||
|
||||
// Create a small scratch buffer used during build of the bottom level acceleration structure
|
||||
RayTracingScratchBuffer scratchBuffer = createScratchBuffer(bottomLevelAS.accelerationStructure);
|
||||
ScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize);
|
||||
|
||||
VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo{};
|
||||
accelerationBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
|
||||
VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR();
|
||||
accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
|
||||
accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
accelerationBuildGeometryInfo.update = VK_FALSE;
|
||||
accelerationBuildGeometryInfo.dstAccelerationStructure = bottomLevelAS.accelerationStructure;
|
||||
accelerationBuildGeometryInfo.geometryArrayOfPointers = VK_FALSE;
|
||||
accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
|
||||
accelerationBuildGeometryInfo.dstAccelerationStructure = bottomLevelAS.handle;
|
||||
accelerationBuildGeometryInfo.geometryCount = 1;
|
||||
accelerationBuildGeometryInfo.ppGeometries = &acceleration_structure_geometries;
|
||||
accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry;
|
||||
accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress;
|
||||
|
||||
VkAccelerationStructureBuildOffsetInfoKHR accelerationBuildOffsetInfo{};
|
||||
accelerationBuildOffsetInfo.primitiveCount = numTriangles;
|
||||
accelerationBuildOffsetInfo.primitiveOffset = 0x0;
|
||||
accelerationBuildOffsetInfo.firstVertex = 0;
|
||||
accelerationBuildOffsetInfo.transformOffset = 0x0;
|
||||
VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{};
|
||||
accelerationStructureBuildRangeInfo.primitiveCount = numTriangles;
|
||||
accelerationStructureBuildRangeInfo.primitiveOffset = 0;
|
||||
accelerationStructureBuildRangeInfo.firstVertex = 0;
|
||||
accelerationStructureBuildRangeInfo.transformOffset = 0;
|
||||
std::vector<VkAccelerationStructureBuildRangeInfoKHR*> accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo };
|
||||
|
||||
std::vector<VkAccelerationStructureBuildOffsetInfoKHR*> accelerationBuildOffsets = { &accelerationBuildOffsetInfo };
|
||||
|
||||
if (rayTracingFeatures.rayTracingHostAccelerationStructureCommands)
|
||||
if (accelerationStructureFeatures.accelerationStructureHostCommands)
|
||||
{
|
||||
// Implementation supports building acceleration structure building on host
|
||||
VK_CHECK_RESULT(vkBuildAccelerationStructureKHR(device, 1, &accelerationBuildGeometryInfo, accelerationBuildOffsets.data()));
|
||||
vkBuildAccelerationStructuresKHR(
|
||||
device,
|
||||
VK_NULL_HANDLE,
|
||||
1,
|
||||
&accelerationBuildGeometryInfo,
|
||||
accelerationBuildStructureRangeInfos.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Acceleration structure needs to be build on the device
|
||||
VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||
vkCmdBuildAccelerationStructureKHR(commandBuffer, 1, &accelerationBuildGeometryInfo, accelerationBuildOffsets.data());
|
||||
vkCmdBuildAccelerationStructuresKHR(
|
||||
commandBuffer,
|
||||
1,
|
||||
&accelerationBuildGeometryInfo,
|
||||
accelerationBuildStructureRangeInfos.data());
|
||||
vulkanDevice->flushCommandBuffer(commandBuffer, queue);
|
||||
}
|
||||
|
||||
VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{};
|
||||
accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
|
||||
accelerationDeviceAddressInfo.accelerationStructure = bottomLevelAS.accelerationStructure;
|
||||
|
||||
bottomLevelAS.handle = vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
|
||||
|
||||
deleteScratchBuffer(scratchBuffer);
|
||||
}
|
||||
|
||||
|
|
@ -365,132 +167,133 @@ public:
|
|||
*/
|
||||
void createTopLevelAccelerationStructure()
|
||||
{
|
||||
VkAccelerationStructureCreateGeometryTypeInfoKHR accelerationCreateGeometryInfo{};
|
||||
accelerationCreateGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR;
|
||||
accelerationCreateGeometryInfo.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
|
||||
accelerationCreateGeometryInfo.maxPrimitiveCount = 1;
|
||||
accelerationCreateGeometryInfo.allowsTransforms = VK_FALSE;
|
||||
|
||||
VkAccelerationStructureCreateInfoKHR accelerationCI{};
|
||||
accelerationCI.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR;
|
||||
accelerationCI.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
|
||||
accelerationCI.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
accelerationCI.maxGeometryCount = 1;
|
||||
accelerationCI.pGeometryInfos = &accelerationCreateGeometryInfo;
|
||||
VK_CHECK_RESULT(vkCreateAccelerationStructureKHR(device, &accelerationCI, nullptr, &topLevelAS.accelerationStructure));
|
||||
|
||||
// Bind object memory to the top level acceleration structure
|
||||
topLevelAS.objectMemory = createObjectMemory(topLevelAS.accelerationStructure);
|
||||
|
||||
VkBindAccelerationStructureMemoryInfoKHR bindAccelerationMemoryInfo{};
|
||||
bindAccelerationMemoryInfo.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR;
|
||||
bindAccelerationMemoryInfo.accelerationStructure = topLevelAS.accelerationStructure;
|
||||
bindAccelerationMemoryInfo.memory = topLevelAS.objectMemory.memory;
|
||||
VK_CHECK_RESULT(vkBindAccelerationStructureMemoryKHR(device, 1, &bindAccelerationMemoryInfo));
|
||||
|
||||
VkTransformMatrixKHR transform_matrix = {
|
||||
VkTransformMatrixKHR transformMatrix = {
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f };
|
||||
|
||||
VkAccelerationStructureInstanceKHR instance{};
|
||||
instance.transform = transform_matrix;
|
||||
instance.transform = transformMatrix;
|
||||
instance.instanceCustomIndex = 0;
|
||||
instance.mask = 0xFF;
|
||||
instance.instanceShaderBindingTableRecordOffset = 0;
|
||||
instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||
instance.accelerationStructureReference = bottomLevelAS.handle;
|
||||
instance.accelerationStructureReference = bottomLevelAS.deviceAddress;
|
||||
|
||||
// Buffer for instance data
|
||||
vks::Buffer instancesBuffer;
|
||||
VK_CHECK_RESULT(vulkanDevice->createBuffer(
|
||||
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
|
||||
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
&instancesBuffer,
|
||||
sizeof(instance),
|
||||
sizeof(VkAccelerationStructureInstanceKHR),
|
||||
&instance));
|
||||
|
||||
VkDeviceOrHostAddressConstKHR instance_data_device_address{};
|
||||
instance_data_device_address.deviceAddress = getBufferDeviceAddress(instancesBuffer.buffer);
|
||||
VkDeviceOrHostAddressConstKHR instanceDataDeviceAddress{};
|
||||
instanceDataDeviceAddress.deviceAddress = getBufferDeviceAddress(instancesBuffer.buffer);
|
||||
|
||||
VkAccelerationStructureGeometryKHR accelerationStructureGeometry{};
|
||||
accelerationStructureGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
|
||||
accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
|
||||
VkAccelerationStructureGeometryKHR accelerationStructureGeometry = vks::initializers::accelerationStructureGeometryKHR();
|
||||
accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
|
||||
accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
|
||||
accelerationStructureGeometry.geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR;
|
||||
accelerationStructureGeometry.geometry.instances.arrayOfPointers = VK_FALSE;
|
||||
accelerationStructureGeometry.geometry.instances.data.deviceAddress = instance_data_device_address.deviceAddress;
|
||||
accelerationStructureGeometry.geometry.instances.data = instanceDataDeviceAddress;
|
||||
|
||||
std::vector<VkAccelerationStructureGeometryKHR> acceleration_geometries = { accelerationStructureGeometry };
|
||||
VkAccelerationStructureGeometryKHR* acceleration_structure_geometries = acceleration_geometries.data();
|
||||
// Get size info
|
||||
VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR();
|
||||
accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
|
||||
accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
accelerationStructureBuildGeometryInfo.geometryCount = 1;
|
||||
accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry;
|
||||
|
||||
uint32_t primitive_count = 1;
|
||||
|
||||
VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo = vks::initializers::accelerationStructureBuildSizesInfoKHR();
|
||||
vkGetAccelerationStructureBuildSizesKHR(
|
||||
device,
|
||||
VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
|
||||
&accelerationStructureBuildGeometryInfo,
|
||||
&primitive_count,
|
||||
&accelerationStructureBuildSizesInfo);
|
||||
|
||||
createAccelerationStructure(topLevelAS, VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, accelerationStructureBuildSizesInfo);
|
||||
|
||||
// Create a small scratch buffer used during build of the top level acceleration structure
|
||||
RayTracingScratchBuffer scratchBuffer = createScratchBuffer(topLevelAS.accelerationStructure);
|
||||
ScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize);
|
||||
|
||||
VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo{};
|
||||
accelerationBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
|
||||
VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR();
|
||||
accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
|
||||
accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
accelerationBuildGeometryInfo.update = VK_FALSE;
|
||||
accelerationBuildGeometryInfo.srcAccelerationStructure = VK_NULL_HANDLE;
|
||||
accelerationBuildGeometryInfo.dstAccelerationStructure = topLevelAS.accelerationStructure;
|
||||
accelerationBuildGeometryInfo.geometryArrayOfPointers = VK_FALSE;
|
||||
accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
|
||||
accelerationBuildGeometryInfo.dstAccelerationStructure = topLevelAS.handle;
|
||||
accelerationBuildGeometryInfo.geometryCount = 1;
|
||||
accelerationBuildGeometryInfo.ppGeometries = &acceleration_structure_geometries;
|
||||
accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry;
|
||||
accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress;
|
||||
|
||||
VkAccelerationStructureBuildOffsetInfoKHR accelerationBuildOffsetInfo{};
|
||||
accelerationBuildOffsetInfo.primitiveCount = 1;
|
||||
accelerationBuildOffsetInfo.primitiveOffset = 0x0;
|
||||
accelerationBuildOffsetInfo.firstVertex = 0;
|
||||
accelerationBuildOffsetInfo.transformOffset = 0x0;
|
||||
std::vector<VkAccelerationStructureBuildOffsetInfoKHR*> accelerationBuildOffsets = { &accelerationBuildOffsetInfo };
|
||||
VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{};
|
||||
accelerationStructureBuildRangeInfo.primitiveCount = 1;
|
||||
accelerationStructureBuildRangeInfo.primitiveOffset = 0;
|
||||
accelerationStructureBuildRangeInfo.firstVertex = 0;
|
||||
accelerationStructureBuildRangeInfo.transformOffset = 0;
|
||||
std::vector<VkAccelerationStructureBuildRangeInfoKHR*> accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo };
|
||||
|
||||
if (rayTracingFeatures.rayTracingHostAccelerationStructureCommands)
|
||||
if (accelerationStructureFeatures.accelerationStructureHostCommands)
|
||||
{
|
||||
// Implementation supports building acceleration structure building on host
|
||||
VK_CHECK_RESULT(vkBuildAccelerationStructureKHR(device, 1, &accelerationBuildGeometryInfo, accelerationBuildOffsets.data()));
|
||||
vkBuildAccelerationStructuresKHR(
|
||||
device,
|
||||
VK_NULL_HANDLE,
|
||||
1,
|
||||
&accelerationBuildGeometryInfo,
|
||||
accelerationBuildStructureRangeInfos.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Acceleration structure needs to be build on the device
|
||||
VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||
vkCmdBuildAccelerationStructureKHR(commandBuffer, 1, &accelerationBuildGeometryInfo, accelerationBuildOffsets.data());
|
||||
vkCmdBuildAccelerationStructuresKHR(
|
||||
commandBuffer,
|
||||
1,
|
||||
&accelerationBuildGeometryInfo,
|
||||
accelerationBuildStructureRangeInfos.data());
|
||||
vulkanDevice->flushCommandBuffer(commandBuffer, queue);
|
||||
}
|
||||
|
||||
VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{};
|
||||
accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
|
||||
accelerationDeviceAddressInfo.accelerationStructure = topLevelAS.accelerationStructure;
|
||||
|
||||
topLevelAS.handle = vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
|
||||
|
||||
deleteScratchBuffer(scratchBuffer);
|
||||
instancesBuffer.destroy();
|
||||
}
|
||||
|
||||
/*
|
||||
Create the Shader Binding Table that binds the programs and top-level acceleration structure
|
||||
Create the Shader Binding Tables that binds the programs and top-level acceleration structure
|
||||
|
||||
SBT Layout used in this sample:
|
||||
|
||||
/-----------\
|
||||
| raygen |
|
||||
|-----------|
|
||||
| miss |
|
||||
|-----------|
|
||||
| hit |
|
||||
\-----------/
|
||||
|
||||
*/
|
||||
void createShaderBindingTable() {
|
||||
void createShaderBindingTables() {
|
||||
const uint32_t handleSize = rayTracingPipelineProperties.shaderGroupHandleSize;
|
||||
const uint32_t handleAlignment = rayTracingPipelineProperties.shaderGroupHandleAlignment;
|
||||
const uint32_t groupCount = static_cast<uint32_t>(shaderGroups.size());
|
||||
const uint32_t sbtSize = handleSize * groupCount;
|
||||
|
||||
const uint32_t sbtSize = rayTracingProperties.shaderGroupBaseAlignment * groupCount;
|
||||
VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &shaderBindingTable, sbtSize));
|
||||
shaderBindingTable.map();
|
||||
|
||||
// Write the shader handles to the shader binding table
|
||||
std::vector<uint8_t> shaderHandleStorage(sbtSize);
|
||||
VK_CHECK_RESULT(vkGetRayTracingShaderGroupHandlesKHR(device, pipeline, 0, groupCount, sbtSize, shaderHandleStorage.data()));
|
||||
|
||||
auto* data = static_cast<uint8_t*>(shaderBindingTable.mapped);
|
||||
// This part is required, as the alignment and handle size may differ
|
||||
for (uint32_t i = 0; i < groupCount; i++)
|
||||
{
|
||||
memcpy(data, shaderHandleStorage.data() + i * rayTracingProperties.shaderGroupHandleSize, rayTracingProperties.shaderGroupHandleSize);
|
||||
data += rayTracingProperties.shaderGroupBaseAlignment;
|
||||
}
|
||||
shaderBindingTable.unmap();
|
||||
createShaderBindingTable(shaderBindingTables.raygen, 1);
|
||||
createShaderBindingTable(shaderBindingTables.miss, 1);
|
||||
createShaderBindingTable(shaderBindingTables.hit, 1);
|
||||
|
||||
// Copy handles
|
||||
memcpy(shaderBindingTables.raygen.mapped, shaderHandleStorage.data(), handleSize);
|
||||
memcpy(shaderBindingTables.miss.mapped, shaderHandleStorage.data() + handleAlignment, handleSize);
|
||||
memcpy(shaderBindingTables.hit.mapped, shaderHandleStorage.data() + handleAlignment * 2, handleSize);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -510,10 +313,9 @@ public:
|
|||
VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1);
|
||||
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet));
|
||||
|
||||
VkWriteDescriptorSetAccelerationStructureKHR descriptorAccelerationStructureInfo{};
|
||||
descriptorAccelerationStructureInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR;
|
||||
VkWriteDescriptorSetAccelerationStructureKHR descriptorAccelerationStructureInfo = vks::initializers::writeDescriptorSetAccelerationStructureKHR();
|
||||
descriptorAccelerationStructureInfo.accelerationStructureCount = 1;
|
||||
descriptorAccelerationStructureInfo.pAccelerationStructures = &topLevelAS.accelerationStructure;
|
||||
descriptorAccelerationStructureInfo.pAccelerationStructures = &topLevelAS.handle;
|
||||
|
||||
VkWriteDescriptorSet accelerationStructureWrite{};
|
||||
accelerationStructureWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
|
|
@ -524,29 +326,21 @@ public:
|
|||
accelerationStructureWrite.descriptorCount = 1;
|
||||
accelerationStructureWrite.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
|
||||
|
||||
VkDescriptorImageInfo storageImageDescriptor{};
|
||||
storageImageDescriptor.imageView = storageImage.view;
|
||||
storageImageDescriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
|
||||
VkDescriptorBufferInfo vertexBufferDescriptor{};
|
||||
vertexBufferDescriptor.buffer = scene.vertices.buffer;
|
||||
vertexBufferDescriptor.range = VK_WHOLE_SIZE;
|
||||
|
||||
VkDescriptorBufferInfo indexBufferDescriptor{};
|
||||
indexBufferDescriptor.buffer = scene.indices.buffer;
|
||||
indexBufferDescriptor.range = VK_WHOLE_SIZE;
|
||||
|
||||
VkWriteDescriptorSet resultImageWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor);
|
||||
VkWriteDescriptorSet uniformBufferWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &ubo.descriptor);
|
||||
VkWriteDescriptorSet vertexBufferWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3, &vertexBufferDescriptor);
|
||||
VkWriteDescriptorSet indexBufferWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4, &indexBufferDescriptor);
|
||||
VkDescriptorImageInfo storageImageDescriptor{ VK_NULL_HANDLE, storageImage.view, VK_IMAGE_LAYOUT_GENERAL };
|
||||
VkDescriptorBufferInfo vertexBufferDescriptor{ scene.vertices.buffer, 0, VK_WHOLE_SIZE };
|
||||
VkDescriptorBufferInfo indexBufferDescriptor{ scene.indices.buffer, 0, VK_WHOLE_SIZE };
|
||||
|
||||
std::vector<VkWriteDescriptorSet> writeDescriptorSets = {
|
||||
// Binding 0: Top level acceleration structure
|
||||
accelerationStructureWrite,
|
||||
resultImageWrite,
|
||||
uniformBufferWrite,
|
||||
vertexBufferWrite,
|
||||
indexBufferWrite
|
||||
// Binding 0: Top level acceleration structure
|
||||
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor),
|
||||
// Binding 1: Ray tracing result image
|
||||
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &ubo.descriptor),
|
||||
// Binding 1: Ray tracing result image
|
||||
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3, &vertexBufferDescriptor),
|
||||
// Binding 1: Ray tracing result image
|
||||
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4, &indexBufferDescriptor),
|
||||
};
|
||||
vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, VK_NULL_HANDLE);
|
||||
}
|
||||
|
|
@ -556,112 +350,82 @@ public:
|
|||
*/
|
||||
void createRayTracingPipeline()
|
||||
{
|
||||
VkDescriptorSetLayoutBinding accelerationStructureLayoutBinding{};
|
||||
accelerationStructureLayoutBinding.binding = 0;
|
||||
accelerationStructureLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
|
||||
accelerationStructureLayoutBinding.descriptorCount = 1;
|
||||
accelerationStructureLayoutBinding.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
|
||||
std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings = {
|
||||
// Binding 0: Acceleration structure
|
||||
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 0),
|
||||
// Binding 1: Storage image
|
||||
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_RAYGEN_BIT_KHR, 1),
|
||||
// Binding 2: Uniform buffer
|
||||
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR, 2),
|
||||
// Binding 3: Vertex buffer
|
||||
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 3),
|
||||
// Binding 4: Index buffer
|
||||
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 4),
|
||||
};
|
||||
|
||||
VkDescriptorSetLayoutBinding resultImageLayoutBinding{};
|
||||
resultImageLayoutBinding.binding = 1;
|
||||
resultImageLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||
resultImageLayoutBinding.descriptorCount = 1;
|
||||
resultImageLayoutBinding.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR;
|
||||
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings);
|
||||
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayout));
|
||||
|
||||
VkDescriptorSetLayoutBinding uniformBufferBinding{};
|
||||
uniformBufferBinding.binding = 2;
|
||||
uniformBufferBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
uniformBufferBinding.descriptorCount = 1;
|
||||
uniformBufferBinding.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR;
|
||||
|
||||
VkDescriptorSetLayoutBinding vertexBufferBinding{};
|
||||
vertexBufferBinding.binding = 3;
|
||||
vertexBufferBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
vertexBufferBinding.descriptorCount = 1;
|
||||
vertexBufferBinding.stageFlags = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
|
||||
|
||||
VkDescriptorSetLayoutBinding indexBufferBinding{};
|
||||
indexBufferBinding.binding = 4;
|
||||
indexBufferBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
indexBufferBinding.descriptorCount = 1;
|
||||
indexBufferBinding.stageFlags = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
|
||||
|
||||
std::vector<VkDescriptorSetLayoutBinding> bindings({
|
||||
accelerationStructureLayoutBinding,
|
||||
resultImageLayoutBinding,
|
||||
uniformBufferBinding,
|
||||
vertexBufferBinding,
|
||||
indexBufferBinding
|
||||
});
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo layoutInfo{};
|
||||
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
|
||||
layoutInfo.pBindings = bindings.data();
|
||||
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout));
|
||||
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{};
|
||||
pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
pipelineLayoutCreateInfo.setLayoutCount = 1;
|
||||
pipelineLayoutCreateInfo.pSetLayouts = &descriptorSetLayout;
|
||||
|
||||
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
|
||||
|
||||
const uint32_t shaderIndexRaygen = 0;
|
||||
const uint32_t shaderIndexMiss = 1;
|
||||
const uint32_t shaderIndexClosestHit = 2;
|
||||
|
||||
std::array<VkPipelineShaderStageCreateInfo, 3> shaderStages;
|
||||
shaderStages[shaderIndexRaygen] = loadShader(getShadersPath() + "raytracingreflections/raygen.rgen.spv", VK_SHADER_STAGE_RAYGEN_BIT_KHR);
|
||||
shaderStages[shaderIndexMiss] = loadShader(getShadersPath() + "raytracingreflections/miss.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR);
|
||||
shaderStages[shaderIndexClosestHit] = loadShader(getShadersPath() + "raytracingreflections/closesthit.rchit.spv", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
||||
|
||||
// Pass recursion depth for reflections to ray generation shader via specialization constant
|
||||
VkSpecializationMapEntry specializationMapEntry = vks::initializers::specializationMapEntry(0, 0, sizeof(uint32_t));
|
||||
uint32_t maxRecursion = 4;
|
||||
VkSpecializationInfo specializationInfo = vks::initializers::specializationInfo(1, &specializationMapEntry, sizeof(maxRecursion), &maxRecursion);
|
||||
shaderStages[shaderIndexRaygen].pSpecializationInfo = &specializationInfo;
|
||||
VkPipelineLayoutCreateInfo pPipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1);
|
||||
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCI, nullptr, &pipelineLayout));
|
||||
|
||||
/*
|
||||
Setup ray tracing shader groups
|
||||
*/
|
||||
VkRayTracingShaderGroupCreateInfoKHR raygenGroupCI{};
|
||||
raygenGroupCI.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
|
||||
raygenGroupCI.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
|
||||
raygenGroupCI.generalShader = shaderIndexRaygen;
|
||||
raygenGroupCI.closestHitShader = VK_SHADER_UNUSED_KHR;
|
||||
raygenGroupCI.anyHitShader = VK_SHADER_UNUSED_KHR;
|
||||
raygenGroupCI.intersectionShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroups.push_back(raygenGroupCI);
|
||||
std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
|
||||
|
||||
VkRayTracingShaderGroupCreateInfoKHR missGroupCI{};
|
||||
missGroupCI.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
|
||||
missGroupCI.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
|
||||
missGroupCI.generalShader = shaderIndexMiss;
|
||||
missGroupCI.closestHitShader = VK_SHADER_UNUSED_KHR;
|
||||
missGroupCI.anyHitShader = VK_SHADER_UNUSED_KHR;
|
||||
missGroupCI.intersectionShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroups.push_back(missGroupCI);
|
||||
// Ray generation group
|
||||
{
|
||||
shaderStages.push_back(loadShader(getShadersPath() + "raytracingreflections/raygen.rgen.spv", VK_SHADER_STAGE_RAYGEN_BIT_KHR));
|
||||
// Pass recursion depth for reflections to ray generation shader via specialization constant
|
||||
VkSpecializationMapEntry specializationMapEntry = vks::initializers::specializationMapEntry(0, 0, sizeof(uint32_t));
|
||||
uint32_t maxRecursion = 4;
|
||||
VkSpecializationInfo specializationInfo = vks::initializers::specializationInfo(1, &specializationMapEntry, sizeof(maxRecursion), &maxRecursion);
|
||||
shaderStages.back().pSpecializationInfo = &specializationInfo;
|
||||
VkRayTracingShaderGroupCreateInfoKHR shaderGroup{};
|
||||
shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
|
||||
shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
|
||||
shaderGroup.generalShader = static_cast<uint32_t>(shaderStages.size()) - 1;
|
||||
shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroups.push_back(shaderGroup);
|
||||
}
|
||||
|
||||
VkRayTracingShaderGroupCreateInfoKHR closesHitGroupCI{};
|
||||
closesHitGroupCI.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
|
||||
closesHitGroupCI.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR;
|
||||
closesHitGroupCI.generalShader = VK_SHADER_UNUSED_KHR;
|
||||
closesHitGroupCI.closestHitShader = shaderIndexClosestHit;
|
||||
closesHitGroupCI.anyHitShader = VK_SHADER_UNUSED_KHR;
|
||||
closesHitGroupCI.intersectionShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroups.push_back(closesHitGroupCI);
|
||||
// Miss group
|
||||
{
|
||||
shaderStages.push_back(loadShader(getShadersPath() + "raytracingreflections/miss.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR));
|
||||
VkRayTracingShaderGroupCreateInfoKHR shaderGroup{};
|
||||
shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
|
||||
shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
|
||||
shaderGroup.generalShader = static_cast<uint32_t>(shaderStages.size()) - 1;
|
||||
shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroups.push_back(shaderGroup);
|
||||
}
|
||||
|
||||
VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCI{};
|
||||
rayTracingPipelineCI.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR;
|
||||
// Closest hit group
|
||||
{
|
||||
shaderStages.push_back(loadShader(getShadersPath() + "raytracingreflections/closesthit.rchit.spv", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR));
|
||||
VkRayTracingShaderGroupCreateInfoKHR shaderGroup{};
|
||||
shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
|
||||
shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR;
|
||||
shaderGroup.generalShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroup.closestHitShader = static_cast<uint32_t>(shaderStages.size()) - 1;
|
||||
shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroups.push_back(shaderGroup);
|
||||
}
|
||||
|
||||
VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCI = vks::initializers::rayTracingPipelineCreateInfoKHR();
|
||||
rayTracingPipelineCI.stageCount = static_cast<uint32_t>(shaderStages.size());
|
||||
rayTracingPipelineCI.pStages = shaderStages.data();
|
||||
rayTracingPipelineCI.groupCount = static_cast<uint32_t>(shaderGroups.size());
|
||||
rayTracingPipelineCI.pGroups = shaderGroups.data();
|
||||
rayTracingPipelineCI.maxRecursionDepth = 4;
|
||||
rayTracingPipelineCI.maxPipelineRayRecursionDepth = 4;
|
||||
rayTracingPipelineCI.layout = pipelineLayout;
|
||||
rayTracingPipelineCI.libraries.sType = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR;
|
||||
VK_CHECK_RESULT(vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &pipeline));
|
||||
VK_CHECK_RESULT(vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &pipeline));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -685,12 +449,8 @@ public:
|
|||
*/
|
||||
void handleResize()
|
||||
{
|
||||
// Delete allocated resources
|
||||
vkDestroyImageView(device, storageImage.view, nullptr);
|
||||
vkDestroyImage(device, storageImage.image, nullptr);
|
||||
vkFreeMemory(device, storageImage.memory, nullptr);
|
||||
// Recreate image
|
||||
createStorageImage();
|
||||
createStorageImage(swapChain.colorFormat, { width, height, 1 });
|
||||
// Update descriptor
|
||||
VkDescriptorImageInfo storageImageDescriptor{ VK_NULL_HANDLE, storageImage.view, VK_IMAGE_LAYOUT_GENERAL };
|
||||
VkWriteDescriptorSet resultImageWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor);
|
||||
|
|
@ -722,36 +482,18 @@ public:
|
|||
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout, 0, 1, &descriptorSet, 0, 0);
|
||||
|
||||
/*
|
||||
Setup the buffer regions pointing to the shaders in our shader binding table
|
||||
Dispatch the ray tracing commands
|
||||
*/
|
||||
const VkDeviceSize sbtSize = rayTracingProperties.shaderGroupBaseAlignment * (VkDeviceSize)shaderGroups.size();
|
||||
|
||||
VkStridedBufferRegionKHR raygenShaderSBTEntry{};
|
||||
raygenShaderSBTEntry.buffer = shaderBindingTable.buffer;
|
||||
raygenShaderSBTEntry.offset = static_cast<VkDeviceSize>(rayTracingProperties.shaderGroupBaseAlignment * INDEX_RAYGEN_GROUP);
|
||||
raygenShaderSBTEntry.stride = rayTracingProperties.shaderGroupBaseAlignment;
|
||||
raygenShaderSBTEntry.size = sbtSize;
|
||||
|
||||
VkStridedBufferRegionKHR missShaderSBTEntry{};
|
||||
missShaderSBTEntry.buffer = shaderBindingTable.buffer;
|
||||
missShaderSBTEntry.offset = static_cast<VkDeviceSize>(rayTracingProperties.shaderGroupBaseAlignment * INDEX_MISS_GROUP);
|
||||
missShaderSBTEntry.stride = rayTracingProperties.shaderGroupBaseAlignment;
|
||||
missShaderSBTEntry.size = sbtSize;
|
||||
|
||||
VkStridedBufferRegionKHR hitShaderSBTEntry{};
|
||||
hitShaderSBTEntry.buffer = shaderBindingTable.buffer;
|
||||
hitShaderSBTEntry.offset = static_cast<VkDeviceSize>(rayTracingProperties.shaderGroupBaseAlignment * INDEX_CLOSEST_HIT_GROUP);
|
||||
hitShaderSBTEntry.stride = rayTracingProperties.shaderGroupBaseAlignment;
|
||||
hitShaderSBTEntry.size = sbtSize;
|
||||
|
||||
VkStridedBufferRegionKHR callableShaderSBTEntry{};
|
||||
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline);
|
||||
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout, 0, 1, &descriptorSet, 0, 0);
|
||||
|
||||
VkStridedDeviceAddressRegionKHR emptySbtEntry = {};
|
||||
vkCmdTraceRaysKHR(
|
||||
drawCmdBuffers[i],
|
||||
&raygenShaderSBTEntry,
|
||||
&missShaderSBTEntry,
|
||||
&hitShaderSBTEntry,
|
||||
&callableShaderSBTEntry,
|
||||
&shaderBindingTables.raygen.stridedDeviceAddressRegion,
|
||||
&shaderBindingTables.miss.stridedDeviceAddressRegion,
|
||||
&shaderBindingTables.hit.stridedDeviceAddressRegion,
|
||||
&emptySbtEntry,
|
||||
width,
|
||||
height,
|
||||
1);
|
||||
|
|
@ -825,52 +567,29 @@ public:
|
|||
enabledBufferDeviceAddresFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES;
|
||||
enabledBufferDeviceAddresFeatures.bufferDeviceAddress = VK_TRUE;
|
||||
|
||||
enabledRayTracingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR;
|
||||
enabledRayTracingFeatures.rayTracing = VK_TRUE;
|
||||
enabledRayTracingFeatures.pNext = &enabledBufferDeviceAddresFeatures;
|
||||
enabledRayTracingPipelineFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR;
|
||||
enabledRayTracingPipelineFeatures.rayTracingPipeline = VK_TRUE;
|
||||
enabledRayTracingPipelineFeatures.pNext = &enabledBufferDeviceAddresFeatures;
|
||||
|
||||
deviceCreatepNextChain = &enabledRayTracingFeatures;
|
||||
enabledAccelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR;
|
||||
enabledAccelerationStructureFeatures.accelerationStructure = VK_TRUE;
|
||||
enabledAccelerationStructureFeatures.pNext = &enabledRayTracingPipelineFeatures;
|
||||
|
||||
deviceCreatepNextChain = &enabledAccelerationStructureFeatures;
|
||||
}
|
||||
|
||||
void prepare()
|
||||
{
|
||||
VulkanExampleBase::prepare();
|
||||
|
||||
// Query the ray tracing properties of the current implementation, we will need them later on
|
||||
rayTracingProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR;
|
||||
VkPhysicalDeviceProperties2 deviceProps2{};
|
||||
deviceProps2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
|
||||
deviceProps2.pNext = &rayTracingProperties;
|
||||
vkGetPhysicalDeviceProperties2(physicalDevice, &deviceProps2);
|
||||
|
||||
// Query the ray tracing properties of the current implementation, we will need them later on
|
||||
rayTracingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR;
|
||||
VkPhysicalDeviceFeatures2 deviceFeatures2{};
|
||||
deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
|
||||
deviceFeatures2.pNext = &rayTracingFeatures;
|
||||
vkGetPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures2);
|
||||
|
||||
// Get the function pointers required for ray tracing
|
||||
vkGetBufferDeviceAddressKHR = reinterpret_cast<PFN_vkGetBufferDeviceAddressKHR>(vkGetDeviceProcAddr(device, "vkGetBufferDeviceAddressKHR"));
|
||||
vkBindAccelerationStructureMemoryKHR = reinterpret_cast<PFN_vkBindAccelerationStructureMemoryKHR>(vkGetDeviceProcAddr(device, "vkBindAccelerationStructureMemoryKHR"));
|
||||
vkCreateAccelerationStructureKHR = reinterpret_cast<PFN_vkCreateAccelerationStructureKHR>(vkGetDeviceProcAddr(device, "vkCreateAccelerationStructureKHR"));
|
||||
vkDestroyAccelerationStructureKHR = reinterpret_cast<PFN_vkDestroyAccelerationStructureKHR>(vkGetDeviceProcAddr(device, "vkDestroyAccelerationStructureKHR"));
|
||||
vkGetAccelerationStructureMemoryRequirementsKHR = reinterpret_cast<PFN_vkGetAccelerationStructureMemoryRequirementsKHR>(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureMemoryRequirementsKHR"));
|
||||
vkCmdBuildAccelerationStructureKHR = reinterpret_cast<PFN_vkCmdBuildAccelerationStructureKHR>(vkGetDeviceProcAddr(device, "vkCmdBuildAccelerationStructureKHR"));
|
||||
vkBuildAccelerationStructureKHR = reinterpret_cast<PFN_vkBuildAccelerationStructureKHR>(vkGetDeviceProcAddr(device, "vkBuildAccelerationStructureKHR"));
|
||||
vkGetAccelerationStructureDeviceAddressKHR = reinterpret_cast<PFN_vkGetAccelerationStructureDeviceAddressKHR>(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureDeviceAddressKHR"));
|
||||
vkCmdTraceRaysKHR = reinterpret_cast<PFN_vkCmdTraceRaysKHR>(vkGetDeviceProcAddr(device, "vkCmdTraceRaysKHR"));
|
||||
vkGetRayTracingShaderGroupHandlesKHR = reinterpret_cast<PFN_vkGetRayTracingShaderGroupHandlesKHR>(vkGetDeviceProcAddr(device, "vkGetRayTracingShaderGroupHandlesKHR"));
|
||||
vkCreateRayTracingPipelinesKHR = reinterpret_cast<PFN_vkCreateRayTracingPipelinesKHR>(vkGetDeviceProcAddr(device, "vkCreateRayTracingPipelinesKHR"));
|
||||
VulkanRaytracingSample::prepare();
|
||||
|
||||
// Create the acceleration structures used to render the ray traced scene
|
||||
createBottomLevelAccelerationStructure();
|
||||
createTopLevelAccelerationStructure();
|
||||
|
||||
createStorageImage();
|
||||
createStorageImage(swapChain.colorFormat, { width, height, 1 });
|
||||
createUniformBuffer();
|
||||
createRayTracingPipeline();
|
||||
createShaderBindingTable();
|
||||
createShaderBindingTables();
|
||||
createDescriptorSets();
|
||||
buildCommandBuffers();
|
||||
prepared = true;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Vulkan Example - Hardware accelerated ray tracing shadow example using VK_KHR_ray_traying
|
||||
* Vulkan Example - Hardware accelerated ray tracing shadow example
|
||||
*
|
||||
* Renders a complex scene using multiple hit and miss shaders for implementing shadows
|
||||
*
|
||||
|
|
@ -8,69 +8,21 @@
|
|||
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
||||
*/
|
||||
|
||||
#define VK_ENABLE_BETA_EXTENSIONS
|
||||
|
||||
#include "vulkanexamplebase.h"
|
||||
#include "VulkanRaytracingSample.h"
|
||||
#include "VulkanglTFModel.h"
|
||||
|
||||
// Ray tracing utility structures, see ray tracing basic sample for details
|
||||
struct RayTracingScratchBuffer
|
||||
{
|
||||
uint64_t deviceAddress = 0;
|
||||
VkBuffer buffer = VK_NULL_HANDLE;
|
||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
struct RayTracingObjectMemory
|
||||
{
|
||||
uint64_t deviceAddress = 0;
|
||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
struct AccelerationStructure {
|
||||
VkAccelerationStructureKHR accelerationStructure;
|
||||
uint64_t handle;
|
||||
RayTracingObjectMemory objectMemory;
|
||||
};
|
||||
|
||||
// Indices for the different ray tracing groups used in this example
|
||||
#define INDEX_RAYGEN_GROUP 0
|
||||
#define INDEX_MISS_GROUP 1
|
||||
#define INDEX_CLOSEST_HIT_GROUP 3
|
||||
|
||||
class VulkanExample : public VulkanExampleBase
|
||||
class VulkanExample : public VulkanRaytracingSample
|
||||
{
|
||||
public:
|
||||
PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR;
|
||||
PFN_vkBindAccelerationStructureMemoryKHR vkBindAccelerationStructureMemoryKHR;
|
||||
PFN_vkCreateAccelerationStructureKHR vkCreateAccelerationStructureKHR;
|
||||
PFN_vkDestroyAccelerationStructureKHR vkDestroyAccelerationStructureKHR;
|
||||
PFN_vkGetAccelerationStructureMemoryRequirementsKHR vkGetAccelerationStructureMemoryRequirementsKHR;
|
||||
PFN_vkCmdBuildAccelerationStructureKHR vkCmdBuildAccelerationStructureKHR;
|
||||
PFN_vkBuildAccelerationStructureKHR vkBuildAccelerationStructureKHR;
|
||||
PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR;
|
||||
PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR;
|
||||
PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR;
|
||||
PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR;
|
||||
|
||||
VkPhysicalDeviceRayTracingPropertiesKHR rayTracingProperties{};
|
||||
VkPhysicalDeviceRayTracingFeaturesKHR rayTracingFeatures{};
|
||||
|
||||
VkPhysicalDeviceBufferDeviceAddressFeatures enabledBufferDeviceAddresFeatures{};
|
||||
VkPhysicalDeviceRayTracingFeaturesKHR enabledRayTracingFeatures{};
|
||||
|
||||
AccelerationStructure bottomLevelAS;
|
||||
AccelerationStructure topLevelAS;
|
||||
|
||||
std::vector<VkRayTracingShaderGroupCreateInfoKHR> shaderGroups{};
|
||||
vks::Buffer shaderBindingTable;
|
||||
|
||||
struct StorageImage {
|
||||
VkDeviceMemory memory;
|
||||
VkImage image;
|
||||
VkImageView view;
|
||||
VkFormat format;
|
||||
} storageImage;
|
||||
struct ShaderBindingTables {
|
||||
ShaderBindingTable raygen;
|
||||
ShaderBindingTable miss;
|
||||
ShaderBindingTable hit;
|
||||
} shaderBindingTables;
|
||||
|
||||
struct UniformData {
|
||||
glm::mat4 viewInverse;
|
||||
|
|
@ -87,7 +39,8 @@ public:
|
|||
|
||||
vkglTF::Model scene;
|
||||
|
||||
VulkanExample() : VulkanExampleBase()
|
||||
// This sample is derived from an extended base class that saves most of the ray tracing setup boiler plate
|
||||
VulkanExample() : VulkanRaytracingSample()
|
||||
{
|
||||
title = "Ray traced shadows";
|
||||
settings.overlay = false;
|
||||
|
|
@ -96,17 +49,7 @@ public:
|
|||
camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f);
|
||||
camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f));
|
||||
camera.setTranslation(glm::vec3(0.0f, 3.0f, -10.0f));
|
||||
// Enable instance and device extensions required to use VK_KHR_ray_tracing
|
||||
enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_RAY_TRACING_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME);
|
||||
// We require Vulkan 1.2 for ray tracing
|
||||
apiVersion = VK_API_VERSION_1_2;
|
||||
enableExtensions();
|
||||
}
|
||||
|
||||
~VulkanExample()
|
||||
|
|
@ -114,146 +57,13 @@ public:
|
|||
vkDestroyPipeline(device, pipeline, nullptr);
|
||||
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
|
||||
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
|
||||
vkDestroyImageView(device, storageImage.view, nullptr);
|
||||
vkDestroyImage(device, storageImage.image, nullptr);
|
||||
vkFreeMemory(device, storageImage.memory, nullptr);
|
||||
vkDestroyAccelerationStructureKHR(device, bottomLevelAS.accelerationStructure, nullptr);
|
||||
vkDestroyAccelerationStructureKHR(device, topLevelAS.accelerationStructure, nullptr);
|
||||
shaderBindingTable.destroy();
|
||||
deleteStorageImage();
|
||||
deleteAccelerationStructure(bottomLevelAS);
|
||||
deleteAccelerationStructure(topLevelAS);
|
||||
shaderBindingTables.raygen.destroy();
|
||||
shaderBindingTables.miss.destroy();
|
||||
shaderBindingTables.hit.destroy();
|
||||
ubo.destroy();
|
||||
deleteObjectMemory(bottomLevelAS.objectMemory);
|
||||
deleteObjectMemory(topLevelAS.objectMemory);
|
||||
}
|
||||
|
||||
/*
|
||||
Ray tracing utility functions, see ray tracing basic sample for details
|
||||
*/
|
||||
RayTracingScratchBuffer createScratchBuffer(VkAccelerationStructureKHR accelerationStructure)
|
||||
{
|
||||
RayTracingScratchBuffer scratchBuffer{};
|
||||
VkMemoryRequirements2 memoryRequirements2{};
|
||||
memoryRequirements2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
|
||||
VkAccelerationStructureMemoryRequirementsInfoKHR accelerationStructureMemoryRequirements{};
|
||||
accelerationStructureMemoryRequirements.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR;
|
||||
accelerationStructureMemoryRequirements.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR;
|
||||
accelerationStructureMemoryRequirements.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR;
|
||||
accelerationStructureMemoryRequirements.accelerationStructure = accelerationStructure;
|
||||
vkGetAccelerationStructureMemoryRequirementsKHR(device, &accelerationStructureMemoryRequirements, &memoryRequirements2);
|
||||
VkBufferCreateInfo bufferCI{};
|
||||
bufferCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
bufferCI.size = memoryRequirements2.memoryRequirements.size;
|
||||
bufferCI.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
|
||||
bufferCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCI, nullptr, &scratchBuffer.buffer));
|
||||
VkMemoryRequirements memoryRequirements{};
|
||||
vkGetBufferMemoryRequirements(device, scratchBuffer.buffer, &memoryRequirements);
|
||||
VkMemoryAllocateFlagsInfo memoryAllocateFI{};
|
||||
memoryAllocateFI.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO;
|
||||
memoryAllocateFI.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR;
|
||||
VkMemoryAllocateInfo memoryAI{};
|
||||
memoryAI.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
memoryAI.pNext = &memoryAllocateFI;
|
||||
memoryAI.allocationSize = memoryRequirements.size;
|
||||
memoryAI.memoryTypeIndex = vulkanDevice->getMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
VK_CHECK_RESULT(vkAllocateMemory(device, &memoryAI, nullptr, &scratchBuffer.memory));
|
||||
VK_CHECK_RESULT(vkBindBufferMemory(device, scratchBuffer.buffer, scratchBuffer.memory, 0));
|
||||
VkBufferDeviceAddressInfoKHR buffer_device_address_info{};
|
||||
buffer_device_address_info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
|
||||
buffer_device_address_info.buffer = scratchBuffer.buffer;
|
||||
scratchBuffer.deviceAddress = vkGetBufferDeviceAddressKHR(device, &buffer_device_address_info);
|
||||
return scratchBuffer;
|
||||
}
|
||||
|
||||
void deleteScratchBuffer(RayTracingScratchBuffer& scratchBuffer)
|
||||
{
|
||||
if (scratchBuffer.memory != VK_NULL_HANDLE) {
|
||||
vkFreeMemory(device, scratchBuffer.memory, nullptr);
|
||||
}
|
||||
if (scratchBuffer.buffer != VK_NULL_HANDLE) {
|
||||
vkDestroyBuffer(device, scratchBuffer.buffer, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
RayTracingObjectMemory createObjectMemory(VkAccelerationStructureKHR acceleration_structure)
|
||||
{
|
||||
RayTracingObjectMemory objectMemory{};
|
||||
VkMemoryRequirements2 memoryRequirements2{};
|
||||
memoryRequirements2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
|
||||
VkAccelerationStructureMemoryRequirementsInfoKHR accelerationStructureMemoryRequirements{};
|
||||
accelerationStructureMemoryRequirements.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR;
|
||||
accelerationStructureMemoryRequirements.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR;
|
||||
accelerationStructureMemoryRequirements.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR;
|
||||
accelerationStructureMemoryRequirements.accelerationStructure = acceleration_structure;
|
||||
vkGetAccelerationStructureMemoryRequirementsKHR(device, &accelerationStructureMemoryRequirements, &memoryRequirements2);
|
||||
VkMemoryRequirements memoryRequirements = memoryRequirements2.memoryRequirements;
|
||||
VkMemoryAllocateInfo memoryAI{};
|
||||
memoryAI.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
memoryAI.allocationSize = memoryRequirements.size;
|
||||
memoryAI.memoryTypeIndex = vulkanDevice->getMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
VK_CHECK_RESULT(vkAllocateMemory(device, &memoryAI, nullptr, &objectMemory.memory));
|
||||
return objectMemory;
|
||||
}
|
||||
|
||||
void deleteObjectMemory(RayTracingObjectMemory& objectMemory)
|
||||
{
|
||||
if (objectMemory.memory != VK_NULL_HANDLE) {
|
||||
vkFreeMemory(device, objectMemory.memory, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t getBufferDeviceAddress(VkBuffer buffer)
|
||||
{
|
||||
VkBufferDeviceAddressInfoKHR bufferDeviceAI{};
|
||||
bufferDeviceAI.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
|
||||
bufferDeviceAI.buffer = buffer;
|
||||
return vkGetBufferDeviceAddressKHR(device, &bufferDeviceAI);
|
||||
}
|
||||
|
||||
/*
|
||||
Set up a storage image that the ray generation shader will be writing to
|
||||
*/
|
||||
void createStorageImage()
|
||||
{
|
||||
VkImageCreateInfo image = vks::initializers::imageCreateInfo();
|
||||
image.imageType = VK_IMAGE_TYPE_2D;
|
||||
image.format = swapChain.colorFormat;
|
||||
image.extent.width = width;
|
||||
image.extent.height = height;
|
||||
image.extent.depth = 1;
|
||||
image.mipLevels = 1;
|
||||
image.arrayLayers = 1;
|
||||
image.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
image.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
image.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
|
||||
image.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &storageImage.image));
|
||||
|
||||
VkMemoryRequirements memReqs;
|
||||
vkGetImageMemoryRequirements(device, storageImage.image, &memReqs);
|
||||
VkMemoryAllocateInfo memoryAllocateInfo = vks::initializers::memoryAllocateInfo();
|
||||
memoryAllocateInfo.allocationSize = memReqs.size;
|
||||
memoryAllocateInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
VK_CHECK_RESULT(vkAllocateMemory(device, &memoryAllocateInfo, nullptr, &storageImage.memory));
|
||||
VK_CHECK_RESULT(vkBindImageMemory(device, storageImage.image, storageImage.memory, 0));
|
||||
|
||||
VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo();
|
||||
colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
colorImageView.format = swapChain.colorFormat;
|
||||
colorImageView.subresourceRange = {};
|
||||
colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
colorImageView.subresourceRange.baseMipLevel = 0;
|
||||
colorImageView.subresourceRange.levelCount = 1;
|
||||
colorImageView.subresourceRange.baseArrayLayer = 0;
|
||||
colorImageView.subresourceRange.layerCount = 1;
|
||||
colorImageView.image = storageImage.image;
|
||||
VK_CHECK_RESULT(vkCreateImageView(device, &colorImageView, nullptr, &storageImage.view));
|
||||
|
||||
VkCommandBuffer cmdBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||
vks::tools::setImageLayout(cmdBuffer, storageImage.image,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_GENERAL,
|
||||
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
|
||||
vulkanDevice->flushCommandBuffer(cmdBuffer, queue);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -263,99 +73,92 @@ public:
|
|||
{
|
||||
// Instead of a simple triangle, we'll be loading a more complex scene for this example
|
||||
// The shaders are accessing the vertex and index buffers of the scene, so the proper usage flag has to be set on the vertex and index buffers for the scene
|
||||
vkglTF::memoryPropertyFlags = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
|
||||
vkglTF::memoryPropertyFlags = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
const uint32_t glTFLoadingFlags = vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY;
|
||||
scene.loadFromFile(getAssetPath() + "models/vulkanscene_shadow.gltf", vulkanDevice, queue, glTFLoadingFlags);
|
||||
|
||||
const uint32_t numTriangles = static_cast<uint32_t>(scene.indices.count) / 3;
|
||||
|
||||
VkDeviceOrHostAddressConstKHR vertexBufferDeviceAddress{};
|
||||
VkDeviceOrHostAddressConstKHR indexBufferDeviceAddress{};
|
||||
|
||||
vertexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(scene.vertices.buffer);
|
||||
indexBufferDeviceAddress.deviceAddress = getBufferDeviceAddress(scene.indices.buffer);
|
||||
|
||||
VkAccelerationStructureCreateGeometryTypeInfoKHR accelerationCreateGeometryInfo{};
|
||||
accelerationCreateGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR;
|
||||
accelerationCreateGeometryInfo.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
|
||||
accelerationCreateGeometryInfo.maxPrimitiveCount = numTriangles;
|
||||
accelerationCreateGeometryInfo.indexType = VK_INDEX_TYPE_UINT32;
|
||||
accelerationCreateGeometryInfo.maxVertexCount = static_cast<uint32_t>(scene.vertices.count);
|
||||
accelerationCreateGeometryInfo.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
|
||||
accelerationCreateGeometryInfo.allowsTransforms = VK_FALSE;
|
||||
uint32_t numTriangles = static_cast<uint32_t>(scene.indices.count) / 3;
|
||||
uint32_t maxVertex = scene.vertices.count;
|
||||
|
||||
VkAccelerationStructureCreateInfoKHR accelerationCI{};
|
||||
accelerationCI.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR;
|
||||
accelerationCI.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
|
||||
accelerationCI.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
accelerationCI.maxGeometryCount = 1;
|
||||
accelerationCI.pGeometryInfos = &accelerationCreateGeometryInfo;
|
||||
VK_CHECK_RESULT(vkCreateAccelerationStructureKHR(device, &accelerationCI, nullptr, &bottomLevelAS.accelerationStructure));
|
||||
|
||||
// Bind object memory to the top level acceleration structure
|
||||
bottomLevelAS.objectMemory = createObjectMemory(bottomLevelAS.accelerationStructure);
|
||||
|
||||
VkBindAccelerationStructureMemoryInfoKHR bindAccelerationMemoryInfo{};
|
||||
bindAccelerationMemoryInfo.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR;
|
||||
bindAccelerationMemoryInfo.accelerationStructure = bottomLevelAS.accelerationStructure;
|
||||
bindAccelerationMemoryInfo.memory = bottomLevelAS.objectMemory.memory;
|
||||
VK_CHECK_RESULT(vkBindAccelerationStructureMemoryKHR(device, 1, &bindAccelerationMemoryInfo));
|
||||
|
||||
VkAccelerationStructureGeometryKHR accelerationStructureGeometry{};
|
||||
accelerationStructureGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
|
||||
// Build
|
||||
VkAccelerationStructureGeometryKHR accelerationStructureGeometry = vks::initializers::accelerationStructureGeometryKHR();
|
||||
accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
|
||||
accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
|
||||
accelerationStructureGeometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
|
||||
accelerationStructureGeometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
|
||||
accelerationStructureGeometry.geometry.triangles.vertexData.deviceAddress = vertexBufferDeviceAddress.deviceAddress;
|
||||
accelerationStructureGeometry.geometry.triangles.vertexData = vertexBufferDeviceAddress;
|
||||
accelerationStructureGeometry.geometry.triangles.maxVertex = maxVertex;
|
||||
accelerationStructureGeometry.geometry.triangles.vertexStride = sizeof(vkglTF::Vertex);
|
||||
accelerationStructureGeometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
|
||||
accelerationStructureGeometry.geometry.triangles.indexData.deviceAddress = indexBufferDeviceAddress.deviceAddress;
|
||||
accelerationStructureGeometry.geometry.triangles.indexData = indexBufferDeviceAddress;
|
||||
accelerationStructureGeometry.geometry.triangles.transformData.deviceAddress = 0;
|
||||
accelerationStructureGeometry.geometry.triangles.transformData.hostAddress = nullptr;
|
||||
|
||||
std::vector<VkAccelerationStructureGeometryKHR> acceleration_geometries = { accelerationStructureGeometry };
|
||||
VkAccelerationStructureGeometryKHR* acceleration_structure_geometries = acceleration_geometries.data();
|
||||
// Get size info
|
||||
VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR();
|
||||
accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
|
||||
accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
accelerationStructureBuildGeometryInfo.geometryCount = 1;
|
||||
accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry;
|
||||
|
||||
VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo = vks::initializers::accelerationStructureBuildSizesInfoKHR();
|
||||
vkGetAccelerationStructureBuildSizesKHR(
|
||||
device,
|
||||
VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
|
||||
&accelerationStructureBuildGeometryInfo,
|
||||
&numTriangles,
|
||||
&accelerationStructureBuildSizesInfo);
|
||||
|
||||
createAccelerationStructure(bottomLevelAS, VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, accelerationStructureBuildSizesInfo);
|
||||
|
||||
// Create a small scratch buffer used during build of the bottom level acceleration structure
|
||||
RayTracingScratchBuffer scratchBuffer = createScratchBuffer(bottomLevelAS.accelerationStructure);
|
||||
ScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize);
|
||||
|
||||
VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo{};
|
||||
accelerationBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
|
||||
VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR();
|
||||
accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
|
||||
accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
accelerationBuildGeometryInfo.update = VK_FALSE;
|
||||
accelerationBuildGeometryInfo.dstAccelerationStructure = bottomLevelAS.accelerationStructure;
|
||||
accelerationBuildGeometryInfo.geometryArrayOfPointers = VK_FALSE;
|
||||
accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
|
||||
accelerationBuildGeometryInfo.dstAccelerationStructure = bottomLevelAS.handle;
|
||||
accelerationBuildGeometryInfo.geometryCount = 1;
|
||||
accelerationBuildGeometryInfo.ppGeometries = &acceleration_structure_geometries;
|
||||
accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry;
|
||||
accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress;
|
||||
|
||||
VkAccelerationStructureBuildOffsetInfoKHR accelerationBuildOffsetInfo{};
|
||||
accelerationBuildOffsetInfo.primitiveCount = numTriangles;
|
||||
accelerationBuildOffsetInfo.primitiveOffset = 0x0;
|
||||
accelerationBuildOffsetInfo.firstVertex = 0;
|
||||
accelerationBuildOffsetInfo.transformOffset = 0x0;
|
||||
VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{};
|
||||
accelerationStructureBuildRangeInfo.primitiveCount = numTriangles;
|
||||
accelerationStructureBuildRangeInfo.primitiveOffset = 0;
|
||||
accelerationStructureBuildRangeInfo.firstVertex = 0;
|
||||
accelerationStructureBuildRangeInfo.transformOffset = 0;
|
||||
std::vector<VkAccelerationStructureBuildRangeInfoKHR*> accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo };
|
||||
|
||||
std::vector<VkAccelerationStructureBuildOffsetInfoKHR*> accelerationBuildOffsets = { &accelerationBuildOffsetInfo };
|
||||
|
||||
if (rayTracingFeatures.rayTracingHostAccelerationStructureCommands)
|
||||
if (accelerationStructureFeatures.accelerationStructureHostCommands)
|
||||
{
|
||||
// Implementation supports building acceleration structure building on host
|
||||
VK_CHECK_RESULT(vkBuildAccelerationStructureKHR(device, 1, &accelerationBuildGeometryInfo, accelerationBuildOffsets.data()));
|
||||
// Implementation supports building acceleration structure building on host
|
||||
vkBuildAccelerationStructuresKHR(
|
||||
device,
|
||||
VK_NULL_HANDLE,
|
||||
1,
|
||||
&accelerationBuildGeometryInfo,
|
||||
accelerationBuildStructureRangeInfos.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Acceleration structure needs to be build on the device
|
||||
VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||
vkCmdBuildAccelerationStructureKHR(commandBuffer, 1, &accelerationBuildGeometryInfo, accelerationBuildOffsets.data());
|
||||
vkCmdBuildAccelerationStructuresKHR(
|
||||
commandBuffer,
|
||||
1,
|
||||
&accelerationBuildGeometryInfo,
|
||||
accelerationBuildStructureRangeInfos.data());
|
||||
vulkanDevice->flushCommandBuffer(commandBuffer, queue);
|
||||
}
|
||||
|
||||
VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{};
|
||||
accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
|
||||
accelerationDeviceAddressInfo.accelerationStructure = bottomLevelAS.accelerationStructure;
|
||||
|
||||
bottomLevelAS.handle = vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
|
||||
|
||||
deleteScratchBuffer(scratchBuffer);
|
||||
}
|
||||
|
||||
|
|
@ -364,132 +167,138 @@ public:
|
|||
*/
|
||||
void createTopLevelAccelerationStructure()
|
||||
{
|
||||
VkAccelerationStructureCreateGeometryTypeInfoKHR accelerationCreateGeometryInfo{};
|
||||
accelerationCreateGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR;
|
||||
accelerationCreateGeometryInfo.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
|
||||
accelerationCreateGeometryInfo.maxPrimitiveCount = 1;
|
||||
accelerationCreateGeometryInfo.allowsTransforms = VK_FALSE;
|
||||
|
||||
VkAccelerationStructureCreateInfoKHR accelerationCI{};
|
||||
accelerationCI.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR;
|
||||
accelerationCI.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
|
||||
accelerationCI.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
accelerationCI.maxGeometryCount = 1;
|
||||
accelerationCI.pGeometryInfos = &accelerationCreateGeometryInfo;
|
||||
VK_CHECK_RESULT(vkCreateAccelerationStructureKHR(device, &accelerationCI, nullptr, &topLevelAS.accelerationStructure));
|
||||
|
||||
// Bind object memory to the top level acceleration structure
|
||||
topLevelAS.objectMemory = createObjectMemory(topLevelAS.accelerationStructure);
|
||||
|
||||
VkBindAccelerationStructureMemoryInfoKHR bindAccelerationMemoryInfo{};
|
||||
bindAccelerationMemoryInfo.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR;
|
||||
bindAccelerationMemoryInfo.accelerationStructure = topLevelAS.accelerationStructure;
|
||||
bindAccelerationMemoryInfo.memory = topLevelAS.objectMemory.memory;
|
||||
VK_CHECK_RESULT(vkBindAccelerationStructureMemoryKHR(device, 1, &bindAccelerationMemoryInfo));
|
||||
|
||||
VkTransformMatrixKHR transform_matrix = {
|
||||
VkTransformMatrixKHR transformMatrix = {
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f };
|
||||
|
||||
VkAccelerationStructureInstanceKHR instance{};
|
||||
instance.transform = transform_matrix;
|
||||
instance.transform = transformMatrix;
|
||||
instance.instanceCustomIndex = 0;
|
||||
instance.mask = 0xFF;
|
||||
instance.instanceShaderBindingTableRecordOffset = 0;
|
||||
instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||
instance.accelerationStructureReference = bottomLevelAS.handle;
|
||||
instance.accelerationStructureReference = bottomLevelAS.deviceAddress;
|
||||
|
||||
// Buffer for instance data
|
||||
vks::Buffer instancesBuffer;
|
||||
VK_CHECK_RESULT(vulkanDevice->createBuffer(
|
||||
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
|
||||
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
&instancesBuffer,
|
||||
sizeof(instance),
|
||||
sizeof(VkAccelerationStructureInstanceKHR),
|
||||
&instance));
|
||||
|
||||
VkDeviceOrHostAddressConstKHR instance_data_device_address{};
|
||||
instance_data_device_address.deviceAddress = getBufferDeviceAddress(instancesBuffer.buffer);
|
||||
VkDeviceOrHostAddressConstKHR instanceDataDeviceAddress{};
|
||||
instanceDataDeviceAddress.deviceAddress = getBufferDeviceAddress(instancesBuffer.buffer);
|
||||
|
||||
VkAccelerationStructureGeometryKHR accelerationStructureGeometry{};
|
||||
accelerationStructureGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
|
||||
accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
|
||||
VkAccelerationStructureGeometryKHR accelerationStructureGeometry = vks::initializers::accelerationStructureGeometryKHR();
|
||||
accelerationStructureGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
|
||||
accelerationStructureGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
|
||||
accelerationStructureGeometry.geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR;
|
||||
accelerationStructureGeometry.geometry.instances.arrayOfPointers = VK_FALSE;
|
||||
accelerationStructureGeometry.geometry.instances.data.deviceAddress = instance_data_device_address.deviceAddress;
|
||||
accelerationStructureGeometry.geometry.instances.data = instanceDataDeviceAddress;
|
||||
|
||||
std::vector<VkAccelerationStructureGeometryKHR> acceleration_geometries = { accelerationStructureGeometry };
|
||||
VkAccelerationStructureGeometryKHR* acceleration_structure_geometries = acceleration_geometries.data();
|
||||
// Get size info
|
||||
VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR();
|
||||
accelerationStructureBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
|
||||
accelerationStructureBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
accelerationStructureBuildGeometryInfo.geometryCount = 1;
|
||||
accelerationStructureBuildGeometryInfo.pGeometries = &accelerationStructureGeometry;
|
||||
|
||||
uint32_t primitive_count = 1;
|
||||
|
||||
VkAccelerationStructureBuildSizesInfoKHR accelerationStructureBuildSizesInfo = vks::initializers::accelerationStructureBuildSizesInfoKHR();
|
||||
vkGetAccelerationStructureBuildSizesKHR(
|
||||
device,
|
||||
VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
|
||||
&accelerationStructureBuildGeometryInfo,
|
||||
&primitive_count,
|
||||
&accelerationStructureBuildSizesInfo);
|
||||
|
||||
// @todo: as return value?
|
||||
createAccelerationStructure(topLevelAS, VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, accelerationStructureBuildSizesInfo);
|
||||
|
||||
// Create a small scratch buffer used during build of the top level acceleration structure
|
||||
RayTracingScratchBuffer scratchBuffer = createScratchBuffer(topLevelAS.accelerationStructure);
|
||||
ScratchBuffer scratchBuffer = createScratchBuffer(accelerationStructureBuildSizesInfo.buildScratchSize);
|
||||
|
||||
VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo{};
|
||||
accelerationBuildGeometryInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
|
||||
VkAccelerationStructureBuildGeometryInfoKHR accelerationBuildGeometryInfo = vks::initializers::accelerationStructureBuildGeometryInfoKHR();
|
||||
accelerationBuildGeometryInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
|
||||
accelerationBuildGeometryInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
accelerationBuildGeometryInfo.update = VK_FALSE;
|
||||
accelerationBuildGeometryInfo.srcAccelerationStructure = VK_NULL_HANDLE;
|
||||
accelerationBuildGeometryInfo.dstAccelerationStructure = topLevelAS.accelerationStructure;
|
||||
accelerationBuildGeometryInfo.geometryArrayOfPointers = VK_FALSE;
|
||||
accelerationBuildGeometryInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
|
||||
accelerationBuildGeometryInfo.dstAccelerationStructure = topLevelAS.handle;
|
||||
accelerationBuildGeometryInfo.geometryCount = 1;
|
||||
accelerationBuildGeometryInfo.ppGeometries = &acceleration_structure_geometries;
|
||||
accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry;
|
||||
accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress;
|
||||
|
||||
VkAccelerationStructureBuildOffsetInfoKHR accelerationBuildOffsetInfo{};
|
||||
accelerationBuildOffsetInfo.primitiveCount = 1;
|
||||
accelerationBuildOffsetInfo.primitiveOffset = 0x0;
|
||||
accelerationBuildOffsetInfo.firstVertex = 0;
|
||||
accelerationBuildOffsetInfo.transformOffset = 0x0;
|
||||
std::vector<VkAccelerationStructureBuildOffsetInfoKHR*> accelerationBuildOffsets = { &accelerationBuildOffsetInfo };
|
||||
VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{};
|
||||
accelerationStructureBuildRangeInfo.primitiveCount = 1;
|
||||
accelerationStructureBuildRangeInfo.primitiveOffset = 0;
|
||||
accelerationStructureBuildRangeInfo.firstVertex = 0;
|
||||
accelerationStructureBuildRangeInfo.transformOffset = 0;
|
||||
std::vector<VkAccelerationStructureBuildRangeInfoKHR*> accelerationBuildStructureRangeInfos = { &accelerationStructureBuildRangeInfo };
|
||||
|
||||
if (rayTracingFeatures.rayTracingHostAccelerationStructureCommands)
|
||||
if (accelerationStructureFeatures.accelerationStructureHostCommands)
|
||||
{
|
||||
// Implementation supports building acceleration structure building on host
|
||||
VK_CHECK_RESULT(vkBuildAccelerationStructureKHR(device, 1, &accelerationBuildGeometryInfo, accelerationBuildOffsets.data()));
|
||||
// Implementation supports building acceleration structure building on host
|
||||
vkBuildAccelerationStructuresKHR(
|
||||
device,
|
||||
VK_NULL_HANDLE,
|
||||
1,
|
||||
&accelerationBuildGeometryInfo,
|
||||
accelerationBuildStructureRangeInfos.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Acceleration structure needs to be build on the device
|
||||
VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||
vkCmdBuildAccelerationStructureKHR(commandBuffer, 1, &accelerationBuildGeometryInfo, accelerationBuildOffsets.data());
|
||||
vkCmdBuildAccelerationStructuresKHR(
|
||||
commandBuffer,
|
||||
1,
|
||||
&accelerationBuildGeometryInfo,
|
||||
accelerationBuildStructureRangeInfos.data());
|
||||
vulkanDevice->flushCommandBuffer(commandBuffer, queue);
|
||||
}
|
||||
|
||||
VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{};
|
||||
accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
|
||||
accelerationDeviceAddressInfo.accelerationStructure = topLevelAS.accelerationStructure;
|
||||
|
||||
topLevelAS.handle = vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
|
||||
|
||||
deleteScratchBuffer(scratchBuffer);
|
||||
instancesBuffer.destroy();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Create the Shader Binding Table that binds the programs and top-level acceleration structure
|
||||
Create the Shader Binding Tables that binds the programs and top-level acceleration structure
|
||||
|
||||
SBT Layout used in this sample:
|
||||
|
||||
/-----------\
|
||||
| raygen |
|
||||
|-----------|
|
||||
| miss |
|
||||
|-----------|
|
||||
| hit |
|
||||
\-----------/
|
||||
|
||||
*/
|
||||
void createShaderBindingTable() {
|
||||
void createShaderBindingTables() {
|
||||
const uint32_t handleSize = rayTracingPipelineProperties.shaderGroupHandleSize;
|
||||
const uint32_t handleAlignment = rayTracingPipelineProperties.shaderGroupHandleAlignment;
|
||||
const uint32_t groupCount = static_cast<uint32_t>(shaderGroups.size());
|
||||
const uint32_t sbtSize = handleSize * groupCount;
|
||||
|
||||
const uint32_t sbtSize = rayTracingProperties.shaderGroupBaseAlignment * groupCount;
|
||||
VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &shaderBindingTable, sbtSize));
|
||||
shaderBindingTable.map();
|
||||
|
||||
// Write the shader handles to the shader binding table
|
||||
std::vector<uint8_t> shaderHandleStorage(sbtSize);
|
||||
VK_CHECK_RESULT(vkGetRayTracingShaderGroupHandlesKHR(device, pipeline, 0, groupCount, sbtSize, shaderHandleStorage.data()));
|
||||
|
||||
auto* data = static_cast<uint8_t*>(shaderBindingTable.mapped);
|
||||
// This part is required, as the alignment and handle size may differ
|
||||
for (uint32_t i = 0; i < groupCount; i++)
|
||||
{
|
||||
memcpy(data, shaderHandleStorage.data() + i * rayTracingProperties.shaderGroupHandleSize, rayTracingProperties.shaderGroupHandleSize);
|
||||
data += rayTracingProperties.shaderGroupBaseAlignment;
|
||||
}
|
||||
shaderBindingTable.unmap();
|
||||
createShaderBindingTable(shaderBindingTables.raygen, 1);
|
||||
// We are using two miss shaders
|
||||
createShaderBindingTable(shaderBindingTables.miss, 2);
|
||||
createShaderBindingTable(shaderBindingTables.hit, 1);
|
||||
|
||||
// Copy handles
|
||||
memcpy(shaderBindingTables.raygen.mapped, shaderHandleStorage.data(), handleSize);
|
||||
// We are using two miss shaders, so we need to get two handles for the miss shader binding table
|
||||
memcpy(shaderBindingTables.miss.mapped, shaderHandleStorage.data() + handleAlignment, handleSize * 2);
|
||||
memcpy(shaderBindingTables.hit.mapped, shaderHandleStorage.data() + handleAlignment * 3, handleSize);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -509,10 +318,9 @@ public:
|
|||
VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1);
|
||||
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet));
|
||||
|
||||
VkWriteDescriptorSetAccelerationStructureKHR descriptorAccelerationStructureInfo{};
|
||||
descriptorAccelerationStructureInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR;
|
||||
VkWriteDescriptorSetAccelerationStructureKHR descriptorAccelerationStructureInfo = vks::initializers::writeDescriptorSetAccelerationStructureKHR();
|
||||
descriptorAccelerationStructureInfo.accelerationStructureCount = 1;
|
||||
descriptorAccelerationStructureInfo.pAccelerationStructures = &topLevelAS.accelerationStructure;
|
||||
descriptorAccelerationStructureInfo.pAccelerationStructures = &topLevelAS.handle;
|
||||
|
||||
VkWriteDescriptorSet accelerationStructureWrite{};
|
||||
accelerationStructureWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
|
|
@ -523,29 +331,21 @@ public:
|
|||
accelerationStructureWrite.descriptorCount = 1;
|
||||
accelerationStructureWrite.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
|
||||
|
||||
VkDescriptorImageInfo storageImageDescriptor{};
|
||||
storageImageDescriptor.imageView = storageImage.view;
|
||||
storageImageDescriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
|
||||
VkDescriptorBufferInfo vertexBufferDescriptor{};
|
||||
vertexBufferDescriptor.buffer = scene.vertices.buffer;
|
||||
vertexBufferDescriptor.range = VK_WHOLE_SIZE;
|
||||
|
||||
VkDescriptorBufferInfo indexBufferDescriptor{};
|
||||
indexBufferDescriptor.buffer = scene.indices.buffer;
|
||||
indexBufferDescriptor.range = VK_WHOLE_SIZE;
|
||||
|
||||
VkWriteDescriptorSet resultImageWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor);
|
||||
VkWriteDescriptorSet uniformBufferWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &ubo.descriptor);
|
||||
VkWriteDescriptorSet vertexBufferWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3, &vertexBufferDescriptor);
|
||||
VkWriteDescriptorSet indexBufferWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4, &indexBufferDescriptor);
|
||||
VkDescriptorImageInfo storageImageDescriptor{ VK_NULL_HANDLE, storageImage.view, VK_IMAGE_LAYOUT_GENERAL };
|
||||
VkDescriptorBufferInfo vertexBufferDescriptor{ scene.vertices.buffer, 0, VK_WHOLE_SIZE };
|
||||
VkDescriptorBufferInfo indexBufferDescriptor{ scene.indices.buffer, 0, VK_WHOLE_SIZE };
|
||||
|
||||
std::vector<VkWriteDescriptorSet> writeDescriptorSets = {
|
||||
// Binding 0: Top level acceleration structure
|
||||
accelerationStructureWrite,
|
||||
resultImageWrite,
|
||||
uniformBufferWrite,
|
||||
vertexBufferWrite,
|
||||
indexBufferWrite
|
||||
// Binding 0: Top level acceleration structure
|
||||
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor),
|
||||
// Binding 1: Ray tracing result image
|
||||
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &ubo.descriptor),
|
||||
// Binding 1: Ray tracing result image
|
||||
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3, &vertexBufferDescriptor),
|
||||
// Binding 1: Ray tracing result image
|
||||
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4, &indexBufferDescriptor),
|
||||
};
|
||||
vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, VK_NULL_HANDLE);
|
||||
}
|
||||
|
|
@ -555,111 +355,81 @@ public:
|
|||
*/
|
||||
void createRayTracingPipeline()
|
||||
{
|
||||
VkDescriptorSetLayoutBinding accelerationStructureLayoutBinding{};
|
||||
accelerationStructureLayoutBinding.binding = 0;
|
||||
accelerationStructureLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
|
||||
accelerationStructureLayoutBinding.descriptorCount = 1;
|
||||
accelerationStructureLayoutBinding.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
|
||||
std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings = {
|
||||
// Binding 0: Acceleration structure
|
||||
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 0),
|
||||
// Binding 1: Storage image
|
||||
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_RAYGEN_BIT_KHR, 1),
|
||||
// Binding 2: Uniform buffer
|
||||
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR, 2),
|
||||
// Binding 3: Vertex buffer
|
||||
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 3),
|
||||
// Binding 4: Index buffer
|
||||
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 4),
|
||||
};
|
||||
|
||||
VkDescriptorSetLayoutBinding resultImageLayoutBinding{};
|
||||
resultImageLayoutBinding.binding = 1;
|
||||
resultImageLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||
resultImageLayoutBinding.descriptorCount = 1;
|
||||
resultImageLayoutBinding.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR;
|
||||
|
||||
VkDescriptorSetLayoutBinding uniformBufferBinding{};
|
||||
uniformBufferBinding.binding = 2;
|
||||
uniformBufferBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
uniformBufferBinding.descriptorCount = 1;
|
||||
uniformBufferBinding.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
|
||||
|
||||
VkDescriptorSetLayoutBinding vertexBufferBinding{};
|
||||
vertexBufferBinding.binding = 3;
|
||||
vertexBufferBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
vertexBufferBinding.descriptorCount = 1;
|
||||
vertexBufferBinding.stageFlags = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
|
||||
|
||||
VkDescriptorSetLayoutBinding indexBufferBinding{};
|
||||
indexBufferBinding.binding = 4;
|
||||
indexBufferBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
indexBufferBinding.descriptorCount = 1;
|
||||
indexBufferBinding.stageFlags = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
|
||||
|
||||
std::vector<VkDescriptorSetLayoutBinding> bindings({
|
||||
accelerationStructureLayoutBinding,
|
||||
resultImageLayoutBinding,
|
||||
uniformBufferBinding,
|
||||
vertexBufferBinding,
|
||||
indexBufferBinding
|
||||
});
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo layoutInfo{};
|
||||
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
|
||||
layoutInfo.pBindings = bindings.data();
|
||||
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout));
|
||||
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{};
|
||||
pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
pipelineLayoutCreateInfo.setLayoutCount = 1;
|
||||
pipelineLayoutCreateInfo.pSetLayouts = &descriptorSetLayout;
|
||||
|
||||
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
|
||||
|
||||
const uint32_t shaderIndexRaygen = 0;
|
||||
const uint32_t shaderIndexMiss = 1;
|
||||
const uint32_t shaderIndexShadowMiss = 2;
|
||||
const uint32_t shaderIndexClosestHit = 3;
|
||||
|
||||
std::array<VkPipelineShaderStageCreateInfo, 4> shaderStages;
|
||||
shaderStages[shaderIndexRaygen] = loadShader(getShadersPath() + "raytracingshadows/raygen.rgen.spv", VK_SHADER_STAGE_RAYGEN_BIT_KHR);
|
||||
shaderStages[shaderIndexMiss] = loadShader(getShadersPath() + "raytracingshadows/miss.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR);
|
||||
shaderStages[shaderIndexShadowMiss] = loadShader(getShadersPath() + "raytracingshadows/shadow.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR);
|
||||
shaderStages[shaderIndexClosestHit] = loadShader(getShadersPath() + "raytracingshadows/closesthit.rchit.spv", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
||||
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings);
|
||||
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayout));
|
||||
|
||||
VkPipelineLayoutCreateInfo pPipelineLayoutCI = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1);
|
||||
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCI, nullptr, &pipelineLayout));
|
||||
|
||||
/*
|
||||
Setup ray tracing shader groups
|
||||
*/
|
||||
VkRayTracingShaderGroupCreateInfoKHR raygenGroupCI{};
|
||||
raygenGroupCI.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
|
||||
raygenGroupCI.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
|
||||
raygenGroupCI.generalShader = shaderIndexRaygen;
|
||||
raygenGroupCI.closestHitShader = VK_SHADER_UNUSED_KHR;
|
||||
raygenGroupCI.anyHitShader = VK_SHADER_UNUSED_KHR;
|
||||
raygenGroupCI.intersectionShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroups.push_back(raygenGroupCI);
|
||||
std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
|
||||
|
||||
VkRayTracingShaderGroupCreateInfoKHR missGroupCI{};
|
||||
missGroupCI.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
|
||||
missGroupCI.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
|
||||
missGroupCI.generalShader = shaderIndexMiss;
|
||||
missGroupCI.closestHitShader = VK_SHADER_UNUSED_KHR;
|
||||
missGroupCI.anyHitShader = VK_SHADER_UNUSED_KHR;
|
||||
missGroupCI.intersectionShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroups.push_back(missGroupCI);
|
||||
// Second miss group for the shadow miss shader
|
||||
missGroupCI.generalShader = shaderIndexShadowMiss;
|
||||
shaderGroups.push_back(missGroupCI);
|
||||
// Ray generation group
|
||||
{
|
||||
shaderStages.push_back(loadShader(getShadersPath() + "raytracingshadows/raygen.rgen.spv", VK_SHADER_STAGE_RAYGEN_BIT_KHR));
|
||||
VkRayTracingShaderGroupCreateInfoKHR shaderGroup{};
|
||||
shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
|
||||
shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
|
||||
shaderGroup.generalShader = static_cast<uint32_t>(shaderStages.size()) - 1;
|
||||
shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroups.push_back(shaderGroup);
|
||||
}
|
||||
|
||||
VkRayTracingShaderGroupCreateInfoKHR closesHitGroupCI{};
|
||||
closesHitGroupCI.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
|
||||
closesHitGroupCI.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR;
|
||||
closesHitGroupCI.generalShader = VK_SHADER_UNUSED_KHR;
|
||||
closesHitGroupCI.closestHitShader = shaderIndexClosestHit;
|
||||
closesHitGroupCI.anyHitShader = VK_SHADER_UNUSED_KHR;
|
||||
closesHitGroupCI.intersectionShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroups.push_back(closesHitGroupCI);
|
||||
// Miss group
|
||||
{
|
||||
shaderStages.push_back(loadShader(getShadersPath() + "raytracingshadows/miss.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR));
|
||||
VkRayTracingShaderGroupCreateInfoKHR shaderGroup{};
|
||||
shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
|
||||
shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
|
||||
shaderGroup.generalShader = static_cast<uint32_t>(shaderStages.size()) - 1;
|
||||
shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroups.push_back(shaderGroup);
|
||||
// Second shader for shadows
|
||||
shaderStages.push_back(loadShader(getShadersPath() + "raytracingshadows/shadow.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR));
|
||||
shaderGroup.generalShader = static_cast<uint32_t>(shaderStages.size()) - 1;
|
||||
shaderGroups.push_back(shaderGroup);
|
||||
}
|
||||
|
||||
VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCI{};
|
||||
rayTracingPipelineCI.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR;
|
||||
// Closest hit group
|
||||
{
|
||||
shaderStages.push_back(loadShader(getShadersPath() + "raytracingshadows/closesthit.rchit.spv", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR));
|
||||
VkRayTracingShaderGroupCreateInfoKHR shaderGroup{};
|
||||
shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
|
||||
shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR;
|
||||
shaderGroup.generalShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroup.closestHitShader = static_cast<uint32_t>(shaderStages.size()) - 1;
|
||||
shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR;
|
||||
shaderGroups.push_back(shaderGroup);
|
||||
}
|
||||
|
||||
VkRayTracingPipelineCreateInfoKHR rayTracingPipelineCI = vks::initializers::rayTracingPipelineCreateInfoKHR();
|
||||
rayTracingPipelineCI.stageCount = static_cast<uint32_t>(shaderStages.size());
|
||||
rayTracingPipelineCI.pStages = shaderStages.data();
|
||||
rayTracingPipelineCI.groupCount = static_cast<uint32_t>(shaderGroups.size());
|
||||
rayTracingPipelineCI.pGroups = shaderGroups.data();
|
||||
rayTracingPipelineCI.maxRecursionDepth = 2;
|
||||
rayTracingPipelineCI.maxPipelineRayRecursionDepth = 2;
|
||||
rayTracingPipelineCI.layout = pipelineLayout;
|
||||
rayTracingPipelineCI.libraries.sType = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR;
|
||||
VK_CHECK_RESULT(vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &pipeline));
|
||||
VK_CHECK_RESULT(vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &pipeline));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -683,12 +453,8 @@ public:
|
|||
*/
|
||||
void handleResize()
|
||||
{
|
||||
// Delete allocated resources
|
||||
vkDestroyImageView(device, storageImage.view, nullptr);
|
||||
vkDestroyImage(device, storageImage.image, nullptr);
|
||||
vkFreeMemory(device, storageImage.memory, nullptr);
|
||||
// Recreate image
|
||||
createStorageImage();
|
||||
createStorageImage(swapChain.colorFormat, { width, height, 1 });
|
||||
// Update descriptor
|
||||
VkDescriptorImageInfo storageImageDescriptor{ VK_NULL_HANDLE, storageImage.view, VK_IMAGE_LAYOUT_GENERAL };
|
||||
VkWriteDescriptorSet resultImageWrite = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &storageImageDescriptor);
|
||||
|
|
@ -719,37 +485,13 @@ public:
|
|||
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline);
|
||||
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout, 0, 1, &descriptorSet, 0, 0);
|
||||
|
||||
/*
|
||||
Setup the buffer regions pointing to the shader groups in the shader binding table
|
||||
*/
|
||||
const VkDeviceSize sbtSize = rayTracingProperties.shaderGroupBaseAlignment * (VkDeviceSize)shaderGroups.size();
|
||||
|
||||
VkStridedBufferRegionKHR raygenShaderSBTEntry{};
|
||||
raygenShaderSBTEntry.buffer = shaderBindingTable.buffer;
|
||||
raygenShaderSBTEntry.offset = static_cast<VkDeviceSize>(rayTracingProperties.shaderGroupBaseAlignment * INDEX_RAYGEN_GROUP);
|
||||
raygenShaderSBTEntry.stride = rayTracingProperties.shaderGroupBaseAlignment;
|
||||
raygenShaderSBTEntry.size = sbtSize;
|
||||
|
||||
VkStridedBufferRegionKHR missShaderSBTEntry{};
|
||||
missShaderSBTEntry.buffer = shaderBindingTable.buffer;
|
||||
missShaderSBTEntry.offset = static_cast<VkDeviceSize>(rayTracingProperties.shaderGroupBaseAlignment * INDEX_MISS_GROUP);
|
||||
missShaderSBTEntry.stride = rayTracingProperties.shaderGroupBaseAlignment;
|
||||
missShaderSBTEntry.size = sbtSize;
|
||||
|
||||
VkStridedBufferRegionKHR hitShaderSBTEntry{};
|
||||
hitShaderSBTEntry.buffer = shaderBindingTable.buffer;
|
||||
hitShaderSBTEntry.offset = static_cast<VkDeviceSize>(rayTracingProperties.shaderGroupBaseAlignment * INDEX_CLOSEST_HIT_GROUP);
|
||||
hitShaderSBTEntry.stride = rayTracingProperties.shaderGroupBaseAlignment;
|
||||
hitShaderSBTEntry.size = sbtSize;
|
||||
|
||||
VkStridedBufferRegionKHR callableShaderSBTEntry{};
|
||||
|
||||
VkStridedDeviceAddressRegionKHR emptySbtEntry = {};
|
||||
vkCmdTraceRaysKHR(
|
||||
drawCmdBuffers[i],
|
||||
&raygenShaderSBTEntry,
|
||||
&missShaderSBTEntry,
|
||||
&hitShaderSBTEntry,
|
||||
&callableShaderSBTEntry,
|
||||
&shaderBindingTables.raygen.stridedDeviceAddressRegion,
|
||||
&shaderBindingTables.miss.stridedDeviceAddressRegion,
|
||||
&shaderBindingTables.hit.stridedDeviceAddressRegion,
|
||||
&emptySbtEntry,
|
||||
width,
|
||||
height,
|
||||
1);
|
||||
|
|
@ -818,52 +560,29 @@ public:
|
|||
enabledBufferDeviceAddresFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES;
|
||||
enabledBufferDeviceAddresFeatures.bufferDeviceAddress = VK_TRUE;
|
||||
|
||||
enabledRayTracingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR;
|
||||
enabledRayTracingFeatures.rayTracing = VK_TRUE;
|
||||
enabledRayTracingFeatures.pNext = &enabledBufferDeviceAddresFeatures;
|
||||
enabledRayTracingPipelineFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR;
|
||||
enabledRayTracingPipelineFeatures.rayTracingPipeline = VK_TRUE;
|
||||
enabledRayTracingPipelineFeatures.pNext = &enabledBufferDeviceAddresFeatures;
|
||||
|
||||
deviceCreatepNextChain = &enabledRayTracingFeatures;
|
||||
enabledAccelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR;
|
||||
enabledAccelerationStructureFeatures.accelerationStructure = VK_TRUE;
|
||||
enabledAccelerationStructureFeatures.pNext = &enabledRayTracingPipelineFeatures;
|
||||
|
||||
deviceCreatepNextChain = &enabledAccelerationStructureFeatures;
|
||||
}
|
||||
|
||||
void prepare()
|
||||
{
|
||||
VulkanExampleBase::prepare();
|
||||
|
||||
// Query the ray tracing properties of the current implementation, we will need them later on
|
||||
rayTracingProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR;
|
||||
VkPhysicalDeviceProperties2 deviceProps2{};
|
||||
deviceProps2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
|
||||
deviceProps2.pNext = &rayTracingProperties;
|
||||
vkGetPhysicalDeviceProperties2(physicalDevice, &deviceProps2);
|
||||
|
||||
// Query the ray tracing properties of the current implementation, we will need them later on
|
||||
rayTracingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR;
|
||||
VkPhysicalDeviceFeatures2 deviceFeatures2{};
|
||||
deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
|
||||
deviceFeatures2.pNext = &rayTracingFeatures;
|
||||
vkGetPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures2);
|
||||
|
||||
// Get the function pointers required for ray tracing
|
||||
vkGetBufferDeviceAddressKHR = reinterpret_cast<PFN_vkGetBufferDeviceAddressKHR>(vkGetDeviceProcAddr(device, "vkGetBufferDeviceAddressKHR"));
|
||||
vkBindAccelerationStructureMemoryKHR = reinterpret_cast<PFN_vkBindAccelerationStructureMemoryKHR>(vkGetDeviceProcAddr(device, "vkBindAccelerationStructureMemoryKHR"));
|
||||
vkCreateAccelerationStructureKHR = reinterpret_cast<PFN_vkCreateAccelerationStructureKHR>(vkGetDeviceProcAddr(device, "vkCreateAccelerationStructureKHR"));
|
||||
vkDestroyAccelerationStructureKHR = reinterpret_cast<PFN_vkDestroyAccelerationStructureKHR>(vkGetDeviceProcAddr(device, "vkDestroyAccelerationStructureKHR"));
|
||||
vkGetAccelerationStructureMemoryRequirementsKHR = reinterpret_cast<PFN_vkGetAccelerationStructureMemoryRequirementsKHR>(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureMemoryRequirementsKHR"));
|
||||
vkCmdBuildAccelerationStructureKHR = reinterpret_cast<PFN_vkCmdBuildAccelerationStructureKHR>(vkGetDeviceProcAddr(device, "vkCmdBuildAccelerationStructureKHR"));
|
||||
vkBuildAccelerationStructureKHR = reinterpret_cast<PFN_vkBuildAccelerationStructureKHR>(vkGetDeviceProcAddr(device, "vkBuildAccelerationStructureKHR"));
|
||||
vkGetAccelerationStructureDeviceAddressKHR = reinterpret_cast<PFN_vkGetAccelerationStructureDeviceAddressKHR>(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureDeviceAddressKHR"));
|
||||
vkCmdTraceRaysKHR = reinterpret_cast<PFN_vkCmdTraceRaysKHR>(vkGetDeviceProcAddr(device, "vkCmdTraceRaysKHR"));
|
||||
vkGetRayTracingShaderGroupHandlesKHR = reinterpret_cast<PFN_vkGetRayTracingShaderGroupHandlesKHR>(vkGetDeviceProcAddr(device, "vkGetRayTracingShaderGroupHandlesKHR"));
|
||||
vkCreateRayTracingPipelinesKHR = reinterpret_cast<PFN_vkCreateRayTracingPipelinesKHR>(vkGetDeviceProcAddr(device, "vkCreateRayTracingPipelinesKHR"));
|
||||
VulkanRaytracingSample::prepare();
|
||||
|
||||
// Create the acceleration structures used to render the ray traced scene
|
||||
createBottomLevelAccelerationStructure();
|
||||
createTopLevelAccelerationStructure();
|
||||
|
||||
createStorageImage();
|
||||
createStorageImage(swapChain.colorFormat, { width, height, 1 });
|
||||
createUniformBuffer();
|
||||
createRayTracingPipeline();
|
||||
createShaderBindingTable();
|
||||
createShaderBindingTables();
|
||||
createDescriptorSets();
|
||||
buildCommandBuffers();
|
||||
prepared = true;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue