From 542d4603648085a5210f24275d808207faaffe4b Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Tue, 27 Oct 2020 12:29:08 +0100 Subject: [PATCH] Handle case where block is loop header, continue AND break block. --- .../loop-header-self-continue-break.asm.comp | 89 ++++++++++++++ .../loop-header-self-continue-break.asm.comp | 109 ++++++++++++++++++ spirv_glsl.cpp | 8 +- 3 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 reference/shaders-no-opt/asm/loop-header-self-continue-break.asm.comp create mode 100644 shaders-no-opt/asm/loop-header-self-continue-break.asm.comp diff --git a/reference/shaders-no-opt/asm/loop-header-self-continue-break.asm.comp b/reference/shaders-no-opt/asm/loop-header-self-continue-break.asm.comp new file mode 100644 index 00000000..bd2a3c27 --- /dev/null +++ b/reference/shaders-no-opt/asm/loop-header-self-continue-break.asm.comp @@ -0,0 +1,89 @@ +#version 450 + +#ifndef SPIRV_CROSS_CONSTANT_ID_0 +#define SPIRV_CROSS_CONSTANT_ID_0 1u +#endif +#ifndef SPIRV_CROSS_CONSTANT_ID_1 +#define SPIRV_CROSS_CONSTANT_ID_1 1u +#endif +#ifndef SPIRV_CROSS_CONSTANT_ID_2 +#define SPIRV_CROSS_CONSTANT_ID_2 1u +#endif + +layout(local_size_x = SPIRV_CROSS_CONSTANT_ID_0, local_size_y = SPIRV_CROSS_CONSTANT_ID_1, local_size_z = SPIRV_CROSS_CONSTANT_ID_2) in; + +layout(binding = 0, std430) buffer _4_6 +{ + float _m0[]; +} _6; + +layout(binding = 1, std430) buffer _4_7 +{ + float _m0[]; +} _7; + +uvec3 _28 = gl_WorkGroupSize; + +void main() +{ + float _44_copy; + float _46; + uint _47; + float _63; + uint _65; + float _36 = _6._m0[0u]; + uint _39 = 0u; + float _44; + for (;;) + { + _44 = _36; + _46 = _6._m0[35u]; + _47 = 0u; + for (;;) + { + uint _48 = _47 + 1u; + float _45 = _6._m0[_48]; + _6._m0[_47] = ((_46 + _44) + _45) / 3.0; + if (!(_47 < 34u)) + { + break; + } + else + { + _44_copy = _44; + _44 = _45; + _46 = _44_copy; + _47 = _48; + } + } + _6._m0[35u] = (_36 + (_44 + _6._m0[35u])) / 3.0; + if (!(_39 < 5u)) + { + _63 = _6._m0[0u]; + _65 = 1u; + break; + } + else + { + _36 = _6._m0[0u]; + _39++; + continue; + } + } + float _64; + for (;;) + { + _64 = (_63 < _6._m0[_65]) ? _6._m0[_65] : _63; + if (!(_65 < 35u)) + { + break; + } + else + { + _63 = _64; + _65++; + } + } + _7._m0[gl_GlobalInvocationID.x] = _64; +} + diff --git a/shaders-no-opt/asm/loop-header-self-continue-break.asm.comp b/shaders-no-opt/asm/loop-header-self-continue-break.asm.comp new file mode 100644 index 00000000..a38b1112 --- /dev/null +++ b/shaders-no-opt/asm/loop-header-self-continue-break.asm.comp @@ -0,0 +1,109 @@ +; SPIR-V +; Version: 1.0 +; Generator: Google Clspv; 0 +; Bound: 83 +; Schema: 0 + OpCapability Shader + OpExtension "SPV_KHR_storage_buffer_storage_class" + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %19 "main" %gl_GlobalInvocationID + OpSource OpenCL_C 120 + OpDecorate %_runtimearr_float ArrayStride 4 + OpMemberDecorate %_struct_3 0 Offset 0 + OpDecorate %_struct_3 Block + OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId + OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize + OpDecorate %15 DescriptorSet 0 + OpDecorate %15 Binding 0 + OpDecorate %16 DescriptorSet 0 + OpDecorate %16 Binding 1 + OpDecorate %10 SpecId 0 + OpDecorate %11 SpecId 1 + OpDecorate %12 SpecId 2 + %float = OpTypeFloat 32 +%_runtimearr_float = OpTypeRuntimeArray %float + %_struct_3 = OpTypeStruct %_runtimearr_float +%_ptr_StorageBuffer__struct_3 = OpTypePointer StorageBuffer %_struct_3 + %uint = OpTypeInt 32 0 + %v3uint = OpTypeVector %uint 3 +%_ptr_Input_v3uint = OpTypePointer Input %v3uint +%_ptr_Private_v3uint = OpTypePointer Private %v3uint + %10 = OpSpecConstant %uint 1 + %11 = OpSpecConstant %uint 1 + %12 = OpSpecConstant %uint 1 +%gl_WorkGroupSize = OpSpecConstantComposite %v3uint %10 %11 %12 + %void = OpTypeVoid + %18 = OpTypeFunction %void +%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float + %uint_0 = OpConstant %uint 0 +%_ptr_Input_uint = OpTypePointer Input %uint + %uint_35 = OpConstant %uint 35 + %uint_1 = OpConstant %uint 1 + %float_3 = OpConstant %float 3 + %bool = OpTypeBool + %uint_34 = OpConstant %uint 34 + %uint_5 = OpConstant %uint 5 +%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input + %14 = OpVariable %_ptr_Private_v3uint Private %gl_WorkGroupSize + %15 = OpVariable %_ptr_StorageBuffer__struct_3 StorageBuffer + %16 = OpVariable %_ptr_StorageBuffer__struct_3 StorageBuffer + %19 = OpFunction %void None %18 + %20 = OpLabel + %23 = OpAccessChain %_ptr_StorageBuffer_float %15 %uint_0 %uint_0 + %25 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0 + %26 = OpLoad %uint %25 + %27 = OpLoad %float %23 + %29 = OpAccessChain %_ptr_StorageBuffer_float %15 %uint_0 %uint_35 + OpBranch %31 + %31 = OpLabel + %32 = OpPhi %float %27 %20 %67 %58 + %33 = OpPhi %uint %uint_0 %20 %63 %58 + %34 = OpLoad %float %29 + OpLoopMerge %69 %58 None + OpBranch %37 + %37 = OpLabel + %38 = OpPhi %float %46 %37 %32 %31 + %39 = OpPhi %float %38 %37 %34 %31 + %40 = OpPhi %uint %44 %37 %uint_0 %31 + %41 = OpAccessChain %_ptr_StorageBuffer_float %15 %uint_0 %40 + %42 = OpFAdd %float %39 %38 + %44 = OpIAdd %uint %40 %uint_1 + %45 = OpAccessChain %_ptr_StorageBuffer_float %15 %uint_0 %44 + %46 = OpLoad %float %45 + %47 = OpFAdd %float %42 %46 + %49 = OpFDiv %float %47 %float_3 + OpStore %41 %49 + %52 = OpULessThan %bool %40 %uint_34 + %53 = OpLogicalNot %bool %52 + OpLoopMerge %56 %37 None + OpBranchConditional %53 %56 %37 + %56 = OpLabel + OpBranch %58 + %58 = OpLabel + %59 = OpLoad %float %29 + %60 = OpFAdd %float %38 %59 + %61 = OpFAdd %float %32 %60 + %62 = OpFDiv %float %61 %float_3 + OpStore %29 %62 + %63 = OpIAdd %uint %33 %uint_1 + %65 = OpULessThan %bool %33 %uint_5 + %66 = OpLogicalNot %bool %65 + %67 = OpLoad %float %23 + OpBranchConditional %66 %69 %31 + %69 = OpLabel + %70 = OpPhi %float %75 %69 %67 %58 + %71 = OpPhi %uint %76 %69 %uint_1 %58 + %72 = OpAccessChain %_ptr_StorageBuffer_float %15 %uint_0 %71 + %73 = OpLoad %float %72 + %74 = OpFOrdLessThan %bool %70 %73 + %75 = OpSelect %float %74 %73 %70 + %76 = OpIAdd %uint %71 %uint_1 + %77 = OpULessThan %bool %71 %uint_35 + %78 = OpLogicalNot %bool %77 + OpLoopMerge %81 %69 None + OpBranchConditional %78 %81 %69 + %81 = OpLabel + %82 = OpAccessChain %_ptr_StorageBuffer_float %16 %uint_0 %26 + OpStore %82 %75 + OpReturn + OpFunctionEnd diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index e5db12f3..7b1efaa0 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -13253,8 +13253,14 @@ void CompilerGLSL::branch(BlockID from, BlockID to) // and end the chain here. statement("continue;"); } - else if (is_break(to)) + else if (from != to && is_break(to)) { + // We cannot break to ourselves, so check explicitly for from != to. + // This case can trigger if a loop header is all three of these things: + // - Continue block + // - Loop header + // - Break merge target all at once ... + // Very dirty workaround. // Switch constructs are able to break, but they cannot break out of a loop at the same time. // Only sensible solution is to make a ladder variable, which we declare at the top of the switch block,