////
- Copyright (c) 2023-2024, Sascha Willems
-
- SPDX-License-Identifier: Apache-2.0
-
- Licensed under the Apache License, Version 2.0 the "License";
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
////
= Ray tracing position fetch

ifdef::site-gen-antora[]
TIP: The source for this sample can be found in the https://github.com/KhronosGroup/Vulkan-Samples/tree/main/samples/extensions/ray_tracing_position_fetch[Khronos Vulkan samples github repository].
endif::[]

== Background

Accessing per-vertex attributes in a ray tracing shader stage is a common use case, but often requires passing those attributes via some buffer and then doing manual indexing (and unpacking) in the shader. Even if it's something already stored in the acceleration structure like vertex positions.

Using the `VK_KHR_ray_tracing_position_fetch` extension it's now possible to directly access vertex positions from an acceleration structure

image::./images/sample.png[Ray tracing position fetch sample]
_Model "PICA PICA - Robot 01" by SEED.EA, acquired from https://sketchfab.com/3d-models/pica-pica-robot-01-438e3a1589a6411a8e704471930389e1[this url]_

== In the application

Enabling vertex position fetch in the application is straight-forward:

- Enable the `VK_KHR_ray_tracing_position_fetch` device extension
- Enable the `rayTracingPositionFetch` feature in the `VkPhysicalDeviceRayTracingPositionFetchFeaturesKHR` struct
- Add the `VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_KHR` flag (`VkBuildAccelerationStructureFlagsKHR`) to the build flags  of the bottom level acceleration structure to allow access to the positions from shaders

== In the shader

As part of this extension, `SPV_KHR_ray_tracing_position_fetch` adds new built-ins for accessing vertex positions to the any-hit and closest-hit ray tracing shaders.

=== GLSL

[,glsl]
----
// This extension is required for fetching position data in the closest hit shader
#extension GL_EXT_ray_tracing_position_fetch : require

...

// Get the vertex positions of the hit triangle
vec3 pos0 = gl_HitTriangleVertexPositionsEXT[0];
vec3 pos1 = gl_HitTriangleVertexPositionsEXT[1];
vec3 pos2 = gl_HitTriangleVertexPositionsEXT[2];
----

=== HLSL

[,hlsl]
----
// For HLSL, we need to use SPIR-V intrinsics for vertex position fetch
#define HitTriangleVertexPositionsKHR 5335
#define RayTracingPositionFetchKHR 5336

[[vk::ext_extension("SPV_KHR_ray_tracing_position_fetch")]]
[[vk::ext_capability(RayTracingPositionFetchKHR)]]
[[vk::ext_builtin_input(HitTriangleVertexPositionsKHR)]]
const static float3 gl_HitTriangleVertexPositions[3];

...

// Get the vertex positions of the hit triangle
float3 pos0 = gl_HitTriangleVertexPositions[0];
float3 pos1 = gl_HitTriangleVertexPositions[1];
float3 pos2 = gl_HitTriangleVertexPositions[2];
----

== Additional resources

* https://www.khronos.org/blog/introducing-vulkan-ray-tracing-position-fetch-extension[Introducing Vulkan Ray Tracing Position Fetch Extension]