// Copyright 2017-2021 The Khronos Group, Inc.
//
// SPDX-License-Identifier: CC-BY-4.0

include::{generated}/meta/{refprefix}VK_KHR_ray_tracing_pipeline.txt[]

=== Other Extension Metadata

*Last Modified Date*::
    2020-11-12
*Interactions and External Dependencies*::
  - This extension requires
    https://htmlpreview.github.io/?https://github.com/KhronosGroup/SPIRV-Registry/blob/master/extensions/KHR/SPV_KHR_ray_tracing.html[`SPV_KHR_ray_tracing`]
  - This extension provides API support for
    https://github.com/KhronosGroup/GLSL/blob/master/extensions/ext/GLSL_EXT_ray_tracing.txt[`GLSL_EXT_ray_tracing`]
  - This extension interacts with <<version-1.2, Vulkan 1.2>> and
    <<VK_KHR_vulkan_memory_model>>, adding the <<shader-call-related,
    shader-call-related>> relation of invocations, <<shader-call-order,
    shader-call-order>> partial order of dynamic instances of instructions,
    and the <<shader-scope-shadercall, code:ShaderCallKHR>> scope.
  - This extension interacts with <<VK_KHR_pipeline_library>>, enabling
    pipeline libraries to be used with ray tracing pipelines and enabling
    usage of slink:VkRayTracingPipelineInterfaceCreateInfoKHR.
*Contributors*::
  - Matthäus Chajdas, AMD
  - Greg Grebe, AMD
  - Nicolai Hähnle, AMD
  - Tobias Hector, AMD
  - Dave Oldcorn, AMD
  - Skyler Saleh, AMD
  - Mathieu Robart, Arm
  - Marius Bjorge, Arm
  - Tom Olson, Arm
  - Sebastian Tafuri, EA
  - Henrik Rydgard, Embark
  - Juan Cañada, Epic Games
  - Patrick Kelly, Epic Games
  - Yuriy O'Donnell, Epic Games
  - Michael Doggett, Facebook/Oculus
  - Andrew Garrard, Imagination
  - Don Scorgie, Imagination
  - Dae Kim, Imagination
  - Joshua Barczak, Intel
  - Slawek Grajewski, Intel
  - Jeff Bolz, NVIDIA
  - Pascal Gautron, NVIDIA
  - Daniel Koch, NVIDIA
  - Christoph Kubisch, NVIDIA
  - Ashwin Lele, NVIDIA
  - Robert Stepinski, NVIDIA
  - Martin Stich, NVIDIA
  - Nuno Subtil, NVIDIA
  - Eric Werness, NVIDIA
  - Jon Leech, Khronos
  - Jeroen van Schijndel, OTOY
  - Juul Joosten, OTOY
  - Alex Bourd, Qualcomm
  - Roman Larionov, Qualcomm
  - David McAllister, Qualcomm
  - Spencer Fricke, Samsung
  - Lewis Gordon, Samsung
  - Ralph Potter, Samsung
  - Jasper Bekkers, Traverse Research
  - Jesse Barker, Unity
  - Baldur Karlsson, Valve

=== Description

Rasterization has been the dominant method to produce interactive graphics,
but increasing performance of graphics hardware has made ray tracing a
viable option for interactive rendering.
Being able to integrate ray tracing with traditional rasterization makes it
easier for applications to incrementally add ray traced effects to existing
applications or to do hybrid approaches with rasterization for primary
visibility and ray tracing for secondary queries.

To enable ray tracing, this extension adds a few different categories of new
functionality:

  * A new ray tracing pipeline type with new shader domains: ray generation,
    intersection, any-hit, closest hit, miss, and callable
  * A shader binding indirection table to link shader groups with
    acceleration structure items
  * Ray tracing commands which initiate the ray pipeline traversal and
    invocation of the various new shader domains depending on which
    traversal conditions are met

This extension adds support for the following SPIR-V extension in Vulkan:

  * `SPV_KHR_ray_tracing`

include::{generated}/interfaces/VK_KHR_ray_tracing_pipeline.txt[]

