ray_tracing_indirect_scissor/hello_vulkan.cpp
void HelloVulkan::createRtPipeline()
{
  enum StageIndices
  {
    eRaygen,
    eMiss,
    eMissShd,
    eMissLantern,
    eClosestHit,
    eClosestHitLantern,
    eClosestHitLanternShdObj,
    eClosestHitLanternShd,
    eShaderGroupCount
  };

  // All stages
  std::array<VkPipelineShaderStageCreateInfo, eShaderGroupCount> stages{};
  VkPipelineShaderStageCreateInfo stage{VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO};
  stage.pName = "main";  // All the same entry point
  // Raygen
  stage.module = nvvk::createShaderModule(m_device, nvh::loadFile("spv/raytrace.rgen.spv", true, defaultSearchPaths, true));
  stage.stage     = VK_SHADER_STAGE_RAYGEN_BIT_KHR;
  stages[eRaygen] = stage;
  // Miss shader 0 invoked when a primary ray doesn't hit geometry. Fills in clear color.
  stage.module = nvvk::createShaderModule(m_device, nvh::loadFile("spv/raytrace.rmiss.spv", true, defaultSearchPaths, true));
  stage.stage   = VK_SHADER_STAGE_MISS_BIT_KHR;
  stages[eMiss] = stage;
  // Miss shader 1 is invoked when a shadow ray (for the main scene light)
  // misses the geometry. It simply indicates that no occlusion has been found.
  stage.module =
      nvvk::createShaderModule(m_device, nvh::loadFile("spv/raytraceShadow.rmiss.spv", true, defaultSearchPaths, true));
  stage.stage      = VK_SHADER_STAGE_MISS_BIT_KHR;
  stages[eMissShd] = stage;
  // Miss shader 2 is invoked when a shadow ray for lantern lighting misses the
  // lantern. It shouldn't be invoked, but I include it just in case.
  stage.module = nvvk::createShaderModule(m_device, nvh::loadFile("spv/lanternShadow.rmiss.spv", true, defaultSearchPaths, true));
  stage.stage          = VK_SHADER_STAGE_MISS_BIT_KHR;
  stages[eMissLantern] = stage;
  // OBJ Primary Ray Hit Group - Closest Hit
  stage.module = nvvk::createShaderModule(m_device, nvh::loadFile("spv/raytrace.rchit.spv", true, defaultSearchPaths, true));
  stage.stage         = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
  stages[eClosestHit] = stage;

  // Lantern Primary Ray Hit Group
  stage.module = nvvk::createShaderModule(m_device, nvh::loadFile("spv/lantern.rchit.spv", true, defaultSearchPaths, true));
  stage.stage                = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
  stages[eClosestHitLantern] = stage;

  // OBJ Lantern Shadow Ray Hit Group
  stage.module =
      nvvk::createShaderModule(m_device, nvh::loadFile("spv/lanternShadowObj.rchit.spv", true, defaultSearchPaths, true));
  stage.stage                      = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
  stages[eClosestHitLanternShdObj] = stage;


  // Lantern Lantern Shadow Ray Hit Group
  stage.module =
      nvvk::createShaderModule(m_device, nvh::loadFile("spv/lanternShadowLantern.rchit.spv", true, defaultSearchPaths, true));
  stage.stage                   = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
  stages[eClosestHitLanternShd] = stage;


  // Shader groups
  VkRayTracingShaderGroupCreateInfoKHR group{VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR};
  group.anyHitShader       = VK_SHADER_UNUSED_KHR;
  group.closestHitShader   = VK_SHADER_UNUSED_KHR;
  group.generalShader      = VK_SHADER_UNUSED_KHR;
  group.intersectionShader = VK_SHADER_UNUSED_KHR;

  // Raygen
  group.type          = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
  group.generalShader = eRaygen;
  m_rtShaderGroups.push_back(group);

  // Miss
  group.type          = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
  group.generalShader = eMiss;
  m_rtShaderGroups.push_back(group);

  // Shadow Miss
  group.type          = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
  group.generalShader = eMissShd;
  m_rtShaderGroups.push_back(group);

  // Lantern Shadow Miss
  group.type          = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
  group.generalShader = eMissLantern;
  m_rtShaderGroups.push_back(group);


  // closest hit shader
  group.type             = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR;
  group.generalShader    = VK_SHADER_UNUSED_KHR;
  group.closestHitShader = eClosestHit;
  m_rtShaderGroups.push_back(group);


  group.closestHitShader = eClosestHitLantern;
  m_rtShaderGroups.push_back(group);

  group.closestHitShader = eClosestHitLanternShdObj;
  m_rtShaderGroups.push_back(group);

  group.closestHitShader = eClosestHitLanternShd;
  m_rtShaderGroups.push_back(group);


  // Push constant: we want to be able to update constants used by the shaders
  VkPushConstantRange pushConstant{VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR,
                                   0, sizeof(PushConstantRay)};


  VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO};
  pipelineLayoutCreateInfo.pushConstantRangeCount = 1;
  pipelineLayoutCreateInfo.pPushConstantRanges    = &pushConstant;

  // Descriptor sets: one specific to ray tracing, and one shared with the rasterization pipeline
  std::vector<VkDescriptorSetLayout> rtDescSetLayouts = {m_rtDescSetLayout, m_descSetLayout};
  pipelineLayoutCreateInfo.setLayoutCount             = static_cast<uint32_t>(rtDescSetLayouts.size());
  pipelineLayoutCreateInfo.pSetLayouts                = rtDescSetLayouts.data();

  vkCreatePipelineLayout(m_device, &pipelineLayoutCreateInfo, nullptr, &m_rtPipelineLayout);


  // Assemble the shader stages and recursion depth info into the ray tracing pipeline
  VkRayTracingPipelineCreateInfoKHR rayPipelineInfo{VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR};
  rayPipelineInfo.stageCount = static_cast<uint32_t>(stages.size());  // Stages are shaders
  rayPipelineInfo.pStages    = stages.data();

  // In this case, m_rtShaderGroups.size() == 4: we have one raygen group,
  // two miss shader groups, and one hit group.
  rayPipelineInfo.groupCount = static_cast<uint32_t>(m_rtShaderGroups.size());
  rayPipelineInfo.pGroups    = m_rtShaderGroups.data();

  // The ray tracing process can shoot rays from the camera, and a shadow ray can be shot from the
  // hit points of the camera rays, hence a recursion level of 2. This number should be kept as low
  // as possible for performance reasons. Even recursive ray tracing should be flattened into a loop
  // in the ray generation to avoid deep recursion.
  rayPipelineInfo.maxPipelineRayRecursionDepth = 2;  // Ray depth
  rayPipelineInfo.layout                       = m_rtPipelineLayout;

  vkCreateRayTracingPipelinesKHR(m_device, {}, {}, 1, &rayPipelineInfo, nullptr, &m_rtPipeline);


  for(auto& s : stages)
    vkDestroyShaderModule(m_device, s.module, nullptr);
}
//--------------------------------------------------------------------------------------------------
// Pipeline for the ray tracer: all shaders, raygen, chit, miss
//
// Shader list:
//
// 0 ======  Ray Generation Shaders  =====================================================
//
//    Raygen shader: Ray generation shader. Casts primary rays from camera to scene.
//
// 1 ======  Miss Shaders  ===============================================================
//
//    Miss shader 0: Miss shader when casting primary rays. Fill in clear color.
//
// 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
//    Miss shader 1: Miss shader when casting shadow rays towards main light.
//                   Reports no shadow.
//
// 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
//    Miss shader 2: Miss shader when casting shadow rays towards a lantern.
//                   Reports no lantern hit (-1).
//
// 4 ======  Hit Groups for Primary Rays (sbtRecordOffset=0)  ============================
//
//    chit shader 0: Closest hit shader for primary rays hitting OBJ instances
//                   (hitGroupId=0). Casts shadow ray (to sky light or to lantern,
//                   depending on pass number) and returns specular
//                   and diffuse light to add to output image.
//
// 5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
//    chit shader 1: Closest hit shader for primary rays hitting lantern instances
//                   (hitGroupId=1). Returns color value to replace the current
//                   image pixel color with (lanterns are self-illuminating).
//
// 6 - - - -  Hit Groups for Lantern Shadow Rays (sbtRecordOffset=2) - - - - - - - - - - -
//
//    chit shader 2: Closest hit shader for OBJ instances hit when casting shadow
//                   rays to a lantern. Returns -1 to report that the shadow ray
//                   failed to reach the targetted lantern.
//
// 7 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
//    chit shader 3: Closest hit shader for lantern instances hit when casting shadow
//                   rays to a lantern. Returns the gl_CustomInstanceIndexEXT [lantern
//                   number] of the lantern hit.
//
// 8 =====================================================================================
Pipeline for the ray tracer: all shaders, raygen, chit, miss
Shader list.

