Ray tracing position fetch

The source for this sample can be found in the Khronos Vulkan samples github repository.

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

Ray tracing position fetch sample

Model "PICA PICA - Robot 01" by SEED.EA, acquired from 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

// 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

// 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];