-
Notifications
You must be signed in to change notification settings - Fork 51
[NNNN] ClusterID() support #630
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
41541e8
HLSL and DXIL support for ClusterID intrinsic
jenatali 203c33f
Apply suggestions from code review
jenatali 5835ba6
Additional PR feedback
jenatali 839a33a
Add shader stage validation comment
jenatali 3bd0d19
Assign 0045
jenatali 316878a
Add a note about CLUSTER_ID_INVALID always being supported
jenatali File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,274 @@ | ||
| --- | ||
| title: 0045 - HLSL support for Clustered Geometry in Raytracing | ||
| params: | ||
| authors: | ||
| - jschmid-nvidia: Jan Schmid | ||
| - simoll: Simon Moll | ||
| sponsors: | ||
| - jenatali: Jesse Natalie | ||
| status: Under Review | ||
| --- | ||
|
|
||
| ## Introduction | ||
|
|
||
| Acceleration structure build times can become a bottleneck in raytracing | ||
| applications that require large amounts of dynamic geometry. Example scenarios | ||
| include new geometry being streamed in from disk, high numbers of animated | ||
| objects, level-of-detail systems, or dynamic tessellation. | ||
|
|
||
| Clustered Geometry is a proposed future DXR feature that aims to address this | ||
| issue by enabling the application to construct bottom-level acceleration structures | ||
| from previously generated clusters of primitives, resulting in significant speedups | ||
| in acceleration structure build times. The DXR spec details for this are not available | ||
| yet, but as an example for now see [NVIDIA's blog](https://developer.nvidia.com/blog/nvidia-rtx-mega-geometry-now-available-with-new-vulkan-samples/) describing the overall concept of clustered | ||
| geometry (among other topics). | ||
|
|
||
| How clustered geometry gets exposed in D3D overall is to be determined but this document is | ||
| certainly a part: a proposal for the HLSL operations needed for clustered geometry. | ||
|
|
||
| ## Motivation | ||
|
|
||
| Clustered Geometry refers to a building block for Bottom Level Acceleration Structures | ||
| (BLASes). Most of the details of what a cluster is are out of scope for this spec. | ||
| What's relevant is that the application can build BLASes out of cluster building | ||
| blocks. When raytracing, hit shaders will want to know the ID of the cluster that is hit | ||
| so the shader can do things like look up cluster-specific user data. Hence the need for a `ClusterID()` intrinsic. | ||
|
|
||
| This isn't an index into the clusters in a given BLAS but rather an ID assigned by | ||
| the user for each cluster in a BLAS. Different BLASs could reuse simmilar building blocks, and | ||
| thus share cluster ID. | ||
|
|
||
| ## HLSL | ||
|
|
||
| ### Enums | ||
|
|
||
| ```C | ||
| enum CLUSTER_ID_CONSTANTS : uint | ||
| { | ||
| CLUSTER_ID_INVALID = 0xffffffff, | ||
| }; | ||
| ``` | ||
|
|
||
| ClusterID values returned by [ClusterID()](#clusterid) with predefined meaning | ||
|
|
||
| Value | Definition | ||
| ----- | ---- | ||
| `CLUSTER_ID_INVALID` | Returned if a BLAS was intersected that was not constructed from CLAS | ||
|
|
||
| ### DXR 1.0 System Value Intrinsics | ||
|
|
||
| A new DXR System Value Intrinsic is added to support fetching the `ClusterID` of an intersected CLAS. | ||
|
|
||
| #### ClusterID | ||
|
|
||
| ```C | ||
| uint ClusterID() | ||
| ``` | ||
|
|
||
| Returns a `uint` containing the user-defined `ClusterID` value a CLAS was | ||
| built with. If a non-clustered BLAS was intersected, `CLUSTER_ID_INVALID` | ||
| is returned. | ||
|
|
||
| The following table shows which shaders can access it: | ||
| | **values \\ shaders** | ray generation | intersection | any hit | closest hit | miss | callable | | ||
| |:---------------------------------------------------------:|:--------------:|:------------:|:-------:|:-----------:|:----:|:--------:| | ||
| | *Primitive/object space system values:* | | | | | | | | ||
| | uint [ClusterID()](#clusterid) | | | \* | \* | | | | ||
|
|
||
| ## Extension to DXR 1.1 RayQuery API | ||
|
|
||
| New intrinsics [CandidateClusterID()](#rayquery-candidateclusterid) and | ||
| [CommittedClusterID()](#rayquery-committedclusterid) are added to `RayQuery`. | ||
| Behavior of all other intrinsics is unchanged. | ||
|
|
||
| ### RayQuery intrinsics | ||
|
|
||
| The following table lists intrinsics available when | ||
| [RayQuery::Proceed()](https://github.com/microsoft/DirectX-Specs/blob/master/d3d/Raytracing.md#rayquery-proceed) returned `TRUE`, | ||
| meaning a type of hit candidate that requires shader evaluation has been found. | ||
| Methods named `Committed*()` in this table may actually not be available | ||
| depending on the current [CommittedStatus()](https://github.com/microsoft/DirectX-Specs/blob/master/d3d/Raytracing.md#rayquery-committedstatus) | ||
| (i.e. what type of hit has been committed yet, if any) - this is further | ||
| clarified in another table further below. | ||
|
|
||
| | **Intrinsic** \ **CandidateType()** | `HIT_CANDIDATE_NON_OPAQUE_TRIANGLE` | `HIT_CANDIDATE_PROCEDURAL_PRIMITIVE` | | ||
| |:---------------------------------------------------------|:-----------------------------------:|:------------------------------------:| | ||
| | uint [CandidateClusterID()](#rayquery-candidateclusterid)| \* | | | ||
| | uint [CommittedClusterID()](#rayquery-committedclusterid)| \* | | | ||
|
|
||
| The following table lists intrinsics available depending on the current | ||
| [COMMITTED_STATUS](https://github.com/microsoft/DirectX-Specs/blob/master/d3d/Raytracing.md#committed_status) (i.e. what type of | ||
| hit has been committed, if any). This applies regardless of whether | ||
| [RayQuery::Proceed()](https://github.com/microsoft/DirectX-Specs/blob/master/d3d/Raytracing.md#rayquery-proceed) has returned | ||
| `TRUE` (shader evaluation needed for traversal), or `FALSE` (traversal | ||
| complete). If `TRUE`, additional methods than those shown below are | ||
| available (see the above table). | ||
|
|
||
| | **Intrinsic** \ **CommittedStatus()** | `COMMITTED_TRIANGLE_HIT` | `COMMITTED_PROCEDURAL_PRIMITIVE_HIT` | `COMMITTED_NOTHING` | | ||
| |:---------------------------------------------------------|:------------------------:|:------------------------------------:|:-------------------:| | ||
| | uint [CommittedClusterID()](#rayquery-committedclusterid)| \* | | | | ||
|
|
||
| #### RayQuery CandidateClusterID | ||
|
|
||
| The user-provided `ClusterID` of the intersected CLAS, if a Cluster BLAS was | ||
| intersected for the current hit candidate. | ||
| Returns `CLUSTER_ID_INVALID` if a non-Cluster BLAS was intersected. | ||
|
|
||
| ```C++ | ||
| uint RayQuery::CandidateClusterID(); | ||
| ``` | ||
|
|
||
| [RayQuery intrinsics](#rayquery-intrinsics) illustrates when this is valid to | ||
| call. | ||
| Lowers to [RayQuery_CandidateClusterID DXIL Opcode](#rayquery_candidateclusterid-dxil-opcode). | ||
|
|
||
| #### RayQuery CommittedClusterID | ||
|
|
||
| The user-provided `ClusterID` of the intersected CLAS, if a Cluster BLAS was | ||
| intersected for the closest hit committed so far. | ||
| Returns `CLUSTER_ID_INVALID` if a non-Cluster BLAS was intersected. | ||
|
|
||
| ```C++ | ||
| uint RayQuery::CommittedClusterID(); | ||
| ``` | ||
|
|
||
| [RayQuery intrinsics](#rayquery-intrinsics) illustrates when this is valid to | ||
| call. | ||
| Lowers to [RayQuery_CommittedClusterID DXIL Opcode](#rayquery_committedclusterid-dxil-opcode). | ||
|
|
||
| ### Extension to the DXR 1.2 HitObject API | ||
|
|
||
| Cluster Geometries are also supported with the HitObject feature. | ||
| The following intrinsic is added to `HitObject` type. | ||
|
|
||
| #### HitObject::GetClusterID | ||
|
|
||
| ```C | ||
| uint HitObject::GetClusterID(); | ||
| ``` | ||
|
|
||
| Returns the user-provided `ClusterID` of the intersected CLAS of a hit. | ||
| Returns `CLUSTER_ID_INVALID` if a non-Cluster BLAS was intersected or if | ||
| the `HitObject` does not encode a hit. | ||
| Lowers to [HitObject_ClusterID DXIL Opcode](#hitobject_clusterid-dxil-opcode). | ||
|
|
||
| ### Diagnostic Changes | ||
|
|
||
| This proposal does not introduce or remove diagnostics or warnings. | ||
|
|
||
| ## Testing | ||
|
|
||
| ### Unit Tests | ||
|
|
||
| #### CodeGen & AST Tests | ||
|
|
||
| * Expected AST for new implicit HLSL ops. | ||
| * Lowering from HLSL to HL. | ||
| * Lowering from HL to DXIL. | ||
| * Lowering from HLSL to DXIL. | ||
|
|
||
| #### Diagnostics Tests | ||
|
|
||
| * Expected error when ClusterID builtins called from unsupported shader kinds. | ||
|
|
||
| ### DXIL | ||
|
|
||
| | Opcode | Opcode name | Description | ||
| |:--- |:--- |:--- | ||
| XXX | ClusterID | Returns the cluster ID of this hit | ||
| XXX + 1 | RayQuery_CandidateClusterID | Returns the candidate hit cluster ID | ||
| XXX + 2 | RayQuery_CommittedClusterID | Returns the committed hit cluster ID | ||
| XXX + 2 | HitObject_ClusterID | Returns the cluster ID of this committed hit | ||
|
|
||
| #### ClusterID DXIL Opcode | ||
|
|
||
| ```DXIL | ||
| declare i32 @dx.op.clusterID( | ||
| i32) ; Opcode (ClusterID) | ||
| nounwind readnone | ||
| ``` | ||
|
|
||
| Valid shader kinds defined in [ClusterID HLSL](#clusterid). | ||
|
|
||
| #### RayQuery_CandidateClusterID DXIL Opcode | ||
|
|
||
| ```DXIL | ||
| declare i32 @dx.op.rayQuery_StateScalar.i32( | ||
| i32, ; Opcode (RayQuery_CandidateClusterID) | ||
| i32) ; RayQuery handle | ||
| nounwind readonly | ||
| ``` | ||
|
|
||
| Validation errors: | ||
| * Validate that the RayQuery handle is not `undef`. | ||
|
|
||
| #### RayQuery_CommittedClusterID DXIL Opcode | ||
|
|
||
| ```DXIL | ||
| declare i32 @dx.op.rayQuery_StateScalar.i32( | ||
| i32, ; Opcode (RayQuery_CommittedClusterID) | ||
| i32) ; RayQuery handle | ||
| nounwind readonly | ||
| ``` | ||
|
|
||
| Validation errors: | ||
| * Validate that the RayQuery handle is not `undef`. | ||
|
|
||
| #### HitObject_ClusterID DXIL Opcode | ||
|
|
||
| ```DXIL | ||
| declare i32 @dx.op.hitObject_StateScalar.i32( | ||
| i32, ; Opcode (HitObject_ClusterID) | ||
| %dx.types.HitObject) ; HitObject | ||
| nounwind readnone | ||
| ``` | ||
|
|
||
| Validation errors: | ||
| * Validate that the HitObject is not `undef`. | ||
|
|
||
| ### Diagnostic Changes | ||
|
|
||
| This proposal does not introduce or remove diagnostics or warnings. | ||
|
|
||
| ### Runtime Additions | ||
jenatali marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| TODO: link the DXR spec proposal when available | ||
|
|
||
| Note: No unique raytracing tier is required to use this intrinsic. If the device does not support clustered geometry, it must still support returning `CLUSTER_ID_INVALID` from this intrinsic. | ||
|
|
||
| ## Testing | ||
|
|
||
| ### Validation Tests | ||
|
|
||
| * Valid calls to new DXIL ops pass validation. | ||
| * Invalid calls fail validation (undef `i32` RayQuery handle or `%dx.types.HitObject` HitObject parameter). | ||
jenatali marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| * Calls in invalid shader stages fail validation. | ||
|
|
||
| ### Execution Tests | ||
|
|
||
| #### ClusterID Execution Tests | ||
|
|
||
| Test in both `anyhit` and `closesthit` shader kinds. | ||
|
|
||
| * Query for CLAS hit returns expected Cluster ID. | ||
| * Query for non-clustered BLAS hit returns `CLUSTER_ID_INVALID`. | ||
|
|
||
| #### RayQuery Execution Tests | ||
|
|
||
| Test both [RayQuery::CandidateClusterID](#rayquery-candidateclusterid) and [RayQuery::CommittedClusterID](#rayquery-committedclusterid). | ||
| Builtins to test in the these RayQuery object states: | ||
|
|
||
| * Queries for CLAS committed hits return expected Cluster ID (`COMMITTED_TRIANGLE_HIT`). | ||
| * Query for committed cluster ID in no-hit-committed state returns `CLUSTER_ID_INVALID`. | ||
| * Queries for candidate cluster ID for CLAS candidate hits return expected Cluster ID (`CANDIDATE_NON_OPAQUE_TRIANGLE` and when first call to `Proceed` returns `FALSE` ). | ||
| * Queries for non-clustered BLAS candidate/committed hits return `CLUSTER_ID_INVALID`. | ||
|
|
||
| #### HitObject Execution Tests | ||
|
|
||
| Test CLAS and non-CLAS hit return expected values for candidate hit. | ||
| Builtin [HitObject::GetClusterID](#hitobjectgetclusterid) to test in these HitObject setups: | ||
|
|
||
| * Add `HitObject::FromRayQuery` + `HitObject::GetClusterID` variants in [RayQuery execution tests](#rayquery-execution-tests). | ||
| * Test expected cluster ID value for HitObject obtained from `HitObject::TraceRay` (CLAS hit, CLAS miss, non-CLAS hit). | ||
| * Test `CLUSTER_ID_INVALID` for HitObject constructed from `HitObject::MakeMiss` and `HitObject::MakeNop`. | ||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.