=== New or Modified Built-In Variables

  * <<interfaces-builtin-variables-launchid,code:LaunchIdKHR>>
  * <<interfaces-builtin-variables-launchsize,code:LaunchSizeKHR>>
  * <<interfaces-builtin-variables-worldrayorigin,code:WorldRayOriginKHR>>
  * <<interfaces-builtin-variables-worldraydirection,code:WorldRayDirectionKHR>>
  * <<interfaces-builtin-variables-objectrayorigin,code:ObjectRayOriginKHR>>
  * <<interfaces-builtin-variables-objectraydirection,code:ObjectRayDirectionKHR>>
  * <<interfaces-builtin-variables-raytmin,code:RayTminKHR>>
  * <<interfaces-builtin-variables-raytmax,code:RayTmaxKHR>>
  * <<interfaces-builtin-variables-instancecustomindex,code:InstanceCustomIndexKHR>>
  * <<interfaces-builtin-variables-instanceid,code:InstanceId>>
  * <<interfaces-builtin-variables-objecttoworld,code:ObjectToWorldKHR>>
  * <<interfaces-builtin-variables-worldtoobject,code:WorldToObjectKHR>>
  * <<interfaces-builtin-variables-hitkind,code:HitKindKHR>>
  * <<interfaces-builtin-variables-incomingrayflags,code:IncomingRayFlagsKHR>>
  * <<interfaces-builtin-variables-raygeometryindex,code:RayGeometryIndexKHR>>
  * (modified)code:PrimitiveId

=== New SPIR-V Capabilities

  * <<spirvenv-capabilities-table-RayTracingKHR,RayTracingKHR>>
  * <<spirvenv-capabilities-table-RayTraversalPrimitiveCullingKHR,RayTraversalPrimitiveCullingKHR>>

=== Issues

(1) How does this extension differ from VK_NV_ray_tracing?
--
*DISCUSSION*:

The following is a summary of the main functional differences between
VK_KHR_ray_tracing_pipeline and VK_NV_ray_tracing:

  * added support for indirect ray tracing (flink:vkCmdTraceRaysIndirectKHR)
  * uses SPV_KHR_ray_tracing instead of SPV_NV_ray_tracing
  ** refer to KHR SPIR-V enums instead of NV SPIR-V enums (which are
     functionally equivalent and aliased to the same values).
  ** added code:RayGeometryIndexKHR built-in
  * removed vkCompileDeferredNV compilation functionality and replaced with
    <<deferred-host-operations, deferred host operations>> interactions for
    ray tracing
  * added slink:VkPhysicalDeviceRayTracingPipelineFeaturesKHR structure
  * extended slink:VkPhysicalDeviceRayTracingPipelinePropertiesKHR structure
  ** renamed pname:maxRecursionDepth to pname:maxRayRecursionDepth and it
     has a minimum of 1 instead of 31
  ** require pname:shaderGroupHandleSize to be 32 bytes
  ** added pname:maxRayDispatchInvocationCount,
     pname:shaderGroupHandleAlignment and pname:maxRayHitAttributeSize
  * reworked geometry structures so they could be better shared between
    device, host, and indirect builds
  * changed SBT parameters to a structure and added size
    (slink:VkStridedDeviceAddressRegionKHR)
  * add parameter for requesting memory requirements for host and/or device
    build
  * added <<pipeline-library,pipeline library>> support for ray tracing
  * added <<ray-traversal-watertight, watertightness guarantees>>
  * added no-null-shader pipeline flags
    (etext:VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_*_SHADERS_BIT_KHR)
  * added <<ray-tracing-shader-call,memory model interactions>> with ray
    tracing and define how subgroups work and can be repacked
--

ifdef::VK_NV_ray_tracing[]
(2) Can you give a more detailed comparision of differences and similarities
between VK_NV_ray_tracing and VK_KHR_ray_tracing_pipeline?
--
*DISCUSSION*:

The following is a more detailed comparision of which commands, structures,
and enums are aliased, changed, or removed.

  * Aliased functionality -- enums, structures, and commands that are
    considered equivalent:
  ** elink:VkRayTracingShaderGroupTypeNV {harr}
     elink:VkRayTracingShaderGroupTypeKHR
  ** flink:vkGetRayTracingShaderGroupHandlesNV {harr}
     flink:vkGetRayTracingShaderGroupHandlesKHR

  * Changed enums, structures, and commands:
  ** slink:VkRayTracingShaderGroupCreateInfoNV ->
     slink:VkRayTracingShaderGroupCreateInfoKHR (added
     pname:pShaderGroupCaptureReplayHandle)
  ** slink:VkRayTracingPipelineCreateInfoNV ->
     slink:VkRayTracingPipelineCreateInfoKHR (changed type of pname:pGroups,
     added pname:libraries, pname:pLibraryInterface, and
     pname:pDynamicState)
  ** slink:VkPhysicalDeviceRayTracingPropertiesNV ->
     VkPhysicalDeviceRayTracingPropertiesKHR (renamed pname:maxTriangleCount
     to pname:maxPrimitiveCount, added
     pname:shaderGroupHandleCaptureReplaySize)
  ** flink:vkCmdTraceRaysNV -> flink:vkCmdTraceRaysKHR (params to struct)
  ** flink:vkCreateRayTracingPipelinesNV ->
     flink:vkCreateRayTracingPipelinesKHR (different struct, changed
     functionality)

  * Added enums, structures and commands:
  ** ename:VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR
     ename:VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR,
     ename:VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR,
     ename:VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR,
     ename:VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR,
     ename:VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR to
     elink:VkPipelineCreateFlagBits
  ** slink:VkPhysicalDeviceRayTracingPipelineFeaturesKHR structure
  ** slink:VkDeviceOrHostAddressKHR and slink:VkDeviceOrHostAddressConstKHR
     unions
  ** slink:VkPipelineLibraryCreateInfoKHR struct
  ** slink:VkRayTracingPipelineInterfaceCreateInfoKHR struct
  ** slink:VkStridedDeviceAddressRegionKHR struct
  ** flink:vkCmdTraceRaysIndirectKHR command and
     slink:VkTraceRaysIndirectCommandKHR struct
  ** flink:vkGetRayTracingCaptureReplayShaderGroupHandlesKHR (shader group
     capture/replay)
  ** flink:vkCmdSetRayTracingPipelineStackSizeKHR and
     flink:vkGetRayTracingShaderGroupStackSizeKHR commands for stack size
     control

  * Functionality removed:
  ** ename:VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV
  ** flink:vkCompileDeferredNV command (replaced with
     <<VK_KHR_deferred_host_operations>>)
