当前位置:网站首页>Vulkan official example interpretation raytracing
Vulkan official example interpretation raytracing
2022-06-11 04:17:00 【A little caviar】
List of articles
Preface
VK_KHR_acceleration_structure and VK_KHR_ray_tracing_pipeline Extend the basic example of hardware accelerated ray tracing . Shows how to set up an acceleration structure 、 Ray tracing pipeline and shader binding table required for actual ray tracing .
One 、CPP file
1.RayTracing data structure
// Save data that is used as a raytrace temporary buffer for temporary storage
struct RayTracingScratchBuffer
{
uint64_t deviceAddress = 0;
VkBuffer handle = VK_NULL_HANDLE;
VkDeviceMemory memory = VK_NULL_HANDLE;
};
// Ray tracing acceleration structure
struct AccelerationStructure {
VkAccelerationStructureKHR handle;
uint64_t deviceAddress = 0;
VkDeviceMemory memory;
VkBuffer buffer;
};
2.RayTracing class
class VulkanExample : public VulkanExampleBase
{
public:
PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR;
PFN_vkCreateAccelerationStructureKHR vkCreateAccelerationStructureKHR;
PFN_vkDestroyAccelerationStructureKHR vkDestroyAccelerationStructureKHR;
PFN_vkGetAccelerationStructureBuildSizesKHR vkGetAccelerationStructureBuildSizesKHR;
PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR;
PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR;
PFN_vkBuildAccelerationStructuresKHR vkBuildAccelerationStructuresKHR;
PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR;
PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR;
PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR;
VkPhysicalDeviceRayTracingPipelinePropertiesKHR rayTracingPipelineProperties{
};
VkPhysicalDeviceAccelerationStructureFeaturesKHR accelerationStructureFeatures{
};
VkPhysicalDeviceBufferDeviceAddressFeatures enabledBufferDeviceAddresFeatures{
};
VkPhysicalDeviceRayTracingPipelineFeaturesKHR enabledRayTracingPipelineFeatures{
};
VkPhysicalDeviceAccelerationStructureFeaturesKHR enabledAccelerationStructureFeatures{
};
AccelerationStructure bottomLevelAS{
};
AccelerationStructure topLevelAS{
};
vks::Buffer vertexBuffer;
vks::Buffer indexBuffer;
uint32_t indexCount;
vks::Buffer transformBuffer;
std::vector<VkRayTracingShaderGroupCreateInfoKHR> shaderGroups{
};
vks::Buffer raygenShaderBindingTable;
vks::Buffer missShaderBindingTable;
vks::Buffer hitShaderBindingTable;
struct StorageImage {
VkDeviceMemory memory;
VkImage image;
VkImageView view;
VkFormat format;
} storageImage;
struct UniformData {
glm::mat4 viewInverse;
glm::mat4 projInverse;
} uniformData;
vks::Buffer ubo;
VkPipeline pipeline;
VkPipelineLayout pipelineLayout;
VkDescriptorSet descriptorSet;
VkDescriptorSetLayout descriptorSetLayout;
2. function
Create a temporary buffer to hold the temporary data of the ray tracing acceleration structure
RayTracingScratchBuffer createScratchBuffer(VkDeviceSize size)
{
RayTracingScratchBuffer scratchBuffer{
};
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.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(device, &memoryAllocateInfo, nullptr, &scratchBuffer.memory));
VK_CHECK_RESULT(vkBindBufferMemory(device, scratchBuffer.handle, scratchBuffer.memory, 0));
VkBufferDeviceAddressInfoKHR bufferDeviceAddressInfo{
};
bufferDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
bufferDeviceAddressInfo.buffer = scratchBuffer.handle;
scratchBuffer.deviceAddress = vkGetBufferDeviceAddressKHR(device, &bufferDeviceAddressInfo);
return scratchBuffer;
}
Create acceleration structure Buffer
void createAccelerationStructureBuffer(AccelerationStructure &accelerationStructure, VkAccelerationStructureBuildSizesInfoKHR buildSizeInfo)
{
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));
}
Get the device address from the buffer required by some buffers used for ray tracing
uint64_t getBufferDeviceAddress(VkBuffer buffer)
{
VkBufferDeviceAddressInfoKHR bufferDeviceAI{
};
bufferDeviceAI.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
bufferDeviceAI.buffer = buffer;
return vkGetBufferDeviceAddressKHR(device, &bufferDeviceAI);
}
Set the stored image that the ray generation shader will be written 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);
}
Create the actual geometry that contains the scene ( The vertices 、 triangle ) Bottom acceleration structure of
void createBottomLevelAccelerationStructure()
{
// Setup vertices for a single triangle
struct Vertex {
float pos[3];
};
std::vector<Vertex> vertices = {
{
{
1.0f, 1.0f, 0.0f } },
{
{
-1.0f, 1.0f, 0.0f } },
{
{
0.0f, -1.0f, 0.0f } }
};
// Setup indices
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_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_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);
// 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 = vertexBufferDeviceAddress;
accelerationStructureGeometry.geometry.triangles.maxVertex = 3;
accelerationStructureGeometry.geometry.triangles.vertexStride = sizeof(Vertex);
accelerationStructureGeometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
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);
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(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.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
accelerationBuildGeometryInfo.dstAccelerationStructure = bottomLevelAS.handle;
accelerationBuildGeometryInfo.geometryCount = 1;
accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry;
accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress;
VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{
};
accelerationStructureBuildRangeInfo.primitiveCount = numTriangles;
accelerationStructureBuildRangeInfo.primitiveOffset = 0;
accelerationStructureBuildRangeInfo.firstVertex = 0;
accelerationStructureBuildRangeInfo.transformOffset = 0;
std::vector<VkAccelerationStructureBuildRangeInfoKHR*> accelerationBuildStructureRangeInfos = {
&accelerationStructureBuildRangeInfo };
// Build the acceleration structure on the device via a one-time command buffer submission
// Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds
VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
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.handle;
bottomLevelAS.deviceAddress = vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
deleteScratchBuffer(scratchBuffer);
}
Set up high-level acceleration structure
void createBottomLevelAccelerationStructure()
{
// Setup vertices for a single triangle
struct Vertex {
float pos[3];
};
std::vector<Vertex> vertices = {
{
{
1.0f, 1.0f, 0.0f } },
{
{
-1.0f, 1.0f, 0.0f } },
{
{
0.0f, -1.0f, 0.0f } }
};
// Setup indices
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_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_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);
// 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 = vertexBufferDeviceAddress;
accelerationStructureGeometry.geometry.triangles.maxVertex = 3;
accelerationStructureGeometry.geometry.triangles.vertexStride = sizeof(Vertex);
accelerationStructureGeometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
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);
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(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.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
accelerationBuildGeometryInfo.dstAccelerationStructure = bottomLevelAS.handle;
accelerationBuildGeometryInfo.geometryCount = 1;
accelerationBuildGeometryInfo.pGeometries = &accelerationStructureGeometry;
accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress;
VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{
};
accelerationStructureBuildRangeInfo.primitiveCount = numTriangles;
accelerationStructureBuildRangeInfo.primitiveOffset = 0;
accelerationStructureBuildRangeInfo.firstVertex = 0;
accelerationStructureBuildRangeInfo.transformOffset = 0;
std::vector<VkAccelerationStructureBuildRangeInfoKHR*> accelerationBuildStructureRangeInfos = {
&accelerationStructureBuildRangeInfo };
// Build the acceleration structure on the device via a one-time command buffer submission
// Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds
VkCommandBuffer commandBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
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.handle;
bottomLevelAS.deviceAddress = vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
deleteScratchBuffer(scratchBuffer);
}
Create shader binding tables for binders and top-level acceleration structures
void createShaderBindingTable() {
...
}
Create a descriptor set for ray tracing scheduling
void createDescriptorSets()
{
...
}
Create a render pipeline
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;
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;
std::vector<VkDescriptorSetLayoutBinding> bindings({
accelerationStructureLayoutBinding,
resultImageLayoutBinding,
uniformBufferBinding
});
VkDescriptorSetLayoutCreateInfo descriptorSetlayoutCI{
};
descriptorSetlayoutCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
descriptorSetlayoutCI.bindingCount = static_cast<uint32_t>(bindings.size());
descriptorSetlayoutCI.pBindings = bindings.data();
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetlayoutCI, nullptr, &descriptorSetLayout));
VkPipelineLayoutCreateInfo pipelineLayoutCI{
};
pipelineLayoutCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutCI.setLayoutCount = 1;
pipelineLayoutCI.pSetLayouts = &descriptorSetLayout;
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout));
/* Setup ray tracing shader groups */
std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
// 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);
}
// 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.maxPipelineRayRecursionDepth = 1;
rayTracingPipelineCI.layout = pipelineLayout;
VK_CHECK_RESULT(vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &rayTracingPipelineCI, nullptr, &pipeline));
}
Create command buffer
void buildCommandBuffers()
{
if (resized)
{
handleResize();
}
VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo();
VkImageSubresourceRange subresourceRange = {
VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
for (int32_t i = 0; i < drawCmdBuffers.size(); ++i)
{
VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo));
/* Setup the buffer regions pointing to the shaders in our shader binding table */
const uint32_t handleSizeAligned = vks::tools::alignedSize(rayTracingPipelineProperties.shaderGroupHandleSize, rayTracingPipelineProperties.shaderGroupHandleAlignment);
VkStridedDeviceAddressRegionKHR raygenShaderSbtEntry{
};
raygenShaderSbtEntry.deviceAddress = getBufferDeviceAddress(raygenShaderBindingTable.buffer);
raygenShaderSbtEntry.stride = handleSizeAligned;
raygenShaderSbtEntry.size = handleSizeAligned;
VkStridedDeviceAddressRegionKHR missShaderSbtEntry{
};
missShaderSbtEntry.deviceAddress = getBufferDeviceAddress(missShaderBindingTable.buffer);
missShaderSbtEntry.stride = handleSizeAligned;
missShaderSbtEntry.size = handleSizeAligned;
VkStridedDeviceAddressRegionKHR hitShaderSbtEntry{
};
hitShaderSbtEntry.deviceAddress = getBufferDeviceAddress(hitShaderBindingTable.buffer);
hitShaderSbtEntry.stride = handleSizeAligned;
hitShaderSbtEntry.size = handleSizeAligned;
VkStridedDeviceAddressRegionKHR callableShaderSbtEntry{
};
/* 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);
vkCmdTraceRaysKHR(
drawCmdBuffers[i],
&raygenShaderSbtEntry,
&missShaderSbtEntry,
&hitShaderSbtEntry,
&callableShaderSbtEntry,
width,
height,
1);
/* Copy ray tracing output to swap chain image */
// Prepare current swap chain image as transfer destination
vks::tools::setImageLayout(
drawCmdBuffers[i],
swapChain.images[i],
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
subresourceRange);
// Prepare ray tracing output image as transfer source
vks::tools::setImageLayout(
drawCmdBuffers[i],
storageImage.image,
VK_IMAGE_LAYOUT_GENERAL,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
subresourceRange);
VkImageCopy copyRegion{
};
copyRegion.srcSubresource = {
VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
copyRegion.srcOffset = {
0, 0, 0 };
copyRegion.dstSubresource = {
VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
copyRegion.dstOffset = {
0, 0, 0 };
copyRegion.extent = {
width, height, 1 };
vkCmdCopyImage(drawCmdBuffers[i], storageImage.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, swapChain.images[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region);
// Transition swap chain image back for presentation
vks::tools::setImageLayout(
drawCmdBuffers[i],
swapChain.images[i],
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
subresourceRange);
// Transition ray tracing output image back to general layout
vks::tools::setImageLayout(
drawCmdBuffers[i],
storageImage.image,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_IMAGE_LAYOUT_GENERAL,
subresourceRange);
VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i]));
}
}
Two 、 Use steps
1.closesthit.rchit
The code is as follows ( Example ):
#version 460
#extension GL_EXT_ray_tracing : enable
#extension GL_EXT_nonuniform_qualifier : enable
layout(location = 0) rayPayloadInEXT vec3 hitValue;
hitAttributeEXT vec2 attribs;
void main()
{
const vec3 barycentricCoords = vec3(1.0f - attribs.x - attribs.y, attribs.x, attribs.y);
hitValue = barycentricCoords;
}
2.miss.rmiss
The code is as follows ( Example ):
#version 460
#extension GL_EXT_ray_tracing : enable
layout(location = 0) rayPayloadInEXT vec3 hitValue;
void main()
{
hitValue = vec3(0.0, 0.0, 0.2);
}
3.raygen.rgen
The code is as follows ( Example ):
#version 460
#extension GL_EXT_ray_tracing : enable
layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS;
layout(binding = 1, set = 0, rgba8) uniform image2D image;
layout(binding = 2, set = 0) uniform CameraProperties
{
mat4 viewInverse;
mat4 projInverse;
} cam;
layout(location = 0) rayPayloadEXT vec3 hitValue;
void main()
{
const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5);
const vec2 inUV = pixelCenter/vec2(gl_LaunchSizeEXT.xy);
vec2 d = inUV * 2.0 - 1.0;
vec4 origin = cam.viewInverse * vec4(0,0,0,1);
vec4 target = cam.projInverse * vec4(d.x, d.y, 1, 1) ;
vec4 direction = cam.viewInverse*vec4(normalize(target.xyz), 0) ;
float tmin = 0.001;
float tmax = 10000.0;
hitValue = vec3(0.0);
traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, origin.xyz, tmin, direction.xyz, tmax, 0);
imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(hitValue, 0.0));
}

