diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2022-11-15 15:27:28 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-11-15 15:27:28 -0500 |
| commit | 4917d71100aafcc38a81cd99d2a44a4cb3a89a0c (patch) | |
| tree | 8e474c4f5a7db41ef1c1f2230f36f57fb4c6f446 /source | |
| parent | 7222b6cdb1ed192b267e91896b1f56da3f0c21d6 (diff) | |
Shader Execution Reordering for VK (#2491)
* #include an absolute path didn't work - because paths were taken to always be relative.
* Fixes around MakeMiss.
* Add preliminary support for HitObject::MakeHit.
* Make Nop.
* Add HitObject::TraceRay.
* HitObject::Invoke for VK.
* Remove line numbers from SER GLSL output.
* Add support for HitObjectAttributes
Add support for GLSL HitObject.GetAttributes<T>()
Simplified code around getting locations.
* Be more explicit about requiring GL_EXT_ray_tracing in SER.
* Split out LocationTracker from CLikeEmitter.
* Small doc improvements.
* Add motion ray support.
* Use inlining to get correct GLSL behavior around hitObjectNV.
* Add assignment HitObject test.
* Add a HitObject array test. Shows doesn't work correctly for VK/GLSL.
* Add call to `hitObjectGetAttributesNV` before getting attributes.
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/core.meta.slang | 3 | ||||
| -rw-r--r-- | source/slang/hlsl.meta.slang | 660 | ||||
| -rw-r--r-- | source/slang/slang-ast-modifier.h | 10 | ||||
| -rw-r--r-- | source/slang/slang-check-modifier.cpp | 9 | ||||
| -rwxr-xr-x | source/slang/slang-compiler.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-emit-c-like.cpp | 90 | ||||
| -rw-r--r-- | source/slang/slang-emit-c-like.h | 57 | ||||
| -rw-r--r-- | source/slang/slang-emit-glsl.cpp | 71 | ||||
| -rw-r--r-- | source/slang/slang-intrinsic-expand.cpp | 75 | ||||
| -rw-r--r-- | source/slang/slang-ir-inst-defs.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-ir-insts.h | 11 | ||||
| -rw-r--r-- | source/slang/slang-ir.cpp | 1 | ||||
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 6 |
13 files changed, 820 insertions, 177 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index e1eb9c776..0a6278ec1 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -2797,6 +2797,9 @@ __attributeTarget(VarDeclBase) attribute_syntax [__vulkanCallablePayload(location : int = -1)] : VulkanCallablePayloadAttribute; __attributeTarget(VarDeclBase) +attribute_syntax [__vulkanHitObjectAttributes(location : int = -1)] : VulkanHitObjectAttributesAttribute; + +__attributeTarget(VarDeclBase) attribute_syntax [__vulkanHitAttributes] : VulkanHitAttributesAttribute; __attributeTarget(FunctionDeclBase) diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index 2a9a9f9d3..81df2b5e4 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -5557,12 +5557,44 @@ struct VkSubpassInputMS<T> /// /// https://developer.nvidia.com/rtx/path-tracing/nvapi/get-started /// +/// For VK the specification is currently in this PR +/// +/// https://github.com/KhronosGroup/GLSL/pull/196/files + +/// Internal helper functions + +// This is a bit of a hack for GLSL HitObjectAttributes +// It relies on [ForceInline] removing the surrounding function and just inserting the *contained* `t` as a global +// The __ref should indicate the desire for the returned value to not be a copy of t, but *t*. +// In practive __ref doesn't have this effect in practice. +// +// We need this to be able access the payload outside of a function (which is all that TraceRay for example needs) +// We access the HitObjectAttributes via this function for the desired type, and it acts *as if* it's just an access +// to the global t. +[ForceInline] +__ref T __hitObjectAttributes<T>() +{ + [__vulkanHitObjectAttributes] + static T t; + return t; +} + +// Next is the custom intrinsic that will compute the hitObjectAttributes location +// for GLSL-based targets. +// +__generic<Payload> +__target_intrinsic(__glslRayTracing, "$XH") +[__readNone] +int __hitObjectAttributesLocation(Payload payload); /// Immutable data type representing a ray hit or a miss. Can be used to invoke hit or miss shading, /// 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. -__target_intrinsic(hlsl, NvHitObject) [__requiresNVAPI] +__target_intrinsic(hlsl, NvHitObject) +__glsl_extension(GL_NV_shader_invocation_reorder) +__glsl_extension(GL_EXT_ray_tracing) +__target_intrinsic(glsl, hitObjectNV) struct HitObject { /// Executes ray traversal (including anyhit and intersection shaders) like TraceRay, but returns the @@ -5577,20 +5609,104 @@ struct HitObject uint MissShaderIndex, RayDesc Ray, inout payload_t Payload) - { - HitObject hitObj; - __traceRay( - AccelerationStructure, - RayFlags, - InstanceInclusionMask, - RayContributionToHitGroupIndex, - MultiplierForGeometryContributionToHitGroupIndex, - MissShaderIndex, - Ray, - Payload, - hitObj); - return hitObj; - } + { + HitObject hitObj; + __hlslTraceRay( + AccelerationStructure, + RayFlags, + InstanceInclusionMask, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + Ray, + Payload, + hitObj); + return hitObj; + } + + [ForceInline] + __specialized_for_target(glsl) + static HitObject TraceRay<payload_t>( + RaytracingAccelerationStructure AccelerationStructure, + uint RayFlags, + uint InstanceInclusionMask, + uint RayContributionToHitGroupIndex, + uint MultiplierForGeometryContributionToHitGroupIndex, + uint MissShaderIndex, + RayDesc Ray, + inout payload_t Payload) + { + HitObject hitObj; + + [__vulkanRayPayload] + static payload_t p; + + // Save the payload + p = Payload; + + __glslTraceRay( + hitObj, + AccelerationStructure, + RayFlags, // Assumes D3D/VK have some RayFlags values + InstanceInclusionMask, // cullMask + RayContributionToHitGroupIndex, // sbtRecordOffset + MultiplierForGeometryContributionToHitGroupIndex, // sbtRecordStride + MissShaderIndex, + Ray.Origin, + Ray.TMin, + Ray.Direction, + Ray.TMax, + __rayPayloadLocation(p)); + + // Write the payload out + Payload = p; + + return hitObj; + } + + /// Executes motion 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. + [ForceInline] + __specialized_for_target(glsl) + static HitObject TraceMotionRay<payload_t>( + RaytracingAccelerationStructure AccelerationStructure, + uint RayFlags, + uint InstanceInclusionMask, + uint RayContributionToHitGroupIndex, + uint MultiplierForGeometryContributionToHitGroupIndex, + uint MissShaderIndex, + RayDesc Ray, + float CurrentTime, + inout payload_t Payload) + { + HitObject hitObj; + + [__vulkanRayPayload] + static payload_t p; + + // Save the payload + p = Payload; + + __glslTraceMotionRay( + hitObj, + AccelerationStructure, + RayFlags, // Assumes D3D/VK have some RayFlags values + InstanceInclusionMask, // cullMask + RayContributionToHitGroupIndex, // sbtRecordOffset + MultiplierForGeometryContributionToHitGroupIndex, // sbtRecordStride + MissShaderIndex, + Ray.Origin, + Ray.TMin, + Ray.Direction, + Ray.TMax, + CurrentTime, + __rayPayloadLocation(p)); + + // Write the payload out + Payload = p; + + return hitObj; + } /// Creates a HitObject representing a hit based on values explicitly passed as arguments, without /// tracing a ray. The primitive specified by AccelerationStructure, InstanceIndex, GeometryIndex, @@ -5611,8 +5727,8 @@ struct HitObject attr_t attributes) { HitObject hitObj; - __makeHit( - AccelerationStructure, + __hlslMakeHit( + AccelerationStructure, InstanceIndex, GeometryIndex, PrimitiveIndex, @@ -5625,6 +5741,84 @@ struct HitObject return hitObj; } + [ForceInline] + __specialized_for_target(glsl) + static HitObject MakeHit<attr_t>( + RaytracingAccelerationStructure AccelerationStructure, + uint InstanceIndex, + uint GeometryIndex, + uint PrimitiveIndex, + uint HitKind, + uint RayContributionToHitGroupIndex, + uint MultiplierForGeometryContributionToHitGroupIndex, + RayDesc Ray, + attr_t attributes) + { + HitObject hitObj; + + // Save the attributes + __ref attr_t attr = __hitObjectAttributes<attr_t>(); + + attr = attributes; + + __glslMakeHit(hitObj, + AccelerationStructure, + InstanceIndex, + PrimitiveIndex, + GeometryIndex, + HitKind, + RayContributionToHitGroupIndex, /// sbtRecordOffset? + MultiplierForGeometryContributionToHitGroupIndex, /// sbtRecordStride? + Ray.Origin, + Ray.TMin, + Ray.Direction, + Ray.TMax, + __hitObjectAttributesLocation(__hitObjectAttributes<attr_t>())); + + return hitObj; + } + + /// See MakeHit but handles Motion + /// Currently only supported on VK + [ForceInline] + __specialized_for_target(glsl) + static HitObject MakeMotionHit<attr_t>( + RaytracingAccelerationStructure AccelerationStructure, + uint InstanceIndex, + uint GeometryIndex, + uint PrimitiveIndex, + uint HitKind, + uint RayContributionToHitGroupIndex, + uint MultiplierForGeometryContributionToHitGroupIndex, + RayDesc Ray, + float CurrentTime, + attr_t attributes) + { + HitObject hitObj; + + // Save the attributes + __ref attr_t attr = __hitObjectAttributes<attr_t>(); + + attr = attributes; + + __glslMakeMotionHit(hitObj, + AccelerationStructure, + InstanceIndex, + PrimitiveIndex, + GeometryIndex, + HitKind, + RayContributionToHitGroupIndex, /// sbtRecordOffset? + MultiplierForGeometryContributionToHitGroupIndex, /// sbtRecordStride? + Ray.Origin, + Ray.TMin, + Ray.Direction, + Ray.TMax, + CurrentTime, + __hitObjectAttributesLocation(__hitObjectAttributes<attr_t>())); + + return hitObj; + } + /// Creates a HitObject representing a hit based on values explicitly passed as arguments, without /// tracing a ray. The primitive specified by AccelerationStructure, InstanceIndex, GeometryIndex, /// and PrimitiveIndex must exist. The shader table index is explicitly provided as an argument @@ -5644,9 +5838,9 @@ struct HitObject attr_t attributes) { HitObject hitObj; - __makeHitWithRecordIndex( - HitGroupRecordIndex, - AccelerationStructure, + __hlslMakeHitWithRecordIndex( + HitGroupRecordIndex, + AccelerationStructure, InstanceIndex, GeometryIndex, PrimitiveIndex, @@ -5657,81 +5851,221 @@ struct HitObject return hitObj; } + [ForceInline] + __specialized_for_target(glsl) + static HitObject MakeHit<attr_t>( + uint HitGroupRecordIndex, + RaytracingAccelerationStructure AccelerationStructure, + uint InstanceIndex, + uint GeometryIndex, + uint PrimitiveIndex, + uint HitKind, + RayDesc Ray, + attr_t attributes) + { + HitObject hitObj; + + // Save the attributes + __ref attr_t attr = __hitObjectAttributes<attr_t>(); + attr = attributes; + + __glslMakeHitWithIndex(hitObj, + AccelerationStructure, + InstanceIndex, ///? Same as instanceid ? + GeometryIndex, + PrimitiveIndex, + HitKind, /// Assuming HitKinds are compatible + HitGroupRecordIndex, /// sbtRecordIndex + Ray.Origin, + Ray.TMin, + Ray.Direction, + Ray.TMax, + __hitObjectAttributesLocation(__hitObjectAttributes<attr_t>())); + + return hitObj; + } + + /// See MakeHit but handles Motion + /// Currently only supported on VK + [ForceInline] + __specialized_for_target(glsl) + static HitObject MakeMotionHit<attr_t>( + uint HitGroupRecordIndex, + RaytracingAccelerationStructure AccelerationStructure, + uint InstanceIndex, + uint GeometryIndex, + uint PrimitiveIndex, + uint HitKind, + RayDesc Ray, + float CurrentTime, + attr_t attributes) + { + HitObject hitObj; + + // Save the attributes + __ref attr_t attr = __hitObjectAttributes<attr_t>(); + attr = attributes; + + __glslMakeMotionHitWithIndex(hitObj, + AccelerationStructure, + InstanceIndex, ///? Same as instanceid ? + GeometryIndex, + PrimitiveIndex, + HitKind, /// Assuming HitKinds are compatible + HitGroupRecordIndex, /// sbtRecordIndex + Ray.Origin, + Ray.TMin, + Ray.Direction, + Ray.TMax, + CurrentTime, + __hitObjectAttributesLocation(__hitObjectAttributes<attr_t>())); + + return hitObj; + } + /// Creates a HitObject representing a miss based on values explicitly passed as arguments, without /// tracing a ray. The provided shader table index must reference a valid miss record in the shader /// table. - __target_intrinsic(hlsl, "NvMakeMiss") [__requiresNVAPI] - static HitObject MakeMiss( - uint MissShaderIndex, + __target_intrinsic(hlsl, "NvMakeMiss") + static HitObject MakeMiss( + uint MissShaderIndex, RayDesc Ray); + [ForceInline] + __specialized_for_target(glsl) + static HitObject MakeMiss( + uint MissShaderIndex, + RayDesc Ray) + { + HitObject hitObj; + __glslMakeMiss(hitObj, MissShaderIndex, Ray.Origin, Ray.TMin, Ray.Direction, Ray.TMax); + return hitObj; + } + + /// See MakeMiss but handles Motion + /// Currently only supported on VK + [ForceInline] + __specialized_for_target(glsl) + static HitObject MakeMotionMiss( + uint MissShaderIndex, + RayDesc Ray, + float CurrentTime) + { + HitObject hitObj; + __glslMakeMotionMiss(hitObj, MissShaderIndex, Ray.Origin, Ray.TMin, Ray.Direction, Ray.TMax, CurrentTime); + return hitObj; + } + /// Creates a HitObject representing “NOP” (no operation) which is neither a hit nor a miss. Invoking a /// NOP hit object using HitObject::Invoke has no effect. Reordering by hit objects using /// ReorderThread will group NOP hit objects together. This can be useful in some reordering /// scenarios where future control flow for some threads is known to process neither a hit nor a /// miss. - __target_intrinsic(hlsl, "NvMakeNop") [__requiresNVAPI] + __target_intrinsic(hlsl, "NvMakeNop") static HitObject MakeNop(); + [ForceInline] + __specialized_for_target(glsl) + static HitObject MakeNop() + { + HitObject hitObj; + __glslMakeNop(hitObj); + return hitObj; + } + /// Invokes closesthit or miss shading for the specified hit object. In case of a NOP HitObject, no /// shader is invoked. - __target_intrinsic(hlsl, "NvInvokeHitObject") [__requiresNVAPI] + __target_intrinsic(hlsl, "NvInvokeHitObject") static void Invoke<payload_t>( RaytracingAccelerationStructure AccelerationStructure, HitObject HitOrMiss, inout payload_t Payload); + __specialized_for_target(glsl) + static void Invoke<payload_t>( + RaytracingAccelerationStructure AccelerationStructure, + HitObject HitOrMiss, + inout payload_t Payload) + { + [__vulkanRayPayload] + static payload_t p; + + // Save the payload + p = Payload; + + __glslInvoke(HitOrMiss, __rayPayloadLocation(p)); + + // Write payload result + Payload = p; + } + /// Returns true if the HitObject encodes a miss, otherwise returns false. - __target_intrinsic(hlsl) [__requiresNVAPI] + __target_intrinsic(hlsl) + __target_intrinsic(glsl, "hitObjectIsMissNV($0)") bool IsMiss(); /// Returns true if the HitObject encodes a hit, otherwise returns false. - __target_intrinsic(hlsl) [__requiresNVAPI] + __target_intrinsic(hlsl) + __target_intrinsic(glsl, "hitObjectIsHitNV($0)") bool IsHit(); /// Returns true if the HitObject encodes a nop, otherwise returns false. - __target_intrinsic(hlsl) [__requiresNVAPI] + __target_intrinsic(hlsl) + __target_intrinsic(glsl, "hitObjectIsEmptyNV($0)") bool IsNop(); /// Queries ray properties from HitObject. Valid if the hit object represents a hit or a miss. - __target_intrinsic(hlsl) [__requiresNVAPI] + __target_intrinsic(hlsl) RayDesc GetRayDesc(); + __specialized_for_target(glsl) + RayDesc GetRayDesc() + { + RayDesc ray = { __glslGetRayWorldOrigin(), __glslGetTMin(), __glslGetRayDirection(), __glslGetTMax() }; + return ray; + } + /// Queries shader table index from HitObject. Valid if the hit object represents a hit or a miss. - __target_intrinsic(hlsl) [__requiresNVAPI] + __target_intrinsic(hlsl) + __target_intrinsic(glsl, "hitObjectGetShaderBindingTableRecordIndexNV($0)") uint GetShaderTableIndex(); /// Returns the instance index of a hit. Valid if the hit object represents a hit. - __target_intrinsic(hlsl) [__requiresNVAPI] + __target_intrinsic(hlsl) + __target_intrinsic(glsl, "hitObjectGetInstanceCustomIndexNV($0)") uint GetInstanceIndex(); /// Returns the instance ID of a hit. Valid if the hit object represents a hit. - __target_intrinsic(hlsl) [__requiresNVAPI] + __target_intrinsic(hlsl) + __target_intrinsic(glsl, "hitObjectGetInstanceIdNV($0)") uint GetInstanceID(); /// Returns the geometry index of a hit. Valid if the hit object represents a hit. - __target_intrinsic(hlsl) [__requiresNVAPI] + __target_intrinsic(hlsl) + __target_intrinsic(glsl, "hitObjectGetGeometryIndexNV($0)") uint GetGeometryIndex(); /// Returns the primitive index of a hit. Valid if the hit object represents a hit. - __target_intrinsic(hlsl) [__requiresNVAPI] + __target_intrinsic(hlsl) + __target_intrinsic(glsl, "hitObjectGetPrimitiveIndexNV($0)") uint GetPrimitiveIndex(); /// Returns the hit kind. Valid if the hit object represents a hit. - __target_intrinsic(hlsl) [__requiresNVAPI] + __target_intrinsic(hlsl) + __target_intrinsic(glsl, "hitObjectGetHitKindNV($0)") uint GetHitKind(); /// Returns the attributes of a hit. Valid if the hit object represents a hit or a miss. @@ -5739,61 +6073,245 @@ struct HitObject attr_t GetAttributes<attr_t>() { attr_t v; - __getAttributesFromHitObject(v); + __hlslGetAttributesFromHitObject(v); return v; } + __specialized_for_target(glsl) + attr_t GetAttributes<attr_t>() + { + // Work out the location + int attributeLocation = __hitObjectAttributesLocation(__hitObjectAttributes<attr_t>()); + + // Load the attributes from the location + __glslGetAttributes(attributeLocation); + + // Return the attributes + return __hitObjectAttributes<attr_t>(); + } /// Loads a root constant from the local root table referenced by the hit object. Valid if the hit object /// represents a hit or a miss. RootConstantOffsetInBytes must be a multiple of 4. __target_intrinsic(hlsl) [__requiresNVAPI] uint LoadLocalRootTableConstant(uint RootConstantOffsetInBytes); - /// - /// !!!! Internal impl. Do not use! - /// + /// + /// !!!! Internal NVAPI HLSL impl. Not part of interface! !!!!!!!!!!!! + /// __target_intrinsic(hlsl, "NvGetAttributesFromHitObject($0, $1)") [__requiresNVAPI] - void __getAttributesFromHitObject<T>(out T t); + void __hlslGetAttributesFromHitObject<T>(out T t); __target_intrinsic(hlsl, "NvMakeHitWithRecordIndex") [__requiresNVAPI] - static void __makeHitWithRecordIndex<attr_t>(uint HitGroupRecordIndex, - RaytracingAccelerationStructure AccelerationStructure, - uint InstanceIndex, - uint GeometryIndex, - uint PrimitiveIndex, - uint HitKind, - RayDesc Ray, - attr_t attributes, + static void __hlslMakeHitWithRecordIndex<attr_t>(uint HitGroupRecordIndex, + RaytracingAccelerationStructure AccelerationStructure, + uint InstanceIndex, + uint GeometryIndex, + uint PrimitiveIndex, + uint HitKind, + RayDesc Ray, + attr_t attributes, out HitObject hitObj); __target_intrinsic(hlsl, "NvMakeHit") [__requiresNVAPI] - static void __makeHit<attr_t>(RaytracingAccelerationStructure AccelerationStructure, - uint InstanceIndex, - uint GeometryIndex, - uint PrimitiveIndex, - uint HitKind, - uint RayContributionToHitGroupIndex, - uint MultiplierForGeometryContributionToHitGroupIndex, - RayDesc Ray, - attr_t attributes, + static void __hlslMakeHit<attr_t>(RaytracingAccelerationStructure AccelerationStructure, + uint InstanceIndex, + uint GeometryIndex, + uint PrimitiveIndex, + uint HitKind, + uint RayContributionToHitGroupIndex, + uint MultiplierForGeometryContributionToHitGroupIndex, + RayDesc Ray, + attr_t attributes, out HitObject hitObj); __target_intrinsic(hlsl, "NvTraceRayHitObject") [__requiresNVAPI] - static void __traceRay<payload_t>( - RaytracingAccelerationStructure AccelerationStructure, - uint RayFlags, - uint InstanceInclusionMask, - uint RayContributionToHitGroupIndex, - uint MultiplierForGeometryContributionToHitGroupIndex, - uint MissShaderIndex, - RayDesc Ray, + static void __hlslTraceRay<payload_t>( + RaytracingAccelerationStructure AccelerationStructure, + uint RayFlags, + uint InstanceInclusionMask, + uint RayContributionToHitGroupIndex, + uint MultiplierForGeometryContributionToHitGroupIndex, + uint MissShaderIndex, + RayDesc Ray, inout payload_t Payload, out HitObject hitObj); + + /// + /// !!!! Internal GLSL GL_NV_shader_invocation_reorder impl. Not part of interface! !!!!!!!!!!!! + /// + + __glsl_extension(GL_NV_shader_invocation_reorder) + __glsl_extension(GL_EXT_ray_tracing) + __target_intrinsic(glsl, "hitObjectRecordMissNV") + static void __glslMakeMiss( + HitObject hitObj, + uint MissShaderIndex, + float3 Origin, + float TMin, + float3 Direction, + float TMax); + + __glsl_extension(GL_NV_shader_invocation_reorder) + __glsl_extension(GL_EXT_ray_tracing) + __glsl_extension(GLSL_NV_ray_tracing_motion_blur) + __target_intrinsic(glsl, "hitObjectRecordMissNV") + static void __glslMakeMotionMiss( + HitObject hitObj, + uint MissShaderIndex, + float3 Origin, + float TMin, + float3 Direction, + float TMax, + float CurrentTime); + + __glsl_extension(GL_NV_shader_invocation_reorder) + __glsl_extension(GL_EXT_ray_tracing) + __target_intrinsic(glsl, "hitObjectRecordEmptyNV($0)") + static void __glslMakeNop(HitObject hitObj); + + __glsl_extension(GL_NV_shader_invocation_reorder) + __target_intrinsic(glsl, "hitObjectGetObjectRayDirectionNV($0)") + float3 __glslGetRayDirection(); + + __glsl_extension(GL_NV_shader_invocation_reorder) + __target_intrinsic(glsl, "hitObjectGetWorldRayOriginNV($0)") + float3 __glslGetRayWorldOrigin(); + + __glsl_extension(GL_NV_shader_invocation_reorder) + __target_intrinsic(glsl, "hitObjectGetRayTMaxNV($0)") + float __glslGetTMax(); + + __glsl_extension(GL_NV_shader_invocation_reorder) + __target_intrinsic(glsl, "hitObjectGetRayTMinNV($0)") + float __glslGetTMin(); + + __glsl_extension(GL_NV_shader_invocation_reorder) + __glsl_extension(GL_EXT_ray_tracing) + __target_intrinsic(glsl, "hitObjectRecordHitWithIndexNV") + static void __glslMakeHitWithIndex( + HitObject hitObj, + RaytracingAccelerationStructure accelerationStructure, + uint instanceid, + uint primitiveid, + uint geometryindex, + uint hitKind, + uint sbtRecordIndex, + float3 origin, + float Tmin, + float3 direction, + float Tmax, + int attributeLocation); + + __glsl_extension(GL_NV_shader_invocation_reorder) + __glsl_extension(GL_EXT_ray_tracing) + __glsl_extension(GLSL_NV_ray_tracing_motion_blur) + __target_intrinsic(glsl, "hitObjectRecordHitWithIndexMotionNV ") + static void __glslMakeMotionHitWithIndex( + HitObject hitObj, + RaytracingAccelerationStructure accelerationStructure, + uint instanceid, + uint primitiveid, + uint geometryindex, + uint hitKind, + uint sbtRecordIndex, + float3 origin, + float Tmin, + float3 direction, + float Tmax, + float CurrentTime, + int attributeLocation); + + __glsl_extension(GL_EXT_ray_tracing) + __glsl_extension(GL_NV_shader_invocation_reorder) + __target_intrinsic(glsl, "hitObjectRecordHitNV") + static void __glslMakeHit( + HitObject hitObj, + RaytracingAccelerationStructure accelerationStructure, + uint instanceid, + uint primitiveid, + uint geometryindex, + uint hitKind, + uint sbtRecordOffset, + uint sbtRecordStride, + float3 origin, + float Tmin, + float3 direction, + float Tmax, + int attributeLocation); + + __glsl_extension(GL_EXT_ray_tracing) + __glsl_extension(GL_NV_shader_invocation_reorder) + __glsl_extension(GLSL_NV_ray_tracing_motion_blur) + __target_intrinsic(glsl, "hitObjectRecordHitMotionNV") + static void __glslMakeMotionHit( + HitObject hitObj, + RaytracingAccelerationStructure accelerationStructure, + uint instanceid, + uint primitiveid, + uint geometryindex, + uint hitKind, + uint sbtRecordOffset, + uint sbtRecordStride, + float3 origin, + float Tmin, + float3 direction, + float Tmax, + float CurrentTime, + int attributeLocation); + + + __glsl_extension(GL_EXT_ray_tracing) + __glsl_extension(GL_NV_shader_invocation_reorder) + __target_intrinsic(glsl, "hitObjectGetAttributesNV($0, $1)") + void __glslGetAttributes(int attributeLocation); + + __glsl_extension(GL_EXT_ray_tracing) + __glsl_extension(GL_NV_shader_invocation_reorder) + __target_intrinsic(glsl, "hitObjectTraceRayNV") + static void __glslTraceRay( + HitObject hitObj, + RaytracingAccelerationStructure accelerationStructure, + uint rayFlags, + uint cullMask, + uint sbtRecordOffset, + uint sbtRecordStride, + uint missIndex, + float3 origin, + float Tmin, + float3 direction, + float Tmax, + int payload); + + __glsl_extension(GL_EXT_ray_tracing) + __glsl_extension(GL_NV_shader_invocation_reorder) + __glsl_extension(GLSL_NV_ray_tracing_motion_blur) + __target_intrinsic(glsl, "hitObjectTraceRayMotionNV") + static void __glslTraceMotionRay( + HitObject hitObj, + RaytracingAccelerationStructure accelerationStructure, + uint rayFlags, + uint cullMask, + uint sbtRecordOffset, + uint sbtRecordStride, + uint missIndex, + float3 origin, + float Tmin, + float3 direction, + float Tmax, + float currentTime, + int payload); + + __glsl_extension(GL_EXT_ray_tracing) + __glsl_extension(GL_NV_shader_invocation_reorder) + __target_intrinsic(glsl, "hitObjectExecuteShaderNV") + static void __glslInvoke( + HitObject hitObj, + int payload); }; /// Reorders threads based on a coherence hint value. NumCoherenceHintBits indicates how many of @@ -5803,8 +6321,11 @@ struct HitObject /// NumCoherenceHintBits. /// Where possible, reordering will also attempt to retain locality in the thread’s launch indices /// (DispatchRaysIndex in DXR). -__target_intrinsic(hlsl, "NvReorderThread") [__requiresNVAPI] +__target_intrinsic(hlsl, "NvReorderThread") +__glsl_extension(GL_NV_shader_invocation_reorder) +__glsl_extension(GL_EXT_ray_tracing) +__target_intrinsic(glsl, "reorderThreadNV") void ReorderThread( uint CoherenceHint, uint NumCoherenceHintBitsFromLSB ); /// Reorders threads based on a hit object, optionally extended by a coherence hint value. Coherence @@ -5822,8 +6343,11 @@ void ReorderThread( uint CoherenceHint, uint NumCoherenceHintBitsFromLSB ); /// same shader ID. (Miss shaders and NOP HitObjects are grouped separately). Within each of these /// groups, it will attempt to order threads by the value of their coherence hints. And within ranges /// of equal coherence hints, it will attempt to maximize locality in 3D space of the ray hit (if any). -__target_intrinsic(hlsl, "NvReorderThread") [__requiresNVAPI] +__target_intrinsic(hlsl, "NvReorderThread") +__glsl_extension(GL_NV_shader_invocation_reorder) +__glsl_extension(GL_EXT_ray_tracing) +__target_intrinsic(glsl, "reorderThreadNV") void ReorderThread( HitObject HitOrMiss, uint CoherenceHint, uint NumCoherenceHintBitsFromLSB ); /// Is equivalent to @@ -5833,4 +6357,6 @@ void ReorderThread( HitObject HitOrMiss, uint CoherenceHint, uint NumCoherenceHi /// With CoherenceHint and NumCoherenceHintBitsFromLSB as 0, meaning they are ignored. [__requiresNVAPI] __target_intrinsic(hlsl, "NvReorderThread") +__glsl_extension(GL_NV_shader_invocation_reorder) +__target_intrinsic(glsl, "reorderThreadNV") void ReorderThread( HitObject HitOrMiss ); diff --git a/source/slang/slang-ast-modifier.h b/source/slang/slang-ast-modifier.h index 8419facce..9146c21d9 100644 --- a/source/slang/slang-ast-modifier.h +++ b/source/slang/slang-ast-modifier.h @@ -829,6 +829,16 @@ class VulkanHitAttributesAttribute : public Attribute SLANG_AST_CLASS(VulkanHitAttributesAttribute) }; +// A `[__vulkanHitObjectAttributes(location)]` attribute, which is used in the +// standard library implementation to indicate that a variable +// actually represents the attributes on a HitObject as part of +// Shader ExecutionReordering +class VulkanHitObjectAttributesAttribute : public Attribute +{ + SLANG_AST_CLASS(VulkanHitObjectAttributesAttribute) + + int location; +}; // A `[mutating]` attribute, which indicates that a member // function is allowed to modify things through its `this` diff --git a/source/slang/slang-check-modifier.cpp b/source/slang/slang-check-modifier.cpp index b8ac21e2d..aa28571a7 100644 --- a/source/slang/slang-check-modifier.cpp +++ b/source/slang/slang-check-modifier.cpp @@ -604,6 +604,15 @@ namespace Slang callablePayloadAttr->location = (int32_t)val->value; } + else if (auto hitObjectAttributesAttr = as<VulkanHitObjectAttributesAttribute>(attr)) + { + SLANG_ASSERT(attr->args.getCount() == 1); + auto val = checkConstantIntVal(attr->args[0]); + + if (!val) return false; + + hitObjectAttributesAttr->location = (int32_t)val->value; + } else if (auto forwardDerivativeAttr = as<ForwardDerivativeAttribute>(attr)) { SLANG_ASSERT(attr->args.getCount() == 1); diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index eb6d6c1a5..14ac63531 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -2267,7 +2267,7 @@ namespace Slang /// ProgramLayout* getOrCreateLayout(DiagnosticSink* sink); - /// Get the layout for the program on the taarget. + /// Get the layout for the program on the target. /// /// This routine assumes that `getOrCreateLayout` /// has already been called previously. diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp index 09a18a31c..e872bffb1 100644 --- a/source/slang/slang-emit-c-like.cpp +++ b/source/slang/slang-emit-c-like.cpp @@ -41,6 +41,56 @@ struct CLikeSourceEmitter::ComputeEmitActionsContext List<EmitAction>* actions; }; +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!! LocationTracker !!!!!!!!!!!!!!!!!!!!!!!!!! */ + +/* static */LocationTracker::Kind LocationTracker::getKindFromDecoration(IRDecoration* decoration) +{ + switch (decoration->getOp()) + { + case kIROp_VulkanRayPayloadDecoration: return Kind::RayPayload; + case kIROp_VulkanCallablePayloadDecoration: return Kind::CallablePayload; + case kIROp_VulkanHitObjectAttributesDecoration: return Kind::HitObjectAttribute; + default: break; + } + return Kind::Invalid; +} + +Index LocationTracker::getValue(IRInst* inst, IRDecoration* decoration) +{ + const Kind kind = getKindFromDecoration(decoration); + SLANG_RELEASE_ASSERT(kind != Kind::Invalid); + if (kind == Kind::Invalid) + { + return -1; + } + + return getValue(kind, inst, decoration); +} + +Index LocationTracker::getValue(Kind kind, IRInst* inst, IRDecoration* decoration) +{ + if (decoration->getOperandCount() > 0) + { + // TODO(JS): + // There could be a clash with the auto generated location, and the user set value/ + // Perhaps the implication in practice is that either all are marked or none. + const int explicitLocation = int(getIntVal(decoration->getOperand(0))); + if (explicitLocation >= 0) + return UInt(explicitLocation); + } + + auto& nextValue = m_nextValueForKind[Index(kind)]; + + const Location defaultLocation{kind, nextValue}; + const Location foundLocation = m_mapIRToLocations.GetOrAddValue(inst, defaultLocation); + + // Increase if it was the default + nextValue += Index(defaultLocation == foundLocation); + + // Has to match the kind + return (foundLocation.kind == kind) ? foundLocation.value : -1; +} + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!! CLikeSourceEmitter !!!!!!!!!!!!!!!!!!!!!!!!!! */ /* static */SourceLanguage CLikeSourceEmitter::getSourceLanguage(CodeGenTarget target) @@ -3009,46 +3059,6 @@ void CLikeSourceEmitter::emitInterpolationModifiers(IRInst* varInst, IRType* val emitInterpolationModifiersImpl(varInst, valueType, layout); } -UInt CLikeSourceEmitter::getRayPayloadLocation(IRInst* inst) -{ - if (auto rayPayloadDecoration = inst->findDecoration<IRVulkanRayPayloadDecoration>()) - { - int explicitLocation = int(getIntVal(rayPayloadDecoration->getOperand(0))); - - if (explicitLocation >= 0) - return UInt(explicitLocation); - } - - auto& map = m_mapIRValueToRayPayloadLocation; - UInt value = 0; - if(map.TryGetValue(inst, value)) - return value; - - value = map.Count(); - map.Add(inst, value); - return value; -} - -UInt CLikeSourceEmitter::getCallablePayloadLocation(IRInst* inst) -{ - if (auto callablePayloadDecoration = inst->findDecoration<IRVulkanCallablePayloadDecoration>()) - { - int explicitLocation = int(getIntVal(callablePayloadDecoration->getOperand(0))); - - if (explicitLocation >= 0) - return UInt(explicitLocation); - } - - auto& map = m_mapIRValueToCallablePayloadLocation; - UInt value = 0; - if(map.TryGetValue(inst, value)) - return value; - - value = map.Count(); - map.Add(inst, value); - return value; -} - /// Emit modifiers that should apply even for a declaration of an SSA temporary. void CLikeSourceEmitter::emitTempModifiers(IRInst* temp) { diff --git a/source/slang/slang-emit-c-like.h b/source/slang/slang-emit-c-like.h index d85e336e0..e702dbf01 100644 --- a/source/slang/slang-emit-c-like.h +++ b/source/slang/slang-emit-c-like.h @@ -17,6 +17,48 @@ namespace Slang { +class LocationTracker +{ +public: + enum class Kind + { + Invalid = -1, + RayPayload, ///< GLSL rayPayload + CallablePayload, ///< GLSL callableData + HitObjectAttribute, ///< GLSL hitObjectAttribute + CountOf, + }; + + /// Given a decoration returns the Kind, or Kind::Invalid if that is not appropriate + static Kind getKindFromDecoration(IRDecoration* decoration); + + /// Get the location value associated with inst (and decoration). + /// Will return -1, if no location is associated + Index getValue(IRInst* inst, IRDecoration* decoration); + + /// Get the location value associated with inst (and decoration). + /// The kind must match that for the decoration. + /// Will return -1, if no location is associated + Index getValue(Kind kind, IRInst* inst, IRDecoration* decoration); + +protected: + struct Location + { + typedef Location ThisType; + + bool operator==(const ThisType& rhs) const { return kind == rhs.kind && value == rhs.value; } + bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } + + Kind kind; ///< The kind of location + Index value; ///< The value of the location. Must be >= 0 + }; + + Index m_nextValueForKind[Count(Kind::CountOf)] = { 0, }; + + Dictionary<IRInst*, Location> m_mapIRToLocations; +}; + + class CLikeSourceEmitter: public SourceEmitterBase { public: @@ -201,6 +243,8 @@ public: {} }; + + /// Must be called before used virtual SlangResult init(); @@ -233,6 +277,8 @@ public: ComponentType* getProgram() { return m_codeGenContext->getProgram(); } TargetProgram* getTargetProgram() { return m_codeGenContext->getTargetProgram(); } + LocationTracker& getLocationTracker() { return m_locationTracker; } + // // Types // @@ -357,16 +403,12 @@ public: void emitStruct(IRStructType* structType); void emitClass(IRClassType* structType); - - /// Emit type attributes that should appear after, e.g., a `struct` keyword void emitPostKeywordTypeAttributes(IRInst* inst) { emitPostKeywordTypeAttributesImpl(inst); } void emitInterpolationModifiers(IRInst* varInst, IRType* valueType, IRVarLayout* layout); - UInt getRayPayloadLocation(IRInst* inst); - - UInt getCallablePayloadLocation(IRInst* inst); + /// Emit modifiers that should apply even for a declaration of an SSA temporary. virtual void emitTempModifiers(IRInst* temp); @@ -540,8 +582,9 @@ public: // to use for it when emitting code. Dictionary<IRInst*, String> m_mapInstToName; - Dictionary<IRInst*, UInt> m_mapIRValueToRayPayloadLocation; - Dictionary<IRInst*, UInt> m_mapIRValueToCallablePayloadLocation; + // Maps instructions to locations. Used for GLSL output for locations, but could potentially + // be used for other kinds of location. + LocationTracker m_locationTracker; }; } diff --git a/source/slang/slang-emit-glsl.cpp b/source/slang/slang-emit-glsl.cpp index 48dcd21f7..e187f5e59 100644 --- a/source/slang/slang-emit-glsl.cpp +++ b/source/slang/slang-emit-glsl.cpp @@ -2240,45 +2240,62 @@ void GLSLSourceEmitter::emitVarDecorationsImpl(IRInst* varDecl) // the payload won't automatically get a layout applied // (it isn't part of the user-visible interface...) // - if (varDecl->findDecoration<IRVulkanRayPayloadDecoration>()) - { - m_writer->emit("layout(location = "); - m_writer->emit(getRayPayloadLocation(varDecl)); - m_writer->emit(")\n"); - if( getTargetCaps().implies(CapabilityAtom::GL_NV_ray_tracing) ) - { - m_writer->emit("rayPayloadNV\n"); - } - else - { - m_writer->emit("rayPayloadEXT\n"); - } - } - if (varDecl->findDecoration<IRVulkanCallablePayloadDecoration>()) + + for (auto decoration : varDecl->getDecorations()) { - m_writer->emit("layout(location = "); - m_writer->emit(getCallablePayloadLocation(varDecl)); - m_writer->emit(")\n"); - if( getTargetCaps().implies(CapabilityAtom::GL_NV_ray_tracing) ) + typedef LocationTracker::Kind LocationKind; + + LocationKind locationKind = LocationKind::Invalid; + UnownedStringSlice prefix; + if (as<IRVulkanHitAttributesDecoration>(decoration)) { - m_writer->emit("callableDataNV\n"); + prefix = toSlice("hitAttribute"); } else { - m_writer->emit("callableDataEXT\n"); + // Handle attributes that have location + const LocationKind decorationLocationKind = LocationTracker::getKindFromDecoration(decoration); + if (decorationLocationKind == LocationKind::Invalid) + { + // Next decoration + continue; + } + + locationKind = decorationLocationKind; + + // Get the location value + const auto locationValue = m_locationTracker.getValue(locationKind, varDecl, decoration); + + m_writer->emit(toSlice("layout(location = ")); + m_writer->emit(locationValue); + m_writer->emit(toSlice(")\n")); + + switch (locationKind) + { + case LocationKind::CallablePayload: prefix = toSlice("callableData"); break; + case LocationKind::HitObjectAttribute: prefix = toSlice("hitObjectAttribute"); break; + case LocationKind::RayPayload: prefix = toSlice("rayPayload"); break; + default: break; + } } - } - if (varDecl->findDecoration<IRVulkanHitAttributesDecoration>()) - { - if( getTargetCaps().implies(CapabilityAtom::GL_NV_ray_tracing) ) + SLANG_ASSERT(prefix.getLength()); + m_writer->emit(prefix); + + // Special case hitObjectAttribute as is only NV currently + if (locationKind == LocationKind::HitObjectAttribute || + getTargetCaps().implies(CapabilityAtom::GL_NV_ray_tracing)) { - m_writer->emit("hitAttributeNV\n"); + m_writer->emit(toSlice("NV")); } else { - m_writer->emit("hitAttributeEXT\n"); + m_writer->emit(toSlice("EXT")); } + m_writer->emit(toSlice("\n")); + + // If we emit a location we are done. + break; } if (varDecl->findDecoration<IRGloballyCoherentDecoration>()) diff --git a/source/slang/slang-intrinsic-expand.cpp b/source/slang/slang-intrinsic-expand.cpp index 48186b94a..64ef4e761 100644 --- a/source/slang/slang-intrinsic-expand.cpp +++ b/source/slang/slang-intrinsic-expand.cpp @@ -710,46 +710,53 @@ const char* IntrinsicExpandContext::_emitSpecial(const char* cursor) // shaders. case 'X': { + typedef LocationTracker::Kind LocationKind; + SLANG_RELEASE_ASSERT(*cursor); - switch (*cursor++) + const auto kindChar = *cursor++; + + LocationKind kind = LocationKind::Invalid; + + // The `$XP`/`$XC`/`$XH` case handles looking up + // the associated `location` for a variable + // used as the argument. + switch (kindChar) { - case 'P': - { - // The `$XP` case handles looking up - // the associated `location` for a variable - // used as the argument ray payload at a - // trace call site. - - Index argIndex = 0; - SLANG_RELEASE_ASSERT(m_argCount > argIndex); - auto arg = m_args[argIndex].get(); - auto argLoad = as<IRLoad>(arg); - SLANG_RELEASE_ASSERT(argLoad); - auto argVar = argLoad->getOperand(0); - m_writer->emit(m_emitter->getRayPayloadLocation(argVar)); - } - break; + case 'P': kind = LocationKind::RayPayload; break; + case 'C': kind = LocationKind::CallablePayload; break; + case 'H': kind = LocationKind::HitObjectAttribute; break; + default: break; + } - case 'C': + SLANG_ASSERT(kind != LocationKind::Invalid); + + if (kind != LocationKind::Invalid) + { + Index argIndex = 0; + SLANG_RELEASE_ASSERT(m_argCount > argIndex); + auto arg = m_args[argIndex].get(); + auto argLoad = as<IRLoad>(arg); + SLANG_RELEASE_ASSERT(argLoad); + + auto argVar = argLoad->getOperand(0); + + // Find the associated decoration + IRDecoration* foundDecoration = nullptr; + for (auto decoration : argVar->getDecorations()) { - // The `$XC` case handles looking up - // the associated `location` for a variable - // used as the argument callable payload at a - // call site. - - Index argIndex = 0; - SLANG_RELEASE_ASSERT(m_argCount > argIndex); - auto arg = m_args[argIndex].get(); - auto argLoad = as<IRLoad>(arg); - SLANG_RELEASE_ASSERT(argLoad); - auto argVar = argLoad->getOperand(0); - m_writer->emit(m_emitter->getCallablePayloadLocation(argVar)); + const auto curKind = LocationTracker::getKindFromDecoration(decoration); + if (curKind == kind) + { + foundDecoration = decoration; + break; + } } - break; - default: - SLANG_RELEASE_ASSERT(false); - break; + // Must have found the decoration + SLANG_ASSERT(foundDecoration); + + const auto location = m_emitter->getLocationTracker().getValue(kind, argVar, foundDecoration); + m_writer->emit(location); } } break; diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h index 51811f59e..9f3111b87 100644 --- a/source/slang/slang-ir-inst-defs.h +++ b/source/slang/slang-ir-inst-defs.h @@ -586,6 +586,8 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0) INST(VulkanRayPayloadDecoration, vulkanRayPayload, 0, 0) INST(VulkanHitAttributesDecoration, vulkanHitAttributes, 0, 0) + INST(VulkanHitObjectAttributesDecoration, vulkanHitObjectAttributes, 0, 0) + INST(RequireSPIRVVersionDecoration, requireSPIRVVersion, 1, 0) INST(RequireGLSLVersionDecoration, requireGLSLVersion, 1, 0) INST(RequireGLSLExtensionDecoration, requireGLSLExtension, 1, 0) diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index 5eea12de8..f5c3d10ae 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -239,6 +239,11 @@ IR_SIMPLE_DECORATION(VulkanCallablePayloadDecoration) /// to it. IR_SIMPLE_DECORATION(VulkanHitAttributesDecoration) +/// A decoration that indicates that a variable represents +/// vulkan hit object attributes, and should have a location assigned +/// to it. +IR_SIMPLE_DECORATION(VulkanHitObjectAttributesDecoration) + struct IRRequireGLSLVersionDecoration : IRDecoration { enum { kOp = kIROp_RequireGLSLVersionDecoration }; @@ -3358,6 +3363,12 @@ public: { addDecoration(inst, kIROp_VulkanCallablePayloadDecoration, getIntValue(getIntType(), location)); } + + void addVulkanHitObjectAttributesDecoration(IRInst* inst, int location) + { + addDecoration(inst, kIROp_VulkanHitObjectAttributesDecoration, getIntValue(getIntType(), location)); + } + }; void addHoistableInst( diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp index 6112beaf2..7aa51f31b 100644 --- a/source/slang/slang-ir.cpp +++ b/source/slang/slang-ir.cpp @@ -48,6 +48,7 @@ namespace Slang case kIROp_VulkanCallablePayloadDecoration: case kIROp_VulkanHitAttributesDecoration: case kIROp_VulkanRayPayloadDecoration: + case kIROp_VulkanHitObjectAttributesDecoration: { return true; } diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index a0158cf38..cf3781415 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -2115,7 +2115,11 @@ void addVarDecorations( { builder->addVulkanCallablePayloadDecoration(inst, callablePayloadAttr->location); } - else if(as<VulkanHitAttributesAttribute>(mod)) + else if (auto hitObjectAttr = as<VulkanHitObjectAttributesAttribute>(mod)) + { + builder->addVulkanHitObjectAttributesDecoration(inst, hitObjectAttr->location); + } + else if (as<VulkanHitAttributesAttribute>(mod)) { builder->addSimpleDecoration<IRVulkanHitAttributesDecoration>(inst); } |
