• BLAS and TLAS — Acceleration Structures


  • Conceptual Overview

    • Two-level hierarchy
      • BLAS (Bottom-Level AS): geometry BVH — triangles or AABBs
      • TLAS (Top-Level AS): instance BVH — references to BLASes with transforms
    • Why two levels?
      • Allows instancing: one BLAS, many TLAS instances (e.g., 1000 trees from 1 mesh)
      • TLAS can be rebuilt cheaply (just transforms) while BLASes stay static
      • Hardware traversal handles both levels transparently
    • Analogy to software BVH
      • BLAS ≈ per-mesh BVH (built offline or at load time)
      • TLAS ≈ scene BVH (rebuilt every frame)

  • BLAS Construction

    • Input: vertex buffer + index buffer (triangle list)
    • VkAccelerationStructureGeometryKHR
    • Build flags
      • VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR — optimize for traversal (static geometry)
      • VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR — optimize for build speed (dynamic geometry)
      • VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR — allow incremental updates (skinned meshes)
      • VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR — compact after build (saves memory)
    • Memory requirements
      • Query with vkGetAccelerationStructureBuildSizesKHR
      • Returns: accelerationStructureSize, buildScratchSize, updateScratchSize
      • Scratch buffer is temporary — can be reused after build completes
    • Compaction (important for memory)
      • Build with ALLOW_COMPACTION flag
      • Query compacted size with VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR
      • Copy to smaller buffer with vkCmdCopyAccelerationStructureKHR
      • Typical compaction ratio: 50-70% size reduction

  • TLAS Construction

    • Input: array of VkAccelerationStructureInstanceKHR
    • Instance struct fields
      • transform — 3×4 row-major affine transform matrix
      • instanceCustomIndex — 24-bit value accessible as gl_InstanceCustomIndexEXT in shaders
      • mask — 8-bit visibility mask (AND with ray mask in traceRayEXT)
      • instanceShaderBindingTableRecordOffset — SBT hit group offset for this instance
      • flagsVK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR etc.
      • accelerationStructureReference — device address of the BLAS
    • TLAS is rebuilt every frame
      • Upload new instance buffer with updated transforms
      • vkCmdBuildAccelerationStructuresKHR with VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR
      • Or use MODE_UPDATE_KHR for incremental update (faster but lower quality BVH)

  • Memory Layout and Device Addresses

    • PathTracer Learning - Concept - Device Address Bit
    • All AS input buffers need VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT
    • AS buffer needs VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR
    • Scratch buffer needs VK_BUFFER_USAGE_STORAGE_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT

  • Traversal in Shaders

    • traceRayEXT(tlas, rayFlags, cullMask, sbtOffset, sbtStride, missIndex, origin, tMin, dir, tMax, payloadLocation)
    • Ray flags
      • gl_RayFlagsOpaqueEXT — skip any-hit shaders (faster)
      • gl_RayFlagsTerminateOnFirstHitEXT — stop at first hit (shadow rays)
      • gl_RayFlagsSkipClosestHitShaderEXT — don’t call closest-hit (occlusion only)
    • Built-in variables in hit shaders
      • gl_HitTEXT — distance to hit
      • gl_PrimitiveID — triangle index within the BLAS geometry
      • gl_InstanceID — instance index in the TLAS
      • gl_InstanceCustomIndexEXT — custom index from instance struct
      • gl_WorldRayOriginEXT, gl_WorldRayDirectionEXT — ray in world space
      • gl_ObjectRayOriginEXT, gl_ObjectRayDirectionEXT — ray in object space
      • gl_ObjectToWorldEXT, gl_WorldToObjectEXT — transform matrices