diff --git a/3rdparty/spirv-cross/reference/shaders-no-opt/asm/frag/demote-impure-function-call.vk.nocompat.asm.frag.vk b/3rdparty/spirv-cross/reference/shaders-no-opt/asm/frag/demote-impure-function-call.vk.nocompat.asm.frag.vk new file mode 100644 index 000000000..adde5fcbf --- /dev/null +++ b/3rdparty/spirv-cross/reference/shaders-no-opt/asm/frag/demote-impure-function-call.vk.nocompat.asm.frag.vk @@ -0,0 +1,22 @@ +#version 450 +#extension GL_EXT_demote_to_helper_invocation : require + +layout(location = 0) flat in int vA; +layout(location = 0) out vec4 FragColor; + +vec4 foobar(int a) +{ + if (a < 0) + { + demote; + } + return vec4(10.0); +} + +void main() +{ + int param = vA; + vec4 _25 = foobar(param); + FragColor = vec4(10.0); +} + diff --git a/3rdparty/spirv-cross/reference/shaders-no-opt/asm/frag/discard-impure-function-call.asm.frag b/3rdparty/spirv-cross/reference/shaders-no-opt/asm/frag/discard-impure-function-call.asm.frag new file mode 100644 index 000000000..0fe71f64b --- /dev/null +++ b/3rdparty/spirv-cross/reference/shaders-no-opt/asm/frag/discard-impure-function-call.asm.frag @@ -0,0 +1,21 @@ +#version 450 + +layout(location = 0) flat in int vA; +layout(location = 0) out vec4 FragColor; + +vec4 foobar(int a) +{ + if (a < 0) + { + discard; + } + return vec4(10.0); +} + +void main() +{ + int param = vA; + vec4 _25 = foobar(param); + FragColor = vec4(10.0); +} + diff --git a/3rdparty/spirv-cross/shaders-no-opt/asm/frag/demote-impure-function-call.vk.nocompat.asm.frag b/3rdparty/spirv-cross/shaders-no-opt/asm/frag/demote-impure-function-call.vk.nocompat.asm.frag new file mode 100644 index 000000000..9f1a4573d --- /dev/null +++ b/3rdparty/spirv-cross/shaders-no-opt/asm/frag/demote-impure-function-call.vk.nocompat.asm.frag @@ -0,0 +1,63 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 7 +; Bound: 33 +; Schema: 0 + OpCapability Shader + OpCapability DemoteToHelperInvocationEXT + OpExtension "SPV_EXT_demote_to_helper_invocation" + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %vA %FragColor + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 450 + OpSourceExtension "GL_EXT_demote_to_helper_invocation" + OpName %main "main" + OpName %foobar_i1_ "foobar(i1;" + OpName %a "a" + OpName %a_0 "a" + OpName %vA "vA" + OpName %param "param" + OpName %FragColor "FragColor" + OpDecorate %vA Flat + OpDecorate %vA Location 0 + OpDecorate %FragColor Location 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %int = OpTypeInt 32 1 +%_ptr_Function_int = OpTypePointer Function %int + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 + %10 = OpTypeFunction %v4float %_ptr_Function_int + %int_0 = OpConstant %int 0 + %bool = OpTypeBool + %float_10 = OpConstant %float 10 + %21 = OpConstantComposite %v4float %float_10 %float_10 %float_10 %float_10 +%_ptr_Function_v4float = OpTypePointer Function %v4float +%_ptr_Input_int = OpTypePointer Input %int + %vA = OpVariable %_ptr_Input_int Input +%_ptr_Output_v4float = OpTypePointer Output %v4float + %FragColor = OpVariable %_ptr_Output_v4float Output + %main = OpFunction %void None %3 + %5 = OpLabel + %a_0 = OpVariable %_ptr_Function_v4float Function + %param = OpVariable %_ptr_Function_int Function + %29 = OpLoad %int %vA + OpStore %param %29 + %30 = OpFunctionCall %v4float %foobar_i1_ %param + OpStore %FragColor %21 + OpReturn + OpFunctionEnd + %foobar_i1_ = OpFunction %v4float None %10 + %a = OpFunctionParameter %_ptr_Function_int + %13 = OpLabel + %14 = OpLoad %int %a + %17 = OpSLessThan %bool %14 %int_0 + OpSelectionMerge %19 None + OpBranchConditional %17 %18 %19 + %18 = OpLabel + OpDemoteToHelperInvocationEXT + OpBranch %19 + %19 = OpLabel + OpReturnValue %21 + OpFunctionEnd diff --git a/3rdparty/spirv-cross/shaders-no-opt/asm/frag/discard-impure-function-call.asm.frag b/3rdparty/spirv-cross/shaders-no-opt/asm/frag/discard-impure-function-call.asm.frag new file mode 100644 index 000000000..0f039166b --- /dev/null +++ b/3rdparty/spirv-cross/shaders-no-opt/asm/frag/discard-impure-function-call.asm.frag @@ -0,0 +1,59 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 7 +; Bound: 34 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %vA %FragColor + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 450 + OpName %main "main" + OpName %foobar_i1_ "foobar(i1;" + OpName %a "a" + OpName %a_0 "a" + OpName %vA "vA" + OpName %param "param" + OpName %FragColor "FragColor" + OpDecorate %vA Flat + OpDecorate %vA Location 0 + OpDecorate %FragColor Location 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %int = OpTypeInt 32 1 +%_ptr_Function_int = OpTypePointer Function %int + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 + %10 = OpTypeFunction %v4float %_ptr_Function_int + %int_0 = OpConstant %int 0 + %bool = OpTypeBool + %float_10 = OpConstant %float 10 + %22 = OpConstantComposite %v4float %float_10 %float_10 %float_10 %float_10 +%_ptr_Function_v4float = OpTypePointer Function %v4float +%_ptr_Input_int = OpTypePointer Input %int + %vA = OpVariable %_ptr_Input_int Input +%_ptr_Output_v4float = OpTypePointer Output %v4float + %FragColor = OpVariable %_ptr_Output_v4float Output + %main = OpFunction %void None %3 + %5 = OpLabel + %a_0 = OpVariable %_ptr_Function_v4float Function + %param = OpVariable %_ptr_Function_int Function + %30 = OpLoad %int %vA + OpStore %param %30 + %31 = OpFunctionCall %v4float %foobar_i1_ %param + OpStore %FragColor %22 + OpReturn + OpFunctionEnd + %foobar_i1_ = OpFunction %v4float None %10 + %a = OpFunctionParameter %_ptr_Function_int + %13 = OpLabel + %14 = OpLoad %int %a + %17 = OpSLessThan %bool %14 %int_0 + OpSelectionMerge %19 None + OpBranchConditional %17 %18 %19 + %18 = OpLabel + OpKill + %19 = OpLabel + OpReturnValue %22 + OpFunctionEnd diff --git a/3rdparty/spirv-cross/spirv_cross.cpp b/3rdparty/spirv-cross/spirv_cross.cpp index 2a6b96438..c73ecdf10 100644 --- a/3rdparty/spirv-cross/spirv_cross.cpp +++ b/3rdparty/spirv-cross/spirv_cross.cpp @@ -88,6 +88,10 @@ bool Compiler::variable_storage_is_aliased(const SPIRVariable &v) bool Compiler::block_is_pure(const SPIRBlock &block) { + // This is a global side effect of the function. + if (block.terminator == SPIRBlock::Kill) + return false; + for (auto &i : block.ops) { auto ops = stream(i); @@ -156,6 +160,10 @@ bool Compiler::block_is_pure(const SPIRBlock &block) // OpExtInst is potentially impure depending on extension, but GLSL builtins are at least pure. + case OpDemoteToHelperInvocationEXT: + // This is a global side effect of the function. + return false; + default: break; } diff --git a/3rdparty/spirv-cross/spirv_msl.cpp b/3rdparty/spirv-cross/spirv_msl.cpp index 9c7bc2328..a142afaf1 100644 --- a/3rdparty/spirv-cross/spirv_msl.cpp +++ b/3rdparty/spirv-cross/spirv_msl.cpp @@ -5774,9 +5774,9 @@ void CompilerMSL::emit_array_copy(const string &lhs, uint32_t rhs_id, StorageCla add_spv_func_and_recompile(SPVFuncImplArrayCopy); bool lhs_thread = - lhs_storage == StorageClassFunction || lhs_storage == StorageClassGeneric || lhs_storage == StorageClassPrivate; + lhs_storage == StorageClassOutput || lhs_storage == StorageClassFunction || lhs_storage == StorageClassGeneric || lhs_storage == StorageClassPrivate; bool rhs_thread = - rhs_storage == StorageClassFunction || rhs_storage == StorageClassGeneric || rhs_storage == StorageClassPrivate; + rhs_storage == StorageClassInput || rhs_storage == StorageClassFunction || rhs_storage == StorageClassGeneric || rhs_storage == StorageClassPrivate; const char *tag = nullptr; if (lhs_thread && is_constant)