Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/KhronosGroup/SPIRV-Cross.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans-Kristian Arntzen <post@arntzen-software.no>2022-01-17 16:12:01 +0300
committerHans-Kristian Arntzen <post@arntzen-software.no>2022-01-17 16:12:01 +0300
commit1d13a3e36a56e446020057beedb82cdce6d23c58 (patch)
tree06285488c1ab8b50ecaeacb15c2bc8351ec2112a
parenta1bb29ccbb285618028a24efb3fe4f6718cee0b5 (diff)
Rework how loop iteration counts are validated.
Introduces an idea of a recompilation making forward progress. There are some extreme edge cases where we need more than 3 loops, but only allow this in specific circumstances where we can reason about forward progress being made.
-rw-r--r--reference/shaders-no-opt/asm/frag/late-expression-invalidation-2.asm.frag262
-rw-r--r--reference/shaders-no-opt/asm/frag/late-expression-invalidation.asm.frag54
-rw-r--r--shaders-no-opt/asm/frag/late-expression-invalidation-2.asm.frag625
-rw-r--r--shaders-no-opt/asm/frag/late-expression-invalidation.asm.frag109
-rw-r--r--spirv_cpp.cpp5
-rw-r--r--spirv_cross.cpp7
-rw-r--r--spirv_cross.hpp2
-rw-r--r--spirv_glsl.cpp31
-rw-r--r--spirv_glsl.hpp2
-rw-r--r--spirv_hlsl.cpp5
-rw-r--r--spirv_msl.cpp5
11 files changed, 1085 insertions, 22 deletions
diff --git a/reference/shaders-no-opt/asm/frag/late-expression-invalidation-2.asm.frag b/reference/shaders-no-opt/asm/frag/late-expression-invalidation-2.asm.frag
new file mode 100644
index 00000000..85bc540f
--- /dev/null
+++ b/reference/shaders-no-opt/asm/frag/late-expression-invalidation-2.asm.frag
@@ -0,0 +1,262 @@
+#version 320 es
+#if defined(GL_EXT_control_flow_attributes)
+#extension GL_EXT_control_flow_attributes : require
+#define SPIRV_CROSS_FLATTEN [[flatten]]
+#define SPIRV_CROSS_BRANCH [[dont_flatten]]
+#define SPIRV_CROSS_UNROLL [[unroll]]
+#define SPIRV_CROSS_LOOP [[dont_unroll]]
+#else
+#define SPIRV_CROSS_FLATTEN
+#define SPIRV_CROSS_BRANCH
+#define SPIRV_CROSS_UNROLL
+#define SPIRV_CROSS_LOOP
+#endif
+precision mediump float;
+precision highp int;
+
+layout(binding = 0, std140) uniform buf0
+{
+ highp vec2 resolution;
+} _7;
+
+layout(location = 0) out highp vec4 _GLF_color;
+int map[256];
+highp mat2x4 _60 = mat2x4(vec4(0.0), vec4(0.0));
+
+void main()
+{
+ int _68 = -(256 - 14);
+ highp vec2 pos = gl_FragCoord.xy / _7.resolution;
+ ivec2 ipos = ivec2(int(pos.x * 16.0), int(pos.y * 16.0));
+ int i = 0;
+ for (; i < 256; i++)
+ {
+ map[i] = 0;
+ }
+ ivec2 p = ivec2(0);
+ int v = 0;
+ bool canwalk = true;
+ do
+ {
+ v++;
+ int directions = 0;
+ bool _98 = p.x > 0;
+ bool _111;
+ if (_98)
+ {
+ _111 = map[(p.x - 2) + (p.y * 16)] == 0;
+ }
+ else
+ {
+ _111 = _98;
+ }
+ if (_111)
+ {
+ directions++;
+ }
+ bool _118 = p.y > 0;
+ bool _131;
+ if (_118)
+ {
+ _131 = map[p.x + ((p.y - 2) * 16)] == 0;
+ }
+ else
+ {
+ _131 = _118;
+ }
+ if (_131)
+ {
+ directions++;
+ }
+ bool _138 = p.x < 14;
+ bool _151;
+ if (_138)
+ {
+ _151 = map[(p.x + 2) + (p.y * 16)] == 0;
+ }
+ else
+ {
+ _151 = _138;
+ }
+ if (_151)
+ {
+ directions++;
+ }
+ int _156 = 256 - _68;
+ bool _159 = p.y < 14;
+ bool _172;
+ if (_159)
+ {
+ _172 = map[p.x + ((p.y + 2) * 16)] == 0;
+ }
+ else
+ {
+ _172 = _159;
+ }
+ if (_172)
+ {
+ directions++;
+ }
+ if (directions == 0)
+ {
+ canwalk = false;
+ i = 0;
+ for (;;)
+ {
+ int _186 = i;
+ if (_186 < 8)
+ {
+ int j = 0;
+ _60 = mat2x4(vec4(0.0), vec4(0.0));
+ if (false)
+ {
+ int _216 = i;
+ i = _216 + 1;
+ continue;
+ }
+ else
+ {
+ SPIRV_CROSS_UNROLL
+ for (; j < 8; j++)
+ {
+ if (map[(j * 2) + ((i * 2) * 16)] == 0)
+ {
+ p.x = j * 2;
+ p.y = i * 2;
+ canwalk = true;
+ }
+ }
+ int _216 = i;
+ i = _216 + 1;
+ continue;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ map[p.x + (p.y * 16)] = 1;
+ }
+ else
+ {
+ int d = v % directions;
+ v += directions;
+ bool _232 = d >= 0;
+ bool _238;
+ if (_232)
+ {
+ _238 = p.x > 0;
+ }
+ else
+ {
+ _238 = _232;
+ }
+ bool _251;
+ if (_238)
+ {
+ _251 = map[(p.x - 2) + (p.y * 16)] == 0;
+ }
+ else
+ {
+ _251 = _238;
+ }
+ if (_251)
+ {
+ d--;
+ map[p.x + (p.y * 16)] = 1;
+ map[(p.x - 1) + (p.y * 16)] = 1;
+ map[(p.x - 2) + (p.y * 16)] = 1;
+ p.x -= 2;
+ }
+ bool _284 = d >= 0;
+ bool _290;
+ if (_284)
+ {
+ _290 = p.y > 0;
+ }
+ else
+ {
+ _290 = _284;
+ }
+ bool _303;
+ if (_290)
+ {
+ _303 = map[p.x + ((p.y - 2) * 16)] == 0;
+ }
+ else
+ {
+ _303 = _290;
+ }
+ if (_303)
+ {
+ d--;
+ map[p.x + (p.y * 16)] = 1;
+ map[p.x + ((p.y - 1) * 16)] = 1;
+ map[p.x + ((p.y - 2) * 16)] = 1;
+ p.y -= 2;
+ }
+ bool _336 = d >= 0;
+ bool _342;
+ if (_336)
+ {
+ _342 = p.x < 14;
+ }
+ else
+ {
+ _342 = _336;
+ }
+ bool _355;
+ if (_342)
+ {
+ _355 = map[(p.x + 2) + (p.y * 16)] == 0;
+ }
+ else
+ {
+ _355 = _342;
+ }
+ if (_355)
+ {
+ d--;
+ map[p.x + (p.y * 16)] = 1;
+ map[(p.x + 1) + (p.y * 16)] = 1;
+ map[(p.x + 2) + (p.y * 16)] = 1;
+ p.x += 2;
+ }
+ bool _388 = d >= 0;
+ bool _394;
+ if (_388)
+ {
+ _394 = p.y < 14;
+ }
+ else
+ {
+ _394 = _388;
+ }
+ bool _407;
+ if (_394)
+ {
+ _407 = map[p.x + ((p.y + 2) * 16)] == 0;
+ }
+ else
+ {
+ _407 = _394;
+ }
+ if (_407)
+ {
+ d--;
+ map[p.x + (p.y * 16)] = 1;
+ map[p.x + ((p.y + 1) * 16)] = 1;
+ map[p.x + ((p.y + 2) * 16)] = 1;
+ p.y += 2;
+ }
+ }
+ if (map[(ipos.y * 16) + ipos.x] == 1)
+ {
+ _GLF_color = vec4(1.0);
+ return;
+ }
+ } while (canwalk);
+ _GLF_color = vec4(0.0, 0.0, 0.0, 1.0);
+}
+
diff --git a/reference/shaders-no-opt/asm/frag/late-expression-invalidation.asm.frag b/reference/shaders-no-opt/asm/frag/late-expression-invalidation.asm.frag
new file mode 100644
index 00000000..6522c651
--- /dev/null
+++ b/reference/shaders-no-opt/asm/frag/late-expression-invalidation.asm.frag
@@ -0,0 +1,54 @@
+#version 310 es
+precision mediump float;
+precision highp int;
+
+const mat4 _34[4] = mat4[](mat4(vec4(1.0), vec4(1.0), vec4(1.0), vec4(1.0)), mat4(vec4(1.0), vec4(1.0), vec4(1.0), vec4(1.0)), mat4(vec4(1.0), vec4(1.0), vec4(1.0), vec4(1.0)), mat4(vec4(1.0), vec4(1.0), vec4(1.0), vec4(1.0)));
+
+layout(location = 0) out highp vec4 _GLF_color;
+
+void main()
+{
+ for (;;)
+ {
+ if (gl_FragCoord.x < 10.0)
+ {
+ _GLF_color = vec4(1.0, 0.0, 0.0, 1.0);
+ break;
+ }
+ for (int _46 = 0; _46 < 4; _46++)
+ {
+ int _53;
+ _53 = 0;
+ bool _56;
+ for (;;)
+ {
+ _56 = _53 < 4;
+ if (_56)
+ {
+ if (distance(vec2(1.0), vec2(1.0) / vec2(_34[int(_56)][_46].w)) < 1.0)
+ {
+ _GLF_color = vec4(1.0);
+ int _54 = _53 + 1;
+ _53 = _54;
+ continue;
+ }
+ else
+ {
+ int _54 = _53 + 1;
+ _53 = _54;
+ continue;
+ }
+ int _54 = _53 + 1;
+ _53 = _54;
+ continue;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ break;
+ }
+}
+
diff --git a/shaders-no-opt/asm/frag/late-expression-invalidation-2.asm.frag b/shaders-no-opt/asm/frag/late-expression-invalidation-2.asm.frag
new file mode 100644
index 00000000..a10970e9
--- /dev/null
+++ b/shaders-no-opt/asm/frag/late-expression-invalidation-2.asm.frag
@@ -0,0 +1,625 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos SPIR-V Tools Assembler; 0
+; Bound: 761
+; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %gl_FragCoord %_GLF_color
+ OpExecutionMode %main OriginUpperLeft
+ OpSource ESSL 320
+ OpName %main "main"
+ OpName %pos "pos"
+ OpName %gl_FragCoord "gl_FragCoord"
+ OpName %buf0 "buf0"
+ OpMemberName %buf0 0 "resolution"
+ OpName %_ ""
+ OpName %ipos "ipos"
+ OpName %i "i"
+ OpName %map "map"
+ OpName %p "p"
+ OpName %canwalk "canwalk"
+ OpName %v "v"
+ OpName %directions "directions"
+ OpName %j "j"
+ OpName %d "d"
+ OpName %_GLF_color "_GLF_color"
+ OpDecorate %gl_FragCoord BuiltIn FragCoord
+ OpMemberDecorate %buf0 0 Offset 0
+ OpDecorate %buf0 Block
+ OpDecorate %_ DescriptorSet 0
+ OpDecorate %_ Binding 0
+ OpDecorate %_GLF_color Location 0
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v2float = OpTypeVector %float 2
+%_ptr_Function_v2float = OpTypePointer Function %v2float
+ %v4float = OpTypeVector %float 4
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+ %buf0 = OpTypeStruct %v2float
+%_ptr_Uniform_buf0 = OpTypePointer Uniform %buf0
+ %_ = OpVariable %_ptr_Uniform_buf0 Uniform
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+ %v2int = OpTypeVector %int 2
+%_ptr_Function_v2int = OpTypePointer Function %v2int
+ %uint = OpTypeInt 32 0
+ %uint_0 = OpConstant %uint 0
+%_ptr_Function_float = OpTypePointer Function %float
+ %float_16 = OpConstant %float 16
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_256 = OpConstant %int 256
+ %bool = OpTypeBool
+ %uint_256 = OpConstant %uint 256
+%_arr_int_uint_256 = OpTypeArray %int %uint_256
+%_ptr_Private__arr_int_uint_256 = OpTypePointer Private %_arr_int_uint_256
+ %map = OpVariable %_ptr_Private__arr_int_uint_256 Private
+%_ptr_Private_int = OpTypePointer Private %int
+ %int_1 = OpConstant %int 1
+ %63 = OpConstantComposite %v2int %int_0 %int_0
+%_ptr_Function_bool = OpTypePointer Function %bool
+ %true = OpConstantTrue %bool
+ %int_2 = OpConstant %int 2
+ %int_16 = OpConstant %int 16
+ %int_14 = OpConstant %int 14
+ %false = OpConstantFalse %bool
+ %int_8 = OpConstant %int 8
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %_GLF_color = OpVariable %_ptr_Output_v4float Output
+ %float_1 = OpConstant %float 1
+ %437 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
+ %float_0 = OpConstant %float 0
+ %441 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_1
+%mat2v4float = OpTypeMatrix %v4float 2
+%_ptr_Private_mat2v4float = OpTypePointer Private %mat2v4float
+ %556 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
+ %557 = OpConstantComposite %mat2v4float %556 %556
+ %558 = OpVariable %_ptr_Private_mat2v4float Private %557
+ %760 = OpConstantNull %bool
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %pos = OpVariable %_ptr_Function_v2float Function
+ %ipos = OpVariable %_ptr_Function_v2int Function
+ %i = OpVariable %_ptr_Function_int Function
+ %p = OpVariable %_ptr_Function_v2int Function
+ %canwalk = OpVariable %_ptr_Function_bool Function
+ %v = OpVariable %_ptr_Function_int Function
+ %directions = OpVariable %_ptr_Function_int Function
+ %j = OpVariable %_ptr_Function_int Function
+ %d = OpVariable %_ptr_Function_int Function
+ %13 = OpLoad %v4float %gl_FragCoord
+ %14 = OpVectorShuffle %v2float %13 %13 0 1
+ %564 = OpISub %int %int_256 %int_14
+ %21 = OpAccessChain %_ptr_Uniform_v2float %_ %int_0
+ %22 = OpLoad %v2float %21
+ %566 = OpSNegate %int %564
+ %23 = OpFDiv %v2float %14 %22
+ OpStore %pos %23
+ %30 = OpAccessChain %_ptr_Function_float %pos %uint_0
+ %31 = OpLoad %float %30
+ %33 = OpFMul %float %31 %float_16
+ %34 = OpConvertFToS %int %33
+ %36 = OpAccessChain %_ptr_Function_float %pos %uint_1
+ %37 = OpLoad %float %36
+ %38 = OpFMul %float %37 %float_16
+ %39 = OpConvertFToS %int %38
+ %40 = OpCompositeConstruct %v2int %34 %39
+ OpStore %ipos %40
+ OpStore %i %int_0
+ OpBranch %43
+ %43 = OpLabel
+ OpLoopMerge %45 %46 None
+ OpBranch %47
+ %47 = OpLabel
+ %48 = OpLoad %int %i
+ %51 = OpSLessThan %bool %48 %int_256
+ OpBranchConditional %51 %44 %45
+ %44 = OpLabel
+ %56 = OpLoad %int %i
+ %58 = OpAccessChain %_ptr_Private_int %map %56
+ OpStore %58 %int_0
+ OpBranch %46
+ %46 = OpLabel
+ %59 = OpLoad %int %i
+ %61 = OpIAdd %int %59 %int_1
+ OpStore %i %61
+ OpBranch %43
+ %45 = OpLabel
+ OpStore %p %63
+ OpStore %canwalk %true
+ OpStore %v %int_0
+ OpBranch %68
+ %68 = OpLabel
+ OpLoopMerge %70 %71 None
+ OpBranch %69
+ %69 = OpLabel
+ %72 = OpLoad %int %v
+ %73 = OpIAdd %int %72 %int_1
+ OpStore %v %73
+ OpStore %directions %int_0
+ %75 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %76 = OpLoad %int %75
+ %77 = OpSGreaterThan %bool %76 %int_0
+ OpSelectionMerge %79 None
+ OpBranchConditional %77 %78 %79
+ %78 = OpLabel
+ %80 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %81 = OpLoad %int %80
+ %83 = OpISub %int %81 %int_2
+ %84 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %85 = OpLoad %int %84
+ %87 = OpIMul %int %85 %int_16
+ %88 = OpIAdd %int %83 %87
+ %89 = OpAccessChain %_ptr_Private_int %map %88
+ %90 = OpLoad %int %89
+ %91 = OpIEqual %bool %90 %int_0
+ OpBranch %79
+ %79 = OpLabel
+ %92 = OpPhi %bool %77 %69 %91 %78
+ OpSelectionMerge %94 None
+ OpBranchConditional %92 %93 %94
+ %93 = OpLabel
+ %95 = OpLoad %int %directions
+ %96 = OpIAdd %int %95 %int_1
+ OpStore %directions %96
+ OpBranch %94
+ %94 = OpLabel
+ %97 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %98 = OpLoad %int %97
+ %99 = OpSGreaterThan %bool %98 %int_0
+ OpSelectionMerge %101 None
+ OpBranchConditional %99 %100 %101
+ %100 = OpLabel
+ %102 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %103 = OpLoad %int %102
+ %104 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %105 = OpLoad %int %104
+ %106 = OpISub %int %105 %int_2
+ %107 = OpIMul %int %106 %int_16
+ %108 = OpIAdd %int %103 %107
+ %109 = OpAccessChain %_ptr_Private_int %map %108
+ %110 = OpLoad %int %109
+ %111 = OpIEqual %bool %110 %int_0
+ OpBranch %101
+ %101 = OpLabel
+ %112 = OpPhi %bool %99 %94 %111 %100
+ OpSelectionMerge %114 None
+ OpBranchConditional %112 %113 %114
+ %113 = OpLabel
+ %115 = OpLoad %int %directions
+ %116 = OpIAdd %int %115 %int_1
+ OpStore %directions %116
+ OpBranch %114
+ %114 = OpLabel
+ %117 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %118 = OpLoad %int %117
+ %120 = OpSLessThan %bool %118 %int_14
+ OpSelectionMerge %122 None
+ OpBranchConditional %120 %121 %122
+ %121 = OpLabel
+ %123 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %124 = OpLoad %int %123
+ %125 = OpIAdd %int %124 %int_2
+ %126 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %127 = OpLoad %int %126
+ %128 = OpIMul %int %127 %int_16
+ %129 = OpIAdd %int %125 %128
+ %130 = OpAccessChain %_ptr_Private_int %map %129
+ %131 = OpLoad %int %130
+ %132 = OpIEqual %bool %131 %int_0
+ OpBranch %122
+ %122 = OpLabel
+ %133 = OpPhi %bool %120 %114 %132 %121
+ OpSelectionMerge %135 None
+ OpBranchConditional %133 %134 %135
+ %134 = OpLabel
+ %136 = OpLoad %int %directions
+ %137 = OpIAdd %int %136 %int_1
+ OpStore %directions %137
+ OpBranch %135
+ %135 = OpLabel
+ %594 = OpISub %int %int_256 %566
+ %138 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %139 = OpLoad %int %138
+ %140 = OpSLessThan %bool %139 %int_14
+ OpSelectionMerge %142 None
+ OpBranchConditional %140 %141 %142
+ %141 = OpLabel
+ %143 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %144 = OpLoad %int %143
+ %145 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %146 = OpLoad %int %145
+ %147 = OpIAdd %int %146 %int_2
+ %148 = OpIMul %int %147 %int_16
+ %149 = OpIAdd %int %144 %148
+ %150 = OpAccessChain %_ptr_Private_int %map %149
+ %151 = OpLoad %int %150
+ %152 = OpIEqual %bool %151 %int_0
+ OpBranch %142
+ %142 = OpLabel
+ %153 = OpPhi %bool %140 %135 %152 %141
+ OpSelectionMerge %155 None
+ OpBranchConditional %153 %154 %155
+ %154 = OpLabel
+ %156 = OpLoad %int %directions
+ %157 = OpIAdd %int %156 %int_1
+ OpStore %directions %157
+ OpBranch %155
+ %155 = OpLabel
+ %158 = OpLoad %int %directions
+ %159 = OpIEqual %bool %158 %int_0
+ OpSelectionMerge %161 None
+ OpBranchConditional %159 %160 %207
+ %160 = OpLabel
+ OpStore %canwalk %false
+ OpStore %i %int_0
+ OpBranch %163
+ %163 = OpLabel
+ OpLoopMerge %165 %166 None
+ OpBranch %167
+ %167 = OpLabel
+ %168 = OpLoad %int %i
+ %170 = OpSLessThan %bool %168 %int_8
+ OpBranchConditional %170 %164 %165
+ %164 = OpLabel
+ OpStore %j %int_0
+ %609 = OpISub %int %594 %168
+ OpStore %558 %557
+ OpBranchConditional %760 %166 %172
+ %172 = OpLabel
+ OpLoopMerge %174 %175 Unroll
+ OpBranch %176
+ %176 = OpLabel
+ %177 = OpLoad %int %j
+ %178 = OpSLessThan %bool %177 %int_8
+ OpBranchConditional %178 %173 %174
+ %173 = OpLabel
+ %179 = OpLoad %int %j
+ %180 = OpIMul %int %179 %int_2
+ %181 = OpLoad %int %i
+ %182 = OpIMul %int %181 %int_2
+ %183 = OpIMul %int %182 %int_16
+ %184 = OpIAdd %int %180 %183
+ %185 = OpAccessChain %_ptr_Private_int %map %184
+ %186 = OpLoad %int %185
+ %187 = OpIEqual %bool %186 %int_0
+ OpSelectionMerge %189 None
+ OpBranchConditional %187 %188 %189
+ %188 = OpLabel
+ %190 = OpLoad %int %j
+ %191 = OpIMul %int %190 %int_2
+ %192 = OpAccessChain %_ptr_Function_int %p %uint_0
+ OpStore %192 %191
+ %193 = OpLoad %int %i
+ %194 = OpIMul %int %193 %int_2
+ %195 = OpAccessChain %_ptr_Function_int %p %uint_1
+ OpStore %195 %194
+ OpStore %canwalk %true
+ OpBranch %189
+ %189 = OpLabel
+ OpBranch %175
+ %175 = OpLabel
+ %196 = OpLoad %int %j
+ %197 = OpIAdd %int %196 %int_1
+ OpStore %j %197
+ OpBranch %172
+ %174 = OpLabel
+ OpBranch %166
+ %166 = OpLabel
+ %198 = OpLoad %int %i
+ %199 = OpIAdd %int %198 %int_1
+ OpStore %i %199
+ OpBranch %163
+ %165 = OpLabel
+ %200 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %201 = OpLoad %int %200
+ %202 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %203 = OpLoad %int %202
+ %204 = OpIMul %int %203 %int_16
+ %205 = OpIAdd %int %201 %204
+ %206 = OpAccessChain %_ptr_Private_int %map %205
+ OpStore %206 %int_1
+ OpBranch %161
+ %207 = OpLabel
+ %209 = OpLoad %int %v
+ %210 = OpLoad %int %directions
+ %211 = OpSMod %int %209 %210
+ OpStore %d %211
+ %212 = OpLoad %int %directions
+ %213 = OpLoad %int %v
+ %214 = OpIAdd %int %213 %212
+ OpStore %v %214
+ %215 = OpLoad %int %d
+ %216 = OpSGreaterThanEqual %bool %215 %int_0
+ OpSelectionMerge %218 None
+ OpBranchConditional %216 %217 %218
+ %217 = OpLabel
+ %219 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %220 = OpLoad %int %219
+ %221 = OpSGreaterThan %bool %220 %int_0
+ OpBranch %218
+ %218 = OpLabel
+ %222 = OpPhi %bool %216 %207 %221 %217
+ OpSelectionMerge %224 None
+ OpBranchConditional %222 %223 %224
+ %223 = OpLabel
+ %225 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %226 = OpLoad %int %225
+ %227 = OpISub %int %226 %int_2
+ %228 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %229 = OpLoad %int %228
+ %230 = OpIMul %int %229 %int_16
+ %231 = OpIAdd %int %227 %230
+ %232 = OpAccessChain %_ptr_Private_int %map %231
+ %233 = OpLoad %int %232
+ %234 = OpIEqual %bool %233 %int_0
+ OpBranch %224
+ %224 = OpLabel
+ %235 = OpPhi %bool %222 %218 %234 %223
+ OpSelectionMerge %237 None
+ OpBranchConditional %235 %236 %237
+ %236 = OpLabel
+ %238 = OpLoad %int %d
+ %239 = OpISub %int %238 %int_1
+ OpStore %d %239
+ %240 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %241 = OpLoad %int %240
+ %242 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %243 = OpLoad %int %242
+ %244 = OpIMul %int %243 %int_16
+ %245 = OpIAdd %int %241 %244
+ %246 = OpAccessChain %_ptr_Private_int %map %245
+ OpStore %246 %int_1
+ %247 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %248 = OpLoad %int %247
+ %249 = OpISub %int %248 %int_1
+ %250 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %251 = OpLoad %int %250
+ %252 = OpIMul %int %251 %int_16
+ %253 = OpIAdd %int %249 %252
+ %254 = OpAccessChain %_ptr_Private_int %map %253
+ OpStore %254 %int_1
+ %255 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %256 = OpLoad %int %255
+ %257 = OpISub %int %256 %int_2
+ %258 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %259 = OpLoad %int %258
+ %260 = OpIMul %int %259 %int_16
+ %261 = OpIAdd %int %257 %260
+ %262 = OpAccessChain %_ptr_Private_int %map %261
+ OpStore %262 %int_1
+ %263 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %264 = OpLoad %int %263
+ %265 = OpISub %int %264 %int_2
+ %266 = OpAccessChain %_ptr_Function_int %p %uint_0
+ OpStore %266 %265
+ OpBranch %237
+ %237 = OpLabel
+ %267 = OpLoad %int %d
+ %268 = OpSGreaterThanEqual %bool %267 %int_0
+ OpSelectionMerge %270 None
+ OpBranchConditional %268 %269 %270
+ %269 = OpLabel
+ %271 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %272 = OpLoad %int %271
+ %273 = OpSGreaterThan %bool %272 %int_0
+ OpBranch %270
+ %270 = OpLabel
+ %274 = OpPhi %bool %268 %237 %273 %269
+ OpSelectionMerge %276 None
+ OpBranchConditional %274 %275 %276
+ %275 = OpLabel
+ %277 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %278 = OpLoad %int %277
+ %279 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %280 = OpLoad %int %279
+ %281 = OpISub %int %280 %int_2
+ %282 = OpIMul %int %281 %int_16
+ %283 = OpIAdd %int %278 %282
+ %284 = OpAccessChain %_ptr_Private_int %map %283
+ %285 = OpLoad %int %284
+ %286 = OpIEqual %bool %285 %int_0
+ OpBranch %276
+ %276 = OpLabel
+ %287 = OpPhi %bool %274 %270 %286 %275
+ OpSelectionMerge %289 None
+ OpBranchConditional %287 %288 %289
+ %288 = OpLabel
+ %290 = OpLoad %int %d
+ %291 = OpISub %int %290 %int_1
+ OpStore %d %291
+ %292 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %293 = OpLoad %int %292
+ %294 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %295 = OpLoad %int %294
+ %296 = OpIMul %int %295 %int_16
+ %297 = OpIAdd %int %293 %296
+ %298 = OpAccessChain %_ptr_Private_int %map %297
+ OpStore %298 %int_1
+ %299 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %300 = OpLoad %int %299
+ %301 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %302 = OpLoad %int %301
+ %303 = OpISub %int %302 %int_1
+ %304 = OpIMul %int %303 %int_16
+ %305 = OpIAdd %int %300 %304
+ %306 = OpAccessChain %_ptr_Private_int %map %305
+ OpStore %306 %int_1
+ %307 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %308 = OpLoad %int %307
+ %309 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %310 = OpLoad %int %309
+ %311 = OpISub %int %310 %int_2
+ %312 = OpIMul %int %311 %int_16
+ %313 = OpIAdd %int %308 %312
+ %314 = OpAccessChain %_ptr_Private_int %map %313
+ OpStore %314 %int_1
+ %315 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %316 = OpLoad %int %315
+ %317 = OpISub %int %316 %int_2
+ %318 = OpAccessChain %_ptr_Function_int %p %uint_1
+ OpStore %318 %317
+ OpBranch %289
+ %289 = OpLabel
+ %319 = OpLoad %int %d
+ %320 = OpSGreaterThanEqual %bool %319 %int_0
+ OpSelectionMerge %322 None
+ OpBranchConditional %320 %321 %322
+ %321 = OpLabel
+ %323 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %324 = OpLoad %int %323
+ %325 = OpSLessThan %bool %324 %int_14
+ OpBranch %322
+ %322 = OpLabel
+ %326 = OpPhi %bool %320 %289 %325 %321
+ OpSelectionMerge %328 None
+ OpBranchConditional %326 %327 %328
+ %327 = OpLabel
+ %329 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %330 = OpLoad %int %329
+ %331 = OpIAdd %int %330 %int_2
+ %332 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %333 = OpLoad %int %332
+ %334 = OpIMul %int %333 %int_16
+ %335 = OpIAdd %int %331 %334
+ %336 = OpAccessChain %_ptr_Private_int %map %335
+ %337 = OpLoad %int %336
+ %338 = OpIEqual %bool %337 %int_0
+ OpBranch %328
+ %328 = OpLabel
+ %339 = OpPhi %bool %326 %322 %338 %327
+ OpSelectionMerge %341 None
+ OpBranchConditional %339 %340 %341
+ %340 = OpLabel
+ %342 = OpLoad %int %d
+ %343 = OpISub %int %342 %int_1
+ OpStore %d %343
+ %344 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %345 = OpLoad %int %344
+ %346 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %347 = OpLoad %int %346
+ %348 = OpIMul %int %347 %int_16
+ %349 = OpIAdd %int %345 %348
+ %350 = OpAccessChain %_ptr_Private_int %map %349
+ OpStore %350 %int_1
+ %351 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %352 = OpLoad %int %351
+ %353 = OpIAdd %int %352 %int_1
+ %354 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %355 = OpLoad %int %354
+ %356 = OpIMul %int %355 %int_16
+ %357 = OpIAdd %int %353 %356
+ %358 = OpAccessChain %_ptr_Private_int %map %357
+ OpStore %358 %int_1
+ %359 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %360 = OpLoad %int %359
+ %361 = OpIAdd %int %360 %int_2
+ %362 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %363 = OpLoad %int %362
+ %364 = OpIMul %int %363 %int_16
+ %365 = OpIAdd %int %361 %364
+ %366 = OpAccessChain %_ptr_Private_int %map %365
+ OpStore %366 %int_1
+ %367 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %368 = OpLoad %int %367
+ %369 = OpIAdd %int %368 %int_2
+ %370 = OpAccessChain %_ptr_Function_int %p %uint_0
+ OpStore %370 %369
+ OpBranch %341
+ %341 = OpLabel
+ %371 = OpLoad %int %d
+ %372 = OpSGreaterThanEqual %bool %371 %int_0
+ OpSelectionMerge %374 None
+ OpBranchConditional %372 %373 %374
+ %373 = OpLabel
+ %375 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %376 = OpLoad %int %375
+ %377 = OpSLessThan %bool %376 %int_14
+ OpBranch %374
+ %374 = OpLabel
+ %378 = OpPhi %bool %372 %341 %377 %373
+ OpSelectionMerge %380 None
+ OpBranchConditional %378 %379 %380
+ %379 = OpLabel
+ %381 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %382 = OpLoad %int %381
+ %383 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %384 = OpLoad %int %383
+ %385 = OpIAdd %int %384 %int_2
+ %386 = OpIMul %int %385 %int_16
+ %387 = OpIAdd %int %382 %386
+ %388 = OpAccessChain %_ptr_Private_int %map %387
+ %389 = OpLoad %int %388
+ %390 = OpIEqual %bool %389 %int_0
+ OpBranch %380
+ %380 = OpLabel
+ %391 = OpPhi %bool %378 %374 %390 %379
+ OpSelectionMerge %393 None
+ OpBranchConditional %391 %392 %393
+ %392 = OpLabel
+ %394 = OpLoad %int %d
+ %395 = OpISub %int %394 %int_1
+ OpStore %d %395
+ %396 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %397 = OpLoad %int %396
+ %398 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %399 = OpLoad %int %398
+ %400 = OpIMul %int %399 %int_16
+ %401 = OpIAdd %int %397 %400
+ %402 = OpAccessChain %_ptr_Private_int %map %401
+ OpStore %402 %int_1
+ %403 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %404 = OpLoad %int %403
+ %405 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %406 = OpLoad %int %405
+ %407 = OpIAdd %int %406 %int_1
+ %408 = OpIMul %int %407 %int_16
+ %409 = OpIAdd %int %404 %408
+ %410 = OpAccessChain %_ptr_Private_int %map %409
+ OpStore %410 %int_1
+ %411 = OpAccessChain %_ptr_Function_int %p %uint_0
+ %412 = OpLoad %int %411
+ %413 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %414 = OpLoad %int %413
+ %415 = OpIAdd %int %414 %int_2
+ %416 = OpIMul %int %415 %int_16
+ %417 = OpIAdd %int %412 %416
+ %418 = OpAccessChain %_ptr_Private_int %map %417
+ OpStore %418 %int_1
+ %419 = OpAccessChain %_ptr_Function_int %p %uint_1
+ %420 = OpLoad %int %419
+ %421 = OpIAdd %int %420 %int_2
+ %422 = OpAccessChain %_ptr_Function_int %p %uint_1
+ OpStore %422 %421
+ OpBranch %393
+ %393 = OpLabel
+ OpBranch %161
+ %161 = OpLabel
+ %423 = OpAccessChain %_ptr_Function_int %ipos %uint_1
+ %424 = OpLoad %int %423
+ %425 = OpIMul %int %424 %int_16
+ %426 = OpAccessChain %_ptr_Function_int %ipos %uint_0
+ %427 = OpLoad %int %426
+ %428 = OpIAdd %int %425 %427
+ %429 = OpAccessChain %_ptr_Private_int %map %428
+ %430 = OpLoad %int %429
+ %431 = OpIEqual %bool %430 %int_1
+ OpSelectionMerge %433 None
+ OpBranchConditional %431 %432 %433
+ %432 = OpLabel
+ OpStore %_GLF_color %437
+ OpReturn
+ %433 = OpLabel
+ OpBranch %71
+ %71 = OpLabel
+ %439 = OpLoad %bool %canwalk
+ OpBranchConditional %439 %68 %70
+ %70 = OpLabel
+ OpStore %_GLF_color %441
+ OpReturn
+ OpFunctionEnd
diff --git a/shaders-no-opt/asm/frag/late-expression-invalidation.asm.frag b/shaders-no-opt/asm/frag/late-expression-invalidation.asm.frag
new file mode 100644
index 00000000..6f9192cd
--- /dev/null
+++ b/shaders-no-opt/asm/frag/late-expression-invalidation.asm.frag
@@ -0,0 +1,109 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos SPIR-V Tools Assembler; 0
+; Bound: 68
+; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %gl_FragCoord %_GLF_color
+ OpExecutionMode %main OriginUpperLeft
+ OpSource ESSL 310
+ OpName %main "main"
+ OpName %gl_FragCoord "gl_FragCoord"
+ OpName %_GLF_color "_GLF_color"
+ OpName %m "m"
+ OpDecorate %gl_FragCoord BuiltIn FragCoord
+ OpDecorate %_GLF_color Location 0
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
+ %uint = OpTypeInt 32 0
+ %uint_0 = OpConstant %uint 0
+%_ptr_Input_float = OpTypePointer Input %float
+ %float_10 = OpConstant %float 10
+ %bool = OpTypeBool
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %_GLF_color = OpVariable %_ptr_Output_v4float Output
+ %float_1 = OpConstant %float 1
+ %float_0 = OpConstant %float 0
+ %19 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
+%mat4v4float = OpTypeMatrix %v4float 4
+ %21 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
+ %22 = OpConstantComposite %mat4v4float %21 %21 %21 %21
+ %uint_4 = OpConstant %uint 4
+%_arr_mat4v4float_uint_4 = OpTypeArray %mat4v4float %uint_4
+%_ptr_Function__arr_mat4v4float_uint_4 = OpTypePointer Function %_arr_mat4v4float_uint_4
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+ %int_4 = OpConstant %int 4
+ %v2float = OpTypeVector %float 2
+ %30 = OpConstantComposite %v2float %float_1 %float_1
+ %int_1 = OpConstant %int 1
+ %uint_3 = OpConstant %uint 3
+%_ptr_Function_float = OpTypePointer Function %float
+ %34 = OpConstantComposite %_arr_mat4v4float_uint_4 %22 %22 %22 %22
+ %main = OpFunction %void None %7
+ %35 = OpLabel
+ %m = OpVariable %_ptr_Function__arr_mat4v4float_uint_4 Function
+ OpBranch %36
+ %36 = OpLabel
+ OpLoopMerge %37 %38 None
+ OpBranch %39
+ %39 = OpLabel
+ %40 = OpAccessChain %_ptr_Input_float %gl_FragCoord %uint_0
+ %41 = OpLoad %float %40
+ %42 = OpFOrdLessThan %bool %41 %float_10
+ OpSelectionMerge %43 None
+ OpBranchConditional %42 %44 %43
+ %44 = OpLabel
+ OpStore %_GLF_color %19
+ OpBranch %37
+ %43 = OpLabel
+ OpStore %m %34
+ OpBranch %45
+ %45 = OpLabel
+ %46 = OpPhi %int %int_0 %43 %47 %48
+ %49 = OpSLessThan %bool %46 %int_4
+ OpLoopMerge %50 %48 None
+ OpBranchConditional %49 %51 %50
+ %51 = OpLabel
+ OpBranch %52
+ %52 = OpLabel
+ %53 = OpPhi %int %int_0 %51 %54 %55
+ %56 = OpSLessThan %bool %53 %int_4
+ OpLoopMerge %57 %55 None
+ OpBranchConditional %56 %58 %57
+ %58 = OpLabel
+ %59 = OpSelect %int %56 %int_1 %int_0
+ %60 = OpAccessChain %_ptr_Function_float %m %59 %46 %uint_3
+ %61 = OpLoad %float %60
+ %62 = OpCompositeConstruct %v2float %61 %61
+ %63 = OpFDiv %v2float %30 %62
+ %64 = OpExtInst %float %1 Distance %30 %63
+ %65 = OpFOrdLessThan %bool %64 %float_1
+ OpSelectionMerge %66 None
+ OpBranchConditional %65 %67 %55
+ %67 = OpLabel
+ OpStore %_GLF_color %21
+ OpBranch %55
+ %66 = OpLabel
+ OpBranch %55
+ %55 = OpLabel
+ %54 = OpIAdd %int %53 %int_1
+ OpBranch %52
+ %57 = OpLabel
+ OpBranch %48
+ %48 = OpLabel
+ %47 = OpIAdd %int %46 %int_1
+ OpBranch %45
+ %50 = OpLabel
+ OpBranch %37
+ %38 = OpLabel
+ OpBranch %36
+ %37 = OpLabel
+ OpReturn
+ OpFunctionEnd
diff --git a/spirv_cpp.cpp b/spirv_cpp.cpp
index b7946bf3..8d934d2c 100644
--- a/spirv_cpp.cpp
+++ b/spirv_cpp.cpp
@@ -338,11 +338,8 @@ string CompilerCPP::compile()
uint32_t pass_count = 0;
do
{
- if (pass_count >= 3)
- SPIRV_CROSS_THROW("Over 3 compilation loops detected. Must be a bug!");
-
resource_registrations.clear();
- reset();
+ reset(pass_count);
// Move constructor for this type is broken on GCC 4.9 ...
buffer.reset();
diff --git a/spirv_cross.cpp b/spirv_cross.cpp
index db18bb44..cf60197e 100644
--- a/spirv_cross.cpp
+++ b/spirv_cross.cpp
@@ -4828,6 +4828,12 @@ void Compiler::force_recompile()
is_force_recompile = true;
}
+void Compiler::force_recompile_guarantee_forward_progress()
+{
+ force_recompile();
+ is_force_recompile_forward_progress = true;
+}
+
bool Compiler::is_forcing_recompilation() const
{
return is_force_recompile;
@@ -4836,6 +4842,7 @@ bool Compiler::is_forcing_recompilation() const
void Compiler::clear_force_recompile()
{
is_force_recompile = false;
+ is_force_recompile_forward_progress = false;
}
Compiler::PhysicalStorageBufferPointerHandler::PhysicalStorageBufferPointerHandler(Compiler &compiler_)
diff --git a/spirv_cross.hpp b/spirv_cross.hpp
index af8283d9..4a881197 100644
--- a/spirv_cross.hpp
+++ b/spirv_cross.hpp
@@ -735,9 +735,11 @@ protected:
SPIRBlock::ContinueBlockType continue_block_type(const SPIRBlock &continue_block) const;
void force_recompile();
+ void force_recompile_guarantee_forward_progress();
void clear_force_recompile();
bool is_forcing_recompilation() const;
bool is_force_recompile = false;
+ bool is_force_recompile_forward_progress = false;
bool block_is_loop_candidate(const SPIRBlock &block, SPIRBlock::Method method) const;
diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp
index a96c9671..aae23803 100644
--- a/spirv_glsl.cpp
+++ b/spirv_glsl.cpp
@@ -296,8 +296,19 @@ const char *CompilerGLSL::vector_swizzle(int vecsize, int index)
return swizzle[vecsize - 1][index];
}
-void CompilerGLSL::reset()
-{
+void CompilerGLSL::reset(uint32_t iteration_count)
+{
+ // Sanity check the iteration count to be robust against a certain class of bugs where
+ // we keep forcing recompilations without making clear forward progress.
+ // In buggy situations we will loop forever, or loop for an unbounded number of iterations.
+ // Certain types of recompilations are considered to make forward progress,
+ // but in almost all situations, we'll never see more than 3 iterations.
+ // It is highly context-sensitive when we need to force recompilation,
+ // and it is not practical with the current architecture
+ // to resolve everything up front.
+ if (iteration_count >= 3 && !is_force_recompile_forward_progress)
+ SPIRV_CROSS_THROW("Over 3 compilation loops detected and no forward progress was made. Must be a bug!");
+
// We do some speculative optimizations which should pretty much always work out,
// but just in case the SPIR-V is rather weird, recompile until it's happy.
// This typically only means one extra pass.
@@ -664,10 +675,7 @@ string CompilerGLSL::compile()
uint32_t pass_count = 0;
do
{
- if (pass_count >= 3)
- SPIRV_CROSS_THROW("Over 3 compilation loops detected. Must be a bug!");
-
- reset();
+ reset(pass_count);
buffer.reset();
@@ -4291,8 +4299,13 @@ void CompilerGLSL::handle_invalid_expression(uint32_t id)
{
// We tried to read an invalidated expression.
// This means we need another pass at compilation, but next time, force temporary variables so that they cannot be invalidated.
- forced_temporaries.insert(id);
- force_recompile();
+ auto res = forced_temporaries.insert(id);
+
+ // Forcing new temporaries guarantees forward progress.
+ if (res.second)
+ force_recompile_guarantee_forward_progress();
+ else
+ force_recompile();
}
// Converts the format of the current expression from packed to unpacked,
@@ -14752,7 +14765,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
// as writes to said loop variables might have been masked out, we need a recompile.
if (!emitted_loop_header_variables && !block.loop_variables.empty())
{
- force_recompile();
+ force_recompile_guarantee_forward_progress();
for (auto var : block.loop_variables)
get<SPIRVariable>(var).loop_variable = false;
block.loop_variables.clear();
diff --git a/spirv_glsl.hpp b/spirv_glsl.hpp
index bf7bf38f..496d8cf9 100644
--- a/spirv_glsl.hpp
+++ b/spirv_glsl.hpp
@@ -342,7 +342,7 @@ protected:
// TODO remove this function when all subgroup ops are supported (or make it always return true)
static bool is_supported_subgroup_op_in_opengl(spv::Op op);
- void reset();
+ void reset(uint32_t iteration_count);
void emit_function(SPIRFunction &func, const Bitset &return_flags);
bool has_extension(const std::string &ext) const;
diff --git a/spirv_hlsl.cpp b/spirv_hlsl.cpp
index f8171a24..efd8f99f 100644
--- a/spirv_hlsl.cpp
+++ b/spirv_hlsl.cpp
@@ -5801,10 +5801,7 @@ string CompilerHLSL::compile()
uint32_t pass_count = 0;
do
{
- if (pass_count >= 3)
- SPIRV_CROSS_THROW("Over 3 compilation loops detected. Must be a bug!");
-
- reset();
+ reset(pass_count);
// Move constructor for this type is broken on GCC 4.9 ...
buffer.reset();
diff --git a/spirv_msl.cpp b/spirv_msl.cpp
index c0bfc5e3..4abb437f 100644
--- a/spirv_msl.cpp
+++ b/spirv_msl.cpp
@@ -1446,10 +1446,7 @@ string CompilerMSL::compile()
uint32_t pass_count = 0;
do
{
- if (pass_count >= 3)
- SPIRV_CROSS_THROW("Over 3 compilation loops detected. Must be a bug!");
-
- reset();
+ reset(pass_count);
// Start bindings at zero.
next_metal_resource_index_buffer = 0;