diff options
| author | Theresa Foley <10618364+tangent-vector@users.noreply.github.com> | 2023-06-13 14:40:02 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-06-13 17:40:02 -0400 |
| commit | f161686e8e260a4b0e6e0a773cf1cf16069f41bf (patch) | |
| tree | 1daf16da7f0826eb26cf352b0fab9aa1c61b4327 /tests/pipeline | |
| parent | b255ef068b77a45fdd0b595a555386928a61d56e (diff) | |
Fixes for Shader Execution Reordering on VK (#2929)
* Fixes for Shader Execution Reordering on VK
There are some mismatches between the way that hit objects are
handled between the current NVAPI/HLSL and proposed GLSL extensions
for shader execution reordering. These mismatches create complications
for generating valid GLSL/SPIR-V code from input Slang.
Many of the problems that apply to `HitObject` also apply to the
existing `RayQuery<>` type used for "inline" ray tracing.
In the case of `RayQuery<>` we have that for *both* HLSL and
GLSL/SPIR-V:
* A `RayQuery` (or `rayQueryEXT`) is an opaque handle to underlying
mutable storage
* The storage that backs a `RayQuery` is allocated as part of the
"defualt constructor" for a local variable declared with type
`RayQuery`.
* The `RayQuery` API provides numerous operations that mutate the
storage referred to by the opaque handle.
The key difference between HLSL and GLSL/SPIR-V for the case of a
`RayQuery` amounts to:
* In HLSL, local variables of type `RayQuery` can be assigned to,
and assignment has by-reference semantics. It is possible to create
multiple aliased handles to the same underlying storage.
* In GLSL/SPIR-V, local variables of type `rayQueryEXT` cannot be
assigned to, returned from functions, etc. It is impossible to
create multiple aliased handles to the same underlying storage.
The case for `HitObject`s is signicantly *more* messy, because:
* In NVAPI/HLSL a `HitObject` is effectively a "value type" in that
it only exposes constructors, and there is no way to mutate the
state of a `HitObject` other than by assignment to a variable of that
type. It makes no semantic difference whether a `HitObject` directly
stores the value(s), or if it is a handle, since there is no way
to introduce aliasing of mutable state. Assignment of `HitObject`s
semantically creates a copy.
* In GLSL/SPIR-V, a `hitObjectNV` is, like a `rayQueryEXT`, a handle
to underlying mutable state. These handles cannot be assigned,
returned from functions, etc. There is no way to make a copy of
a hit object.
This change includes several changes to how *both* `RayQuery<>` and
`HitObject` are implemented, with the intention of getting more cases
to work correctly when compiling for GLSL/SPIR-V, and to set up a
more clear mental model for the semantics we want to give to these
types in Slang, and how those semantics can/should map to our targets.
An overview of important changes:
* Marked a few operations on `RayQuery` as `[mutating]` that
realistically should have already been that way.
* Marked the `HitObject` type as being non-copyable (an attribute we
do not currently enforce), and marked the various GLSL operations that
construct a hit object as having an `out` parameter of the `HitObject`
type (even if they are nominally specified in GLSL as not writing
to the correspondign parameter).
* Added a distinct IR opcode (`allocateOpaqueHandle`) to represent the
implicit allocation that happens when declaring a variable of type
`HitObject` or `RayQuery`, and made the "implicit constructor" for
those types map to the new op. This operation took a lot of tweaking
to get emitting in a reasonable way, and I'm still not 100% sure that
all of the emission-related logic for it is strictly required
(or correct).
* Added new IR instructions for `HitObject` and `RayQuery` types, and
made the stdlib types map to those IR instructions.
* Treat `HitObject` and `RayQuery` as resource types for the purpose
of our existing pass that specializes calls to functions that have
outputs of resource type
* Added a new test case that includes a function that returns a
`HitObject` as its result.
* Many test cases saw slight changes in their output (especially around
the relative ordering of declarations of `HitObject`s and `RayQuery`s
with other instructions)
* Remove debugging logic
Diffstat (limited to 'tests/pipeline')
| -rw-r--r-- | tests/pipeline/ray-tracing/trace-ray-inline.slang | 4 | ||||
| -rw-r--r-- | tests/pipeline/ray-tracing/trace-ray-inline.slang.glsl | 138 | ||||
| -rw-r--r-- | tests/pipeline/ray-tracing/trace-ray-inline.slang.hlsl | 118 |
3 files changed, 21 insertions, 239 deletions
diff --git a/tests/pipeline/ray-tracing/trace-ray-inline.slang b/tests/pipeline/ray-tracing/trace-ray-inline.slang index e952bb802..23ec90885 100644 --- a/tests/pipeline/ray-tracing/trace-ray-inline.slang +++ b/tests/pipeline/ray-tracing/trace-ray-inline.slang @@ -1,7 +1,7 @@ // trace-ray-inline.slang -//TEST:CROSS_COMPILE:-target dxil-asm -stage compute -profile sm_6_5 -entry main -//TEST:CROSS_COMPILE:-target spirv-asm -stage compute -profile glsl_460+spirv_1_4 -entry main +//TEST:CROSS_COMPILE:-target dxil-asm -stage compute -profile sm_6_5 -entry main -line-directive-mode none +//TEST:CROSS_COMPILE:-target spirv-asm -stage compute -profile glsl_460+spirv_1_4 -entry main -line-directive-mode none // The goal of this shader is to use all the main pieces // of functionality in DXR 1.1's `TraceRayInline` feature, diff --git a/tests/pipeline/ray-tracing/trace-ray-inline.slang.glsl b/tests/pipeline/ray-tracing/trace-ray-inline.slang.glsl index 56926e956..e1a54a30a 100644 --- a/tests/pipeline/ray-tracing/trace-ray-inline.slang.glsl +++ b/tests/pipeline/ray-tracing/trace-ray-inline.slang.glsl @@ -3,8 +3,6 @@ #extension GL_EXT_ray_query : require layout(row_major) uniform; layout(row_major) buffer; - -#line 91 "tests/pipeline/ray-tracing/trace-ray-inline.slang" struct SLANG_ParameterGroup_C_0 { vec3 origin_0; @@ -16,8 +14,6 @@ struct SLANG_ParameterGroup_C_0 uint shouldStopAtFirstHit_0; }; - -#line 91 layout(binding = 2) layout(std140) uniform _S1 { @@ -29,267 +25,159 @@ layout(std140) uniform _S1 uint instanceMask_0; uint shouldStopAtFirstHit_0; }C_0; - -#line 12 layout(binding = 0) uniform accelerationStructureEXT myAccelerationStructure_0; - -#line 86 layout(std430, binding = 1) buffer _S2 { int _data[]; } resultBuffer_0; - -#line 59 struct MyProceduralHitAttrs_0 { int value_0; }; - -#line 81 bool myProceduralIntersection_0(inout float tHit_0, inout MyProceduralHitAttrs_0 hitAttrs_0) { return true; } - -#line 26 struct MyRayPayload_0 { int value_1; }; - -#line 69 bool myProceduralAnyHit_0(inout MyRayPayload_0 payload_0) { return true; } - -#line 51 bool myTriangleAnyHit_0(inout MyRayPayload_0 payload_1) { return true; } - -#line 40 void myTriangleClosestHit_0(inout MyRayPayload_0 payload_2) { payload_2.value_1 = 1; return; } - -#line 65 void myProceduralClosestHit_0(inout MyRayPayload_0 payload_3, MyProceduralHitAttrs_0 attrs_0) { payload_3.value_1 = attrs_0.value_0; return; } - -#line 33 void myMiss_0(inout MyRayPayload_0 payload_4) { payload_4.value_1 = 0; return; } - -#line 105 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; void main() { - -#line 107 uint index_0 = gl_GlobalInvocationID.x; - -#line 112 + rayQueryEXT query_0; MyRayPayload_0 payload_5; - -#line 112 payload_5.value_1 = -1; - -#line 109 - rayQueryEXT query_0; - -#line 114 rayQueryInitializeEXT((query_0), (myAccelerationStructure_0), (C_0.rayFlags_0 | 512), (C_0.instanceMask_0), (C_0.origin_0), (C_0.tMin_0), (C_0.direction_0), (C_0.tMax_0)); - -#line 114 MyProceduralHitAttrs_0 committedProceduralAttrs_0; - -#line 114 for(;;) { - -#line 123 bool _S3 = rayQueryProceedEXT(query_0); - -#line 123 if(!_S3) { - -#line 123 break; } - -#line 123 + uint _S4 = (rayQueryGetIntersectionTypeEXT((query_0), false)); MyProceduralHitAttrs_0 committedProceduralAttrs_1; - - switch((rayQueryGetIntersectionTypeEXT((query_0), false))) + switch(_S4) { case 1U: { MyProceduralHitAttrs_0 candidateProceduralAttrs_0; - -#line 129 candidateProceduralAttrs_0.value_0 = 0; float tHit_1 = 0.0; - bool _S4 = myProceduralIntersection_0(tHit_1, candidateProceduralAttrs_0); - -#line 131 - if(_S4) + bool _S5 = myProceduralIntersection_0(tHit_1, candidateProceduralAttrs_0); + if(_S5) { - bool _S5 = myProceduralAnyHit_0(payload_5); - -#line 133 - if(_S5) + bool _S6 = myProceduralAnyHit_0(payload_5); + if(_S6) { rayQueryGenerateIntersectionEXT(query_0, tHit_1); - MyProceduralHitAttrs_0 _S6 = candidateProceduralAttrs_0; + MyProceduralHitAttrs_0 _S7 = candidateProceduralAttrs_0; if(C_0.shouldStopAtFirstHit_0 != 0U) { - -#line 138 rayQueryTerminateEXT(query_0); - -#line 137 } else { - -#line 137 } - -#line 137 - committedProceduralAttrs_1 = _S6; - -#line 137 + committedProceduralAttrs_1 = _S7; } else { - -#line 137 committedProceduralAttrs_1 = committedProceduralAttrs_0; - -#line 137 } - -#line 137 } else { - -#line 137 committedProceduralAttrs_1 = committedProceduralAttrs_0; - -#line 137 } - -#line 137 break; } case 0U: { - -#line 146 - bool _S7 = myTriangleAnyHit_0(payload_5); - -#line 146 - if(_S7) + bool _S8 = myTriangleAnyHit_0(payload_5); + if(_S8) { rayQueryConfirmIntersectionEXT(query_0); if(C_0.shouldStopAtFirstHit_0 != 0U) { - -#line 150 rayQueryTerminateEXT(query_0); - -#line 149 } else { - -#line 149 } - -#line 146 } else { - -#line 146 } - -#line 146 committedProceduralAttrs_1 = committedProceduralAttrs_0; - -#line 146 break; } default: { - -#line 146 committedProceduralAttrs_1 = committedProceduralAttrs_0; - -#line 146 break; } } - -#line 121 committedProceduralAttrs_0 = committedProceduralAttrs_1; - -#line 121 } - -#line 160 - switch((rayQueryGetIntersectionTypeEXT((query_0), true))) + uint _S9 = (rayQueryGetIntersectionTypeEXT((query_0), true)); + switch(_S9) { case 1U: { - -#line 163 myTriangleClosestHit_0(payload_5); break; } case 2U: { - -#line 167 myProceduralClosestHit_0(payload_5, committedProceduralAttrs_0); break; } case 0U: { - -#line 171 myMiss_0(payload_5); break; } default: { - -#line 172 break; } } ((resultBuffer_0)._data[(index_0)]) = payload_5.value_1; return; } - diff --git a/tests/pipeline/ray-tracing/trace-ray-inline.slang.hlsl b/tests/pipeline/ray-tracing/trace-ray-inline.slang.hlsl index e96cbb8f4..bf10cc2e1 100644 --- a/tests/pipeline/ray-tracing/trace-ray-inline.slang.hlsl +++ b/tests/pipeline/ray-tracing/trace-ray-inline.slang.hlsl @@ -1,11 +1,5 @@ #pragma pack_matrix(column_major) -#ifdef SLANG_HLSL_ENABLE_NVAPI -#include "nvHLSLExtns.h" -#endif -#pragma warning(disable: 3557) - -#line 91 "tests/pipeline/ray-tracing/trace-ray-inline.slang" struct SLANG_ParameterGroup_C_0 { float3 origin_0; @@ -17,272 +11,172 @@ struct SLANG_ParameterGroup_C_0 uint shouldStopAtFirstHit_0; }; - -#line 91 cbuffer C_0 : register(b0) { SLANG_ParameterGroup_C_0 C_0; } -#line 12 RaytracingAccelerationStructure myAccelerationStructure_0 : register(t0); - -#line 86 RWStructuredBuffer<int > resultBuffer_0 : register(u0); - -#line 59 struct MyProceduralHitAttrs_0 { int value_0; }; - -#line 81 bool myProceduralIntersection_0(inout float tHit_0, inout MyProceduralHitAttrs_0 hitAttrs_0) { return true; } - -#line 26 struct MyRayPayload_0 { int value_1; }; - -#line 69 bool myProceduralAnyHit_0(inout MyRayPayload_0 payload_0) { return true; } - -#line 51 bool myTriangleAnyHit_0(inout MyRayPayload_0 payload_1) { return true; } - -#line 40 void myTriangleClosestHit_0(inout MyRayPayload_0 payload_2) { payload_2.value_1 = int(1); return; } - -#line 65 void myProceduralClosestHit_0(inout MyRayPayload_0 payload_3, MyProceduralHitAttrs_0 attrs_0) { payload_3.value_1 = attrs_0.value_0; return; } - -#line 33 void myMiss_0(inout MyRayPayload_0 payload_4) { payload_4.value_1 = int(0); return; } - -#line 105 [shader("compute")][numthreads(1, 1, 1)] void main(uint3 tid_0 : SV_DISPATCHTHREADID) { - -#line 107 uint index_0 = tid_0.x; + RayQuery<int(512) > query_0; -#line 112 MyRayPayload_0 payload_5; - -#line 112 payload_5.value_1 = int(-1); - RayDesc ray_0 = { C_0.origin_0, C_0.tMin_0, C_0.direction_0, C_0.tMax_0 }; -#line 109 - RayQuery<int(512) > query_0; + RayDesc ray_0 = { C_0.origin_0, C_0.tMin_0, C_0.direction_0, C_0.tMax_0 }; -#line 114 query_0.TraceRayInline(myAccelerationStructure_0, C_0.rayFlags_0, C_0.instanceMask_0, ray_0); -#line 114 MyProceduralHitAttrs_0 committedProceduralAttrs_0; -#line 114 for(;;) { -#line 123 bool _S1 = query_0.Proceed(); -#line 123 if(!_S1) { -#line 123 break; } -#line 123 MyProceduralHitAttrs_0 committedProceduralAttrs_1; - switch(query_0.CandidateType()) { case 1U: { MyProceduralHitAttrs_0 candidateProceduralAttrs_0; - -#line 129 candidateProceduralAttrs_0.value_0 = int(0); + float tHit_1 = 0.0; bool _S2 = myProceduralIntersection_0(tHit_1, candidateProceduralAttrs_0); - -#line 131 if(_S2) { bool _S3 = myProceduralAnyHit_0(payload_5); - -#line 133 if(_S3) { query_0.CommitProceduralPrimitiveHit(tHit_1); MyProceduralHitAttrs_0 _S4 = candidateProceduralAttrs_0; if(C_0.shouldStopAtFirstHit_0 != 0U) { - -#line 138 query_0.Abort(); - -#line 137 } else - { - -#line 137 - } + {} -#line 137 committedProceduralAttrs_1 = _S4; - -#line 137 } else { - -#line 137 committedProceduralAttrs_1 = committedProceduralAttrs_0; - -#line 137 } - -#line 137 } else { - -#line 137 committedProceduralAttrs_1 = committedProceduralAttrs_0; - -#line 137 } - -#line 137 break; } case 0U: { - -#line 146 bool _S5 = myTriangleAnyHit_0(payload_5); - -#line 146 if(_S5) { query_0.CommitNonOpaqueTriangleHit(); if(C_0.shouldStopAtFirstHit_0 != 0U) { - -#line 150 query_0.Abort(); - -#line 149 } else - { - -#line 149 - } - -#line 146 + {} } else - { - -#line 146 - } + {} -#line 146 committedProceduralAttrs_1 = committedProceduralAttrs_0; - -#line 146 break; } default: { - -#line 146 committedProceduralAttrs_1 = committedProceduralAttrs_0; - -#line 146 break; } } -#line 121 committedProceduralAttrs_0 = committedProceduralAttrs_1; - -#line 121 } -#line 160 switch(query_0.CommittedStatus()) { case 1U: { - -#line 163 myTriangleClosestHit_0(payload_5); break; } case 2U: { - -#line 167 myProceduralClosestHit_0(payload_5, committedProceduralAttrs_0); break; } case 0U: { - -#line 171 myMiss_0(payload_5); break; } default: { - -#line 172 break; } } resultBuffer_0[index_0] = payload_5.value_1; return; } - |
