diff options
| author | ArielG-NV <159081215+ArielG-NV@users.noreply.github.com> | 2024-07-30 23:04:08 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-30 20:04:08 -0700 |
| commit | 04e7327a2067c82db3eaef51955f211e148ac933 (patch) | |
| tree | 8a8320db5165e280efb2fdb9aa4ecd078d380c72 | |
| parent | fef0a87ddee9c0f252a6625395b684b1cb5d85e0 (diff) | |
Move SPIRV global variables into a context variable (#4741)
| -rw-r--r-- | include/slang.h | 1 | ||||
| -rw-r--r-- | source/slang/slang-emit.cpp | 8 | ||||
| -rw-r--r-- | source/slang/slang-ir-explicit-global-context.cpp | 171 | ||||
| -rw-r--r-- | source/slang/slang-options.cpp | 2 | ||||
| -rw-r--r-- | tests/bugs/spirv-opt-SROA-of-globals.slang | 37 | ||||
| -rw-r--r-- | tests/spirv/address-space-specialize.slang | 7 | ||||
| -rw-r--r-- | tests/spirv/explicit-context-validation-builtin-compute-glsl.slang | 19 | ||||
| -rw-r--r-- | tests/spirv/explicit-context-validation-builtin-compute-hlsl.slang | 16 | ||||
| -rw-r--r-- | tests/spirv/explicit-context-validation-builtin-vertex-glsl.slang | 35 | ||||
| -rw-r--r-- | tests/spirv/explicit-context-validation-groupshared.slang | 30 | ||||
| -rw-r--r-- | tests/spirv/explicit-context-validation-raytracing-glsl.slang | 78 | ||||
| -rw-r--r-- | tests/spirv/explicit-context-validation-raytracing-hlsl.slang | 53 | ||||
| -rw-r--r-- | tests/spirv/subgroup-size-2.slang | 21 |
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; } |
