llvm / llvm/offload-test-suite

[EPIC]: Improve inline raytracing test coverage

Open
#1,258 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
18
Forks
39
Avg merge
2d 18h
Merged PRs (30d)
40

Description

This issue tracks expanding the inline raytracing (`RayQuery`) test suite. The bring-up PRs introduce a baseline of three scenarios under `test/Feature/InlineRT/` β€” a single-triangle hit, an indexed triangle hit, and instance selection via translated transforms. The list below walks the HLSL inline-RT spec surface β€” limited to behavior observable from a shader, since that is what this suite tests β€” and notes what becomes testable after those PRs land versus what still needs further framework / YAML work.

### Bring-up PRs (foundation for everything below)
- [x] YAML-driven acceleration structure definitions in `.test` files
- https://github.com/llvm/offload-test-suite/pull/1214
- [ ] RT acceleration structure abstraction (size queries, resource allocation) πŸ‘€
- https://github.com/llvm/offload-test-suite/pull/1232
- [ ] Bind acceleration structures and enable the InlineRT tests πŸ‘€
- https://github.com/llvm/offload-test-suite/pull/1245

Legend:
- [ ] Not started
- [ ] In progress πŸ—οΈ
- [ ] In review πŸ‘€
- [x] Finished (merged in main)
- πŸ‘ testable on top of the bring-up PRs above
- πŸ—οΈ requires additional backend or YAML work first

## RayQuery API surface (`cs_6_5`)

### `TraceRayInline` parameters
- [ ] `RAY_FLAG_NONE`, default mask `0xFF` πŸ‘€
- covered by the bring-up tests in #1245
- [ ] Per-call `RayFlags` argument != template flags (runtime-OR with template) β€” πŸ‘
- [ ] `InstanceInclusionMask` filtering β€” TLAS instances with various `InstanceMask` values, query with overlapping/disjoint masks πŸ‘€
- covered by `instance-mask.test` in #1274
- [ ] `RayDesc` with non-axis-aligned direction (no auto-normalization) β€” πŸ‘
- [ ] `RayDesc` with `TMin > 0` excluding a near hit πŸ‘€
- covered by `tmin-tmax-clip.test` in #1271
- [ ] `RayDesc` with `TMax` clipping a far hit πŸ‘€
- covered by `tmin-tmax-clip.test` in #1271
- [ ] Multiple `TraceRayInline` calls on the same `RayQuery` object β€” πŸ‘
- [ ] Multiple distinct `RayQuery` objects in the same shader β€” πŸ‘

