Graphics glossary 50 terms mentioned in this lesson
Select any term for a clear definition. The return button brings you back to the exact term link you used.
Hardware ray tracing does not begin with a new lighting equation. It begins by reorganising geometry so that the device can reject large regions without testing every triangle. Vulkan calls those organisations acceleration structures. A bottom-level acceleration structure contains geometry; a top-level acceleration structure contains instances that refer to bottom-level structures.
A ray query from the compute shader makes the first comparison narrow enough to audit. The camera, storage image, material buffers and accumulation path remain familiar. Only the exhaustive triangle loop is replaced.
What you should be able to account for
- Enable acceleration-structure, buffer-device-address and ray-query support only after querying it.
- Build one triangle BLAS and an instancing TLAS with explicit scratch storage and dependencies.
- Run a bounded ray query and compare its committed result with the manual triangle traversal.
Treat hardware support as a branch, not an assumption
The course baseline remains Vulkan 1.3, but ray-query support is optional. Enumerate device extensions and query a feature chain containing VkPhysicalDeviceAccelerationStructureFeaturesKHR, VkPhysicalDeviceRayQueryFeaturesKHR and the core buffer-device-address feature. Require the corresponding device extensions when they are not supplied by a promoted core feature, and enable only the fields that were reported true.
VkPhysicalDeviceRayQueryFeaturesKHR rayQueryFeatures{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR
};
VkPhysicalDeviceAccelerationStructureFeaturesKHR asFeatures{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR,
.pNext = &rayQueryFeatures
};
VkPhysicalDeviceVulkan12Features vulkan12Features{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
.pNext = &asFeatures
};
VkPhysicalDeviceFeatures2 features{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
.pNext = &vulkan12Features
};
vkGetPhysicalDeviceFeatures2(physicalDevice, &features);
For this route, require bufferDeviceAddress, accelerationStructure and rayQuery. If any are absent, keep the compute reference route available and explain the unsupported route in the user interface. Device selection should not fail merely because an optional teaching comparison is unavailable, unless the application was explicitly launched in hardware-only mode.
Give geometry a device address
The BLAS build input uses device addresses rather than descriptor bindings. Create position and index buffers with acceleration-structure-build-input-read-only and shader-device-address usage in addition to the transfer use required by the upload path. Allocate their memory with the device-address allocation flag and retrieve addresses after binding.
VkBufferDeviceAddressInfo addressInfo{
.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
.buffer = vertexBuffer
};
VkDeviceAddress vertexAddress =
vkGetBufferDeviceAddress(device, &addressInfo);
The address is meaningful only while the bound resource and memory remain alive. Do not store it as a permanent asset identity or use a host pointer in its place.
Describe triangles to the BLAS builder
VkAccelerationStructureGeometryTrianglesDataKHR triangleData{
.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR,
.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT,
.vertexData = {.deviceAddress = vertexAddress},
.vertexStride = sizeof(VertexGPU),
.maxVertex = vertexCount - 1,
.indexType = VK_INDEX_TYPE_UINT32,
.indexData = {.deviceAddress = indexAddress}
};
VkAccelerationStructureGeometryKHR geometry{
.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR,
.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR,
.geometry = {.triangles = triangleData},
.flags = VK_GEOMETRY_OPAQUE_BIT_KHR
};
Opaque geometry tells traversal that no any-hit shader or candidate confirmation is required for opacity policy. Our triangle material is opaque, so this matches the scene. Do not use the flag for geometry whose alpha test is meant to reject intersections.
Query sizes before allocating the result
Fill a build-geometry info structure and call vkGetAccelerationStructureBuildSizesKHR with the primitive count. The returned sizes determine the acceleration-structure storage and scratch requirements. Create the result buffer with acceleration-structure-storage and shader-device-address use, then create the BLAS object over that buffer. Create a scratch buffer with storage-buffer and shader-device-address use, respecting the device's reported scratch-address alignment.
The acceleration-structure object and its backing buffer are different lifetime responsibilities. Destroying the buffer while the BLAS remains in use invalidates the structure.
Worked Vulkan account
How Geometry and Instances Become Traversal Data
Bottom-level structures describe reusable geometry. The top-level structure describes where instances of that geometry are placed for traversal.
What the code must establish
A BLAS describes triangle geometry using device addresses and build ranges. A TLAS describes placed instances that reference those bottom-level structures and supply transforms, masks and application indices. Vulkan reports the storage and scratch requirements for each build. After the builds and their dependencies complete, a ray query can traverse the TLAS from a compute shader.
What to inspect
Retain the queried feature support, geometry descriptions, primitive counts, build sizes, scratch alignment and instance records. For selected rays, compare manual and ray-query miss or hit, distance, instance identity, primitive identity and barycentric coordinates. A completed build is preparation for that comparison, not a replacement for it.
What this establishes, and what it does not: A successful acceleration-structure build establishes that Vulkan accepted the supplied build description. It does not establish agreement with the manual tracer, and a triangle BLAS does not silently include analytic spheres that were never represented as triangles.
Record the BLAS build
VkAccelerationStructureBuildRangeInfoKHR range{
.primitiveCount = triangleCount,
.primitiveOffset = 0,
.firstVertex = 0,
.transformOffset = 0
};
const VkAccelerationStructureBuildRangeInfoKHR* ranges[] = {&range};
buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
buildInfo.dstAccelerationStructure = blas;
buildInfo.scratchData.deviceAddress = scratchAddress;
vkCmdBuildAccelerationStructuresKHR(
commandBuffer, 1, &buildInfo, ranges);
The uploaded vertex and index writes must be visible to the acceleration-structure build stage before this command. If scratch storage is reused for a later build, make the earlier build's scratch writes available before reuse. A convenient queue-idle wait can prove an early prototype but should be replaced with a dependency that names the actual stages and accesses.
Make the TLAS contain instances
Obtain the BLAS device address with vkGetAccelerationStructureDeviceAddressKHR. Fill one or more VkAccelerationStructureInstanceKHR records. Each contains a 3-by-4 transform, a 24-bit custom index, an eight-bit visibility mask, a shader-binding-table record offset, flags and the referenced BLAS address.
VkAccelerationStructureInstanceKHR instance{};
instance.transform = objectToWorld3x4;
instance.instanceCustomIndex = materialBase;
instance.mask = 0xff;
instance.instanceShaderBindingTableRecordOffset = 0;
instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
instance.accelerationStructureReference = blasAddress;
Upload the instance array to a device-addressable build-input buffer. Describe that address as VK_GEOMETRY_TYPE_INSTANCES_KHR, query TLAS sizes, allocate its result and scratch storage, create the TLAS and record its build. Establish a build-to-build dependency when the TLAS consumes a BLAS produced earlier in the command sequence.
Separate geometry from placement
One BLAS contains 200 triangles. Three TLAS instances refer to it with different transforms. The BLAS still contains 200 primitive records, while the TLAS contains three instance records. Moving one object changes an instance transform and requires an appropriate TLAS update or rebuild; it does not require uploading three copies of the triangle vertices.
Bind the TLAS as a descriptor
Add a descriptor-set-layout binding of type VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR visible to the compute stage. The descriptor write uses VkWriteDescriptorSetAccelerationStructureKHR in the pNext chain of VkWriteDescriptorSet. Recreate the pipeline layout and compute pipeline if their set layout changed.
Ask a ray query from GLSL
#extension GL_EXT_ray_query : require
layout(set = 0, binding = 8) uniform accelerationStructureEXT topLevel;
TriangleAnswer queryTriangles(Ray ray, float tMin, float tMax) {
rayQueryEXT query;
rayQueryInitializeEXT(
query,
topLevel,
gl_RayFlagsOpaqueEXT,
0xff,
ray.origin,
tMin,
ray.direction,
tMax);
while (rayQueryProceedEXT(query)) {
// Opaque triangles require no application confirmation here.
}
TriangleAnswer answer = noTriangleAnswer();
if (rayQueryGetIntersectionTypeEXT(query, true) != gl_RayQueryCommittedIntersectionNoneEXT) {
answer.found = true;
answer.t = rayQueryGetIntersectionTEXT(query, true);
answer.instanceIndex = rayQueryGetIntersectionInstanceCustomIndexEXT(query, true);
answer.primitiveIndex = rayQueryGetIntersectionPrimitiveIndexEXT(query, true);
vec2 bary = rayQueryGetIntersectionBarycentricsEXT(query, true);
answer.barycentric = vec3(1.0 - bary.x - bary.y, bary);
}
return answer;
}
The true argument asks for the committed intersection after traversal. The query's minimum and maximum retain exactly the bounded meanings used by the manual functions. For a shadow ray, use the light-distance maximum and stop according to an opaque any-hit policy; for a closest primary ray, inspect the committed answer.
Compare before replacing
Run the manual triangle loop and ray-query route on the same selected rays. Compare miss/hit, distance, instance identity, primitive identity and barycentric weights. Allow a stated floating-point tolerance, especially at shared edges, but do not accept a merely similar image. Edge ownership can differ under precise intersection rules; classify those cases rather than hiding them in a large global tolerance.
Keep spheres in the manual route for now or tessellate them deliberately before building. A triangle BLAS does not absorb analytic sphere equations automatically. The hardware route must state which geometry it actually represents.
Move one of four instances
Four TLAS instances refer to the same unchanged BLAS. One instance transform changes. Which structure contains the changed placement?
The answer
The TLAS contains the instance transform, so its instance data and corresponding TLAS update or rebuild are affected. The shared BLAS geometry remains unchanged because its vertex and index data did not move in object space.
Official reference: the Khronos acceleration-structure chapter defines build inputs and lifetimes, while the ray-traversal chapter defines ray-query behaviour.
Build an agreement table
Select at least twenty rays: clear misses, central hits, edge hits, overlapping instances and bounded shadow rays. Record the manual and ray-query hit flags, distances, primitive indices and barycentric weights. Classify every disagreement. Then change one instance transform, rebuild or update the TLAS as your chosen flags permit, and repeat only the affected cases. Keep this table as a regression test rather than deleting the manual route after the first matching picture.
Carry the same TLAS into a ray tracing pipeline
Retain the BLAS, TLAS, instance identities and agreement tests. Lesson 28 will bind the TLAS to dedicated ray-generation, miss and closest-hit shader stages. The acceleration structures do not change merely because traversal is launched with vkCmdTraceRaysKHR rather than from a compute invocation.
Hardware traversal is now an audited implementation of the same interval question, not a black box substituted for understanding. The BLAS organises triangle geometry, the TLAS organises placed instances, and the ray query returns evidence that can be compared with the manual tracer. One final Vulkan route remains: make rays a pipeline operation with dedicated shader stages.