0   Ray Generation Shaders

Raygen shader: Ray generation shader. Casts primary rays from camera to scene.

1   Miss Shaders

Miss shader 0: Miss shader when casting primary rays. Fill in clear color.



Miss shader 1: Miss shader when casting shadow rays towards main light.
Reports no shadow.



Miss shader 2: Miss shader when casting shadow rays towards a lantern.
Reports no lantern hit (-1).

4   Hit Groups for Primary Rays (sbtRecordOffset=0)

chit shader 0: Closest hit shader for primary rays hitting OBJ instances
(hitGroupId=0). Casts shadow ray (to sky light or to lantern,
depending on pass number) and returns specular
and diffuse light to add to output image.



chit shader 1: Closest hit shader for primary rays hitting lantern instances
(hitGroupId=1). Returns color value to replace the current
image pixel color with (lanterns are self-illuminating).



chit shader 2: Closest hit shader for OBJ instances hit when casting shadow
rays to a lantern. Returns -1 to report that the shadow ray
failed to reach the targetted lantern.



chit shader 3: Closest hit shader for lantern instances hit when casting shadow
rays to a lantern. Returns the gl_CustomInstanceIndexEXT [lantern
number] of the lantern hit.

8
Pipeline for the ray tracer : all shaders raygen chit miss Shader list . 0 Ray Generation Shaders Raygen shader : Ray generation shader . Casts primary rays from camera to scene . 1 Miss Shaders Miss shader 0 : Miss shader when casting primary rays . Fill in clear color . Miss shader 1 : Miss shader when casting shadow rays towards main light . Reports no shadow . Miss shader 2 : Miss shader when casting shadow rays towards a lantern . Reports no lantern hit ( - 1 ) . 4 Hit Groups for Primary Rays ( sbtRecordOffset = 0 ) chit shader 0 : Closest hit shader for primary rays hitting OBJ instances ( hitGroupId = 0 ) . Casts shadow ray ( to sky light or to lantern depending on pass number ) and returns specular and diffuse light to add to output image . chit shader 1 : Closest hit shader for primary rays hitting lantern instances ( hitGroupId = 1 ) . Returns color value to replace the current image pixel color with ( lanterns are self - illuminating ) . chit shader 2 : Closest hit shader for OBJ instances hit when casting shadow rays to a lantern . Returns - 1 to report that the shadow ray failed to reach the targetted lantern . chit shader 3 : Closest hit shader for lantern instances hit when casting shadow rays to a lantern . Returns the gl_CustomInstanceIndexEXT [ lantern number ] of the lantern hit . 8
void HelloVulkan::createRtPipeline()
{
  enum StageIndices
  {
    eRaygen,
    eMiss,
    eMissShd,
    eMissLantern,
    eClosestHit,
    eClosestHitLantern,
    eClosestHitLanternShdObj,
    eClosestHitLanternShd,
    eShaderGroupCount
  };
  std::array<VkPipelineShaderStageCreateInfo, eShaderGroupCount> stages{};
  VkPipelineShaderStageCreateInfo stage{VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO};
  stage.pName = "main";  
  stage.module = nvvk::createShaderModule(m_device, nvh::loadFile("spv/raytrace.rgen.spv", true, defaultSearchPaths, true));
  stage.stage     = VK_SHADER_STAGE_RAYGEN_BIT_KHR;
  stages[eRaygen] = stage;
  stage.module = nvvk::createShaderModule(m_device, nvh::loadFile("spv/raytrace.rmiss.spv", true, defaultSearchPaths, true));
  stage.stage   = VK_SHADER_STAGE_MISS_BIT_KHR;
  stages[eMiss] = stage;
  stage.module =
      nvvk::createShaderModule(m_device, nvh::loadFile("spv/raytraceShadow.rmiss.spv", true, defaultSearchPaths, true));
  stage.stage      = VK_SHADER_STAGE_MISS_BIT_KHR;
  stages[eMissShd] = stage;
  stage.module = nvvk::createShaderModule(m_device, nvh::loadFile("spv/lanternShadow.rmiss.spv", true, defaultSearchPaths, true));
  stage.stage          = VK_SHADER_STAGE_MISS_BIT_KHR;
  stages[eMissLantern] = stage;
  stage.module = nvvk::createShaderModule(m_device, nvh::loadFile("spv/raytrace.rchit.spv", true, defaultSearchPaths, true));
  stage.stage         = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
  stages[eClosestHit] = stage;
  stage.module = nvvk::createShaderModule(m_device, nvh::loadFile("spv/lantern.rchit.spv", true, defaultSearchPaths, true));
  stage.stage                = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
  stages[eClosestHitLantern] = stage;
  stage.module =
      nvvk::createShaderModule(m_device, nvh::loadFile("spv/lanternShadowObj.rchit.spv", true, defaultSearchPaths, true));
  stage.stage                      = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
  stages[eClosestHitLanternShdObj] = stage;
  stage.module =
      nvvk::createShaderModule(m_device, nvh::loadFile("spv/lanternShadowLantern.rchit.spv", true, defaultSearchPaths, true));
  stage.stage                   = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
  stages[eClosestHitLanternShd] = stage;
  VkRayTracingShaderGroupCreateInfoKHR group{VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR};
  group.anyHitShader       = VK_SHADER_UNUSED_KHR;
  group.closestHitShader   = VK_SHADER_UNUSED_KHR;
  group.generalShader      = VK_SHADER_UNUSED_KHR;
  group.intersectionShader = VK_SHADER_UNUSED_KHR;
  group.type          = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
  group.generalShader = eRaygen;
  m_rtShaderGroups.push_back(group);
  group.type          = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
  group.generalShader = eMiss;
  m_rtShaderGroups.push_back(group);
  group.type          = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
  group.generalShader = eMissShd;
  m_rtShaderGroups.push_back(group);
  group.type          = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
  group.generalShader = eMissLantern;
  m_rtShaderGroups.push_back(group);
  group.type             = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR;
  group.generalShader    = VK_SHADER_UNUSED_KHR;
  group.closestHitShader = eClosestHit;
  m_rtShaderGroups.push_back(group);
  group.closestHitShader = eClosestHitLantern;
  m_rtShaderGroups.push_back(group);
  group.closestHitShader = eClosestHitLanternShdObj;
  m_rtShaderGroups.push_back(group);
  group.closestHitShader = eClosestHitLanternShd;
  m_rtShaderGroups.push_back(group);
  VkPushConstantRange pushConstant{VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR,
                                   0, sizeof(PushConstantRay)};
  VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO};
  pipelineLayoutCreateInfo.pushConstantRangeCount = 1;
  pipelineLayoutCreateInfo.pPushConstantRanges    = &pushConstant;
  std::vector<VkDescriptorSetLayout> rtDescSetLayouts = {m_rtDescSetLayout, m_descSetLayout};
  pipelineLayoutCreateInfo.setLayoutCount             = static_cast<uint32_t>(rtDescSetLayouts.size());
  pipelineLayoutCreateInfo.pSetLayouts                = rtDescSetLayouts.data();
  vkCreatePipelineLayout(m_device, &pipelineLayoutCreateInfo, nullptr, &m_rtPipelineLayout);
  VkRayTracingPipelineCreateInfoKHR rayPipelineInfo{VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR};
  rayPipelineInfo.stageCount = static_cast<uint32_t>(stages.size());  
  rayPipelineInfo.pStages    = stages.data();
  rayPipelineInfo.groupCount = static_cast<uint32_t>(m_rtShaderGroups.size());
  rayPipelineInfo.pGroups    = m_rtShaderGroups.data();
  rayPipelineInfo.maxPipelineRayRecursionDepth = 2;  
  rayPipelineInfo.layout                       = m_rtPipelineLayout;
  vkCreateRayTracingPipelinesKHR(m_device, {}, {}, 1, &rayPipelineInfo, nullptr, &m_rtPipeline);
  for(auto& s : stages)
    vkDestroyShaderModule(m_device, s.module, nullptr);
}
void HelloVulkan :: createRtPipeline ( ) { enum StageIndices { eRaygen , eMiss , eMissShd , eMissLantern , eClosestHit , eClosestHitLantern , eClosestHitLanternShdObj , eClosestHitLanternShd , eShaderGroupCount } ; std :: array < VkPipelineShaderStageCreateInfo , eShaderGroupCount > stages { } ; VkPipelineShaderStageCreateInfo stage { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO } ; stage . pName = " " ; stage . module = nvvk :: createShaderModule ( m_device , nvh :: loadFile ( " " , true , defaultSearchPaths , true ) ) ; stage . stage = VK_SHADER_STAGE_RAYGEN_BIT_KHR ; stages [ eRaygen ] = stage ; stage . module = nvvk :: createShaderModule ( m_device , nvh :: loadFile ( " " , true , defaultSearchPaths , true ) ) ; stage . stage = VK_SHADER_STAGE_MISS_BIT_KHR ; stages [ eMiss ] = stage ; stage . module = nvvk :: createShaderModule ( m_device , nvh :: loadFile ( " " , true , defaultSearchPaths , true ) ) ; stage . stage = VK_SHADER_STAGE_MISS_BIT_KHR ; stages [ eMissShd ] = stage ; stage . module = nvvk :: createShaderModule ( m_device , nvh :: loadFile ( " " , true , defaultSearchPaths , true ) ) ; stage . stage = VK_SHADER_STAGE_MISS_BIT_KHR ; stages [ eMissLantern ] = stage ; stage . module = nvvk :: createShaderModule ( m_device , nvh :: loadFile ( " " , true , defaultSearchPaths , true ) ) ; stage . stage = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR ; stages [ eClosestHit ] = stage ; stage . module = nvvk :: createShaderModule ( m_device , nvh :: loadFile ( " " , true , defaultSearchPaths , true ) ) ; stage . stage = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR ; stages [ eClosestHitLantern ] = stage ; stage . module = nvvk :: createShaderModule ( m_device , nvh :: loadFile ( " " , true , defaultSearchPaths , true ) ) ; stage . stage = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR ; stages [ eClosestHitLanternShdObj ] = stage ; stage . module = nvvk :: createShaderModule ( m_device , nvh :: loadFile ( " " , true , defaultSearchPaths , true ) ) ; stage . stage = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR ; stages [ eClosestHitLanternShd ] = stage ; VkRayTracingShaderGroupCreateInfoKHR group { VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR } ; group . anyHitShader = VK_SHADER_UNUSED_KHR ; group . closestHitShader = VK_SHADER_UNUSED_KHR ; group . generalShader = VK_SHADER_UNUSED_KHR ; group . intersectionShader = VK_SHADER_UNUSED_KHR ; group . type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR ; group . generalShader = eRaygen ; m_rtShaderGroups . push_back ( group ) ; group . type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR ; group . generalShader = eMiss ; m_rtShaderGroups . push_back ( group ) ; group . type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR ; group . generalShader = eMissShd ; m_rtShaderGroups . push_back ( group ) ; group . type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR ; group . generalShader = eMissLantern ; m_rtShaderGroups . push_back ( group ) ; group . type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR ; group . generalShader = VK_SHADER_UNUSED_KHR ; group . closestHitShader = eClosestHit ; m_rtShaderGroups . push_back ( group ) ; group . closestHitShader = eClosestHitLantern ; m_rtShaderGroups . push_back ( group ) ; group . closestHitShader = eClosestHitLanternShdObj ; m_rtShaderGroups . push_back ( group ) ; group . closestHitShader = eClosestHitLanternShd ; m_rtShaderGroups . push_back ( group ) ; VkPushConstantRange pushConstant { VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_MISS_BIT_KHR , 0 , sizeof ( PushConstantRay ) } ; VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO } ; pipelineLayoutCreateInfo . pushConstantRangeCount = 1 ; pipelineLayoutCreateInfo . pPushConstantRanges = & pushConstant ; std :: vector < VkDescriptorSetLayout > rtDescSetLayouts = { m_rtDescSetLayout , m_descSetLayout } ; pipelineLayoutCreateInfo . setLayoutCount = static_cast < uint32_t > ( rtDescSetLayouts . size ( ) ) ; pipelineLayoutCreateInfo . pSetLayouts = rtDescSetLayouts . data ( ) ; vkCreatePipelineLayout ( m_device , & pipelineLayoutCreateInfo , nullptr , & m_rtPipelineLayout ) ; VkRayTracingPipelineCreateInfoKHR rayPipelineInfo { VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR } ; rayPipelineInfo . stageCount = static_cast < uint32_t > ( stages . size ( ) ) ; rayPipelineInfo . pStages = stages . data ( ) ; rayPipelineInfo . groupCount = static_cast < uint32_t > ( m_rtShaderGroups . size ( ) ) ; rayPipelineInfo . pGroups = m_rtShaderGroups . data ( ) ; rayPipelineInfo . maxPipelineRayRecursionDepth = 2 ; rayPipelineInfo . layout = m_rtPipelineLayout ; vkCreateRayTracingPipelinesKHR ( m_device , { } , { } , 1 , & rayPipelineInfo , nullptr , & m_rtPipeline ) ; for ( auto & s : stages ) vkDestroyShaderModule ( m_device , s . module , nullptr ) ; }
Pipeline for the ray tracer: all shaders, raygen, chit, miss
Shader list:
Pipeline for the ray tracer : all shaders raygen chit miss Shader list :
// All stages // All the same entry point // Raygen // Miss shader 0 invoked when a primary ray doesn't hit geometry. Fills in clear color. // Miss shader 1 is invoked when a shadow ray (for the main scene light) // misses the geometry. It simply indicates that no occlusion has been found. // Miss shader 2 is invoked when a shadow ray for lantern lighting misses the // lantern. It shouldn't be invoked, but I include it just in case. // OBJ Primary Ray Hit Group - Closest Hit // Lantern Primary Ray Hit Group // OBJ Lantern Shadow Ray Hit Group // Lantern Lantern Shadow Ray Hit Group // Shader groups // Raygen // Miss // Shadow Miss // Lantern Shadow Miss // closest hit shader // Push constant: we want to be able to update constants used by the shaders // Descriptor sets: one specific to ray tracing, and one shared with the rasterization pipeline // Assemble the shader stages and recursion depth info into the ray tracing pipeline // Stages are shaders // In this case, m_rtShaderGroups.size() == 4: we have one raygen group, // two miss shader groups, and one hit group. // The ray tracing process can shoot rays from the camera, and a shadow ray can be shot from the // hit points of the camera rays, hence a recursion level of 2. This number should be kept as low // as possible for performance reasons. Even recursive ray tracing should be flattened into a loop // in the ray generation to avoid deep recursion. // Ray depth