summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheresa Foley <10618364+tangent-vector@users.noreply.github.com>2023-06-13 14:40:02 -0700
committerGitHub <noreply@github.com>2023-06-13 17:40:02 -0400
commitf161686e8e260a4b0e6e0a773cf1cf16069f41bf (patch)
tree1daf16da7f0826eb26cf352b0fab9aa1c61b4327
parentb255ef068b77a45fdd0b595a555386928a61d56e (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
-rw-r--r--source/slang/hlsl.meta.slang59
-rw-r--r--source/slang/slang-emit-c-like.cpp117
-rw-r--r--source/slang/slang-emit-c-like.h6
-rw-r--r--source/slang/slang-emit-glsl.cpp65
-rw-r--r--source/slang/slang-emit-glsl.h3
-rw-r--r--source/slang/slang-emit-hlsl.cpp37
-rw-r--r--source/slang/slang-emit-hlsl.h2
-rw-r--r--source/slang/slang-ir-inst-defs.h5
-rw-r--r--source/slang/slang-ir-specialize-resources.cpp5
-rw-r--r--source/slang/slang-ir.cpp1
-rw-r--r--source/slang/slang-ir.h10
-rw-r--r--source/slang/slang-lower-to-ir.cpp2
-rw-r--r--tests/hlsl-intrinsic/shader-execution-reordering/hit-object-assign.slang.1.expected12
-rw-r--r--tests/hlsl-intrinsic/shader-execution-reordering/hit-object-make-hit.slang.1.expected34
-rw-r--r--tests/hlsl-intrinsic/shader-execution-reordering/hit-object-make-miss.slang.1.expected9
-rw-r--r--tests/hlsl-intrinsic/shader-execution-reordering/hit-object-output.slang109
-rw-r--r--tests/hlsl-intrinsic/shader-execution-reordering/hit-object-output.slang.1.expected93
-rw-r--r--tests/hlsl-intrinsic/shader-execution-reordering/hit-object-reorder-thread.slang.1.expected2
-rw-r--r--tests/hlsl-intrinsic/shader-execution-reordering/hit-object-trace-motion-ray.slang.1.expected2
-rw-r--r--tests/hlsl-intrinsic/shader-execution-reordering/hit-object-trace-ray.slang.1.expected2
-rw-r--r--tests/pipeline/ray-tracing/trace-ray-inline.slang4
-rw-r--r--tests/pipeline/ray-tracing/trace-ray-inline.slang.glsl138
-rw-r--r--tests/pipeline/ray-tracing/trace-ray-inline.slang.hlsl118
23 files changed, 529 insertions, 306 deletions
diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang
index 40a372a32..b42e17fbe 100644
--- a/source/slang/hlsl.meta.slang
+++ b/source/slang/hlsl.meta.slang
@@ -5702,13 +5702,41 @@ static const CANDIDATE_TYPE CANDIDATE_PROCEDURAL_PRIMITIVE = 1;
// code can resume to continue tracing the ray, and which yields
// back to the user code at interesting events along the ray.
//
-__target_intrinsic(hlsl, RayQuery)
-__target_intrinsic(glsl, rayQueryEXT)
+// Note: The treatment of the `RayQuery` type in Slang does not
+// perfectly match its semantics in vanilla HLSL in some corner
+// cases. Specifically, a `RayQuery` in vanilla HLSL is an
+// opaque handle to mutable storage, and assigning a `RayQuery`
+// or passing one as a parameter will only copy the *handle*,
+// potentially resulting in aliasing of the underlying mutable
+// storage.
+//
+// In contrast, Slang considers a `RayQuery` to own its mutable
+// state, and (because the API does not support cloning of queries),
+// `RayQuery` values are non-copyable (aka "move-only").
+//
+// The main place where this arises as a consideration is when
+// passing a `RayQuery` down into a function that will perform
+// mutating operations on it (e.g., `TraceRay` or `Proceed`):
+//
+// void myFunc( inout RayQuery<FLAGS> q )
+// {
+// q.Proceed();
+// }
+//
+// In Slang, a parameter like `q` above should be declared `inout`.
+// HLSL does not care about whether `q` is declared `inout` or not.
+//
__glsl_extension(GL_EXT_ray_query)
__glsl_version(460)
[__NonCopyableType]
+__intrinsic_type($(kIROp_RayQueryType))
struct RayQuery <let rayFlagsGeneric : RAY_FLAG = RAY_FLAG_NONE>
{
+ // Create a new ray query, initialized to its default state.
+ //
+ __intrinsic_op($(kIROp_AllocateOpaqueHandle))
+ __init();
+
// Initialize a ray-tracing query.
//
// This method may be called on a "fresh" ray query, or
@@ -5733,6 +5761,7 @@ struct RayQuery <let rayFlagsGeneric : RAY_FLAG = RAY_FLAG_NONE>
__target_intrinsic(glsl, "rayQueryInitializeEXT($0, $1, $2, $3, $4, $5, $6, $7)")
__glsl_extension(GL_EXT_ray_query)
__glsl_version(460)
+ [mutating]
void __rayQueryInitializeEXT(
RaytracingAccelerationStructure accelerationStructure,
RAY_FLAG rayFlags,
@@ -5745,6 +5774,7 @@ struct RayQuery <let rayFlagsGeneric : RAY_FLAG = RAY_FLAG_NONE>
[__unsafeForceInlineEarly]
__specialized_for_target(glsl)
[__NoSideEffect]
+ [mutating]
void TraceRayInline(
RaytracingAccelerationStructure accelerationStructure,
RAY_FLAG rayFlags,
@@ -6114,12 +6144,15 @@ int __hitObjectAttributesLocation(__ref Attributes attributes);
/// or as a key in ReorderThread. Created by one of several methods described below. HitObject
/// and its related functions are available in raytracing shader types only.
[__requiresNVAPI]
-__target_intrinsic(hlsl, NvHitObject)
__glsl_extension(GL_NV_shader_invocation_reorder)
__glsl_extension(GL_EXT_ray_tracing)
-__target_intrinsic(glsl, hitObjectNV)
+[__NonCopyableType]
+__intrinsic_type($(kIROp_HitObjectType))
struct HitObject
{
+ __intrinsic_op($(kIROp_AllocateOpaqueHandle))
+ __init();
+
/// Executes ray traversal (including anyhit and intersection shaders) like TraceRay, but returns the
/// resulting hit information as a HitObject and does not trigger closesthit or miss shaders.
__specialized_for_target(hlsl)
@@ -6672,7 +6705,7 @@ struct HitObject
__glsl_extension(GL_EXT_ray_tracing)
__target_intrinsic(glsl, "hitObjectRecordMissNV")
static void __glslMakeMiss(
- HitObject hitObj,
+ out HitObject hitObj,
uint MissShaderIndex,
float3 Origin,
float TMin,
@@ -6685,7 +6718,7 @@ struct HitObject
__glsl_extension(GL_NV_ray_tracing_motion_blur)
__target_intrinsic(glsl, "hitObjectRecordMissNV")
static void __glslMakeMotionMiss(
- HitObject hitObj,
+ out HitObject hitObj,
uint MissShaderIndex,
float3 Origin,
float TMin,
@@ -6696,7 +6729,7 @@ struct HitObject
__glsl_extension(GL_NV_shader_invocation_reorder)
__glsl_extension(GL_EXT_ray_tracing)
__target_intrinsic(glsl, "hitObjectRecordEmptyNV($0)")
- static void __glslMakeNop(HitObject hitObj);
+ static void __glslMakeNop(out HitObject hitObj);
__glsl_extension(GL_NV_shader_invocation_reorder)
__target_intrinsic(glsl, "hitObjectGetObjectRayDirectionNV($0)")
@@ -6719,7 +6752,7 @@ struct HitObject
__glsl_extension(GL_EXT_ray_tracing)
__target_intrinsic(glsl, "hitObjectRecordHitWithIndexNV")
static void __glslMakeHitWithIndex(
- HitObject hitObj,
+ out HitObject hitObj,
RaytracingAccelerationStructure accelerationStructure,
int instanceid,
int primitiveid,
@@ -6738,7 +6771,7 @@ struct HitObject
__glsl_extension(GL_NV_ray_tracing_motion_blur)
__target_intrinsic(glsl, "hitObjectRecordHitWithIndexMotionNV")
static void __glslMakeMotionHitWithIndex(
- HitObject hitObj,
+ out HitObject hitObj,
RaytracingAccelerationStructure accelerationStructure,
int instanceid,
int primitiveid,
@@ -6757,7 +6790,7 @@ struct HitObject
__glsl_extension(GL_NV_shader_invocation_reorder)
__target_intrinsic(glsl, "hitObjectRecordHitNV")
static void __glslMakeHit(
- HitObject hitObj,
+ out HitObject hitObj,
RaytracingAccelerationStructure accelerationStructure,
int instanceid,
int primitiveid,
@@ -6777,7 +6810,7 @@ struct HitObject
__glsl_extension(GL_NV_ray_tracing_motion_blur)
__target_intrinsic(glsl, "hitObjectRecordHitMotionNV")
static void __glslMakeMotionHit(
- HitObject hitObj,
+ out HitObject hitObj,
RaytracingAccelerationStructure accelerationStructure,
int instanceid,
int primitiveid,
@@ -6802,7 +6835,7 @@ struct HitObject
__glsl_extension(GL_NV_shader_invocation_reorder)
__target_intrinsic(glsl, "hitObjectTraceRayNV")
static void __glslTraceRay(
- HitObject hitObj,
+ out HitObject hitObj,
RaytracingAccelerationStructure accelerationStructure,
uint rayFlags,
uint cullMask,
@@ -6820,7 +6853,7 @@ struct HitObject
__glsl_extension(GL_NV_ray_tracing_motion_blur)
__target_intrinsic(glsl, "hitObjectTraceRayMotionNV")
static void __glslTraceMotionRay(
- HitObject hitObj,
+ out HitObject hitObj,
RaytracingAccelerationStructure accelerationStructure,
uint rayFlags,
uint cullMask,
diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp
index 75d7b3cf8..c7ea3a09a 100644
--- a/source/slang/slang-emit-c-like.cpp
+++ b/source/slang/slang-emit-c-like.cpp
@@ -1239,10 +1239,12 @@ bool CLikeSourceEmitter::shouldFoldInstIntoUseSites(IRInst* inst)
{
return true;
}
+ if (as<IRHitObjectType>(type))
+ {
+ return true;
+ }
}
-
-
// If the instruction is at global scope, then it might represent
// a constant (e.g., the value of an enum case).
//
@@ -1292,6 +1294,7 @@ bool CLikeSourceEmitter::shouldFoldInstIntoUseSites(IRInst* inst)
// definition for certain types on certain targets (e.g. `out TriangleStream<T>`
// for GLSL), so we check this only after all those special cases are
// considered.
+ //
if (inst->getOp() == kIROp_undefined)
return false;
@@ -1382,6 +1385,7 @@ bool CLikeSourceEmitter::shouldFoldInstIntoUseSites(IRInst* inst)
if(inst->getParent() != user->getParent())
return false;
+
// Now let's look at all the instructions between this instruction
// and the user. If any of them might have side effects, then lets
// bail out now.
@@ -1410,6 +1414,25 @@ bool CLikeSourceEmitter::shouldFoldInstIntoUseSites(IRInst* inst)
if(as<IRUnconditionalBranch>(user))
return false;
+ // HACK: As a special case, an `allocateOpaqueHandle` operation should
+ // only be folded in if its only use is as the operand of a `store`
+ // that will *itself* get peephole merged in as the initial-value expression
+ // of a `var`:
+ //
+ if (inst->getOp() == kIROp_AllocateOpaqueHandle)
+ {
+ auto store = as<IRStore>(user);
+ if (!store) return false;
+ if (store->getVal() != inst) return false;
+
+ auto var = as<IRVar>(store->getPtr());
+ if (!var) return false;
+
+ if(var->getNextInst() != store) return false;
+
+ return true;
+ }
+
// Okay, if we reach this point then the user comes later in
// the same block, and there are no instructions with side
// effects in between, so it seems safe to fold things in.
@@ -1843,6 +1866,7 @@ void CLikeSourceEmitter::defaultEmitInstExpr(IRInst* inst, const EmitOpInfo& inO
case kIROp_undefined:
case kIROp_DefaultConstruct:
+ case kIROp_AllocateOpaqueHandle:
m_writer->emit(getName(inst));
break;
@@ -2441,19 +2465,13 @@ void CLikeSourceEmitter::_emitInst(IRInst* inst)
case kIROp_DefaultConstruct:
{
auto type = inst->getDataType();
- emitType(type, getName(inst));
+ _emitInstAsDefaultInitializedVar(inst, type);
+ }
+ break;
- // On targets that support empty initializers, we will emit it.
- switch (this->getTarget())
- {
- case CodeGenTarget::CPPSource:
- case CodeGenTarget::HostCPPSource:
- case CodeGenTarget::PyTorchCppBinding:
- case CodeGenTarget::CUDASource:
- m_writer->emit(" = {}");
- break;
- }
- m_writer->emit(";\n");
+ case kIROp_AllocateOpaqueHandle:
+ {
+ _emitAllocateOpaqueHandleImpl(inst);
}
break;
@@ -2466,17 +2484,8 @@ void CLikeSourceEmitter::_emitInst(IRInst* inst)
case kIROp_Store:
{
- if (inst->getPrevInst() == inst->getOperand(0) && inst->getOperand(0)->getOp() == kIROp_Var)
- {
- // If we are storing into a var that is defined right before the store, we have
- // already folded the store in the initialization of the var, so we can skip here.
- break;
- }
- auto prec = getInfo(EmitOp::Assign);
- emitDereferenceOperand(inst->getOperand(0), leftSide(getInfo(EmitOp::General), prec));
- m_writer->emit(" = ");
- emitOperand(inst->getOperand(1), rightSide(prec, getInfo(EmitOp::General)));
- m_writer->emit(";\n");
+ auto store = cast<IRStore>(inst);
+ emitStore(store);
}
break;
@@ -2620,6 +2629,51 @@ void CLikeSourceEmitter::_emitInst(IRInst* inst)
}
}
+void CLikeSourceEmitter::emitStore(IRStore* store)
+{
+ if (store->getPrevInst() == store->getOperand(0) && store->getOperand(0)->getOp() == kIROp_Var)
+ {
+ // If we are storing into a `var` that is defined right before the store, we have
+ // already folded the store in the initialization of the `var`, so we can skip here.
+ //
+ return;
+ }
+ _emitStoreImpl(store);
+}
+
+void CLikeSourceEmitter::_emitStoreImpl(IRStore* store)
+{
+ auto srcVal = store->getVal();
+ auto dstPtr = store->getPtr();
+ auto prec = getInfo(EmitOp::Assign);
+ emitDereferenceOperand(dstPtr, leftSide(getInfo(EmitOp::General), prec));
+ m_writer->emit(" = ");
+ emitOperand(srcVal, rightSide(prec, getInfo(EmitOp::General)));
+ m_writer->emit(";\n");
+}
+
+void CLikeSourceEmitter::_emitInstAsDefaultInitializedVar(IRInst* inst, IRType* type)
+{
+ emitType(type, getName(inst));
+
+ // On targets that support empty initializers, we will emit it.
+ switch (this->getTarget())
+ {
+ case CodeGenTarget::CPPSource:
+ case CodeGenTarget::HostCPPSource:
+ case CodeGenTarget::PyTorchCppBinding:
+ case CodeGenTarget::CUDASource:
+ m_writer->emit(" = {}");
+ break;
+ }
+ m_writer->emit(";\n");
+}
+
+void CLikeSourceEmitter::_emitAllocateOpaqueHandleImpl(IRInst* allocateInst)
+{
+ _emitInstAsDefaultInitializedVar(allocateInst, allocateInst->getDataType());
+}
+
void CLikeSourceEmitter::emitSemanticsUsingVarLayout(IRVarLayout* varLayout)
{
if(auto semanticAttr = varLayout->findAttr<IRSemanticAttr>())
@@ -3415,18 +3469,27 @@ void CLikeSourceEmitter::emitVar(IRVar* varDecl)
emitLayoutSemantics(varDecl);
+ // TODO: ideally this logic should scan ahead to see if it can find a `store`
+ // instruction that writes to the `var`, within the same block, such that all
+ // of the intervening instructions are safe to fold.
+ //
if (auto store = as<IRStore>(varDecl->getNextInst()))
{
if (store->getPtr() == varDecl)
{
- m_writer->emit(" = ");
- emitOperand(store->getVal(), getInfo(EmitOp::General));
+ _emitInstAsVarInitializerImpl(store->getVal());
}
}
m_writer->emit(";\n");
}
+void CLikeSourceEmitter::_emitInstAsVarInitializerImpl(IRInst* inst)
+{
+ m_writer->emit(" = ");
+ emitOperand(inst, getInfo(EmitOp::General));
+}
+
void CLikeSourceEmitter::emitGlobalVar(IRGlobalVar* varDecl)
{
auto allocatedType = varDecl->getDataType();
diff --git a/source/slang/slang-emit-c-like.h b/source/slang/slang-emit-c-like.h
index 393ab602c..636faad46 100644
--- a/source/slang/slang-emit-c-like.h
+++ b/source/slang/slang-emit-c-like.h
@@ -307,6 +307,12 @@ public:
void emitVal(IRInst* val, const EmitOpInfo& outerPrec);
+ void emitStore(IRStore* store);
+ virtual void _emitStoreImpl(IRStore* store);
+ virtual void _emitInstAsVarInitializerImpl(IRInst* inst);
+ void _emitInstAsDefaultInitializedVar(IRInst* inst, IRType* type);
+ virtual void _emitAllocateOpaqueHandleImpl(IRInst* allocateInst);
+
UInt getBindingOffset(EmitVarChain* chain, LayoutResourceKind kind);
UInt getBindingSpace(EmitVarChain* chain, LayoutResourceKind kind);
diff --git a/source/slang/slang-emit-glsl.cpp b/source/slang/slang-emit-glsl.cpp
index bc170dadc..a86971bf5 100644
--- a/source/slang/slang-emit-glsl.cpp
+++ b/source/slang/slang-emit-glsl.cpp
@@ -869,6 +869,61 @@ void GLSLSourceEmitter::emitLoopControlDecorationImpl(IRLoopControlDecoration* d
}
}
+void GLSLSourceEmitter::_emitInstAsVarInitializerImpl(IRInst* inst)
+{
+ // Some opcodes can be folded into a variable initialization
+ // by allowing the variable to be "default-constructed."
+ //
+ switch (inst->getOp())
+ {
+ case kIROp_AllocateOpaqueHandle:
+ //
+ // Note: semantically, we should only elide the initializer
+ // if `inst` is able to be folded here, since otherwise
+ // it could be a single allocation that is used to initialize
+ // multiple local variables (which should then alias the
+ // same location).
+ //
+ // However, since GlSL doesn't support assignment of opaque
+ // handle types, code will fail to compile downstream in
+ // the case where the initializer *doesn't* fold.
+ //
+ // The decision being made here should help ensure that we
+ // don't emit code that silently has different semantics
+ // than the input.
+ //
+ if (shouldFoldInstIntoUseSites(inst))
+ {
+ return;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // We fall back to the default behavior for all targets,
+ // which is to emit `inst` as an initial-value expression
+ // after an `=`.
+ //
+ Super::_emitInstAsVarInitializerImpl(inst);
+}
+
+void GLSLSourceEmitter::_emitStoreImpl(IRStore* store)
+{
+ auto srcVal = store->getVal();
+ switch (srcVal->getOp())
+ {
+ default:
+ Super::_emitStoreImpl(store);
+ break;
+
+ case kIROp_AllocateOpaqueHandle:
+ break;
+ }
+
+}
+
void GLSLSourceEmitter::_emitSpecialFloatImpl(IRType* type, const char* valueExpr)
{
if( type->getOp() != kIROp_FloatType )
@@ -2153,6 +2208,16 @@ void GLSLSourceEmitter::emitSimpleTypeImpl(IRType* type)
m_writer->emit("int");
return;
}
+ case kIROp_RayQueryType:
+ {
+ m_writer->emit("rayQueryEXT");
+ return;
+ }
+ case kIROp_HitObjectType:
+ {
+ m_writer->emit("hitObjectNV");
+ return;
+ }
default: break;
}
diff --git a/source/slang/slang-emit-glsl.h b/source/slang/slang-emit-glsl.h
index 48c6971aa..757955677 100644
--- a/source/slang/slang-emit-glsl.h
+++ b/source/slang/slang-emit-glsl.h
@@ -52,6 +52,9 @@ protected:
virtual void emitSimpleValueImpl(IRInst* inst) SLANG_OVERRIDE;
virtual void emitLoopControlDecorationImpl(IRLoopControlDecoration* decl) SLANG_OVERRIDE;
+ virtual void _emitInstAsVarInitializerImpl(IRInst* inst) SLANG_OVERRIDE;
+ virtual void _emitStoreImpl(IRStore* store) SLANG_OVERRIDE;
+
void _emitGLSLTextureOrTextureSamplerType(IRTextureTypeBase* type, char const* baseName);
void _emitGLSLStructuredBuffer(IRGlobalParam* varDecl, IRHLSLStructuredBufferTypeBase* structuredBufferType);
diff --git a/source/slang/slang-emit-hlsl.cpp b/source/slang/slang-emit-hlsl.cpp
index 96b751789..3f6e79f4a 100644
--- a/source/slang/slang-emit-hlsl.cpp
+++ b/source/slang/slang-emit-hlsl.cpp
@@ -897,6 +897,18 @@ void HLSLSourceEmitter::emitSimpleTypeImpl(IRType* type)
m_writer->emit("int");
return;
}
+ case kIROp_RayQueryType:
+ {
+ m_writer->emit("RayQuery<");
+ emitSimpleValue(type->getOperand(0));
+ m_writer->emit(" >");
+ return;
+ }
+ case kIROp_HitObjectType:
+ {
+ m_writer->emit("HitObject");
+ return;
+ }
default: break;
}
@@ -1095,6 +1107,31 @@ void HLSLSourceEmitter::_emitPrefixTypeAttr(IRAttr* attr)
}
}
+void HLSLSourceEmitter::_emitInstAsVarInitializerImpl(IRInst* inst)
+{
+ // Some opcodes can be folded into a variable initialization
+ // by allowing the variable to be "default-constructed."
+ //
+ switch (inst->getOp())
+ {
+ case kIROp_AllocateOpaqueHandle:
+ if (shouldFoldInstIntoUseSites(inst))
+ {
+ return;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // We fall back to the default behavior for all targets,
+ // which is to emit `inst` as an initial-value expression
+ // after an `=`.
+ //
+ Super::_emitInstAsVarInitializerImpl(inst);
+}
+
void HLSLSourceEmitter::emitSimpleFuncParamImpl(IRParam* param)
{
emitRateQualifiers(param);
diff --git a/source/slang/slang-emit-hlsl.h b/source/slang/slang-emit-hlsl.h
index d69e054b4..2e4eb29b9 100644
--- a/source/slang/slang-emit-hlsl.h
+++ b/source/slang/slang-emit-hlsl.h
@@ -61,6 +61,8 @@ protected:
void _emitPrefixTypeAttr(IRAttr* attr) SLANG_OVERRIDE;
+ virtual void _emitInstAsVarInitializerImpl(IRInst* inst) SLANG_OVERRIDE;
+
// Emit a single `register` semantic, as appropriate for a given resource-type-specific layout info
// Keyword to use in the uniform case (`register` for globals, `packoffset` inside a `cbuffer`)
void _emitHLSLRegisterSemantic(LayoutResourceKind kind, EmitVarChain* chain, char const* uniformSemanticSpelling = "register");
diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h
index da0c3618d..fc020403d 100644
--- a/source/slang/slang-ir-inst-defs.h
+++ b/source/slang/slang-ir-inst-defs.h
@@ -204,7 +204,8 @@ INST(Nop, nop, 0, 0)
INST_RANGE(PointerLikeType, ConstantBufferType, GLSLOutputParameterGroupType)
INST_RANGE(BuiltinGenericType, HLSLPointStreamType, GLSLOutputParameterGroupType)
-
+INST(RayQueryType, RayQuery, 1, HOISTABLE)
+INST(HitObjectType, HitObject, 0, HOISTABLE)
// A user-defined structure declaration at the IR level.
@@ -617,6 +618,8 @@ INST(AllocateTorchTensor, allocTorchTensor, 0, 0)
INST(TorchGetCudaStream, TorchGetCudaStream, 0, 0)
INST(TorchTensorGetView, TorchTensorGetView, 0, 0)
+INST(AllocateOpaqueHandle, allocateOpaqueHandle, 0, 0)
+
/* Decoration */
INST(HighLevelDeclDecoration, highLevelDecl, 1, 0)
diff --git a/source/slang/slang-ir-specialize-resources.cpp b/source/slang/slang-ir-specialize-resources.cpp
index 3d28e0bb0..09c8f1f22 100644
--- a/source/slang/slang-ir-specialize-resources.cpp
+++ b/source/slang/slang-ir-specialize-resources.cpp
@@ -352,6 +352,11 @@ struct ResourceOutputSpecializationPass
if(as<IRSamplerStateTypeBase>(type))
return true;
+ if(as<IRHitObjectType>(type))
+ return true;
+ if(as<IRRayQueryType>(type))
+ return true;
+
// TODO: more cases here?
return false;
diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp
index 72b65ea3e..0a001892a 100644
--- a/source/slang/slang-ir.cpp
+++ b/source/slang/slang-ir.cpp
@@ -7276,6 +7276,7 @@ namespace Slang
case kIROp_MakeTensorView:
case kIROp_TorchTensorGetView:
case kIROp_GetStringHash:
+ case kIROp_AllocateOpaqueHandle:
return false;
case kIROp_ForwardDifferentiate:
diff --git a/source/slang/slang-ir.h b/source/slang/slang-ir.h
index 66295b0fb..f5697c9e1 100644
--- a/source/slang/slang-ir.h
+++ b/source/slang/slang-ir.h
@@ -1625,6 +1625,16 @@ struct IRFuncType : IRType
IR_LEAF_ISA(FuncType)
};
+struct IRRayQueryType : IRType
+{
+ IR_LEAF_ISA(RayQueryType)
+};
+
+struct IRHitObjectType : IRType
+{
+ IR_LEAF_ISA(HitObjectType)
+};
+
bool isDefinition(
IRInst* inVal);
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index 144875e8c..937262758 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -2025,6 +2025,8 @@ struct ValLoweringVisitor : ValVisitor<ValLoweringVisitor, LoweredValInfo, Lower
// type with the appropriate opcode.
IRType* lowerSimpleIntrinsicType(DeclRefType* type)
{
+ SLANG_ASSERT(getBuilder()->getInsertLoc().getMode() != IRInsertLoc::Mode::None);
+
auto intrinsicTypeModifier = type->declRef.getDecl()->findModifier<IntrinsicTypeModifier>();
SLANG_ASSERT(intrinsicTypeModifier);
IROp op = IROp(intrinsicTypeModifier->irOp);
diff --git a/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-assign.slang.1.expected b/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-assign.slang.1.expected
index d921747af..c7be594d1 100644
--- a/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-assign.slang.1.expected
+++ b/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-assign.slang.1.expected
@@ -29,13 +29,15 @@ void main()
ray_0.TMin_0 = 0.00999999977648258209;
ray_0.Direction_0 = vec3(0.0, 1.0, 0.0);
ray_0.TMax_0 = 10000.0;
+ uint _S4 = uint(idx_0);
hitObjectNV hitObj_0;
- hitObjectRecordMissNV(hitObj_0, uint(idx_0), ray_0.Origin_0, ray_0.TMin_0, ray_0.Direction_0, ray_0.TMax_0);
+ hitObjectRecordMissNV(hitObj_0, _S4, ray_0.Origin_0, ray_0.TMin_0, ray_0.Direction_0, ray_0.TMax_0);
+ uint _S5 = uint(idx_0 + 1);
hitObjectNV hitObj_1;
- hitObjectRecordMissNV(hitObj_1, uint(idx_0 + 1), ray_0.Origin_0, ray_0.TMin_0, ray_0.Direction_0, ray_0.TMax_0);
- bool _S4 = (hitObjectIsMissNV((hitObj_1)));
- uint _S5 = uint(int(_S4));
- ((outputBuffer_0)._data[(uint(idx_0))]) = _S5;
+ hitObjectRecordMissNV(hitObj_1, _S5, ray_0.Origin_0, ray_0.TMin_0, ray_0.Direction_0, ray_0.TMax_0);
+ bool _S6 = (hitObjectIsMissNV((hitObj_1)));
+ uint _S7 = uint(int(_S6));
+ ((outputBuffer_0)._data[(uint(idx_0))]) = _S7;
return;
}
diff --git a/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-make-hit.slang.1.expected b/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-make-hit.slang.1.expected
index 81ceff87f..938a19480 100644
--- a/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-make-hit.slang.1.expected
+++ b/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-make-hit.slang.1.expected
@@ -90,23 +90,29 @@ void main()
ray_2.TMin_0 = 0.00999999977648258209;
ray_2.Direction_0 = vec3(0.0, 1.0, 0.0);
ray_2.TMax_0 = 10000.0;
- int _S10 = idx_0 * 2;
- int _S11 = idx_0 * 3;
- RayDesc_0 _S12 = ray_2;
+ uint _S10 = uint(idx_0);
+ int _S11 = idx_0 * 2;
+ uint _S12 = uint(_S11);
+ int _S13 = idx_0 * 3;
+ uint _S14 = uint(_S13);
+ RayDesc_0 _S15 = ray_2;
hitObjectNV hitObj_0;
- int _S13 = int(uint(idx_0));
- int _S14 = int(uint(_S10));
- int _S15 = int(uint(_S11));
- hitObjectRecordHitWithIndexNV(hitObj_0, scene_0, _S13, _S14, _S15, 0U, 0U, _S12.Origin_0, _S12.TMin_0, _S12.Direction_0, _S12.TMax_0, (0));
+ int _S16 = int(_S10);
+ int _S17 = int(_S12);
+ int _S18 = int(_S14);
+ hitObjectRecordHitWithIndexNV(hitObj_0, scene_0, _S16, _S17, _S18, 0U, 0U, _S15.Origin_0, _S15.TMin_0, _S15.Direction_0, _S15.TMax_0, (0));
uint r_3 = calcValue_0(hitObj_0);
- RayDesc_0 _S16 = ray_2;
+ uint _S19 = uint(idx_0);
+ uint _S20 = uint(_S11);
+ uint _S21 = uint(_S13);
+ RayDesc_0 _S22 = ray_2;
hitObjectNV hitObj_1;
- int _S17 = int(uint(idx_0));
- int _S18 = int(uint(_S11));
- int _S19 = int(uint(_S10));
- hitObjectRecordHitNV(hitObj_1, scene_0, _S17, _S18, _S19, 0U, 0U, 4U, _S16.Origin_0, _S16.TMin_0, _S16.Direction_0, _S16.TMax_0, (0));
- uint _S20 = calcValue_0(hitObj_1);
- uint r_4 = r_3 + _S20;
+ int _S23 = int(_S19);
+ int _S24 = int(_S21);
+ int _S25 = int(_S20);
+ hitObjectRecordHitNV(hitObj_1, scene_0, _S23, _S24, _S25, 0U, 0U, 4U, _S22.Origin_0, _S22.TMin_0, _S22.Direction_0, _S22.TMax_0, (0));
+ uint _S26 = calcValue_0(hitObj_1);
+ uint r_4 = r_3 + _S26;
((outputBuffer_0)._data[(uint(idx_0))]) = r_4;
return;
}
diff --git a/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-make-miss.slang.1.expected b/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-make-miss.slang.1.expected
index 2bedf5743..3afe48bc9 100644
--- a/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-make-miss.slang.1.expected
+++ b/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-make-miss.slang.1.expected
@@ -27,11 +27,12 @@ void main()
ray_0.TMin_0 = 0.00999999977648258209;
ray_0.Direction_0 = vec3(0.0, 1.0, 0.0);
ray_0.TMax_0 = 10000.0;
+ uint _S2 = uint(idx_0);
hitObjectNV hitObj_0;
- hitObjectRecordMissNV(hitObj_0, uint(idx_0), ray_0.Origin_0, ray_0.TMin_0, ray_0.Direction_0, ray_0.TMax_0);
- bool _S2 = (hitObjectIsMissNV((hitObj_0)));
- uint _S3 = uint(int(_S2));
- ((outputBuffer_0)._data[(uint(idx_0))]) = _S3;
+ hitObjectRecordMissNV(hitObj_0, _S2, ray_0.Origin_0, ray_0.TMin_0, ray_0.Direction_0, ray_0.TMax_0);
+ bool _S3 = (hitObjectIsMissNV((hitObj_0)));
+ uint _S4 = uint(int(_S3));
+ ((outputBuffer_0)._data[(uint(idx_0))]) = _S4;
return;
}
diff --git a/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-output.slang b/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-output.slang
new file mode 100644
index 000000000..e8afaf217
--- /dev/null
+++ b/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-output.slang
@@ -0,0 +1,109 @@
+// hit-object-output.slang
+
+// This test validates that `HitObject`s can be used
+// as function results (including `out` parameters)
+
+//TEST:SIMPLE: -target dxil -entry rayGenerationMain -stage raygeneration -profile sm_6_5 -DNV_SHADER_EXTN_SLOT=u0
+//TEST:SIMPLE: -target glsl -entry rayGenerationMain -stage raygeneration -profile sm_6_5 -line-directive-mode none
+
+//DISABLE_TEST(compute):COMPARE_COMPUTE:-d3d12 -output-using-type -use-dxil -profile sm_6_5 -render-feature ray-query
+//DISABLE_TEST(compute):COMPARE_COMPUTE:-vk -output-using-type -render-feature ray-query
+
+//TEST_INPUT: set scene = AccelerationStructure
+uniform RaytracingAccelerationStructure scene;
+
+//TEST_INPUT:set outputBuffer = out ubuffer(data=[0, 0, 0, 0], stride=4)
+RWStructuredBuffer<uint> outputBuffer;
+
+struct MyAttributes
+{
+ uint value;
+};
+
+struct MyRayPayload
+{
+ uint value;
+};
+
+void accumulate(inout uint value, HitObject hit)
+{
+ value = value*256;
+
+ if (hit.IsHit())
+ {
+ value += 16 + hit.GetAttributes<MyAttributes>().value;
+ }
+}
+
+RayDesc makeRay(uint idx, uint variation)
+{
+ RayDesc ray;
+ ray.Origin = float3(idx, 0, variation);
+ ray.TMin = 0.01f;
+ ray.Direction = float3(0, 1, 0);
+ ray.TMax = 1e4f;
+ return ray;
+}
+
+HitObject myTraceRay(uint idx)
+{
+ MyRayPayload payload = { idx };
+
+ RayDesc ray = makeRay(idx, 0);
+
+ RAY_FLAG rayFlags = RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH | RAY_FLAG_CULL_BACK_FACING_TRIANGLES;
+ uint instanceInclusionMask = 0xff;
+ uint rayContributionToHitGroupIndex = 0;
+ uint multiplierForGeometryContributionToHitGroupIndex = 4;
+ uint missShaderIndex = 0;
+
+ HitObject hit = HitObject::TraceRay(scene,
+ rayFlags,
+ instanceInclusionMask,
+ rayContributionToHitGroupIndex,
+ multiplierForGeometryContributionToHitGroupIndex,
+ missShaderIndex,
+ ray,
+ payload);
+
+ return hit;
+}
+
+void copyHitObjectHandle(
+ out HitObject dst,
+ HitObject src)
+{
+ dst = src;
+}
+
+void myMakeMiss(
+ uint idx,
+ inout HitObject h)
+{
+ RayDesc ray = makeRay(idx, 1);
+ h = HitObject::MakeMiss(idx, ray);
+}
+
+void rayGenerationMain()
+{
+ uint idx = uint(DispatchRaysIndex().x);
+
+ uint r = 0;
+
+ HitObject hit = myTraceRay(idx);
+
+ accumulate(r, hit);
+
+ HitObject hit2;
+ copyHitObjectHandle(hit2, hit);
+
+ accumulate(r, hit2);
+
+ HitObject hitBackup = hit;
+ myMakeMiss(idx, hit);
+
+ accumulate(r, hit);
+ accumulate(r, hitBackup);
+
+ outputBuffer[idx] = r;
+}
diff --git a/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-output.slang.1.expected b/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-output.slang.1.expected
new file mode 100644
index 000000000..f5e7908af
--- /dev/null
+++ b/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-output.slang.1.expected
@@ -0,0 +1,93 @@
+result code = 0
+standard error = {
+}
+standard output = {
+#version 460
+#extension GL_EXT_ray_tracing : require
+#extension GL_NV_shader_invocation_reorder : require
+layout(row_major) uniform;
+layout(row_major) buffer;
+layout(binding = 0)
+uniform accelerationStructureEXT scene_0;
+
+layout(std430, binding = 1) buffer _S1 {
+ uint _data[];
+} outputBuffer_0;
+struct MyAttributes_0
+{
+ uint value_0;
+};
+
+layout(location = 0)
+hitObjectAttributeNV
+MyAttributes_0 t_0;
+
+struct MyRayPayload_0
+{
+ uint value_1;
+};
+
+layout(location = 0)
+rayPayloadEXT
+MyRayPayload_0 p_0;
+
+struct RayDesc_0
+{
+ vec3 Origin_0;
+ float TMin_0;
+ vec3 Direction_0;
+ float TMax_0;
+};
+
+RayDesc_0 makeRay_0(uint idx_0, uint variation_0)
+{
+ RayDesc_0 ray_0;
+ ray_0.Origin_0 = vec3(float(idx_0), 0.0, float(variation_0));
+ ray_0.TMin_0 = 0.00999999977648258209;
+ ray_0.Direction_0 = vec3(0.0, 1.0, 0.0);
+ ray_0.TMax_0 = 10000.0;
+ return ray_0;
+}
+
+MyAttributes_0 HitObject_GetAttributes_0(hitObjectNV this_0)
+{
+ hitObjectGetAttributesNV((this_0), ((0)));
+ return t_0;
+}
+
+void accumulate_0(inout uint value_2, hitObjectNV hit_0)
+{
+ value_2 = value_2 * 256U;
+ bool _S2 = (hitObjectIsHitNV((hit_0)));
+ if(_S2)
+ {
+ MyAttributes_0 _S3 = HitObject_GetAttributes_0(hit_0);
+ value_2 = value_2 + (16U + _S3.value_0);
+ }
+ else
+ {
+ }
+ return;
+}
+
+void main()
+{
+ uvec3 _S4 = ((gl_LaunchIDEXT));
+ uint idx_1 = _S4.x;
+ uint r_0 = 0U;
+ RayDesc_0 ray_1 = makeRay_0(idx_1, 0U);
+ hitObjectNV hitObj_0;
+ p_0.value_1 = idx_1;
+ hitObjectTraceRayNV(hitObj_0, scene_0, 20U, 255U, 0U, 4U, 0U, ray_1.Origin_0, ray_1.TMin_0, ray_1.Direction_0, ray_1.TMax_0, (0));
+ accumulate_0(r_0, hitObj_0);
+ accumulate_0(r_0, hitObj_0);
+ RayDesc_0 ray_2 = makeRay_0(idx_1, 1U);
+ hitObjectNV hitObj_1;
+ hitObjectRecordMissNV(hitObj_1, idx_1, ray_2.Origin_0, ray_2.TMin_0, ray_2.Direction_0, ray_2.TMax_0);
+ accumulate_0(r_0, hitObj_1);
+ accumulate_0(r_0, hitObj_0);
+ ((outputBuffer_0)._data[(idx_1)]) = r_0;
+ return;
+}
+
+}
diff --git a/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-reorder-thread.slang.1.expected b/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-reorder-thread.slang.1.expected
index 1d3bcc227..09c410591 100644
--- a/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-reorder-thread.slang.1.expected
+++ b/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-reorder-thread.slang.1.expected
@@ -87,9 +87,9 @@ void main()
ray_0.Direction_0 = vec3(0.0, 1.0, 0.0);
ray_0.TMax_0 = 10000.0;
RayDesc_0 _S7 = ray_0;
+ hitObjectNV hitObj_0;
p_1.a_0 = idx_0;
p_1.b_0 = _S6;
- hitObjectNV hitObj_0;
hitObjectTraceRayNV(hitObj_0, scene_0, 20U, 255U, 0U, 4U, 0U, _S7.Origin_0, _S7.TMin_0, _S7.Direction_0, _S7.TMax_0, (1));
uint r_1 = calcValue_0(hitObj_0);
reorderThreadNV(hitObj_0);
diff --git a/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-trace-motion-ray.slang.1.expected b/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-trace-motion-ray.slang.1.expected
index ccd693835..d95a41336 100644
--- a/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-trace-motion-ray.slang.1.expected
+++ b/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-trace-motion-ray.slang.1.expected
@@ -77,9 +77,9 @@ void main()
ray_0.Direction_0 = vec3(0.0, 1.0, 0.0);
ray_0.TMax_0 = 10000.0;
RayDesc_0 _S7 = ray_0;
+ hitObjectNV hitObj_0;
p_0.a_0 = idx_0;
p_0.b_0 = _S6;
- hitObjectNV hitObj_0;
hitObjectTraceRayMotionNV(hitObj_0, scene_0, 20U, 255U, 0U, 4U, 0U, _S7.Origin_0, _S7.TMin_0, _S7.Direction_0, _S7.TMax_0, currentTime_0, (0));
uint _S8 = uint(idx_0);
uint _S9 = calcValue_0(hitObj_0);
diff --git a/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-trace-ray.slang.1.expected b/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-trace-ray.slang.1.expected
index cf36e4623..253e5f50e 100644
--- a/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-trace-ray.slang.1.expected
+++ b/tests/hlsl-intrinsic/shader-execution-reordering/hit-object-trace-ray.slang.1.expected
@@ -75,9 +75,9 @@ void main()
ray_0.Direction_0 = vec3(0.0, 1.0, 0.0);
ray_0.TMax_0 = 10000.0;
RayDesc_0 _S7 = ray_0;
+ hitObjectNV hitObj_0;
p_0.a_0 = idx_0;
p_0.b_0 = _S6;
- hitObjectNV hitObj_0;
hitObjectTraceRayNV(hitObj_0, scene_0, 20U, 255U, 0U, 4U, 0U, _S7.Origin_0, _S7.TMin_0, _S7.Direction_0, _S7.TMax_0, (0));
uint _S8 = uint(idx_0);
uint _S9 = calcValue_0(hitObj_0);
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;
}
-