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
17SHADER vertex vert_shader PASSTHROUGH
18
19SHADER fragment frag_shader GLSL
20#version 430
21
22layout(location = 0) out vec4 color;
23
24void main()
25{
26    color = vec4(1);
27}
28END
29
30SHADER fragment frag_shader_tex GLSL
31#version 430
32layout(location = 0) out vec4 color_out;
33uniform layout(set=0, binding=0, rgba8) readonly image2D texture;
34void main()
35{
36    color_out = imageLoad(texture, ivec2(gl_FragCoord.xy));
37}
38END
39
40SHADER compute compute_shader GLSL
41#version 430
42layout(local_size_x=32, local_size_y=4) in;
43uniform layout (set=0, binding=0, rgba8) image2D img;
44
45int w = 256;
46int h = 256;
47vec4 bg = vec4(0, 0, 0, 1);
48vec4 marked = vec4(0, 1, 1, 1);
49vec4 error = vec4(1, 0, 0, 1);
50
51shared ivec2 stack[256];
52shared int stackPtr;
53shared bool done;
54shared ivec2 pixel;
55
56void pushMarkedPixel(ivec2 p)
57{
58    imageStore(img, p, marked);
59    int slot = atomicAdd(stackPtr, 1);
60    stack[slot] = p;
61}
62
63ivec2 popMarkedPixel()
64{
65    int slot = atomicAdd(stackPtr, -1) - 1;
66    ivec2 p = stack[slot];
67    imageStore(img, p, bg);
68
69    return p;
70}
71
72void main ()
73{
74    if (gl_LocalInvocationIndex == 0)
75    {
76        stack[0] = ivec2(-1);
77        stackPtr = 0;
78        done = false;
79
80        // Use this to break the lines and verify the checker is correct.
81        //for (int x = 0; x < w; x++)
82        //    imageStore(img, ivec2(x, 128), bg);
83        //memoryBarrierImage();
84    }
85
86    barrier();
87
88    // Search for any pixel belonging to a line.
89    // Use 32 x 4 block for the search.
90    ivec2 p = ivec2(gl_LocalInvocationID) + ivec2(0, 128);
91    vec4 c = imageLoad(img, p);
92    // Any of the pixels found by a thread will do as a starting point.
93    if (c != bg)
94        stack[0] = p;
95
96    memoryBarrierImage();
97    barrier();
98
99    if (gl_LocalInvocationIndex == 0 && stack[0] != ivec2(-1))
100    {
101        imageStore(img, stack[0], marked);
102        stackPtr++;
103    }
104
105    memoryBarrierImage();
106    barrier();
107
108    while (!done)
109    {
110        if (gl_LocalInvocationIndex == 0 && stackPtr != 0)
111            pixel = popMarkedPixel();
112
113        memoryBarrierImage();
114        barrier();
115
116        if (gl_LocalInvocationID.x < 3 && gl_LocalInvocationID.y < 3)
117        {
118            ivec2 p = pixel + ivec2(gl_LocalInvocationID) - ivec2(1);
119            if (p.x >= 0 && p.y >= 0 && p.x < w && p.y < h)
120            {
121                vec4 c = imageLoad(img, p);
122                if (c != marked && c != bg)
123                {
124                    pushMarkedPixel(p);
125                }
126            }
127        }
128
129        memoryBarrierImage();
130        barrier();
131
132        if (gl_LocalInvocationIndex == 0 && stackPtr < 1)
133            done = true;
134
135        barrier();
136    }
137}
138END
139
140BUFFER position DATA_TYPE R8G8B8A8_SNORM DATA
141-120 -120   0 127
142-119  120   0 127
143 120  119   0 127
144  10   20   0 127
145 -80   20   0 127
146 -80   95   0 127
147 -83   95   0 127
148 -83  -95   0 127
149 -85   95   0 127
150END
151
152BUFFER texture FORMAT R8G8B8A8_UNORM
153BUFFER framebuffer FORMAT B8G8R8A8_UNORM
154
155PIPELINE graphics pipeline
156  ATTACH vert_shader
157  ATTACH frag_shader
158
159  VERTEX_DATA position LOCATION 0
160
161  BIND BUFFER texture AS color LOCATION 0
162  FRAMEBUFFER_SIZE 256 256
163END
164
165PIPELINE graphics tex_pipeline
166  ATTACH vert_shader
167  ATTACH frag_shader_tex
168  BIND BUFFER texture AS storage_image DESCRIPTOR_SET 0 BINDING 0
169  FRAMEBUFFER_SIZE 256 256
170  BIND BUFFER framebuffer AS color LOCATION 0
171END
172
173PIPELINE compute verification_pipeline
174  ATTACH compute_shader
175  BIND BUFFER texture AS storage_image DESCRIPTOR_SET 0 BINDING 0
176  FRAMEBUFFER_SIZE 256 256
177END
178
179CLEAR_COLOR pipeline 0 0 0 255
180CLEAR pipeline
181
182RUN pipeline DRAW_ARRAY AS LINE_STRIP START_IDX 0 COUNT 9
183RUN verification_pipeline 1 1 1
184RUN tex_pipeline DRAW_RECT POS 0 0 SIZE 256 256
185
186# Everything should be clear color since the checker consumes
187# the drawn pixels if they are continuous.
188EXPECT framebuffer IDX 0 0 SIZE 256 255 EQ_RGBA 0 0 0 255
189