--
endif::VK_NV_ray_tracing[]

(3) What are the changes between the public provisional (VK_KHR_ray_tracing
v8) release and the internal provisional (VK_KHR_ray_tracing v9) release?
--
  * Require Vulkan 1.1 and SPIR-V 1.4
  * Added interactions with Vulkan 1.2 and <<VK_KHR_vulkan_memory_model>>
  * added creation time capture and replay flags
  ** added
     ename:VK_PIPELINE_CREATE_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR
     to elink:VkPipelineCreateFlagBits
  * replace stext:VkStridedBufferRegionKHR with
    slink:VkStridedDeviceAddressRegionKHR and change
    flink:vkCmdTraceRaysKHR, flink:vkCmdTraceRaysIndirectKHR, to take these
    for the shader binding table and use device addresses instead of
    buffers.
  * require the shader binding table buffers to have the
    etext:VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR set
  * make <<VK_KHR_pipeline_library>> an interaction instead of required
    extension
  * rename the pname:libraries member of
    slink:VkRayTracingPipelineCreateInfoKHR to pname:pLibraryInfo and make
    it a pointer
  * make <<VK_KHR_deferred_host_operations>> an interaction instead of a
    required extension (later went back on this)
  * added explicit stack size management for ray tracing pipelines
  ** removed the pname:maxCallableSize member of
     slink:VkRayTracingPipelineInterfaceCreateInfoKHR
  ** added the pname:pDynamicState member to
     slink:VkRayTracingPipelineCreateInfoKHR
  ** added ename:VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR
     dynamic state for ray tracing pipelines
  ** added flink:vkGetRayTracingShaderGroupStackSizeKHR and
     flink:vkCmdSetRayTracingPipelineStackSizeKHR commands
  ** added elink:VkShaderGroupShaderKHR enum
  * Added pname:maxRayDispatchInvocationCount limit to
    slink:VkPhysicalDeviceRayTracingPipelinePropertiesKHR
  * Added pname:shaderGroupHandleAlignment property to
    slink:VkPhysicalDeviceRayTracingPipelinePropertiesKHR
  * Added pname:maxRayHitAttributeSize property to
    slink:VkPhysicalDeviceRayTracingPipelinePropertiesKHR
  * Clarify deferred host ops for pipeline creation
  ** slink:VkDeferredOperationKHR is now a top-level parameter for
     flink:vkCreateRayTracingPipelinesKHR
  ** removed stext:VkDeferredOperationInfoKHR structure
  ** change deferred host creation/return parameter behavior such that the
     implementation can modify such parameters until the deferred host
     operation completes
  ** <<VK_KHR_deferred_host_operations>> is required again
--

