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 | |
| 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
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; } - |