边栏推荐
- Sslstrip Ultimate - location hijacking
- Possible problems with password retrieval function (supplementary)
- 为了实现零丢包,数据中心网络到底有多拼?
- Market prospect analysis and Research Report of single photon counting detector in 2022
- 未來已來,5G-Advanced時代開啟
- Market prospect analysis and Research Report of digital line scan camera in 2022
- How to invest in programming knowledge and reduce the impact of knowledge failure
- golang泛型:generics
- 未来已来,5G-Advanced时代开启
- Safe and borderless, Guanghe tongdai 5g module +ai intelligent security solution shines at CPSE Expo
猜你喜欢

SQL注入关联分析

Eth Transfer

This artifact is highly recommended. One line command will convert the web page to PDF!

众昂矿业:氟化工是萤石的主要消耗领域

JVM(3):类加载器分类、双亲委派机制

MySQL锁总结

CES 2022 𞓜 guanghetong LTE module fm101 has obtained two important ce/fcc certifications with excellent performance

Guanghetong won the "science and Technology Collaboration Award" of Hello travel, driving two rounds of green industries to embrace digital intelligence transformation

JVM(7):动态链接、方法的调用、四种方法调用指令区分非虚方法和虚方法、invokedynamic指令的使用

Esp32 development -lvgl uses internal and external fonts
随机推荐
Personalized use of QT log module
Detailed explanation of network time synchronization (NTP network timing) of video monitoring system
Simulation of radar emitter modulated signal
Market prospect analysis and Research Report of denitrification unit in 2022
Feature selection algorithm based on bare bones particleswarm optimization
Discussion on the development trend of remote power management unit (Intelligent PDU)
JVM (2): loading process of memory structure and classes
What great open source projects does Google have?
从初代播种到落地生花,5G商用三周年“催生万物”
Analysis of zero time technology | discover lightning loan attack
[激光器原理与应用-2]:国内激光器重点品牌
Construction of esp8266/esp32 development environment
JVM (1): introduction, structure, operation and lifecycle
JVM(4):类的主动使用与被动使用、运行时数据区域内部结构、JVM线程说明、PC寄存器
Vulkan official example interpretation shadows (rasterization)
JVM(3):类加载器分类、双亲委派机制
AI助力,释放法务势能!iTerms合同智审系统重磅发布
Sql优化
2022爱分析· 隐私计算厂商全景报告 | 爱分析报告
app直播源码,平台登录页面实现和修改密码页面实现