(4) What are the changes between the internal provisional
(VK_KHR_ray_tracing v9) release and the final (VK_KHR_acceleration_structure
v11 / VK_KHR_ray_tracing_pipeline v1) release?
--
  * refactor VK_KHR_ray_tracing into 3 extensions, enabling implementation
    flexibility and decoupling ray query support from ray pipelines:
  ** <<VK_KHR_acceleration_structure>> (for acceleration structure
     operations)
  ** <<VK_KHR_ray_tracing_pipeline>> (for ray tracing pipeline and shader
     stages)
  ** <<VK_KHR_ray_query>> (for ray queries in existing shader stages)
  * Require code:Volatile for the following builtins in the ray generation,
    closest hit, miss, intersection, and callable shader stages:
  ** code:SubgroupSize, code:SubgroupLocalInvocationId, code:SubgroupEqMask,
     code:SubgroupGeMask, code:SubgroupGtMask, code:SubgroupLeMask,
     code:SubgroupLtMask
  ** code:SMIDNV, code:WarpIDNV
  * clarify buffer usage flags for ray tracing
  ** ename:VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR is added as an alias
     of ename:VK_BUFFER_USAGE_RAY_TRACING_BIT_NV and is required on shader
     binding table buffers
  ** ename:VK_BUFFER_USAGE_STORAGE_BUFFER_BIT is used in
     <<VK_KHR_acceleration_structure>> for pname:scratchData
  * rename pname:maxRecursionDepth to pname:maxRayPipelineRecursionDepth
    (pipeline creation) and pname:maxRayRecursionDepth (limit) to reduce
    confusion
  * Add queryable pname:maxRayHitAttributeSize limit and rename members of
    slink:VkRayTracingPipelineInterfaceCreateInfoKHR to
    pname:maxPipelineRayPayloadSize and pname:maxPipelineRayHitAttributeSize
    for clarity
  * Update SPIRV capabilities to use code:RayTracingKHR
  * extension is no longer provisional
  * define synchronization requirements for indirect trace rays and indirect
    buffer
--

(5) This extension adds gl_InstanceID for the intersection, any-hit, and
    closest hit shaders, but in KHR_vulkan_glsl, gl_InstanceID is replaced
    with gl_InstanceIndex.
    Which should be used for Vulkan in this extension?
--
*RESOLVED*: This extension uses gl_InstanceID and maps it to code:InstanceId
in SPIR-V.
It is acknowledged that this is different than other shader stages in
Vulkan.
There are two main reasons for the difference here:

  * symmetry with gl_PrimitiveID which is also available in these shaders
  * there is no "`baseInstance`" relevant for these shaders, and so ID makes
    it more obvious that this is zero-based.
--

=== Sample Code

Example ray generation GLSL shader

[source,c]
---------------------------------------------------
#version 450 core
#extension GL_EXT_ray_tracing : require
layout(set = 0, binding = 0, rgba8) uniform image2D image;
layout(set = 0, binding = 1) uniform accelerationStructureEXT as;
layout(location = 0) rayPayloadEXT float payload;

void main()
{
   vec4 col = vec4(0, 0, 0, 1);

   vec3 origin = vec3(float(gl_LaunchIDEXT.x)/float(gl_LaunchSizeEXT.x), float(gl_LaunchIDEXT.y)/float(gl_LaunchSizeEXT.y), 1.0);
   vec3 dir = vec3(0.0, 0.0, -1.0);

   traceRayEXT(as, 0, 0xff, 0, 1, 0, origin, 0.0, dir, 1000.0, 0);

   col.y = payload;

   imageStore(image, ivec2(gl_LaunchIDEXT.xy), col);
}
---------------------------------------------------

=== Version History

  * Revision 1, 2020-11-12 (Mathieu Robart, Daniel Koch, Eric Werness,
    Tobias Hector)
    - Decomposition of the specification, from VK_KHR_ray_tracing to
      VK_KHR_ray_tracing_pipeline (#1918,!3912)
    - require certain subgroup and sm_shader_builtin shader builtins to be
      decorated as volatile in the ray generation, closest hit, miss,
      intersection, and callable stages (#1924,!3903,!3954)
    - clarify buffer usage flags for ray tracing (#2181,!3939)
    - rename maxRecursionDepth to maxRayPipelineRecursionDepth and
      maxRayRecursionDepth (#2203,!3937)
    - add queriable maxRayHitAttributeSize and rename members of
      VkRayTracingPipelineInterfaceCreateInfoKHR (#2102,!3966)
    - update to use code:RayTracingKHR SPIR-V capability
    - add VUs for matching hit group type against geometry type
      (#2245,!3994)
    - require code:RayTMaxKHR be volatile in intersection shaders
      (#2268,!4030)
    - add numerical limits for ray parameters (#2235,!3960)
    - fix SBT indexing rules for device addresses (#2308,!4079)
    - relax formula for ray intersection candidate determination
      (#2322,!4080)
    - add more details on code:ShaderRecordBufferKHR variables (#2230,!4083)
    - clarify valid bits for code:InstanceCustomIndexKHR
      (GLSL/GLSL#19,!4128)
    - allow at most one code:IncomingRayPayloadKHR,
      code:IncomingCallableDataKHR, and code:HitAttributeKHR (!4129)
    - add minimum for maxShaderGroupStride (#2353,!4131)
    - require VK_KHR_pipeline_library extension to be supported
      (#2348,!4135)
    - clarify meaning of 'geometry index' (#2272,!4137)
    - restrict traces to TLAS (#2239,!4141)
    - add note about maxPipelineRayPayloadSize (#2383,!4172)
    - do not require raygen shader in pipeline libraries (!4185)
    - define sync for indirect trace rays and indirect buffer (#2407,!4208)

