1#!amber
2# Copyright 2020 Google LLC.
3# Copyright 2020 The Khronos Group Inc.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#     https://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17DEVICE_FEATURE fillModeNonSolid
18
19SHADER vertex vert_shader PASSTHROUGH
20
21SHADER fragment frag_shader GLSL
22#version 430
23
24layout(location = 0) out vec4 color;
25
26void main()
27{
28    color = vec4(1);
29}
30END
31
32SHADER fragment frag_shader_tex GLSL
33#version 430
34layout(location = 0) out vec4 color_out;
35uniform layout(set=0, binding=0, rgba8) readonly image2D texture;
36void main()
37{
38    color_out = imageLoad(texture, ivec2(gl_FragCoord.xy));
39}
40END
41
42SHADER compute compute_shader GLSL
43#version 430
44layout(local_size_x=32, local_size_y=4) in;
45uniform layout (set=0, binding=0, rgba8) image2D img;
46
47int w = 256;
48int h = 256;
49vec4 bg = vec4(0, 0, 0, 1);
50vec4 marked = vec4(0, 1, 1, 1);
51vec4 error = vec4(1, 0, 0, 1);
52
53shared ivec2 stack[256];
54shared int stackPtr;
55shared bool done;
56shared ivec2 pixel;
57
58void pushMarkedPixel(ivec2 p)
59{
60    imageStore(img, p, marked);
61    int slot = atomicAdd(stackPtr, 1);
62    stack[slot] = p;
63}
64
65ivec2 popMarkedPixel()
66{
67    int slot = atomicAdd(stackPtr, -1) - 1;
68    ivec2 p = stack[slot];
69    imageStore(img, p, bg);
70
71    return p;
72}
73
74void main ()
75{
76    if (gl_LocalInvocationIndex == 0)
77    {
78        stack[0] = ivec2(-1);
79        stackPtr = 0;
80        done = false;
81
82        // Use this to break the lines and verify the checker is correct.
83        //for (int x = 0; x < w; x++)
84        //    imageStore(img, ivec2(x, 128), bg);
85        //memoryBarrierImage();
86    }
87
88    barrier();
89
90    // Search for any pixel belonging to a line.
91    // Use 32 x 4 block for the search.
92    ivec2 p = ivec2(gl_LocalInvocationID) + ivec2(0, 10);
93    vec4 c = imageLoad(img, p);
94    // Any of the pixels found by a thread will do as a starting point.
95    if (c != bg)
96        stack[0] = p;
97
98    memoryBarrierImage();
99    barrier();
100
101    if (gl_LocalInvocationIndex == 0 && stack[0] != ivec2(-1))
102    {
103        imageStore(img, stack[0], marked);
104        stackPtr++;
105    }
106
107    memoryBarrierImage();
108    barrier();
109
110    while (!done)
111    {
112        if (gl_LocalInvocationIndex == 0 && stackPtr != 0)
113            pixel = popMarkedPixel();
114
115        memoryBarrierImage();
116        barrier();
117
118        if (gl_LocalInvocationID.x < 3 && gl_LocalInvocationID.y < 3)
119        {
120            ivec2 p = pixel + ivec2(gl_LocalInvocationID) - ivec2(1);
121            if (p.x >= 0 && p.y >= 0 && p.x < w && p.y < h)
122            {
123                vec4 c = imageLoad(img, p);
124                if (c != marked && c != bg)
125                {
126                    pushMarkedPixel(p);
127                }
128            }
129        }
130
131        memoryBarrierImage();
132        barrier();
133
134        if (gl_LocalInvocationIndex == 0 && stackPtr < 1)
135            done = true;
136
137        barrier();
138    }
139}
140END
141
142BUFFER position DATA_TYPE R8G8B8A8_SNORM DATA
143-120 -120  0 127
144   0  120  0 127
145 120 -120  0 127
146
147  0     0  0 127
148120     0  0 127
149 60   -60  0 127
150
151-100  100  0 127
152 110  100  0 127
153 110  103  0 127
154END
155
156BUFFER texture FORMAT R8G8B8A8_UNORM
157BUFFER framebuffer FORMAT B8G8R8A8_UNORM
158
159PIPELINE graphics pipeline
160  ATTACH vert_shader
161  ATTACH frag_shader
162
163  VERTEX_DATA position LOCATION 0
164  POLYGON_MODE line
165
166  BIND BUFFER texture AS color LOCATION 0
167  FRAMEBUFFER_SIZE 256 256
168END
169
170PIPELINE graphics tex_pipeline
171  ATTACH vert_shader
172  ATTACH frag_shader_tex
173  BIND BUFFER texture AS storage_image DESCRIPTOR_SET 0 BINDING 0
174  FRAMEBUFFER_SIZE 256 256
175  BIND BUFFER framebuffer AS color LOCATION 0
176END
177
178PIPELINE compute verification_pipeline
179  ATTACH compute_shader
180  BIND BUFFER texture AS storage_image DESCRIPTOR_SET 0 BINDING 0
181  FRAMEBUFFER_SIZE 256 256
182END
183
184CLEAR_COLOR pipeline 0 0 0 255
185CLEAR pipeline
186
187RUN pipeline DRAW_ARRAY AS TRIANGLE_LIST START_IDX 0 COUNT 9
188RUN verification_pipeline 1 1 1
189RUN tex_pipeline DRAW_RECT POS 0 0 SIZE 256 256
190
191# Everything should be clear color since the checker consumes
192# the drawn pixels if they are continuous.
193EXPECT framebuffer IDX 0 0 SIZE 256 255 EQ_RGBA 0 0 0 255
194