llvm / llvm/offload-test-suite
[EPIC]: Bring-up and test coverage for PSO-based raytracing
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 18
- Forks
- 39
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 40
Description
Companion to the inline-RT epic in #1258. That issue is scoped to `RayQuery` / `TraceRayInline` inside a regular compute shader; the test framework already treats it as a `Compute` pipeline that happens to bind an acceleration structure. PSO-based raytracing is a different beast β it introduces an entirely new pipeline kind, new shader stages, a shader binding table, and the `DispatchRays` command. The framework has none of that today, so this issue tracks both the bring-up work and the shader-visible test surface that becomes unlockable as bring-up progresses.
Reuses the AS YAML / abstraction layers from the inline-RT bring-up (#1214, #1232, #1245), so this work starts above that line.
Legend:
- [ ] Not started
- [ ] In progress ποΈ
- [ ] In review π
- [x] Finished (merged in main)
- π testable on top of the bring-up below
- ποΈ requires additional framework work first
## Bring-up PRs (foundation for everything below)
- [ ] Add `ShaderPipelineKind::RayTracing`, six new RT `Stages`, HitGroups / RayTracingPipelineConfig / ShaderBindingTable YAML schema, `%dxc_target_lib` substitution, the `raytracing-pipeline` lit feature, and a foundational `XFAIL: *` smoke test π
- #1270
- [ ] Vulkan RT pipeline + SBT + `dispatchRays` (drops Vulkan from the smoke test's XFAIL list) π
- #1273
- [ ] D3D12 state object + SBT + `DispatchRays` (drops DirectX from the smoke test's XFAIL list) π
- #1275
- [ ] Metal RT pipeline + SBT + `dispatchRays` via `metal_irconverter` (drops Metal from the smoke test's XFAIL list) π
- #1281
- [ ] First PSO RT test batch: DispatchRays index/dimensions + SBT miss/hit-group routing π
- #1277
- [ ] ClosestHit ray system values: barycentrics, PrimitiveIndex, WorldRay π
- #1278
- [ ] PSO-only RT surface: TraceRay recursion, RAY_FLAG_SKIP_CLOSEST_HIT_SHADER, callable shaders π
- #1279
## Framework bring-up
### Pipeline / stage model
- [ ] Add `ShaderPipelineKind::RayTracing` alongside `Compute` / `TraditionalRaster` / `MeshShaderRaster` in `Support/Pipeline.h` π
- [ ] Add new `Stages`: `RayGeneration`, `Miss`, `ClosestHit`, `AnyHit`, `Intersection`, `Callable` π
- [ ] Extend `validatePipelineKind` to require β₯1 raygen entry and at least one of {miss, hit-group} when the pipeline is RT π
- [ ] YAML mapping for the new stages and pipeline kind π
### Shader compilation
- [ ] Add a `lib_6_3` (or `lib_6_5`) target so `clang-dxc` / `dxc` emits a DXIL library with multiple entry points
- [ ] `%dxc_target_lib` substitution analogous to `%dxc_target` π
- [ ] Lit feature `raytracing-pipeline` (mirrors `acceleration-structure`) gated on the device feature + library-target support π
### Hit groups, payloads, attributes, recursion config
- [ ] YAML `HitGroups:` list (`Name`, `Type: Triangles|Procedural`, `ClosestHit`, optional `AnyHit`, optional `Intersection`) π
- [ ] YAML `RayTracingPipelineConfig:` block (`MaxTraceRecursionDepth`, `MaxPayloadSizeInBytes`, `MaxAttributeSizeInBytes`, optional `PipelineFlags`) π
- [ ] Local root signatures (per shader-record root args) β at minimum a schema that lets a test record SBT-local constants ποΈ
- [ ] Validate payload/attr sizes against shader-declared sizes at YAML parse time
### State Object / RT pipeline creation
- [ ] D3D12 backend: build a `ID3D12StateObject` from the YAML (DXIL library subobject, hit-group subobjects, global/local root signatures, raytracing pipeline + shader config subobjects)
- [ ] Vulkan backend: `VkRayTracingPipelineKHR` + `vkGetRayTracingShaderGroupHandlesKHR`, pipeline-library plumbing if needed; `VK_KHR_ray_tracing_pipeline` feature gate
- [ ] Metal backend: route through `metal_irconverter` for DXILβAIR β it lowers `DispatchRays` into a compute dispatch backed by `MTLVisibleFunctionTable` / `MTLIntersectionFunctionTable` standing in for hit-groups, miss shaders, and callables. The backend work covers emitting the converter-expected compute dispatch and building those function tables. π (#1281)
### Shader binding table
- [ ] Abstract `ShaderBindingTable` resource owned by the RT pipeline
- [ ] YAML `ShaderBindingTable:` block describing raygen / miss / hit-group / callable records, each with `ShaderName`, optional local-root data π
- [ ] Per-backend SBT builders:
- D3D12: identifier from `ID3D12StateObjectProperties::GetShaderIdentifier`, 32-byte aligned records, programmer-managed stride
- Vulkan: `VkStridedDeviceAddressRegionKHR`, alignment from `rayTracingPipelineProperties`
- Metal: visible function tables / intersection function tables
- [ ] Compute SBT record stride from declared local-root data size
### DispatchRays command
- [ ] New `RayTracingEncoder` (or extend `ComputeEncoder`) with `dispatchRays(width, height, depth, sbt)`
- [ ] YAML dispatch parameters: `RayTracingDispatch: { Width, Height, Depth }` β currently reusing `DispatchParameters.DispatchGroupCount` as `{Width, Height, Depth}` for RT pipelines per #1270; a dedicated `RayTracingDispatch` block can come later if useful.
- [ ] Resource-state / barrier handling for SBT and AS reads
### Resource binding parity
- [ ] AS binding from raygen / miss / hit / callable stages (the inline-RT work only wires it up for compute)
- [ ] UAV / SRV / CBV / sampler tables from each new stage
- [ ] Verify cross-API root-signature layout matches between D3D12/Vulkan so the same DXIL works unmodified
## Shader-observable spec surface
Each test asserts behavior visible from a raygen / miss / hit / callable shader. Coverage parallels the inline-RT epic where the same concept appears (e.g. ray flags), then adds the PSO-only surface (payloads, recursion, etc.).
### `TraceRay` (host-side intrinsic)
- [ ] `RayFlags` parameter behaves the same as in `RayQuery<>` β re-run the same flag matrix from #1258 β π once bring-up lands
- [ ] `InstanceInclusionMask` filtering β π
- [ ] `RayContributionToHitGroupIndex` selects the right hit-group record β π
- [ ] `MultiplierForGeometryContributionToHitGroupIndex` (per-geometry hit-group striding) β ποΈ (multi-geometry BLAS)
- [ ] `MissShaderIndex` selects the right miss record β π
- [ ] `RayDesc` corners: `TMin > 0`, `TMax` clip, NaN/Inf direction β π
- [ ] Recursive `TraceRay` up to `MaxTraceRecursionDepth` β π
- [ ] Recursion beyond declared `MaxTraceRecursionDepth` is undefined; verify that the in-spec maximum value works β π
### Raygen shader (`[shader("raygeneration")]`)
- [ ] `DispatchRaysIndex()` matches the dispatch x/y/z lane β π
- [ ] `DispatchRaysDimensions()` echoes the host-side width/height/depth β π
- [ ] Multiple raygen entries, one selected per pipeline β π
- [ ] Writes to UAV indexed by `DispatchRaysIndex` β π
- [ ] Calls `TraceRay` and consumes the returned payload β π
### Miss shader (`[shader("miss")]`)
- [ ] Miss runs when no geometry is hit and payload is observable in raygen β π
- [ ] Multiple miss shaders, `MissShaderIndex` selects between them β π
- [ ] Miss-side ray-system-values: `WorldRayOrigin`, `WorldRayDirection`, `RayTMin`, `RayTCurrent`, `RayFlags`, `DispatchRaysIndex` β π
### Closest-hit shader (`[shader("closesthit")]`)
- [ ] Runs exactly once per accepted hit; payload mutation observable in raygen β π
- [ ] Hit-side ray-system-values: all of the miss-side ones plus `InstanceIndex`, `InstanceID`, `PrimitiveIndex`, `GeometryIndex`, `HitKind`, `ObjectRayOrigin/Direction`, `ObjectToWorld3x4/4x3`, `WorldToObject3x4/4x3` β π
- [ ] `BuiltInTriangleIntersectionAttributes.barycentrics` at known points β π
- [ ] Hit-group routing: distinct closest-hit per hit-group, selected by `RayContributionToHitGroupIndex` + instance contribution β π
- [ ] Closest-hit calls `TraceRay` to spawn a secondary ray (recursion) β π
### Any-hit shader (`[shader("anyhit")]`)
- [ ] Any-hit fires for non-opaque geometry only β ποΈ (non-opaque YAML)
- [ ] `IgnoreHit()` skips a candidate; closest-hit sees next hit β ποΈ
- [ ] `AcceptHitAndEndSearch()` ends traversal immediately β ποΈ
- [ ] Any-hit can mutate payload before `IgnoreHit` (and the mutation must be discarded per spec) β ποΈ
- [ ] Per-geometry `NO_DUPLICATE_ANYHIT_INVOCATION` β ποΈ (geometry flag YAML)
### Intersection shader (`[shader("intersection")]`)
- [ ] `ReportHit(t, kind, attrs)` with custom hit-attribute struct β ποΈ (procedural geometry)
- [ ] Custom `HitKind` value flows through to closest-hit / any-hit β ποΈ
- [ ] `ReportHit` returns true/false based on TMin/TMax + any-hit decision β ποΈ
- [ ] Intersection-side ray-system-values match the rest β ποΈ
### Callable shader (`[shader("callable")]`)
- [ ] `CallShader(index, params)` runs the right callable record β π
- [ ] Callable can be invoked from raygen, miss, closest-hit, callable β π
- [ ] `DispatchRaysIndex` / `Dimensions` visible inside callable β π
### Payload + attribute mechanics
- [ ] Trivial payload (single `uint`) round-trip β π
- [ ] Large payload near `MaxPayloadSizeInBytes` β π
- [ ] `[payload]` qualifier `in` / `out` / `inout` semantics β π
- [ ] Custom hit attribute struct from an intersection shader β ποΈ
- [ ] Payload struct with mixed types (float/int/half) β π
### Hit-group / SBT selection (shader-observable)
- [ ] `InstanceContributionToHitGroupIndex` selects per-instance hit group β ποΈ (YAML field shared with #1258)
- [ ] `RayContributionToHitGroupIndex` per `TraceRay` call β π
- [ ] `MultiplierForGeometryContributionToHitGroupIndex` across multi-geom BLAS β ποΈ (multi-geom YAML)
- [ ] Local-root constants in an SBT record are visible to the shader β π
### Shader control flow / vendor edges
- [ ] Divergent rays per lane (different hit-groups invoked) β π
- [ ] Conditional `TraceRay` (lane mask) β π
- [ ] `TraceRay` with `RAY_FLAG_SKIP_CLOSEST_HIT_SHADER` (PSO-only flag) β π
- [ ] Mix of opaque and non-opaque BLAS in one pipeline β ποΈ
- [ ] Same ray flag matrix as #1258 for parity β π
## Out of scope (intentionally)
- AS build flags / compaction / refit / clone / serialize β not shader-visible; same reasoning as #1258.
- DXR 1.2 / `SER` (ShaderExecutionReordering) β future epic once base PSO RT works on all three backends.
- Work-graph dispatched RT β separate feature.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up β it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with Support/Pipeline.h and the foundational ray-tracing smoke test described under the bring-up PRs, then read #1270 and the related backend work. The epic is done when the framework supports the listed PSO ray-tracing pipelines, shader binding tables, DispatchRays, and the specified shader-observable coverage across the three backends.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- computer-graphics, testing-qa
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100