summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang/hlsl.meta.slang197
-rw-r--r--source/slang/slang-emit-glsl.cpp44
-rw-r--r--source/slang/slang.natvis26
-rw-r--r--tests/pipeline/ray-tracing/trace-ray-inline.slang172
-rw-r--r--tests/pipeline/ray-tracing/trace-ray-inline.slang.glsl219
-rw-r--r--tests/pipeline/ray-tracing/trace-ray-inline.slang.hlsl238
6 files changed, 873 insertions, 23 deletions
diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang
index 77b371662..761016866 100644
--- a/source/slang/hlsl.meta.slang
+++ b/source/slang/hlsl.meta.slang
@@ -4678,6 +4678,9 @@ static const CANDIDATE_TYPE CANDIDATE_PROCEDURAL_PRIMITIVE = 1;
// back to the user code at interesting events along the ray.
//
__target_intrinsic(hlsl, RayQuery)
+__target_intrinsic(glsl, rayQueryEXT)
+__glsl_extension(GL_EXT_ray_query)
+__glsl_version(460)
struct RayQuery <let rayFlags : RAY_FLAG = RAY_FLAG_NONE>
{
// Initialize the query object in a "fresh" state.
@@ -4697,7 +4700,42 @@ struct RayQuery <let rayFlags : RAY_FLAG = RAY_FLAG_NONE>
// `RayQuery` to get the effective ray flags, which
// must obey any API-imposed restrictions.
//
- void TraceRayInline(RaytracingAccelerationStructure accelerationStructure, RAY_FLAG rayFlags, uint instanceInclusionMask, RayDesc ray);
+ __target_intrinsic(hlsl)
+ void TraceRayInline(
+ RaytracingAccelerationStructure accelerationStructure,
+ RAY_FLAG rayFlags,
+ uint instanceInclusionMask,
+ RayDesc ray);
+
+ __target_intrinsic(glsl, "rayQueryInitializeEXT($0, $1, $2, $3, $4, $5, $6, $7)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
+ void __rayQueryInitializeEXT(
+ RaytracingAccelerationStructure accelerationStructure,
+ RAY_FLAG rayFlags,
+ uint instanceInclusionMask,
+ float3 origin,
+ float tMin,
+ float3 direction,
+ float tMax);
+
+ [__unsafeForceInlineEarly]
+ __specialized_for_target(glsl)
+ void TraceRayInline(
+ RaytracingAccelerationStructure accelerationStructure,
+ RAY_FLAG rayFlags,
+ uint instanceInclusionMask,
+ RayDesc ray)
+ {
+ __rayQueryInitializeEXT(
+ accelerationStructure,
+ rayFlags,
+ instanceInclusionMask,
+ ray.Origin,
+ ray.TMin,
+ ray.Direction,
+ ray.TMax);
+ }
// Resume the ray query coroutine.
//
@@ -4713,6 +4751,9 @@ struct RayQuery <let rayFlags : RAY_FLAG = RAY_FLAG_NONE>
// functions to appropriately handle the closest hit (it any)
// that was found.
//
+ __target_intrinsic(glsl, rayQueryProceedEXT)
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
bool Proceed();
// Causes the ray query to terminate.
@@ -4721,6 +4762,9 @@ struct RayQuery <let rayFlags : RAY_FLAG = RAY_FLAG_NONE>
// traversal has terminated, so that subsequent
// `Proceed()` calls will return `false`.
//
+ __target_intrinsic(glsl, rayQueryTerminateEXT)
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
void Abort();
// Get the type of candidate hit being considered.
@@ -4732,73 +4776,210 @@ struct RayQuery <let rayFlags : RAY_FLAG = RAY_FLAG_NONE>
// the kind of candidate hit that must be resolved by
// user code.
//
+ __target_intrinsic(glsl, "rayQueryGetIntersectionTypeEXT($0, false)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
CANDIDATE_TYPE CandidateType();
// Access properties of a candidate hit.
- //
+
+ __target_intrinsic(glsl, "transpose(rayQueryGetIntersectionObjectToWorldEXT($0, false))")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
float3x4 CandidateObjectToWorld3x4();
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionObjectToWorldEXT($0, false)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
float4x3 CandidateObjectToWorld4x3();
+
+ __target_intrinsic(glsl, "transpose(rayQueryGetIntersectionWorldToObjectEXT($0, false))")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
float3x4 CandidateWorldToObject3x4();
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionWorldToObjectEXT($0, false)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
float4x3 CandidateWorldToObject4x3();
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionInstanceCustomIndexEXT($0, false)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
uint CandidateInstanceIndex();
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionInstanceIdEXT($0, false)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
uint CandidateInstanceID();
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionGeometryIndexEXT($0, false)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
uint CandidateGeometryIndex();
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionPrimitiveIndexEXT($0, false)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
uint CandidatePrimitiveIndex();
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT($0, false)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
uint CandidateInstanceContributionToHitGroupIndex();
// Access properties of the ray being traced
// in the object space of a candidate hit.
- //
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionObjectRayOriginEXT($0, false)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
float3 CandidateObjectRayOrigin();
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionObjectRayDirectionEXT($0, false)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
float3 CandidateObjectRayDirection();
// Access properties of a candidate procedural primitive hit.
- //
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionCandidateAABBOpaqueEXT($0, false)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
bool CandidateProceduralPrimitiveNonOpaque();
- // Access properties of a candidate no-opaque triangle hit.
- //
+ // Access properties of a candidate non-opaque triangle hit.
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionFrontFaceEXT($0, false)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
bool CandidateTriangleFrontFace();
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionBarycentricsEXT($0, false)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
float2 CandidateTriangleBarycentrics();
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionTEXT($0, false)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
float CandidateTriangleRayT();
// Commit the current non-opaque triangle hit.
+ __target_intrinsic(glsl, rayQueryConfirmIntersectionEXT)
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
void CommitNonOpaqueTriangleHit();
// Commit the current procedural primitive hit, with hit time `t`.
+ __target_intrinsic(glsl, rayQueryGenerateIntersectionEXT)
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
void CommitProceduralPrimitiveHit(float t);
// Get the status of the committed (closest) hit, if any.
+ __target_intrinsic(glsl, "rayQueryGetIntersectionTypeEXT($0, true)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
COMMITTED_STATUS CommittedStatus();
// Access properties of the committed hit.
//
+ __target_intrinsic(glsl, "transpose(rayQueryGetIntersectionObjectToWorldEXT($0, true))")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
float3x4 CommittedObjectToWorld3x4();
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionObjectToWorldEXT($0, true)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
float4x3 CommittedObjectToWorld4x3();
+
+ __target_intrinsic(glsl, "transpose(rayQueryGetIntersectionWorldToObjectEXT($0, true))")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
float3x4 CommittedWorldToObject3x4();
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionWorldToObjectEXT($0, true)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
float4x3 CommittedWorldToObject4x3();
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionTEXT($0, true)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
float CommittedRayT();
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionInstanceCustomIndexEXT($0, true)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
uint CommittedInstanceIndex();
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionInstanceIdEXT($0, true)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
uint CommittedInstanceID();
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionGeometryIndexEXT($0, true)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
uint CommittedGeometryIndex();
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionPrimitiveIndexEXT($0, true)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
uint CommittedPrimitiveIndex();
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT($0, true)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
uint CommittedInstanceContributionToHitGroupIndex();
// Access properties of the ray being traced
// in the object space of a committed hit.
- //
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionObjectRayOriginEXT($0, true)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
float3 CommittedObjectRayOrigin();
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionObjectRayDirectionEXT($0, true)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
float3 CommittedObjectRayDirection();
// Access properties of a committed triangle hit.
- //
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionFrontFaceEXT($0, true)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
bool CommittedTriangleFrontFace();
+
+ __target_intrinsic(glsl, "rayQueryGetIntersectionBarycentricsEXT($0, true)")
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
float2 CommittedTriangleBarycentrics();
// Access properties of the ray being traced.
+
+ __target_intrinsic(glsl, rayQueryGetRayFlagsEXT)
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
uint RayFlags();
+
+ __target_intrinsic(glsl, rayQueryGetWorldRayOriginEXT)
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
float3 WorldRayOrigin();
+
+ __target_intrinsic(glsl, rayQueryGetWorldRayDirectionEXT)
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
float3 WorldRayDirection();
+
+ __target_intrinsic(glsl, rayQueryGetRayTMinEXT)
+ __glsl_extension(GL_EXT_ray_query)
+ __glsl_version(460)
float RayTMin();
}
diff --git a/source/slang/slang-emit-glsl.cpp b/source/slang/slang-emit-glsl.cpp
index 7b784de8d..fb4417119 100644
--- a/source/slang/slang-emit-glsl.cpp
+++ b/source/slang/slang-emit-glsl.cpp
@@ -95,6 +95,7 @@ void GLSLSourceEmitter::_requireGLSLVersion(int version)
CASE(430);
CASE(440);
CASE(450);
+ CASE(460);
#undef CASE
}
@@ -1801,14 +1802,46 @@ void GLSLSourceEmitter::emitSimpleTypeImpl(IRType* type)
{
case kIROp_RaytracingAccelerationStructureType:
{
- _requireRayTracing();
-
+ // Note: We have the problem here that we want to do `_requireRayTracing()`,
+ // but just based on the use of a ray-tracing acceleration structure we
+ // cannot know which extension the user means to use. The current options are:
+ //
+ // * GL_NV_ray_tracing
+ // * GL_EXT_ray_tracing
+ // * GL_EXT_ray_query
+ //
+ // The first two options there are basically equivalent extensions with
+ // different GLSL syntax. We end up requiring the user to opt in to
+ // `GL_NV_ray_tracing` using target capabilities, and will always default
+ // to `GL_EXT_ray_tracing` otherwise.
+ //
if( getTargetCaps().implies(CapabilityAtom::GL_NV_ray_tracing) )
{
+ // If the user has explicitly opted in to `GL_NV_ray_tracing`,
+ // then we don't need to explicitly request the extentsion again.
+ // We know that the acceleration structure type will translate
+ // to the one from that extension:
+ //
m_writer->emit("accelerationStructureNV");
}
else
{
+ // If the user does *not* opt into a specific extension, then we
+ // have the problem that either `GL_EXT_ray_tracing` or `GL_EXT_ray-query`
+ // could provide the `accelerationSturctureEXT` type, but there
+ // can be drivers that provide only one and not the other.
+ //
+ // Because we can't pick one upon just seeing the type, we need to
+ // emit the type here but *not* call `_requireRayTracing()` or
+ // anything like it, because we don't yet know the specific extension
+ // we should ask for.
+ //
+ // TODO: We might eventually want to have this step set a flag that
+ // will cause a compilation error if nothing else in the code requires
+ // a specific concrete ray-tracing extension. Ideally all of these
+ // details could be subusmed under the capability system sooner or
+ // later.
+ //
m_writer->emit("accelerationStructureEXT");
}
break;
@@ -1827,6 +1860,13 @@ void GLSLSourceEmitter::emitSimpleTypeImpl(IRType* type)
return;
}
+ auto decorated = getResolvedInstForDecorations(type);
+ if(auto targetIntrinsicDecor = findBestTargetIntrinsicDecoration(decorated))
+ {
+ m_writer->emit(targetIntrinsicDecor->getDefinition());
+ return;
+ }
+
SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled type");
}
diff --git a/source/slang/slang.natvis b/source/slang/slang.natvis
index 63ee313da..cb272f974 100644
--- a/source/slang/slang.natvis
+++ b/source/slang/slang.natvis
@@ -72,9 +72,9 @@
</Expand>
</Type>
<Type Name="Slang::IRInst">
- <DisplayString>{{{op}}}</DisplayString>
+ <DisplayString>{{{m_op}}}</DisplayString>
<Expand>
- <Item Name="[op]">op</Item>
+ <Item Name="[op]">m_op</Item>
<Item Name="[type]">typeUse.usedValue</Item>
<CustomListItems MaxItemsPerView="3">
<Variable Name="child" InitialValue="m_decorationsAndChildren.first"/>
@@ -82,20 +82,20 @@
<If Condition="child == 0">
<Break/>
</If>
- <If Condition="child->op == Slang::kIROp_NameHintDecoration">
+ <If Condition="child->m_op == Slang::kIROp_NameHintDecoration">
<Item Name="[name]">((Slang::IRStringLit*)(((Slang::IRUse*)(child + 1))->usedValue))->value.stringVal.chars,[((Slang::IRStringLit*)(((Slang::IRUse*)(child + 1))->usedValue))->value.stringVal.numChars]s8</Item>
</If>
- <If Condition="child->op == Slang::kIROp_ExportDecoration">
+ <If Condition="child->m_op == Slang::kIROp_ExportDecoration">
<Item Name="[exportName]">((Slang::IRStringLit*)(((Slang::IRUse*)(child + 1))->usedValue))->value.stringVal.chars,[((Slang::IRStringLit*)(((Slang::IRUse*)(child + 1))->usedValue))->value.stringVal.numChars]s8</Item>
</If>
- <If Condition="child->op == Slang::kIROp_ImportDecoration">
+ <If Condition="child->m_op == Slang::kIROp_ImportDecoration">
<Item Name="[importName]">((Slang::IRStringLit*)(((Slang::IRUse*)(child + 1))->usedValue))->value.stringVal.chars,[((Slang::IRStringLit*)(((Slang::IRUse*)(child + 1))->usedValue))->value.stringVal.numChars]s8</Item>
</If>
<Exec>child = child->next</Exec>
</Loop>
</CustomListItems>
- <Item Name="[value]" Condition="op == Slang::kIROp_StringLit">((IRStringLit*)this)->value.stringVal.chars,[((IRStringLit*)this)->value.stringVal.numChars]s8</Item>
- <Item Name="[value]" Condition="op == Slang::kIROp_IntLit">((IRIntLit*)this)->value.intVal</Item>
+ <Item Name="[value]" Condition="m_op == Slang::kIROp_StringLit">((IRStringLit*)this)->value.stringVal.chars,[((IRStringLit*)this)->value.stringVal.numChars]s8</Item>
+ <Item Name="[value]" Condition="m_op == Slang::kIROp_IntLit">((IRIntLit*)this)->value.intVal</Item>
<!--
<Synthetic Name="[operands]">
<DisplayString>{{count = {operandCount}}}</DisplayString>
@@ -120,14 +120,14 @@
<Exec>child = pOperandInst->m_decorationsAndChildren.first</Exec>
<Exec>nameDecoration = 0</Exec>
<Loop Condition="child != 0">
- <If Condition="child->op == Slang::kIROp_NameHintDecoration">
+ <If Condition="child->m_op == Slang::kIROp_NameHintDecoration">
<Exec>nameDecoration = child</Exec>
<Break/>
</If>
- <If Condition="child->op == Slang::kIROp_ExportDecoration &amp;&amp; (nameDecoration == 0 || nameDecoration->op != Slang::kIROp_NameHintDecoration)">
+ <If Condition="child->m_op == Slang::kIROp_ExportDecoration &amp;&amp; (nameDecoration == 0 || nameDecoration->m_op != Slang::kIROp_NameHintDecoration)">
<Exec>nameDecoration = child</Exec>
</If>
- <If Condition="child->op == Slang::kIROp_ImportDecoration &amp;&amp; (nameDecoration == 0 || nameDecoration->op != Slang::kIROp_NameHintDecoration)">
+ <If Condition="child->m_op == Slang::kIROp_ImportDecoration &amp;&amp; (nameDecoration == 0 || nameDecoration->m_op != Slang::kIROp_NameHintDecoration)">
<Exec>nameDecoration = child</Exec>
</If>
<Exec>child = child->next</Exec>
@@ -149,14 +149,14 @@
<Exec>child = pItem->m_decorationsAndChildren.first </Exec>
<Exec>nameDecoration = 0</Exec>
<Loop Condition="child != 0">
- <If Condition="child->op == Slang::kIROp_NameHintDecoration">
+ <If Condition="child->m_op == Slang::kIROp_NameHintDecoration">
<Exec>nameDecoration = child</Exec>
<Break/>
</If>
- <If Condition="child->op == Slang::kIROp_ExportDecoration &amp;&amp; (nameDecoration == 0 || nameDecoration->op != Slang::kIROp_NameHintDecoration)">
+ <If Condition="child->m_op == Slang::kIROp_ExportDecoration &amp;&amp; (nameDecoration == 0 || nameDecoration->m_op != Slang::kIROp_NameHintDecoration)">
<Exec>nameDecoration = child</Exec>
</If>
- <If Condition="child->op == Slang::kIROp_ImportDecoration &amp;&amp; (nameDecoration == 0 || nameDecoration->op != Slang::kIROp_NameHintDecoration)">
+ <If Condition="child->m_op == Slang::kIROp_ImportDecoration &amp;&amp; (nameDecoration == 0 || nameDecoration->m_op != Slang::kIROp_NameHintDecoration)">
<Exec>nameDecoration = child</Exec>
</If>
<Exec>child = child->next</Exec>
diff --git a/tests/pipeline/ray-tracing/trace-ray-inline.slang b/tests/pipeline/ray-tracing/trace-ray-inline.slang
new file mode 100644
index 000000000..30c32ee4f
--- /dev/null
+++ b/tests/pipeline/ray-tracing/trace-ray-inline.slang
@@ -0,0 +1,172 @@
+// 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 sm_6_5 -entry main
+
+// The goal of this shader is to use all the main pieces
+// of functionality in DXR 1.1's `TraceRayInline` feature,
+// to ensure that they survive translation to HLSL.
+
+// In order to trace rays, we need an acceleration structure.
+//
+RaytracingAccelerationStructure myAccelerationStructure;
+
+// We also need to decide what to do with hits/misses.
+// The `TraceRayInline` approach eschews separate shader
+// stages for RT, and instead expects users to write
+// those operations as subroutines instead.
+//
+// We will mimic the style and naming of DXR 1.0 here
+// to try and make the parallels clear.
+//
+// We start with a ray "payload" type that will be
+// used for input/output on hit and miss shaders
+//
+
+struct MyRayPayload
+{
+ int value;
+};
+
+// The first and simplest shader is the miss shader.
+//
+void myMiss(inout MyRayPayload payload)
+{
+ payload.value = 0;
+}
+
+// Next, up is a closest hit shader for opaque triangles.
+//
+void myTriangleClosestHit(inout MyRayPayload payload)
+{
+ payload.value = 1;
+}
+
+// In order to support alpha testing, we need an any-hit
+// shader for triangles.
+//
+// In this case, the return value is used to specify
+// whether the hit should be accepted (true) or ignored (false).
+//
+bool myTriangleAnyHit(inout MyRayPayload payload)
+{
+ return true;
+}
+
+// Procedural primitives are different than triangles
+// in that they need user-defined hit attributes.
+//
+struct MyProceduralHitAttrs { int value; }
+
+// Otherwise, the closest- and any-hit shaders
+// for procedural primitives are similar to those
+// for triangles.
+//
+void myProceduralClosestHit(inout MyRayPayload payload, MyProceduralHitAttrs attrs)
+{
+ payload.value = attrs.value;
+}
+bool myProceduralAnyHit(inout MyRayPayload payload)
+{
+ return true;
+}
+
+// The new piece of the puzzle for procedural primitives
+// is the intersection shader, which should be able to
+// report zero or more intersections.
+//
+// For now we will only deal with the single-intersection
+// case.
+//
+bool myProceduralIntersection(inout float tHit, inout MyProceduralHitAttrs hitAttrs)
+{
+ return true;
+}
+
+// In order to kick of tracing we need the properties of a ray
+// query to trace, so we will pipe those in via a constant buffer.
+//
+cbuffer C
+{
+ float3 origin;
+ float tMin;
+ float3 direction;
+ float tMax;
+ uint rayFlags;
+ uint instanceMask;
+ uint shouldStopAtFirstHit;
+}
+
+// The actual tracing is handled by a compute shader,
+// which here takes on the role of a ray generation shader.
+//
+void main(uint3 tid : SV_DispatchThreadID)
+{
+ uint index = tid.x;
+
+ RayQuery<RAY_FLAG_NONE> query;
+ MyProceduralHitAttrs committedProceduralAttrs;
+
+ MyRayPayload payload = { -1 };
+ RayDesc ray = { origin, tMin, direction, tMax };
+ query.TraceRayInline(
+ myAccelerationStructure,
+ rayFlags,
+ instanceMask,
+ ray);
+
+
+ for(;;)
+ {
+ if(!query.Proceed()) break;
+
+ switch(query.CandidateType())
+ {
+ case CANDIDATE_PROCEDURAL_PRIMITIVE:
+ {
+ MyProceduralHitAttrs candidateProceduralAttrs = { 0 };
+ float tHit = 0.0f;
+ if(myProceduralIntersection(tHit, candidateProceduralAttrs))
+ {
+ if(myProceduralAnyHit(payload))
+ {
+ query.CommitProceduralPrimitiveHit(tHit);
+ committedProceduralAttrs = candidateProceduralAttrs;
+ if(shouldStopAtFirstHit)
+ query.Abort();
+ }
+ }
+ }
+ break;
+
+ case CANDIDATE_NON_OPAQUE_TRIANGLE:
+ {
+ if(myTriangleAnyHit(payload))
+ {
+ query.CommitNonOpaqueTriangleHit();
+ if(shouldStopAtFirstHit)
+ query.Abort();
+ }
+ }
+ break;
+
+ }
+
+
+ }
+
+ switch(query.CommittedStatus())
+ {
+ case COMMITTED_TRIANGLE_HIT:
+ myTriangleClosestHit(payload);
+ break;
+
+ case COMMITTED_PROCEDURAL_PRIMITIVE_HIT:
+ myProceduralClosestHit(payload, committedProceduralAttrs);
+ break;
+
+ case COMMITTED_NOTHING:
+ myMiss(payload);
+ break;
+ }
+} \ No newline at end of file
diff --git a/tests/pipeline/ray-tracing/trace-ray-inline.slang.glsl b/tests/pipeline/ray-tracing/trace-ray-inline.slang.glsl
new file mode 100644
index 000000000..883742020
--- /dev/null
+++ b/tests/pipeline/ray-tracing/trace-ray-inline.slang.glsl
@@ -0,0 +1,219 @@
+// trace-ray-inline.slang.glsl
+//TEST_IGNORE_FILE:
+
+#version 460
+#extension GL_EXT_ray_query : require
+
+struct SLANG_ParameterGroup_C_0
+{
+ vec3 origin_0;
+ float tMin_0;
+ vec3 direction_0;
+ float tMax_0;
+ uint rayFlags_0;
+ uint instanceMask_0;
+ uint shouldStopAtFirstHit_0;
+};
+
+layout(binding = 1)
+layout(std140) uniform _S1
+{
+ SLANG_ParameterGroup_C_0 _data;
+} C_0;
+
+struct RayDesc_0
+{
+ vec3 Origin_0;
+ float TMin_0;
+ vec3 Direction_0;
+ float TMax_0;
+};
+
+void RayQuery_TraceRayInline_0(rayQueryEXT this_0, accelerationStructureEXT accelerationStructure_0, uint rayFlags_1, uint instanceInclusionMask_0, RayDesc_0 ray_0)
+{
+ rayQueryInitializeEXT((this_0), (accelerationStructure_0), (rayFlags_1), (instanceInclusionMask_0), (ray_0.Origin_0), (ray_0.TMin_0), (ray_0.Direction_0), (ray_0.TMax_0));
+ return;
+}
+
+layout(binding = 0)
+uniform accelerationStructureEXT myAccelerationStructure_0;
+
+struct MyProceduralHitAttrs_0
+{
+ int value_0;
+};
+
+bool myProceduralIntersection_0(inout float tHit_0, inout MyProceduralHitAttrs_0 hitAttrs_0)
+{
+ return true;
+}
+
+struct MyRayPayload_0
+{
+ int value_1;
+};
+
+bool myProceduralAnyHit_0(inout MyRayPayload_0 payload_0)
+{
+ return true;
+}
+
+bool myTriangleAnyHit_0(inout MyRayPayload_0 payload_1)
+{
+ return true;
+}
+
+void myTriangleClosestHit_0(inout MyRayPayload_0 payload_2)
+{
+ payload_2.value_1 = 1;
+ return;
+}
+
+void myProceduralClosestHit_0(inout MyRayPayload_0 payload_3, MyProceduralHitAttrs_0 attrs_0)
+{
+ payload_3.value_1 = attrs_0.value_0;
+ return;
+}
+
+void myMiss_0(inout MyRayPayload_0 payload_4)
+{
+ payload_4.value_1 = 0;
+ return;
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main()
+{
+ MyRayPayload_0 payload_5;
+ MyProceduralHitAttrs_0 committedProceduralAttrs_0;
+ MyProceduralHitAttrs_0 committedProceduralAttrs_1;
+ MyRayPayload_0 payload_6;
+ MyProceduralHitAttrs_0 committedProceduralAttrs_2;
+ MyRayPayload_0 payload_7;
+ MyProceduralHitAttrs_0 committedProceduralAttrs_3;
+ rayQueryEXT query_0;
+ MyRayPayload_0 _S2 = { -1 };
+ RayDesc_0 ray_1 = { C_0._data.origin_0, C_0._data.tMin_0, C_0._data.direction_0, C_0._data.tMax_0 };
+ RayQuery_TraceRayInline_0(query_0, myAccelerationStructure_0, C_0._data.rayFlags_0, C_0._data.instanceMask_0, ray_1);
+ MyProceduralHitAttrs_0 _S3;
+ payload_5 = _S2;
+ committedProceduralAttrs_0 = _S3;
+ for(;;)
+ {
+ bool _S4 = rayQueryProceedEXT(query_0);
+ if(!_S4)
+ {
+ break;
+ }
+ uint _S5 = (rayQueryGetIntersectionTypeEXT((query_0), false));
+ switch(_S5)
+ {
+ case uint(1):
+ {
+ MyProceduralHitAttrs_0 candidateProceduralAttrs_0 = { 0 };
+ float _S6;
+ _S6 = 0.00000000000000000000;
+ MyProceduralHitAttrs_0 _S7;
+ _S7 = candidateProceduralAttrs_0;
+ bool _S8 = myProceduralIntersection_0(_S6, _S7);
+ float tHit_1 = _S6;
+ MyProceduralHitAttrs_0 candidateProceduralAttrs_1 = _S7;
+ if(_S8)
+ {
+ MyRayPayload_0 _S9;
+ _S9 = payload_5;
+ bool _S10 = myProceduralAnyHit_0(_S9);
+ MyRayPayload_0 _S11 = _S9;
+ if(_S10)
+ {
+ rayQueryGenerateIntersectionEXT(query_0, tHit_1);
+ if(bool(C_0._data.shouldStopAtFirstHit_0))
+ {
+ rayQueryTerminateEXT(query_0);
+ }
+ else
+ {
+ }
+ committedProceduralAttrs_1 = candidateProceduralAttrs_1;
+ }
+ else
+ {
+ committedProceduralAttrs_1 = committedProceduralAttrs_0;
+ }
+ payload_6 = _S11;
+ committedProceduralAttrs_2 = committedProceduralAttrs_1;
+ }
+ else
+ {
+ payload_6 = payload_5;
+ committedProceduralAttrs_2 = committedProceduralAttrs_0;
+ }
+ payload_7 = payload_6;
+ committedProceduralAttrs_3 = committedProceduralAttrs_2;
+ break;
+ }
+ case uint(0):
+ {
+ MyRayPayload_0 _S12;
+ _S12 = payload_5;
+ bool _S13 = myTriangleAnyHit_0(_S12);
+ MyRayPayload_0 _S14 = _S12;
+ if(_S13)
+ {
+ rayQueryConfirmIntersectionEXT(query_0);
+ if(bool(C_0._data.shouldStopAtFirstHit_0))
+ {
+ rayQueryTerminateEXT(query_0);
+ }
+ else
+ {
+ }
+ }
+ else
+ {
+ }
+ payload_7 = _S14;
+ committedProceduralAttrs_3 = committedProceduralAttrs_0;
+ break;
+ }
+ default:
+ {
+ payload_7 = payload_5;
+ committedProceduralAttrs_3 = committedProceduralAttrs_0;
+ break;
+ }
+ }
+ payload_5 = payload_7;
+ committedProceduralAttrs_0 = committedProceduralAttrs_3;
+ }
+ uint _S15 = (rayQueryGetIntersectionTypeEXT((query_0), true));
+ switch(_S15)
+ {
+ case uint(1):
+ {
+ MyRayPayload_0 _S16;
+ _S16 = payload_5;
+ myTriangleClosestHit_0(_S16);
+ break;
+ }
+ case uint(2):
+ {
+ MyRayPayload_0 _S17;
+ _S17 = payload_5;
+ myProceduralClosestHit_0(_S17, committedProceduralAttrs_0);
+ break;
+ }
+ case uint(0):
+ {
+ MyRayPayload_0 _S18;
+ _S18 = payload_5;
+ myMiss_0(_S18);
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ return;
+}
diff --git a/tests/pipeline/ray-tracing/trace-ray-inline.slang.hlsl b/tests/pipeline/ray-tracing/trace-ray-inline.slang.hlsl
new file mode 100644
index 000000000..cdea1668a
--- /dev/null
+++ b/tests/pipeline/ray-tracing/trace-ray-inline.slang.hlsl
@@ -0,0 +1,238 @@
+// trace-ray-inline.slang.hlsl
+//TEST_IGNORE_FILE:
+
+struct SLANG_ParameterGroup_C_0
+{
+ vector<float,3> origin_0;
+ float tMin_0;
+ vector<float,3> direction_0;
+ float tMax_0;
+ uint rayFlags_0;
+ uint instanceMask_0;
+ uint shouldStopAtFirstHit_0;
+};
+
+cbuffer C_0 : register(b0)
+{
+ SLANG_ParameterGroup_C_0 C_0;
+}
+
+RaytracingAccelerationStructure myAccelerationStructure_0 : register(t0);
+
+struct MyProceduralHitAttrs_0
+{
+ int value_0;
+};
+
+bool myProceduralIntersection_0(inout float tHit_0, inout MyProceduralHitAttrs_0 hitAttrs_0)
+{
+ return true;
+}
+
+struct MyRayPayload_0
+{
+ int value_1;
+};
+
+bool myProceduralAnyHit_0(inout MyRayPayload_0 payload_0)
+{
+ return true;
+}
+
+bool myTriangleAnyHit_0(inout MyRayPayload_0 payload_1)
+{
+ return true;
+}
+
+void myTriangleClosestHit_0(inout MyRayPayload_0 payload_2)
+{
+ payload_2.value_1 = int(1);
+ return;
+}
+
+void myProceduralClosestHit_0(inout MyRayPayload_0 payload_3, MyProceduralHitAttrs_0 attrs_0)
+{
+ payload_3.value_1 = attrs_0.value_0;
+ return;
+}
+
+void myMiss_0(inout MyRayPayload_0 payload_4)
+{
+ payload_4.value_1 = int(0);
+ return;
+}
+
+
+[shader("compute")]
+[numthreads(1, 1, 1)]
+void main(vector<uint,3> tid_0 : SV_DISPATCHTHREADID)
+{
+ MyRayPayload_0 payload_5;
+ MyProceduralHitAttrs_0 committedProceduralAttrs_0;
+ MyProceduralHitAttrs_0 committedProceduralAttrs_1;
+ MyRayPayload_0 payload_6;
+ MyProceduralHitAttrs_0 committedProceduralAttrs_2;
+ MyRayPayload_0 payload_7;
+ MyProceduralHitAttrs_0 committedProceduralAttrs_3;
+
+ RayQuery<int(0) > query_0;
+
+ MyRayPayload_0 _S1 = { int(-1) };
+ RayDesc ray_0 = { C_0.origin_0, C_0.tMin_0, C_0.direction_0, C_0.tMax_0 };
+ query_0.TraceRayInline(myAccelerationStructure_0, C_0.rayFlags_0, C_0.instanceMask_0, ray_0);
+
+ MyProceduralHitAttrs_0 _S2;
+
+ payload_5 = _S1;
+ committedProceduralAttrs_0 = _S2;
+ for(;;)
+ {
+ bool _S3 = query_0.Proceed();
+
+ if(!_S3)
+ {
+ break;
+ }
+ uint _S4 = query_0.CandidateType();
+
+ switch(_S4)
+ {
+ case (uint) int(1):
+ {
+ MyProceduralHitAttrs_0 candidateProceduralAttrs_0 = { int(0) };
+
+ float _S5;
+
+ _S5 = 0.00000000000000000000;
+
+ MyProceduralHitAttrs_0 _S6;
+
+ _S6 = candidateProceduralAttrs_0;
+
+ bool _S7 = myProceduralIntersection_0(_S5, _S6);
+
+ float tHit_1 = _S5;
+
+ MyProceduralHitAttrs_0 candidateProceduralAttrs_1 = _S6;
+
+ if(_S7)
+ {
+ MyRayPayload_0 _S8;
+
+ _S8 = payload_5;
+
+ bool _S9 = myProceduralAnyHit_0(_S8);
+
+ MyRayPayload_0 _S10 = _S8;
+
+ if(_S9)
+ {
+ query_0.CommitProceduralPrimitiveHit(tHit_1);
+
+ if((bool) C_0.shouldStopAtFirstHit_0)
+ {
+
+ query_0.Abort();
+ }
+ else
+ {
+ }
+
+ committedProceduralAttrs_1 = candidateProceduralAttrs_1;
+ }
+ else
+ {
+ committedProceduralAttrs_1 = committedProceduralAttrs_0;
+ }
+
+ payload_6 = _S10;
+ committedProceduralAttrs_2 = committedProceduralAttrs_1;
+ }
+ else
+ {
+ payload_6 = payload_5;
+ committedProceduralAttrs_2 = committedProceduralAttrs_0;
+ }
+
+ payload_7 = payload_6;
+ committedProceduralAttrs_3 = committedProceduralAttrs_2;
+ break;
+ }
+ case (uint) int(0):
+ {
+ MyRayPayload_0 _S11;
+ _S11 = payload_5;
+
+ bool _S12 = myTriangleAnyHit_0(_S11);
+ MyRayPayload_0 _S13 = _S11;
+
+ if(_S12)
+ {
+ query_0.CommitNonOpaqueTriangleHit();
+ if((bool) C_0.shouldStopAtFirstHit_0)
+ {
+ query_0.Abort();
+ }
+ else
+ {
+ }
+ }
+ else
+ {
+ }
+
+ payload_7 = _S13;
+ committedProceduralAttrs_3 = committedProceduralAttrs_0;
+ break;
+ }
+ default:
+ {
+ payload_7 = payload_5;
+ committedProceduralAttrs_3 = committedProceduralAttrs_0;
+ break;
+ }
+ }
+
+ payload_5 = payload_7;
+ committedProceduralAttrs_0 = committedProceduralAttrs_3;
+ }
+
+ uint _S14 = query_0.CommittedStatus();
+
+ switch(_S14)
+ {
+ case (uint) int(1):
+ {
+ MyRayPayload_0 _S15;
+
+ _S15 = payload_5;
+
+ myTriangleClosestHit_0(_S15);
+ break;
+ }
+ case (uint) int(2):
+ {
+
+ MyRayPayload_0 _S16;
+ _S16 = payload_5;
+
+ myProceduralClosestHit_0(_S16, committedProceduralAttrs_0);
+ break;
+ }
+ case (uint) int(0):
+ {
+ MyRayPayload_0 _S17;
+
+ _S17 = payload_5;
+
+ myMiss_0(_S17);
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return;
+}