--- /dev/null
+#!amber
+
+# Copyright 2019 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+# A test for a bug found by GraphicsFuzz.
+
+# Short description: A fragment shader that writes red in a nest of loops
+
+# The test passes because the write of red is reachable, it is the only reachable
+# write, and the would-be-infinite loop is not reachable.
+
+SHADER vertex variant_vertex_shader PASSTHROUGH
+
+# variant_fragment_shader is derived from the following GLSL:
+# #version 310 es
+# precision highp float;
+#
+# layout(location = 0) out vec4 _GLF_color;
+#
+# void main()
+# {
+# int idx;
+# mat4x3 m43;
+# m43 = mat4x3(1.0);
+# float sums[9];
+# int ll1 = 0;
+# for(
+# int rows = 2;
+# true;
+# 1
+# )
+# {
+# _GLF_color = vec4(1.0, 0.0, 0.0, 1.0);
+# if(ll1 >= 5) {
+# break;
+# }
+# ll1++;
+#
+# int ll4 = 10;
+# int ll2 = 0;
+# for(
+# int c = 0;
+# c < 1;
+# c ++
+# )
+# {
+# if(ll2 >= 0) {
+# break; // Immediately breaks the loop
+# }
+# ll2++;
+#
+# mat4x3 tempm43;
+# tempm43 = m43;
+# int ll3 = 0;
+# for(
+# int d = 0;
+# 1 < ll4; // This loop is not reachable
+# d ++
+# )
+# {
+# int r;
+# tempm43[d >= 0 && d < 4 ? d : 0][r >= 0 && r < 3 ? r : 0] = 1.0;
+# }
+# sums[idx >= 0 && idx < 9 ? idx : 0] += m43[c][1];
+# }
+# idx ++;
+# }
+# }
+SHADER fragment variant_fragment_shader SPIRV-ASM
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 120
+; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main" %33
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 310
+ OpName %4 "main"
+ OpName %10 "m43"
+ OpName %20 "ll1"
+ OpName %22 "rows"
+ OpName %33 "_GLF_color"
+ OpName %44 "ll4"
+ OpName %46 "ll2"
+ OpName %47 "c"
+ OpName %62 "tempm43"
+ OpName %64 "ll3"
+ OpName %65 "d"
+ OpName %81 "r"
+ OpName %98 "sums"
+ OpName %99 "idx"
+ OpDecorate %20 RelaxedPrecision
+ OpDecorate %22 RelaxedPrecision
+ OpDecorate %33 Location 0
+ OpDecorate %35 RelaxedPrecision
+ OpDecorate %41 RelaxedPrecision
+ OpDecorate %43 RelaxedPrecision
+ OpDecorate %44 RelaxedPrecision
+ OpDecorate %46 RelaxedPrecision
+ OpDecorate %47 RelaxedPrecision
+ OpDecorate %53 RelaxedPrecision
+ OpDecorate %55 RelaxedPrecision
+ OpDecorate %60 RelaxedPrecision
+ OpDecorate %61 RelaxedPrecision
+ OpDecorate %64 RelaxedPrecision
+ OpDecorate %65 RelaxedPrecision
+ OpDecorate %71 RelaxedPrecision
+ OpDecorate %73 RelaxedPrecision
+ OpDecorate %75 RelaxedPrecision
+ OpDecorate %79 RelaxedPrecision
+ OpDecorate %81 RelaxedPrecision
+ OpDecorate %82 RelaxedPrecision
+ OpDecorate %84 RelaxedPrecision
+ OpDecorate %88 RelaxedPrecision
+ OpDecorate %92 RelaxedPrecision
+ OpDecorate %93 RelaxedPrecision
+ OpDecorate %99 RelaxedPrecision
+ OpDecorate %100 RelaxedPrecision
+ OpDecorate %102 RelaxedPrecision
+ OpDecorate %106 RelaxedPrecision
+ OpDecorate %108 RelaxedPrecision
+ OpDecorate %116 RelaxedPrecision
+ OpDecorate %117 RelaxedPrecision
+ OpDecorate %118 RelaxedPrecision
+ OpDecorate %119 RelaxedPrecision
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeFloat 32
+ %7 = OpTypeVector %6 3
+ %8 = OpTypeMatrix %7 4
+ %9 = OpTypePointer Function %8
+ %11 = OpConstant %6 1
+ %12 = OpConstant %6 0
+ %13 = OpConstantComposite %7 %11 %12 %12
+ %14 = OpConstantComposite %7 %12 %11 %12
+ %15 = OpConstantComposite %7 %12 %12 %11
+ %16 = OpConstantComposite %7 %12 %12 %12
+ %17 = OpConstantComposite %8 %13 %14 %15 %16
+ %18 = OpTypeInt 32 1
+ %19 = OpTypePointer Function %18
+ %21 = OpConstant %18 0
+ %23 = OpConstant %18 2
+ %29 = OpTypeBool
+ %30 = OpConstantTrue %29
+ %31 = OpTypeVector %6 4
+ %32 = OpTypePointer Output %31
+ %33 = OpVariable %32 Output
+ %34 = OpConstantComposite %31 %11 %12 %12 %11
+ %36 = OpConstant %18 5
+ %42 = OpConstant %18 1
+ %45 = OpConstant %18 10
+ %76 = OpConstant %18 4
+ %85 = OpConstant %18 3
+ %90 = OpTypePointer Function %6
+ %94 = OpTypeInt 32 0
+ %95 = OpConstant %94 9
+ %96 = OpTypeArray %6 %95
+ %97 = OpTypePointer Function %96
+ %103 = OpConstant %18 9
+ %109 = OpConstant %94 1
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ %10 = OpVariable %9 Function
+ %20 = OpVariable %19 Function
+ %22 = OpVariable %19 Function
+ %44 = OpVariable %19 Function
+ %46 = OpVariable %19 Function
+ %47 = OpVariable %19 Function
+ %62 = OpVariable %9 Function
+ %64 = OpVariable %19 Function
+ %65 = OpVariable %19 Function
+ %81 = OpVariable %19 Function
+ %98 = OpVariable %97 Function
+ %99 = OpVariable %19 Function
+ OpStore %10 %17
+ OpStore %20 %21
+ OpStore %22 %23
+ OpBranch %24
+ %24 = OpLabel
+ OpLoopMerge %26 %27 None
+ OpBranch %28
+ %28 = OpLabel
+ OpBranchConditional %30 %25 %26
+ %25 = OpLabel
+ OpStore %33 %34
+ %35 = OpLoad %18 %20
+ %37 = OpSGreaterThanEqual %29 %35 %36
+ OpSelectionMerge %39 None
+ OpBranchConditional %37 %38 %39
+ %38 = OpLabel
+ OpBranch %26
+ %39 = OpLabel
+ %41 = OpLoad %18 %20
+ %43 = OpIAdd %18 %41 %42
+ OpStore %20 %43
+ OpStore %44 %45
+ OpStore %46 %21
+ OpStore %47 %21
+ OpBranch %48
+ %48 = OpLabel
+ OpLoopMerge %50 %51 None
+ OpBranch %52
+ %52 = OpLabel
+ %53 = OpLoad %18 %47
+ %54 = OpSLessThan %29 %53 %42
+ OpBranchConditional %54 %49 %50
+ %49 = OpLabel
+ %55 = OpLoad %18 %46
+ %56 = OpSGreaterThanEqual %29 %55 %21
+ OpSelectionMerge %58 None
+ OpBranchConditional %56 %57 %58
+ %57 = OpLabel
+ OpBranch %50
+ %58 = OpLabel
+ %60 = OpLoad %18 %46
+ %61 = OpIAdd %18 %60 %42
+ OpStore %46 %61
+ %63 = OpLoad %8 %10
+ OpStore %62 %63
+ OpStore %64 %21
+ OpStore %65 %21
+ OpBranch %66
+ %66 = OpLabel
+ OpLoopMerge %68 %69 None
+ OpBranch %70
+ %70 = OpLabel
+ %71 = OpLoad %18 %44
+ %72 = OpSLessThan %29 %42 %71
+ OpBranchConditional %72 %67 %68
+ %67 = OpLabel
+ %73 = OpLoad %18 %65
+ %74 = OpSGreaterThanEqual %29 %73 %21
+ %75 = OpLoad %18 %65
+ %77 = OpSLessThan %29 %75 %76
+ %78 = OpLogicalAnd %29 %74 %77
+ %79 = OpLoad %18 %65
+ %80 = OpSelect %18 %78 %79 %21
+ %82 = OpLoad %18 %81
+ %83 = OpSGreaterThanEqual %29 %82 %21
+ %84 = OpLoad %18 %81
+ %86 = OpSLessThan %29 %84 %85
+ %87 = OpLogicalAnd %29 %83 %86
+ %88 = OpLoad %18 %81
+ %89 = OpSelect %18 %87 %88 %21
+ %91 = OpAccessChain %90 %62 %80 %89
+ OpStore %91 %11
+ OpBranch %69
+ %69 = OpLabel
+ %92 = OpLoad %18 %65
+ %93 = OpIAdd %18 %92 %42
+ OpStore %65 %93
+ OpBranch %66
+ %68 = OpLabel
+ %100 = OpLoad %18 %99
+ %101 = OpSGreaterThanEqual %29 %100 %21
+ %102 = OpLoad %18 %99
+ %104 = OpSLessThan %29 %102 %103
+ %105 = OpLogicalAnd %29 %101 %104
+ %106 = OpLoad %18 %99
+ %107 = OpSelect %18 %105 %106 %21
+ %108 = OpLoad %18 %47
+ %110 = OpAccessChain %90 %10 %108 %109
+ %111 = OpLoad %6 %110
+ %112 = OpAccessChain %90 %98 %107
+ %113 = OpLoad %6 %112
+ %114 = OpFAdd %6 %113 %111
+ %115 = OpAccessChain %90 %98 %107
+ OpStore %115 %114
+ OpBranch %51
+ %51 = OpLabel
+ %116 = OpLoad %18 %47
+ %117 = OpIAdd %18 %116 %42
+ OpStore %47 %117
+ OpBranch %48
+ %50 = OpLabel
+ %118 = OpLoad %18 %99
+ %119 = OpIAdd %18 %118 %42
+ OpStore %99 %119
+ OpBranch %27
+ %27 = OpLabel
+ OpBranch %24
+ %26 = OpLabel
+ OpReturn
+ OpFunctionEnd
+END
+
+# uniforms for variant
+
+# injected
+BUFFER variant_injected DATA_TYPE int32 DATA
+ 1
+END
+
+BUFFER framebuffer FORMAT B8G8R8A8_UNORM
+
+PIPELINE graphics gfz_pipeline
+ ATTACH variant_vertex_shader
+ ATTACH variant_fragment_shader
+ FRAMEBUFFER_SIZE 256 256
+ BIND BUFFER framebuffer AS color LOCATION 0
+ BIND BUFFER variant_injected AS uniform DESCRIPTOR_SET 0 BINDING 0
+END
+CLEAR_COLOR gfz_pipeline 0 0 0 255
+
+CLEAR gfz_pipeline
+RUN gfz_pipeline DRAW_RECT POS 0 0 SIZE 256 256
+EXPECT framebuffer IDX 0 0 SIZE 256 256 EQ_RGB 255 0 0
\ No newline at end of file
{ "dead-struct-init.amber", "dead-struct-init", "A fragment shader that uses struct initializers" },
{ "do-while-loop-in-conditionals.amber", "do-while-loop-in-conditionals", "A fragment shader with do-while loop in conditional nest" },
{ "early-return-and-barrier.amber", "early-return-and-barrier", "A compute shader with an early return and a barrier" },
+ { "for-condition-always-false.amber", "for-condition-always-false", "A fragment shader that uses a for loop with condition always false" },
{ "fragcoord-control-flow.amber", "fragcoord-control-flow", "A fragment shader that uses FragCoord and somewhat complex control flow" },
{ "fragcoord-control-flow-2.amber", "fragcoord-control-flow-2", "A fragment shader that uses FragCoord and somewhat complex control flow" },
{ "if-and-switch.amber", "if-and-switch", "A fragment shader with a switch and some data flow" },
{ "while-inside-switch.amber", "while-inside-switch", "A fragment shader that uses a while loop inside a switch" },
{ "write-before-break.amber", "write-before-break", "Fragment shader that writes red before loop break" },
{ "write-red-after-search.amber", "write-red-after-search", "A fragment shader performing a search computation, then writing red regardless" },
- { "for-condition-always-false.amber", "for-condition-always-false", "A fragment shader that uses a for loop with condition always false" },
+ { "write-red-in-loop-nest.amber", "write-red-in-loop-nest", "A fragment shader that writes red in a nest of loops" },
};
for (size_t i = 0; i < sizeof tests / sizeof tests[0]; i++)