summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArielG-NV <159081215+ArielG-NV@users.noreply.github.com>2024-07-30 23:04:08 -0400
committerGitHub <noreply@github.com>2024-07-30 20:04:08 -0700
commit04e7327a2067c82db3eaef51955f211e148ac933 (patch)
tree8a8320db5165e280efb2fdb9aa4ecd078d380c72
parentfef0a87ddee9c0f252a6625395b684b1cb5d85e0 (diff)
Move SPIRV global variables into a context variable (#4741)
-rw-r--r--include/slang.h1
-rw-r--r--source/slang/slang-emit.cpp8
-rw-r--r--source/slang/slang-ir-explicit-global-context.cpp171
-rw-r--r--source/slang/slang-options.cpp2
-rw-r--r--tests/bugs/spirv-opt-SROA-of-globals.slang37
-rw-r--r--tests/spirv/address-space-specialize.slang7
-rw-r--r--tests/spirv/explicit-context-validation-builtin-compute-glsl.slang19
-rw-r--r--tests/spirv/explicit-context-validation-builtin-compute-hlsl.slang16
-rw-r--r--tests/spirv/explicit-context-validation-builtin-vertex-glsl.slang35
-rw-r--r--tests/spirv/explicit-context-validation-groupshared.slang30
-rw-r--r--tests/spirv/explicit-context-validation-raytracing-glsl.slang78
-rw-r--r--tests/spirv/explicit-context-validation-raytracing-hlsl.slang53
-rw-r--r--tests/spirv/subgroup-size-2.slang21
13 files changed, 450 insertions, 28 deletions
diff --git a/include/slang.h b/include/slang.h
index edcaa8a3f..25e364504 100644
--- a/include/slang.h
+++ b/include/slang.h
@@ -943,6 +943,7 @@ extern "C"
NoHLSLPackConstantBufferElements,
ValidateUniformity,
AllowGLSL,
+ EnableExperimentalPasses,
// Internal
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index 8f7b5f66f..a8ed469fa 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -1213,9 +1213,17 @@ Result linkAndOptimizeIR(
default:
break;
case CodeGenTarget::GLSL:
+ moveGlobalVarInitializationToEntryPoints(irModule);
+ break;
+ // For SPIR-V to SROA across 2 entry-points a value must not be a global
case CodeGenTarget::SPIRV:
case CodeGenTarget::SPIRVAssembly:
moveGlobalVarInitializationToEntryPoints(irModule);
+ if(targetProgram->getOptionSet().getBoolOption(CompilerOptionName::EnableExperimentalPasses))
+ introduceExplicitGlobalContext(irModule, target);
+ #if 0
+ dumpIRIfEnabled(codeGenContext, irModule, "EXPLICIT GLOBAL CONTEXT INTRODUCED");
+ #endif
break;
case CodeGenTarget::Metal:
case CodeGenTarget::CPPSource:
diff --git a/source/slang/slang-ir-explicit-global-context.cpp b/source/slang/slang-ir-explicit-global-context.cpp
index 56fd62883..3dc3d3ad4 100644
--- a/source/slang/slang-ir-explicit-global-context.cpp
+++ b/source/slang/slang-ir-explicit-global-context.cpp
@@ -12,8 +12,118 @@ namespace Slang
// thread-group, and wrap them up in an explicit "context"
// type that gets passed between functions.
+enum class GlobalObjectKind : UInt
+{
+ None = 0,
+ GlobalVar = 1 << 0,
+ GlobalParam = 1 << 1,
+ All = 0xFFFFFFFF,
+};
+
+enum class HoistGlobalVarOptions : UInt
+{
+ PlainGlobal = 0,
+ SharedGlobal = 1 << 0,
+ RaytracingGlobal = 1 << 1,
+ All = 0xFFFFFFFF,
+};
+
struct IntroduceExplicitGlobalContextPass
{
+
+ // TODO: (#4742) Discontinuity of AddressSpace values between targets
+ // (SpvStorageClassFunction vs. AddressSpace::ThreadLocal) needs
+ // to be addressed. This means `addressSpaceOfLocals` may be refactored out.
+
+ /// Target specific options to manage `IntroduceExplicitGlobalContextPass`
+ class ExplicitContextPolicy
+ {
+ public:
+ ExplicitContextPolicy(CodeGenTarget target)
+ {
+ switch (target)
+ {
+ case CodeGenTarget::SPIRV:
+ case CodeGenTarget::SPIRVAssembly:
+ hoistableGlobalObjectKind = GlobalObjectKind::GlobalVar;
+ requiresFuncTypeCorrectionPass = true;
+ addressSpaceOfLocals = (AddressSpace)SpvStorageClassFunction;
+ hoistGlobalVarOptions = HoistGlobalVarOptions::PlainGlobal;
+ break;
+ case CodeGenTarget::CUDASource:
+ hoistableGlobalObjectKind = GlobalObjectKind::GlobalVar;
+
+ // One important exception is that CUDA *does* support
+ // global variables with the `__shared__` qualifer, with
+ // semantics that exactly match HLSL/Slang `groupshared`.
+ //
+ // We thus need to skip processing of global variables
+ // that were marked `groupshared`. In our current IR,
+ // this is represented as a variable with the `@GroupShared`
+ // rate on its type.
+ //
+ hoistGlobalVarOptions = HoistGlobalVarOptions(0
+ | (UInt)HoistGlobalVarOptions::PlainGlobal
+ | (UInt)HoistGlobalVarOptions::RaytracingGlobal
+ );
+ break;
+ }
+ }
+
+ bool canHoistType(GlobalObjectKind hoistable)
+ {
+ return (UInt)hoistableGlobalObjectKind & (UInt)hoistable;
+ }
+
+ bool canHoistGlobalVar(IRGlobalVar* inst)
+ {
+ if (!((UInt)hoistGlobalVarOptions & (UInt)HoistGlobalVarOptions::SharedGlobal)
+ && as<IRGroupSharedRate>(inst->getRate()))
+ return false;
+
+ if (!((UInt)hoistGlobalVarOptions & (UInt)HoistGlobalVarOptions::RaytracingGlobal))
+ {
+ for (auto decoration : inst->getDecorations())
+ {
+ switch (decoration->getOp())
+ {
+ case kIROp_VulkanRayPayloadDecoration:
+ case kIROp_VulkanRayPayloadInDecoration:
+ case kIROp_VulkanCallablePayloadDecoration:
+ case kIROp_VulkanCallablePayloadInDecoration:
+ case kIROp_VulkanHitObjectAttributesDecoration:
+ case kIROp_VulkanHitAttributesDecoration:
+ return false;
+ default:
+ continue;
+ };
+ }
+ }
+
+ return true;
+ }
+
+ bool requiresFuncTypeCorrection()
+ {
+ return requiresFuncTypeCorrectionPass;
+ }
+
+ AddressSpace getAddressSpaceOfLocal()
+ {
+ return addressSpaceOfLocals;
+ }
+
+ private:
+ HoistGlobalVarOptions hoistGlobalVarOptions = HoistGlobalVarOptions::All;
+ GlobalObjectKind hoistableGlobalObjectKind = GlobalObjectKind::All;
+ bool requiresFuncTypeCorrectionPass = false;
+ AddressSpace addressSpaceOfLocals = AddressSpace::ThreadLocal;
+ };
+
+ IntroduceExplicitGlobalContextPass(IRModule* module, CodeGenTarget target) : m_module(module), m_target(target), m_options(target)
+ {
+ }
+
IRModule* m_module = nullptr;
CodeGenTarget m_target = CodeGenTarget::Unknown;
@@ -24,10 +134,22 @@ struct IntroduceExplicitGlobalContextPass
List<IRGlobalVar*> m_globalVars;
List<IRFunc*> m_entryPoints;
- enum class GlobalObjectKind
+ ExplicitContextPolicy m_options;
+
+ AddressSpace getAddressSpaceOfLocal()
{
- GlobalParam, GlobalVar
- };
+ return m_options.getAddressSpaceOfLocal();
+ }
+
+ bool canHoistType(GlobalObjectKind hoistable)
+ {
+ return m_options.canHoistType(hoistable);
+ }
+
+ bool canHoistGlobalVar(IRGlobalVar* inst)
+ {
+ return m_options.canHoistGlobalVar(inst);
+ }
void processModule()
{
@@ -45,6 +167,8 @@ struct IntroduceExplicitGlobalContextPass
{
case kIROp_GlobalVar:
{
+ if (!canHoistType(GlobalObjectKind::GlobalVar))
+ continue;
// A "global variable" in HLSL (and thus Slang) is actually
// a weird kind of thread-local variable, and so it cannot
// actually be lowered to a global variable on targets where
@@ -58,20 +182,8 @@ struct IntroduceExplicitGlobalContextPass
continue;
}
- // One important exception is that CUDA *does* support
- // global variables with the `__shared__` qualifer, with
- // semantics that exactly match HLSL/Slang `groupshared`.
- //
- // We thus need to skip processing of global variables
- // that were marked `groupshared`. In our current IR,
- // this is represented as a variable with the `@GroupShared`
- // rate on its type.
- //
- if( m_target == CodeGenTarget::CUDASource )
- {
- if( as<IRGroupSharedRate>(globalVar->getRate()) )
- continue;
- }
+ if (!canHoistGlobalVar(globalVar))
+ continue;
m_globalVars.add(globalVar);
}
@@ -79,6 +191,8 @@ struct IntroduceExplicitGlobalContextPass
case kIROp_GlobalParam:
{
+ if (!canHoistType(GlobalObjectKind::GlobalParam))
+ continue;
// Global parameters are another HLSL/Slang concept
// that doesn't have a parallel in langauges like C/C++.
//
@@ -170,7 +284,7 @@ struct IntroduceExplicitGlobalContextPass
// The context will usually be passed around by pointer,
// so we get and cache that pointer type up front.
//
- m_contextStructPtrType = builder.getPtrType(kIROp_PtrType, m_contextStructType, (IRIntegerValue)AddressSpace::ThreadLocal);
+ m_contextStructPtrType = builder.getPtrType(kIROp_PtrType, m_contextStructType, (IRIntegerValue)getAddressSpaceOfLocal());
// The first step will be to create fields in the `KernelContext`
@@ -227,6 +341,17 @@ struct IntroduceExplicitGlobalContextPass
{
replaceUsesOfGlobalVar(globalVar);
}
+
+ // SPIRV requires a correct IR func-type to emit properly
+ if (m_options.requiresFuncTypeCorrection())
+ {
+ for (auto pairOfFuncs : m_mapFuncToContextPtr)
+ {
+ if (pairOfFuncs.second->getOp() == kIROp_Var)
+ continue;
+ fixUpFuncType(pairOfFuncs.first);
+ }
+ }
}
// As noted above, we will maintain mappings to record
@@ -385,7 +510,7 @@ struct IntroduceExplicitGlobalContextPass
{
builder.addNameHintDecoration(var, nameDecor->getName());
}
- auto ptrPtrType = builder.getPtrType(getGlobalVarPtrType(globalVar), AddressSpace::ThreadLocal);
+ auto ptrPtrType = builder.getPtrType(getGlobalVarPtrType(globalVar), getAddressSpaceOfLocal());
auto fieldPtr = builder.emitFieldAddress(ptrPtrType, contextVarPtr, fieldInfo.key);
builder.emitStore(fieldPtr, var);
}
@@ -438,7 +563,7 @@ struct IntroduceExplicitGlobalContextPass
{
return builder.getPtrType(globalVar->getDataType()->getValueType(), AddressSpace::GroupShared);
}
- return builder.getPtrType(globalVar->getDataType()->getValueType(), AddressSpace::ThreadLocal);
+ return builder.getPtrType(globalVar->getDataType()->getValueType(), getAddressSpaceOfLocal());
}
void replaceUsesOfGlobalVar(IRGlobalVar* globalVar)
@@ -452,7 +577,7 @@ struct IntroduceExplicitGlobalContextPass
auto ptrType = getGlobalVarPtrType(globalVar);
if (fieldInfo.needDereference)
- ptrType = builder.getPtrType(kIROp_PtrType, ptrType, AddressSpace::ThreadLocal);
+ ptrType = builder.getPtrType(kIROp_PtrType, ptrType, getAddressSpaceOfLocal());
// We then iterate over the uses of the variable,
// being careful to defend against the use/def information
@@ -628,9 +753,7 @@ void introduceExplicitGlobalContext(
IRModule* module,
CodeGenTarget target)
{
- IntroduceExplicitGlobalContextPass pass;
- pass.m_module = module;
- pass.m_target = target;
+ IntroduceExplicitGlobalContextPass pass(module, target);
pass.processModule();
}
diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp
index 0f5a4b417..c3a0eeddc 100644
--- a/source/slang/slang-options.cpp
+++ b/source/slang/slang-options.cpp
@@ -529,6 +529,7 @@ void initCommandOptions(CommandOptions& options)
"Do not pack elements of constant buffers into structs in the output HLSL code." },
{ OptionKind::ValidateUniformity, "-validate-uniformity", nullptr, "Perform uniformity validation analysis." },
{ OptionKind::AllowGLSL, "-allow-glsl", nullptr, "Enable GLSL as an input language." },
+ { OptionKind::EnableExperimentalPasses, "-enable-experimental-passes", nullptr, "Enable experimental compiler passes" },
};
_addOptions(makeConstArrayView(experimentalOpts), options);
@@ -1693,6 +1694,7 @@ SlangResult OptionsParser::_parse(
case OptionKind::NoMangle:
case OptionKind::ValidateUniformity:
case OptionKind::AllowGLSL:
+ case OptionKind::EnableExperimentalPasses:
case OptionKind::EmitIr:
case OptionKind::DumpIntermediates:
case OptionKind::DumpReproOnError:
diff --git a/tests/bugs/spirv-opt-SROA-of-globals.slang b/tests/bugs/spirv-opt-SROA-of-globals.slang
new file mode 100644
index 000000000..140559b4f
--- /dev/null
+++ b/tests/bugs/spirv-opt-SROA-of-globals.slang
@@ -0,0 +1,37 @@
+//TEST:SIMPLE(filecheck=CHECK): -target spirv -fvk-use-entrypoint-name -enable-experimental-passes
+
+// This test checks that spirv-opt is running SROA (scalar replacement of aggregates) to
+// hoist out all member variables of a struct. If this sucsessfully runs, we should not see
+// any `OpCompositeConstruct` of our `%Data` struct.
+// Note: SROA will only run for 100 elements if spirv-opt does not manually set the spirv-opt `scalar-replacement` option
+
+//CHECK-NOT: OpCompositeConstruct %Data
+struct Data
+{
+ uint data0;
+ uint data1;
+ uint data2;
+};
+
+static Data globalVar;
+ByteAddressBuffer bab;
+RWStructuredBuffer<uint> outputBuffer;
+
+struct Payload_t
+{
+ uint dataOut;
+};
+
+[shader("anyhit")]
+void main1(inout Payload_t payload)
+{
+ globalVar = bab.Load<Data>(0);
+ payload.dataOut = globalVar.data0;
+}
+
+[shader("anyhit")]
+void main2(inout Payload_t payload)
+{
+ globalVar = bab.Load<Data>(0);
+ payload.dataOut = globalVar.data0;
+} \ No newline at end of file
diff --git a/tests/spirv/address-space-specialize.slang b/tests/spirv/address-space-specialize.slang
index e2b48489a..f8201838b 100644
--- a/tests/spirv/address-space-specialize.slang
+++ b/tests/spirv/address-space-specialize.slang
@@ -1,3 +1,4 @@
+//TEST:SIMPLE(filecheck=CHECK_EXPERIMENTAL):-target spirv -entry main -stage compute -emit-spirv-directly -O0 -enable-experimental-passes
//TEST:SIMPLE(filecheck=CHECK):-target spirv -entry main -stage compute -emit-spirv-directly -O0
// Test that we can pass arguments in different address space to an `inout` parameter, and have
@@ -7,6 +8,12 @@
static int gArray0[2];
groupshared int gArray1[2];
+// Note: static globals are inside a context variable
+// CHECK_EXPERIMENTAL: OpTypeArray %int %int_2
+// CHECK_EXPERIMENTAL: OpVariable %_ptr_Function__arr_int_int_2 Function
+// CHECK_EXPERIMENTAL: %array_0 = OpFunctionParameter %_ptr_Workgroup__arr_int_int_2
+
+
// CHECK: %array = OpFunctionParameter %_ptr_Private__arr_int_int_2
// CHECK: %array_0 = OpFunctionParameter %_ptr_Workgroup__arr_int_int_2
diff --git a/tests/spirv/explicit-context-validation-builtin-compute-glsl.slang b/tests/spirv/explicit-context-validation-builtin-compute-glsl.slang
new file mode 100644
index 000000000..9fb0947ae
--- /dev/null
+++ b/tests/spirv/explicit-context-validation-builtin-compute-glsl.slang
@@ -0,0 +1,19 @@
+//TEST:SIMPLE(filecheck=CHECK): -allow-glsl -target spirv -emit-spirv-directly -stage compute -entry computeMain -enable-experimental-passes
+
+// Check to ensure builtin is not moved into a kernelContext (part of entry-point). Ensure builtin is referenced directly.
+
+// CHECK: OpEntryPoint {{.*}} %gl_NumWorkGroups
+// CHECK: OpDecorate %gl_NumWorkGroups BuiltIn NumWorkgroups
+// CHECK: %gl_NumWorkGroups = OpVariable {{.*}} Input
+// CHECK: %[[NUM_WORK_GROUP_LOAD:[A-Za-z0-9_]+]] = OpLoad %v3uint %gl_NumWorkGroups
+// CHECK: OpCompositeExtract %uint %[[NUM_WORK_GROUP_LOAD]] 0
+
+RWStructuredBuffer<uint> outputBuffer;
+
+layout(local_size_x = 32, local_size_y = 1, local_size_z = 1) in;
+void computeMain()
+{
+ outputBuffer[0] = gl_NumWorkGroups.x;
+ outputBuffer[1] = gl_NumWorkGroups.y;
+ outputBuffer[2] = gl_NumWorkGroups.z;
+} \ No newline at end of file
diff --git a/tests/spirv/explicit-context-validation-builtin-compute-hlsl.slang b/tests/spirv/explicit-context-validation-builtin-compute-hlsl.slang
new file mode 100644
index 000000000..24184c9f4
--- /dev/null
+++ b/tests/spirv/explicit-context-validation-builtin-compute-hlsl.slang
@@ -0,0 +1,16 @@
+//TEST:SIMPLE(filecheck=CHECK): -target spirv -emit-spirv-directly -stage compute -entry computeMain -enable-experimental-passes
+
+// Check to ensure builtin is not moved into a kernelContext (part of entry-point). Ensure builtin is referenced directly.
+
+// CHECK: OpEntryPoint {{.*}} %gl_GlobalInvocationID
+// CHECK: OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
+// CHECK: %gl_GlobalInvocationID = OpVariable {{.*}} Input
+// CHECK: %[[NUM_WORK_GROUP_LOAD:[A-Za-z0-9_]+]] = OpLoad %v3uint %gl_GlobalInvocationID
+// CHECK: OpCompositeExtract %uint %[[NUM_WORK_GROUP_LOAD]] 0
+
+RWStructuredBuffer<uint> outputBuffer;
+[numthreads(1, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ outputBuffer[dispatchThreadID.x] = 1;
+} \ No newline at end of file
diff --git a/tests/spirv/explicit-context-validation-builtin-vertex-glsl.slang b/tests/spirv/explicit-context-validation-builtin-vertex-glsl.slang
new file mode 100644
index 000000000..8e37d4814
--- /dev/null
+++ b/tests/spirv/explicit-context-validation-builtin-vertex-glsl.slang
@@ -0,0 +1,35 @@
+//TEST:SIMPLE(filecheck=CHECK): -allow-glsl -target spirv -emit-spirv-directly -stage vertex -entry vertexMain -enable-experimental-passes
+
+// Check to ensure varying output/input and builtin is not moved into a kernelContext (part of entry-point). Ensure varying output/input and builtin is referenced directly.
+
+// CHECK: OpEntryPoint{{((.*)(%.*data1In|%.*data2In|%.*data1Out)(.*))|((.*)(%.*data1In|%.*data2In|%.*data1Out)(.*))|((.*)(%.*data1In|%.*data2In|%.*data1Out)(.*))}}
+
+//CHECK-DAG: OpDecorate %[[DATA_IN_1:.*data1In]] Location 1
+//CHECK-DAG: OpDecorate %[[DATA_IN_2:.*data2In]] Location 2
+//CHECK-DAG: OpDecorate %[[DATA_OUT_1:.*data1Out]] Location 0
+//CHECK-DAG: OpDecorate %gl_Position BuiltIn Position
+
+//CHECK-DAG: %[[DATA_IN_1]] = OpVariable{{.*}} Input
+//CHECK-DAG: %[[DATA_IN_2]] = OpVariable{{.*}} Input
+//CHECK-DAG: %[[DATA_OUT_1]] = OpVariable{{.*}} Output
+
+//CHECK-DAG: OpLoad{{.*}} %[[DATA_IN_1]]
+//CHECK-DAG: OpLoad{{.*}} %[[DATA_IN_2]]
+
+//CHECK-DAG: OpStore %gl_Position
+//CHECK-DAG: OpStore %[[DATA_OUT_1]]
+
+layout(location = 1) in vec4 data1In;
+layout(location = 2) in int data2In;
+layout(location = 0) out int data1Out;
+
+void nestedCall()
+{
+ gl_Position = data1In;
+ data1Out = data2In;
+}
+
+void vertexMain()
+{
+ nestedCall();
+}
diff --git a/tests/spirv/explicit-context-validation-groupshared.slang b/tests/spirv/explicit-context-validation-groupshared.slang
new file mode 100644
index 000000000..7fb27377d
--- /dev/null
+++ b/tests/spirv/explicit-context-validation-groupshared.slang
@@ -0,0 +1,30 @@
+//TEST:SIMPLE(filecheck=CHECK): -target spirv -emit-spirv-directly -stage compute -entry computeMain -enable-experimental-passes
+
+// Check to ensure builtin is not moved into a kernelContext (part of entry-point). Ensure builtin is referenced directly.
+
+// CHECK: OpEntryPoint{{.*}} %val
+// CHECK: %[[GROUP_SHARED_VAR:(.*)]] = OpVariable{{.*}} Workgroup
+
+// CHECK: OpControlBarrier
+// CHECK: OpControlBarrier
+// CHECK-DAG: %[[GROUP_SHARED_VAL:(.*)]] = OpLoad{{.*}} %[[GROUP_SHARED_VAR]]
+// CHECK-DAG: %[[OUTPUT_BUFFER_LOC:(.*)]] = OpAccessChain{{.*}} %outputBuffer
+// CHECK: OpStore %[[OUTPUT_BUFFER_LOC]] %[[GROUP_SHARED_VAL]]
+
+groupshared uint val;
+RWStructuredBuffer<uint> outputBuffer;
+
+void nestedCall(uint index)
+{
+ val += 1;
+ GroupMemoryBarrierWithGroupSync();
+ outputBuffer[index] = val;
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ val = 0;
+ GroupMemoryBarrierWithGroupSync();
+ nestedCall(dispatchThreadID.x);
+} \ No newline at end of file
diff --git a/tests/spirv/explicit-context-validation-raytracing-glsl.slang b/tests/spirv/explicit-context-validation-raytracing-glsl.slang
new file mode 100644
index 000000000..1e7b56a9f
--- /dev/null
+++ b/tests/spirv/explicit-context-validation-raytracing-glsl.slang
@@ -0,0 +1,78 @@
+//TEST:SIMPLE(filecheck=CHECK): -allow-glsl -target spirv -emit-spirv-directly -stage raygeneration -entry main -enable-experimental-passes
+
+// Check to ensure we make global ray-tracing objects. Ensure we store into these variables directly and not through a context-pointer.
+
+// CHECK-DAG: %[[RAYTRACING_AS_TYPE:[A-Za-z0-9_]+]] = OpTypeAccelerationStructureKHR
+// CHECK-DAG: %[[RAYTRACING_AS_PTR_TYPE:[A-Za-z0-9_]+]] = OpTypePointer UniformConstant %[[RAYTRACING_AS_TYPE]]
+// CHECK-DAG: %[[RAYTRACING_AS:[A-Za-z0-9_]+]] = OpVariable %[[RAYTRACING_AS_PTR_TYPE]] UniformConstant
+
+// CHECK-DAG: %[[RAY_PAYLOAD:[A-Za-z0-9_]+]] = OpVariable %{{.*}} RayPayloadKHR
+// CHECK-DAG: %[[HIT_ATTR:[A-Za-z0-9_]+]] = OpVariable %{{.*}} HitObjectAttributeNV
+// CHECK-DAG: %[[CALL_DATA:[A-Za-z0-9_]+]] = OpVariable %{{.*}} CallableDataKHR
+
+
+// CHECK: OpLoad {{.*}} %[[RAYTRACING_AS]]
+// CHECK: OpStore %[[RAY_PAYLOAD]]
+// CHECK: OpStore %[[HIT_ATTR]]
+// CHECK: OpStore %[[CALL_DATA]]
+
+layout(binding = 0) uniform accelerationStructureEXT as;
+
+buffer MyBlockName
+{
+ uint data[];
+} outputBuffer;
+layout(location = 2) rayPayloadEXT vec4 payload;
+layout(location = 2) hitObjectAttributeNV vec4 attrMain;
+layout(location = 0) callableDataEXT vec4 outcall;
+
+bool testHitObjectTraceRay() {
+ hitObjectNV hit;
+
+
+ hitObjectTraceRayNV(hit, as, gl_RayFlagsNoneEXT, 0xff, 0, 0, 0, vec3(0.1, 0.1, 0.0), 0.01f, vec3(0, 0, 1), 1e4f, 2);
+ return true
+ && hitObjectIsHitNV(hit) == true
+ ;
+}
+
+
+bool testPayloadReadWrite() {
+ payload = vec4(2);
+ vec4 read = payload;
+ return true
+ && read != vec4(0)
+ ;
+}
+
+bool testAttributeReadWrite() {
+ attrMain = vec4(2);
+ vec4 read = attrMain;
+ return true
+ && read != vec4(0)
+ ;
+}
+
+bool testCallableReadWrite() {
+ outcall = vec4(2);
+ vec4 read = outcall;
+ return true
+ && read != vec4(0)
+ ;
+}
+
+bool testReadWriteOfObjects(){
+ return true
+ && testPayloadReadWrite()
+ && testAttributeReadWrite()
+ && testCallableReadWrite();
+ ;
+}
+
+void main()
+{
+ outputBuffer.data[0] = true
+ && testHitObjectTraceRay()
+ && testReadWriteOfObjects()
+ ;
+}
diff --git a/tests/spirv/explicit-context-validation-raytracing-hlsl.slang b/tests/spirv/explicit-context-validation-raytracing-hlsl.slang
new file mode 100644
index 000000000..28420eeec
--- /dev/null
+++ b/tests/spirv/explicit-context-validation-raytracing-hlsl.slang
@@ -0,0 +1,53 @@
+//TEST:SIMPLE(filecheck=CHECK): -target spirv -emit-spirv-directly -stage raygeneration -entry main -enable-experimental-passes
+
+// Check to ensure we make global ray-tracing objects. Ensure we store into these variables directly and not through a context-pointer.
+
+// CHECK-DAG: %[[RAYTRACING_AS_TYPE:[A-Za-z0-9_]+]] = OpTypeAccelerationStructureKHR
+// CHECK-DAG: %[[RAYTRACING_AS_PTR_TYPE:[A-Za-z0-9_]+]] = OpTypePointer UniformConstant %[[RAYTRACING_AS_TYPE]]
+// CHECK-DAG: %[[RAYTRACING_AS:[A-Za-z0-9_]+]] = OpVariable %[[RAYTRACING_AS_PTR_TYPE]] UniformConstant
+
+// CHECK-DAG: %[[RAY_PAYLOAD:[A-Za-z0-9_]+]] = OpVariable %{{.*}} RayPayloadKHR
+
+// CHECK: OpLoad {{.*}} %[[RAYTRACING_AS]]
+// CHECK: OpTraceRayKHR{{.*}} %[[RAY_PAYLOAD]]
+
+RaytracingAccelerationStructure as;
+
+struct ShadowRay
+{
+ float hitDistance;
+};
+
+void nestedNestedCall()
+{
+ RayDesc ray = {};
+
+ ShadowRay shadowRay;
+ shadowRay.hitDistance = 0;
+
+ TraceRay(as,
+ // ray flags
+ 1,
+ // cull mask
+ 0xff,
+ // sbt record offset
+ 0,
+ // sbt record stride
+ 0,
+ // missIndex
+ 2,
+ // ray
+ ray,
+ // payload
+ shadowRay);
+}
+
+void nestedCall()
+{
+ nestedNestedCall();
+}
+
+void main()
+{
+ nestedCall();
+} \ No newline at end of file
diff --git a/tests/spirv/subgroup-size-2.slang b/tests/spirv/subgroup-size-2.slang
index bd5ae5eec..500bd63c8 100644
--- a/tests/spirv/subgroup-size-2.slang
+++ b/tests/spirv/subgroup-size-2.slang
@@ -1,8 +1,11 @@
// Test that using workgroup size from more than one entrypoint result in
// correct lowering into global variable.
+//TEST:SIMPLE(filecheck=CHECK_EXPERIMENTAL): -target spirv -emit-spirv-directly -fvk-use-entrypoint-name -O0 -enable-experimental-passes
//TEST:SIMPLE(filecheck=CHECK): -target spirv -emit-spirv-directly -fvk-use-entrypoint-name -O0
+
+
RWStructuredBuffer<int> outputBuffer;
uint3 f() { return WorkgroupSize(); }
@@ -11,16 +14,26 @@ uint3 f() { return WorkgroupSize(); }
[numthreads(1u, 2u, 3)]
void compute1()
{
+ // CHECK_EXPERIMENTAL-DAG: %[[VAR:[A-Za-z0-9_]+]] = OpTypePointer Function %v3int
+ // CHECK_EXPERIMENTAL: OpAccessChain %[[VAR]]
+ //
+ // CHECK_EXPERIMENTAL-DAG: %[[CALL_RS:[A-Za-z0-9_]+]] = OpFunctionCall %v3uint %f
+ // CHECK_EXPERIMENTAL: OpCompositeExtract %uint %[[CALL_RS]] 0
+ //
+ // CHECK_EXPERIMENTAL-DAG: %[[PTR:[A-Za-z0-9_]+]] = OpAccessChain %_ptr_StorageBuffer_int %outputBuffer %int_0 %int_1
+ // CHECK_EXPERIMENTAL: OpStore %[[PTR]] %int_2
+
// CHECK-DAG: %[[VAR:[A-Za-z0-9_]+]] = OpVariable %_ptr_Private_v3int Private
// CHECK: OpStore %[[VAR]]
-
+ //
// CHECK-DAG: %[[CALL_RS:[A-Za-z0-9_]+]] = OpFunctionCall %v3uint %f
// CHECK: OpCompositeExtract %uint %[[CALL_RS]] 0
- const int x = f().x;
- outputBuffer[0] = x;
-
+ //
// CHECK-DAG: %[[PTR:[A-Za-z0-9_]+]] = OpAccessChain %_ptr_StorageBuffer_int %outputBuffer %int_0 %int_1
// CHECK: OpStore %[[PTR]] %int_2
+
+ const int x = f().x;
+ outputBuffer[0] = x;
outputBuffer[1] = WorkgroupSize().y;
}