### Template `` (compile-time)
- [ ] `RAY_FLAG_FORCE_OPAQUE` (skips any-hit / non-opaque candidate path) β€” πŸ‘
- [ ] `RAY_FLAG_FORCE_NON_OPAQUE` (forces candidate path even for opaque geom) β€” πŸ‘
- [ ] `RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH` β€” verify single `Proceed()` iteration stops on first hit β€” πŸ‘
- [ ] `RAY_FLAG_CULL_BACK_FACING_TRIANGLES` β€” πŸ‘
- [ ] `RAY_FLAG_CULL_FRONT_FACING_TRIANGLES` β€” πŸ‘
- [ ] `RAY_FLAG_CULL_OPAQUE` β€” πŸ‘
- [ ] `RAY_FLAG_CULL_NON_OPAQUE` β€” πŸ‘
- [ ] `RAY_FLAG_SKIP_TRIANGLES` (mixed BLAS, triangles skipped, AABBs hit) β€” πŸ‘ (procedural path wired in #1289)
- [ ] `RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES` β€” πŸ‘ (procedural path wired in #1289)
- [ ] Combined flags (e.g. `CULL_BACK_FACING | ACCEPT_FIRST_HIT_AND_END_SEARCH`) β€” πŸ‘

### Candidate-path methods (inside `Proceed()` loop)
- [ ] `CandidateType()` β€” `CANDIDATE_NON_OPAQUE_TRIANGLE` vs `CANDIDATE_PROCEDURAL_PRIMITIVE` β€” πŸ—οΈ (non-opaque + procedural)
- [ ] `CandidateProceduralPrimitiveNonOpaque()` β€” πŸ—οΈ
- [ ] `CandidateTriangleRayT()` β€” πŸ‘ (needs non-opaque geometry)
- [ ] `CandidateInstanceIndex()` / `CandidateInstanceID()` β€” πŸ‘
- [ ] `CandidateInstanceContributionToHitGroupIndex()` β€” πŸ‘ (YAML field added in #1286)
- [ ] `CandidateGeometryIndex()` (multi-geometry BLAS) β€” πŸ—οΈ (YAML: multi-geom)
- [ ] `CandidatePrimitiveIndex()` β€” πŸ‘
- [ ] `CandidateObjectRayOrigin()` / `CandidateObjectRayDirection()` β€” πŸ‘
- [ ] `CandidateObjectToWorld3x4()` / `CandidateObjectToWorld4x3()` β€” πŸ‘
- [ ] `CandidateWorldToObject3x4()` / `CandidateWorldToObject4x3()` β€” πŸ‘
- [ ] `CandidateTriangleFrontFace()` β€” πŸ‘
- [ ] `CandidateTriangleBarycentrics()` (verify u/v at known points) β€” πŸ‘
- [ ] `CommitNonOpaqueTriangleHit()` accept/reject patterns β€” πŸ‘
- [ ] `CommitProceduralPrimitiveHit(t)` accept/reject β€” πŸ—οΈ

### Committed-hit methods
- [ ] `CommittedStatus()` β€” `COMMITTED_TRIANGLE_HIT` πŸ‘€
- covered by the bring-up tests in #1245
- [ ] `CommittedStatus()` β€” `COMMITTED_NOTHING` (miss path) πŸ‘€
- covered by `miss-status.test` in #1271
- [ ] `CommittedStatus()` β€” `COMMITTED_PROCEDURAL_PRIMITIVE_HIT` πŸ‘€
- covered by `aabb-procedural.test` in #1289
- [ ] `CommittedRayT()` β€” verify exact `t` for axis-aligned ray-plane hit πŸ‘€
- covered by `ray-t.test` in #1271
- [ ] `CommittedInstanceIndex()` (TLAS position) vs `CommittedInstanceID()` (user data) on shuffled instance order β€” πŸ‘
- [ ] `CommittedInstanceID()` πŸ‘€
- multi-instance scenario covered in #1245
- [ ] `CommittedInstanceContributionToHitGroupIndex()` πŸ‘€
- covered by `instance-contribution.test` in #1286
- [ ] `CommittedGeometryIndex()` β€” πŸ—οΈ (YAML: multiple geoms per BLAS)
- [ ] `CommittedPrimitiveIndex()` β€” multi-triangle BLAS, primitive lookup πŸ‘€
- covered by `primitive-index.test` in #1272
- [ ] `CommittedObjectRayOrigin()` / `CommittedObjectRayDirection()` β€” verify transform of world-space ray into instance space β€” πŸ‘
- [ ] `CommittedObjectToWorld3x4()` / `4x3()` round-trip β€” πŸ‘
- [ ] `CommittedWorldToObject3x4()` / `4x3()` β€” πŸ‘
- [ ] `CommittedTriangleFrontFace()` (CW vs CCW winding) β€” πŸ‘
- [ ] `CommittedTriangleBarycentrics()` β€” known centroid/edge πŸ‘€
- covered by `barycentrics.test` in #1271

### Ray-side methods
- [ ] `RayFlags()` πŸ‘€
- covered by `world-ray-echo.test` in #1271
- [ ] `WorldRayOrigin()` / `WorldRayDirection()` (echo input) πŸ‘€
- covered by `world-ray-echo.test` in #1271
- [ ] `RayTMin()` πŸ‘€
- covered by `world-ray-echo.test` in #1271
- [ ] `Abort()` mid-`Proceed()` (no commit afterwards) β€” πŸ‘

## BLAS geometry coverage (shader-visible facets)

- [ ] Single triangle, non-indexed, `RGB32Float` πŸ‘€
- covered by `triangle-setup.test` in #1245
- [ ] Indexed triangles, `Uint32` indices πŸ‘€
- covered by `indexed-triangle-setup.test` in #1245
- [ ] `Uint16` index buffer β€” verify primitive lookup unchanged β€” πŸ‘
- [ ] Alternate vertex formats: `RG32Float` (z=0), `RGBA16Float`, `RG16Float`, `R10G10B10A2_UNORM`, `RGBA8_SNORM` (precision of barycentrics / object-space ray vs `RGB32Float`) β€” πŸ‘
- [ ] Per-triangle-geometry `Transform3x4` (BLAS-side bake; visible via `Object*` queries) πŸ‘€
- covered by `geometry-transform.test` in #1288
- [ ] Multiple triangle geometries in one BLAS β€” verify `*GeometryIndex` β€” πŸ—οΈ
- [ ] Non-opaque geometry (`Opaque: false`) β€” drives candidate path β€” πŸ—οΈ (YAML field)
- [ ] AABB / procedural geometry β€” exercises procedural candidate path πŸ‘€
- covered by `aabb-procedural.test` in #1289
- [ ] Mixed-opacity geometries within one BLAS β€” πŸ—οΈ
- [ ] Degenerate triangles (zero area) β€” must not produce hits β€” πŸ‘
- [ ] Watertightness across shared triangle edges β€” πŸ‘

## TLAS instance coverage (shader-visible facets)

- [ ] Multiple instances, distinct translations, distinct `InstanceID` πŸ‘€
- covered by `multi-instance.test` in #1245
- [ ] Rotation/scale transforms (verify `Object*` / `*ToWorld` / `*ToObject`) β€” πŸ‘
- [ ] Non-uniform scale + skew (verify `WorldToObject` inverse) β€” πŸ‘
- [ ] Instance with negative-determinant transform β€” front/back flip β€” πŸ‘
- [ ] `InstanceMask` filtered by `InstanceInclusionMask` πŸ‘€
- covered by `instance-mask.test` in #1274
- [ ] `InstanceContributionToHitGroupIndex` πŸ‘€
- covered by `instance-contribution.test` in #1286
- [ ] Per-instance flags:
- `TRIANGLE_CULL_DISABLE` overrides ray cull flags β€” πŸ‘ (YAML field added in #1287)
- `TRIANGLE_FRONT_COUNTERCLOCKWISE` flips `*TriangleFrontFace` πŸ‘€
- covered by `instance-flags.test` in #1287
- `FORCE_OPAQUE` / `FORCE_NON_OPAQUE` overrides β€” πŸ‘ (YAML field added in #1287)
- [ ] Same BLAS referenced by multiple instances (sharing) β€” πŸ‘
- [ ] Empty TLAS (no instances) β€” currently rejected at build, may want a miss-only path β€” πŸ—οΈ

## Shader control flow

- [ ] Divergent rays per thread (1D dispatch, per-thread direction) πŸ‘€
- covered by `primitive-index.test` in #1272
- [ ] `RayQuery` as a function parameter (`inout`) β€” πŸ‘
- [ ] `RayQuery` as a struct member β€” πŸ‘
- [ ] Nested `RayQuery` (second trace inside a `Proceed()` loop) β€” πŸ—οΈ (non-opaque)
- [ ] Two independent `RayQuery` objects with different template flags in the same shader β€” πŸ‘
- [ ] Conditional `TraceRayInline` (skip on lane mask) β€” πŸ‘
- [ ] Loop-driven `Proceed()` with explicit `while (Q.Proceed())` instead of single-shot β€” πŸ‘
- [ ] Re-using one `RayQuery` for sequential rays without dynamic state leak β€” πŸ‘
- [ ] Storing committed-hit results in groupshared and reading from another lane β€” πŸ‘

## Numerical / vendor edge behavior (shader-observable)

- [ ] Ray exactly hitting a vertex / edge β€” πŸ‘
- [ ] `TMin == hit distance` (boundary inclusive vs exclusive) β€” πŸ‘
- [ ] `TMax == hit distance` (boundary inclusive vs exclusive) β€” πŸ‘
- [ ] NaN / Inf in ray origin or direction β€” must miss safely β€” πŸ‘
- [ ] Very large scene scales (numerical precision) β€” πŸ‘
- [ ] Very thin/sliver triangles β€” πŸ‘
- [ ] Backface culling consistency between DX/VK/MTL (combined with `*TriangleFrontFace` and `CULL_*` ray flags) β€” πŸ‘

## Stages other than compute

Inline RT is allowed in every shader stage from SM 6.5 onward. Adding coverage needs the AS-binding plumbing on those pipelines, but the framework already supports each stage individually.

- [ ] `RayQuery` from a pixel shader β€” πŸ—οΈ (PS-side AS binding)
- [ ] `RayQuery` from a vertex shader β€” πŸ—οΈ
- [ ] `RayQuery` from a mesh shader β€” πŸ—οΈ
- [ ] `RayQuery` from a hull / domain / geometry shader β€” πŸ—οΈ

## Framework / YAML follow-ups

Listed inline above where they block tests; aggregated here for the framework worklist. Limited to gaps that block a shader-visible test.

- [ ] YAML `InstanceFlags` field on `AccelerationStructureInstance` πŸ‘€ #1287
- [ ] YAML `InstanceContributionToHitGroupIndex` πŸ‘€ #1286
- [ ] YAML `Transform` on `TriangleGeometryDesc` (per-geometry bake) πŸ‘€ #1288
- [ ] Multiple geometries per BLAS (`Triangles:` is already a list, but exercise it from a shader)
- [ ] AABB / procedural geometry in YAML (descriptors exist, no shader tests) πŸ‘€ #1289
- [ ] Bind AS to non-compute stages

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up β€” it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the existing tests under test/Feature/InlineRT/ and review the bring-up dependencies linked in the checklist, especially the acceleration-structure and binding work. Use the unchecked RayQuery, geometry, instance, control-flow, and shader-stage items to select a narrowly scoped test; completion means adding coverage for that scenario and recording it in this tracking issue.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, yaml
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.