2020-11-23 12:25:49 +01:00
/*
2024-01-20 18:48:55 +01:00
* Vulkan Example - Using ray queries for hardware accelerated ray tracing
*
* Ray queries ( aka inline ray tracing ) can be used in non - raytracing shaders . This sample makes use of that by
* doing ray traced shadows in a fragment shader
2020-11-23 12:25:49 +01:00
*
2023-09-09 11:33:32 +02:00
* Copyright ( C ) 2020 - 2023 by Sascha Willems - www . saschawillems . de
2020-11-23 12:25:49 +01:00
*
* This code is licensed under the MIT license ( MIT ) ( http : //opensource.org/licenses/MIT)
*/
# include "vulkanexamplebase.h"
# include "VulkanglTFModel.h"
# include "VulkanRaytracingSample.h"
class VulkanExample : public VulkanRaytracingSample
{
public :
glm : : vec3 lightPos = glm : : vec3 ( ) ;
struct UniformData {
glm : : mat4 projection ;
glm : : mat4 view ;
glm : : mat4 model ;
glm : : vec3 lightPos ;
} uniformData ;
2024-01-20 18:48:55 +01:00
vks : : Buffer uniformBuffer ;
2020-11-23 12:25:49 +01:00
vkglTF : : Model scene ;
2024-01-20 18:48:55 +01:00
VkPipeline pipeline { VK_NULL_HANDLE } ;
VkPipelineLayout pipelineLayout { VK_NULL_HANDLE } ;
VkDescriptorSet descriptorSet { VK_NULL_HANDLE } ;
VkDescriptorSetLayout descriptorSetLayout { VK_NULL_HANDLE } ;
2020-11-23 12:25:49 +01:00
VulkanRaytracingSample : : AccelerationStructure bottomLevelAS { } ;
VulkanRaytracingSample : : AccelerationStructure topLevelAS { } ;
VkPhysicalDeviceRayQueryFeaturesKHR enabledRayQueryFeatures { } ;
VulkanExample ( ) : VulkanRaytracingSample ( )
{
2020-12-12 08:40:28 +01:00
title = " Ray queries for ray traced shadows " ;
2020-11-23 12:25:49 +01:00
camera . type = Camera : : CameraType : : lookat ;
2020-12-12 08:40:28 +01:00
timerSpeed * = 0.25f ;
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 ) ) ;
2021-08-28 12:59:10 +02:00
rayQueryOnly = true ;
enableExtensions ( ) ;
2020-11-23 12:25:49 +01:00
enabledDeviceExtensions . push_back ( VK_KHR_RAY_QUERY_EXTENSION_NAME ) ;
}
~ VulkanExample ( )
{
2024-01-20 18:48:55 +01:00
if ( device ) {
vkDestroyPipeline ( device , pipeline , nullptr ) ;
vkDestroyPipelineLayout ( device , pipelineLayout , nullptr ) ;
vkDestroyDescriptorSetLayout ( device , descriptorSetLayout , nullptr ) ;
uniformBuffer . destroy ( ) ;
deleteAccelerationStructure ( bottomLevelAS ) ;
deleteAccelerationStructure ( topLevelAS ) ;
}
2020-11-23 12:25:49 +01:00
}
/*
Create the bottom level acceleration structure contains the scene ' s actual geometry ( vertices , triangles )
*/
void createBottomLevelAccelerationStructure ( )
{
VkDeviceOrHostAddressConstKHR vertexBufferDeviceAddress { } ;
VkDeviceOrHostAddressConstKHR indexBufferDeviceAddress { } ;
vertexBufferDeviceAddress . deviceAddress = getBufferDeviceAddress ( scene . vertices . buffer ) ;
indexBufferDeviceAddress . deviceAddress = getBufferDeviceAddress ( scene . indices . buffer ) ;
uint32_t numTriangles = static_cast < uint32_t > ( scene . indices . count ) / 3 ;
2023-09-09 11:33:32 +02:00
2020-11-23 12:25:49 +01:00
// 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 = vertexBufferDeviceAddress ;
2023-09-09 11:33:32 +02:00
accelerationStructureGeometry . geometry . triangles . maxVertex = scene . vertices . count - 1 ;
2020-11-23 12:25:49 +01:00
accelerationStructureGeometry . geometry . triangles . vertexStride = sizeof ( vkglTF : : 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 ;
// 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
ScratchBuffer scratchBuffer = createScratchBuffer ( accelerationStructureBuildSizesInfo . buildScratchSize ) ;
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 . 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 } ;
2021-02-23 18:24:59 -08:00
// 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 ) ;
2020-11-23 12:25:49 +01:00
deleteScratchBuffer ( scratchBuffer ) ;
}
/*
The top level acceleration structure contains the scene ' s object instances
*/
void createTopLevelAccelerationStructure ( )
{
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 = transformMatrix ;
instance . instanceCustomIndex = 0 ;
instance . mask = 0xFF ;
instance . instanceShaderBindingTableRecordOffset = 0 ;
instance . flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR ;
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_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR ,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ,
& instancesBuffer ,
sizeof ( VkAccelerationStructureInstanceKHR ) ,
& instance ) ) ;
VkDeviceOrHostAddressConstKHR instanceDataDeviceAddress { } ;
instanceDataDeviceAddress . deviceAddress = getBufferDeviceAddress ( instancesBuffer . buffer ) ;
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 = instanceDataDeviceAddress ;
// 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
ScratchBuffer scratchBuffer = createScratchBuffer ( accelerationStructureBuildSizesInfo . buildScratchSize ) ;
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 . mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR ;
accelerationBuildGeometryInfo . dstAccelerationStructure = topLevelAS . handle ;
accelerationBuildGeometryInfo . geometryCount = 1 ;
accelerationBuildGeometryInfo . pGeometries = & accelerationStructureGeometry ;
accelerationBuildGeometryInfo . scratchData . deviceAddress = scratchBuffer . deviceAddress ;
VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo { } ;
accelerationStructureBuildRangeInfo . primitiveCount = 1 ;
accelerationStructureBuildRangeInfo . primitiveOffset = 0 ;
accelerationStructureBuildRangeInfo . firstVertex = 0 ;
accelerationStructureBuildRangeInfo . transformOffset = 0 ;
std : : vector < VkAccelerationStructureBuildRangeInfoKHR * > accelerationBuildStructureRangeInfos = { & accelerationStructureBuildRangeInfo } ;
2021-02-23 18:24:59 -08:00
// 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 ) ;
2020-11-23 12:25:49 +01:00
deleteScratchBuffer ( scratchBuffer ) ;
instancesBuffer . destroy ( ) ;
}
void buildCommandBuffers ( )
{
VkCommandBufferBeginInfo cmdBufInfo = vks : : initializers : : commandBufferBeginInfo ( ) ;
VkClearValue clearValues [ 2 ] ;
VkViewport viewport ;
VkRect2D scissor ;
for ( int32_t i = 0 ; i < drawCmdBuffers . size ( ) ; + + i )
{
VK_CHECK_RESULT ( vkBeginCommandBuffer ( drawCmdBuffers [ i ] , & cmdBufInfo ) ) ;
/*
Note : Explicit synchronization is not required between the render pass , as this is done implicit via sub pass dependencies
*/
/*
Second pass : Scene rendering with applied shadow map
*/
2020-12-12 08:40:28 +01:00
clearValues [ 0 ] . color = { { 0.0f , 0.0f , 0.2f , 1.0f } } ; ;
2020-11-23 12:25:49 +01:00
clearValues [ 1 ] . depthStencil = { 1.0f , 0 } ;
VkRenderPassBeginInfo renderPassBeginInfo = vks : : initializers : : renderPassBeginInfo ( ) ;
renderPassBeginInfo . renderPass = renderPass ;
renderPassBeginInfo . framebuffer = frameBuffers [ i ] ;
renderPassBeginInfo . renderArea . extent . width = width ;
renderPassBeginInfo . renderArea . extent . height = height ;
renderPassBeginInfo . clearValueCount = 2 ;
renderPassBeginInfo . pClearValues = clearValues ;
vkCmdBeginRenderPass ( drawCmdBuffers [ i ] , & renderPassBeginInfo , VK_SUBPASS_CONTENTS_INLINE ) ;
viewport = vks : : initializers : : viewport ( ( float ) width , ( float ) height , 0.0f , 1.0f ) ;
vkCmdSetViewport ( drawCmdBuffers [ i ] , 0 , 1 , & viewport ) ;
scissor = vks : : initializers : : rect2D ( width , height , 0 , 0 ) ;
vkCmdSetScissor ( drawCmdBuffers [ i ] , 0 , 1 , & scissor ) ;
// 3D scene
vkCmdBindDescriptorSets ( drawCmdBuffers [ i ] , VK_PIPELINE_BIND_POINT_GRAPHICS , pipelineLayout , 0 , 1 , & descriptorSet , 0 , nullptr ) ;
vkCmdBindPipeline ( drawCmdBuffers [ i ] , VK_PIPELINE_BIND_POINT_GRAPHICS , pipeline ) ;
scene . draw ( drawCmdBuffers [ i ] ) ;
2021-08-28 12:59:10 +02:00
VulkanExampleBase : : drawUI ( drawCmdBuffers [ i ] ) ;
2020-11-23 12:25:49 +01:00
vkCmdEndRenderPass ( drawCmdBuffers [ i ] ) ;
VK_CHECK_RESULT ( vkEndCommandBuffer ( drawCmdBuffers [ i ] ) ) ;
}
}
void loadAssets ( )
{
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 ) ;
}
2024-01-20 18:48:55 +01:00
void setupDescriptors ( )
2020-11-23 12:25:49 +01:00
{
2024-01-20 18:48:55 +01:00
// Pool
2020-11-23 12:25:49 +01:00
std : : vector < VkDescriptorPoolSize > poolSizes = {
2022-09-10 09:05:07 +02:00
vks : : initializers : : descriptorPoolSize ( VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , 1 ) ,
vks : : initializers : : descriptorPoolSize ( VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR , 1 )
2020-11-23 12:25:49 +01:00
} ;
2022-09-10 09:05:07 +02:00
VkDescriptorPoolCreateInfo descriptorPoolInfo = vks : : initializers : : descriptorPoolCreateInfo ( poolSizes , 1 ) ;
2020-11-23 12:25:49 +01:00
VK_CHECK_RESULT ( vkCreateDescriptorPool ( device , & descriptorPoolInfo , nullptr , & descriptorPool ) ) ;
2024-01-20 18:48:55 +01:00
// Layout
2020-11-23 12:25:49 +01:00
std : : vector < VkDescriptorSetLayoutBinding > setLayoutBindings = {
// Binding 0 : Vertex shader uniform buffer
vks : : initializers : : descriptorSetLayoutBinding ( VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , VK_SHADER_STAGE_VERTEX_BIT , 0 ) ,
2022-09-26 17:47:59 +02:00
// Binding 1: Acceleration structure
vks : : initializers : : descriptorSetLayoutBinding ( VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR , VK_SHADER_STAGE_FRAGMENT_BIT , 1 ) ,
2020-11-23 12:25:49 +01:00
} ;
VkDescriptorSetLayoutCreateInfo descriptorLayout = vks : : initializers : : descriptorSetLayoutCreateInfo ( setLayoutBindings ) ;
VK_CHECK_RESULT ( vkCreateDescriptorSetLayout ( device , & descriptorLayout , nullptr , & descriptorSetLayout ) ) ;
2024-01-20 18:48:55 +01:00
// Sets
2020-11-23 12:25:49 +01:00
std : : vector < VkWriteDescriptorSet > writeDescriptorSets ;
// Debug display
VkDescriptorSetAllocateInfo allocInfo = vks : : initializers : : descriptorSetAllocateInfo ( descriptorPool , & descriptorSetLayout , 1 ) ;
2023-12-21 19:02:07 +01:00
vkUpdateDescriptorSets ( device , static_cast < uint32_t > ( writeDescriptorSets . size ( ) ) , writeDescriptorSets . data ( ) , 0 , nullptr ) ;
2020-11-23 12:25:49 +01:00
// Scene rendering with shadow map applied
VK_CHECK_RESULT ( vkAllocateDescriptorSets ( device , & allocInfo , & descriptorSet ) ) ;
writeDescriptorSets = {
// Binding 0 : Vertex shader uniform buffer
2024-01-20 18:48:55 +01:00
vks : : initializers : : writeDescriptorSet ( descriptorSet , VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , 0 , & uniformBuffer . descriptor )
2020-11-23 12:25:49 +01:00
} ;
2024-01-20 18:48:55 +01:00
// The fragment needs access to the ray tracing acceleration structure, so we pass it as a descriptor
// As this isn't part of Vulkan's core, we need to pass this informationen via pNext chaining
2020-11-23 12:25:49 +01:00
VkWriteDescriptorSetAccelerationStructureKHR descriptorAccelerationStructureInfo = vks : : initializers : : writeDescriptorSetAccelerationStructureKHR ( ) ;
descriptorAccelerationStructureInfo . accelerationStructureCount = 1 ;
descriptorAccelerationStructureInfo . pAccelerationStructures = & topLevelAS . handle ;
VkWriteDescriptorSet accelerationStructureWrite { } ;
accelerationStructureWrite . sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET ;
// The specialized acceleration structure descriptor has to be chained
accelerationStructureWrite . pNext = & descriptorAccelerationStructureInfo ;
accelerationStructureWrite . dstSet = descriptorSet ;
2022-09-26 17:47:59 +02:00
accelerationStructureWrite . dstBinding = 1 ;
2020-11-23 12:25:49 +01:00
accelerationStructureWrite . descriptorCount = 1 ;
accelerationStructureWrite . descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR ;
writeDescriptorSets . push_back ( accelerationStructureWrite ) ;
2023-12-21 19:02:07 +01:00
vkUpdateDescriptorSets ( device , static_cast < uint32_t > ( writeDescriptorSets . size ( ) ) , writeDescriptorSets . data ( ) , 0 , nullptr ) ;
2020-11-23 12:25:49 +01:00
}
void preparePipelines ( )
{
2024-01-20 18:48:55 +01:00
// Layout
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks : : initializers : : pipelineLayoutCreateInfo ( & descriptorSetLayout , 1 ) ;
VK_CHECK_RESULT ( vkCreatePipelineLayout ( device , & pipelineLayoutCreateInfo , nullptr , & pipelineLayout ) ) ;
// Pipeline
2020-11-23 12:25:49 +01:00
VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks : : initializers : : pipelineInputAssemblyStateCreateInfo ( VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST , 0 , VK_FALSE ) ;
VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks : : initializers : : pipelineRasterizationStateCreateInfo ( VK_POLYGON_MODE_FILL , VK_CULL_MODE_BACK_BIT , VK_FRONT_FACE_COUNTER_CLOCKWISE , 0 ) ;
VkPipelineColorBlendAttachmentState blendAttachmentState = vks : : initializers : : pipelineColorBlendAttachmentState ( 0xf , VK_FALSE ) ;
VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks : : initializers : : pipelineColorBlendStateCreateInfo ( 1 , & blendAttachmentState ) ;
VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks : : initializers : : pipelineDepthStencilStateCreateInfo ( VK_TRUE , VK_TRUE , VK_COMPARE_OP_LESS_OR_EQUAL ) ;
VkPipelineViewportStateCreateInfo viewportStateCI = vks : : initializers : : pipelineViewportStateCreateInfo ( 1 , 1 , 0 ) ;
VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks : : initializers : : pipelineMultisampleStateCreateInfo ( VK_SAMPLE_COUNT_1_BIT , 0 ) ;
std : : vector < VkDynamicState > dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT , VK_DYNAMIC_STATE_SCISSOR } ;
2023-12-21 19:02:07 +01:00
VkPipelineDynamicStateCreateInfo dynamicStateCI = vks : : initializers : : pipelineDynamicStateCreateInfo ( dynamicStateEnables ) ;
2020-11-23 12:25:49 +01:00
std : : array < VkPipelineShaderStageCreateInfo , 2 > shaderStages ;
VkGraphicsPipelineCreateInfo pipelineCI = vks : : initializers : : pipelineCreateInfo ( pipelineLayout , renderPass , 0 ) ;
pipelineCI . pInputAssemblyState = & inputAssemblyStateCI ;
pipelineCI . pRasterizationState = & rasterizationStateCI ;
pipelineCI . pColorBlendState = & colorBlendStateCI ;
pipelineCI . pMultisampleState = & multisampleStateCI ;
pipelineCI . pViewportState = & viewportStateCI ;
pipelineCI . pDepthStencilState = & depthStencilStateCI ;
pipelineCI . pDynamicState = & dynamicStateCI ;
2023-12-20 20:14:36 +01:00
pipelineCI . stageCount = static_cast < uint32_t > ( shaderStages . size ( ) ) ;
2020-11-23 12:25:49 +01:00
pipelineCI . pStages = shaderStages . data ( ) ;
// Scene rendering with ray traced shadows applied
pipelineCI . pVertexInputState = vkglTF : : Vertex : : getPipelineVertexInputState ( { vkglTF : : VertexComponent : : Position , vkglTF : : VertexComponent : : UV , vkglTF : : VertexComponent : : Color , vkglTF : : VertexComponent : : Normal } ) ;
rasterizationStateCI . cullMode = VK_CULL_MODE_BACK_BIT ;
shaderStages [ 0 ] = loadShader ( getShadersPath ( ) + " rayquery/scene.vert.spv " , VK_SHADER_STAGE_VERTEX_BIT ) ;
shaderStages [ 1 ] = loadShader ( getShadersPath ( ) + " rayquery/scene.frag.spv " , VK_SHADER_STAGE_FRAGMENT_BIT ) ;
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , pipelineCache , 1 , & pipelineCI , nullptr , & pipeline ) ) ;
}
// Prepare and initialize uniform buffer containing shader uniforms
void prepareUniformBuffers ( )
{
// Scene vertex shader uniform buffer block
VK_CHECK_RESULT ( vulkanDevice - > createBuffer (
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT ,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ,
2024-01-20 18:48:55 +01:00
& uniformBuffer ,
2020-11-23 12:25:49 +01:00
sizeof ( UniformData ) ) ) ;
// Map persistent
2024-01-20 18:48:55 +01:00
VK_CHECK_RESULT ( uniformBuffer . map ( ) ) ;
2020-11-23 12:25:49 +01:00
updateLight ( ) ;
updateUniformBuffers ( ) ;
}
void updateLight ( )
{
// Animate the light source
lightPos . x = cos ( glm : : radians ( timer * 360.0f ) ) * 40.0f ;
lightPos . y = - 50.0f + sin ( glm : : radians ( timer * 360.0f ) ) * 20.0f ;
lightPos . z = 25.0f + sin ( glm : : radians ( timer * 360.0f ) ) * 5.0f ;
}
void updateUniformBuffers ( )
{
uniformData . projection = camera . matrices . perspective ;
uniformData . view = camera . matrices . view ;
uniformData . model = glm : : mat4 ( 1.0f ) ;
uniformData . lightPos = lightPos ;
2024-01-20 18:48:55 +01:00
memcpy ( uniformBuffer . mapped , & uniformData , sizeof ( UniformData ) ) ;
2020-11-23 12:25:49 +01:00
}
void getEnabledFeatures ( )
{
// 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 ;
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 ;
enabledRayQueryFeatures . sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR ;
enabledRayQueryFeatures . rayQuery = VK_TRUE ;
enabledRayQueryFeatures . pNext = & enabledAccelerationStructureFeatures ;
deviceCreatepNextChain = & enabledRayQueryFeatures ;
}
void draw ( )
{
VulkanExampleBase : : prepareFrame ( ) ;
submitInfo . commandBufferCount = 1 ;
submitInfo . pCommandBuffers = & drawCmdBuffers [ currentBuffer ] ;
VK_CHECK_RESULT ( vkQueueSubmit ( queue , 1 , & submitInfo , VK_NULL_HANDLE ) ) ;
VulkanExampleBase : : submitFrame ( ) ;
}
void prepare ( )
{
VulkanRaytracingSample : : prepare ( ) ;
loadAssets ( ) ;
prepareUniformBuffers ( ) ;
createBottomLevelAccelerationStructure ( ) ;
createTopLevelAccelerationStructure ( ) ;
2024-01-20 18:48:55 +01:00
setupDescriptors ( ) ;
preparePipelines ( ) ;
2020-11-23 12:25:49 +01:00
buildCommandBuffers ( ) ;
prepared = true ;
}
virtual void render ( )
{
if ( ! prepared )
return ;
2024-01-20 18:48:55 +01:00
updateUniformBuffers ( ) ;
if ( ! paused | | camera . updated ) {
2020-11-23 12:25:49 +01:00
updateLight ( ) ;
}
2024-01-20 18:48:55 +01:00
draw ( ) ;
2020-11-23 12:25:49 +01:00
}
} ;
VULKAN_EXAMPLE_MAIN ( )