blob: dc88e1213e84fa54e64f33ada00f0f27b94282c8 [file] [log] [blame]
#!amber
# Copyright 2020 The Amber Authors.
#
# 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
#
# https://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.
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
#version 430
layout(location = 0) out vec4 color;
void main()
{
color = vec4(1);
}
END
SHADER fragment frag_shader_tex GLSL
#version 430
layout(location = 0) out vec4 color_out;
uniform layout(set=0, binding=0, rgba8) readonly image2D texture;
void main()
{
color_out = imageLoad(texture, ivec2(gl_FragCoord.xy));
}
END
SHADER compute compute_shader GLSL
#version 430
layout(local_size_x=32, local_size_y=4) in;
uniform layout (set=0, binding=0, rgba8) image2D img;
int w = 256;
int h = 256;
vec4 bg = vec4(0, 0, 0, 1);
vec4 marked = vec4(0, 1, 1, 1);
vec4 error = vec4(1, 0, 0, 1);
shared ivec2 stack[256];
shared int stackPtr;
shared bool done;
shared ivec2 pixel;
void pushMarkedPixel(ivec2 p)
{
imageStore(img, p, marked);
int slot = atomicAdd(stackPtr, 1);
stack[slot] = p;
}
ivec2 popMarkedPixel()
{
int slot = atomicAdd(stackPtr, -1) - 1;
ivec2 p = stack[slot];
imageStore(img, p, bg);
return p;
}
void main ()
{
if (gl_LocalInvocationIndex == 0)
{
stack[0] = ivec2(-1);
stackPtr = 0;
done = false;
// Use this to break the lines and verify the checker is correct.
//for (int x = 0; x < w; x++)
// imageStore(img, ivec2(x, 128), bg);
}
barrier();
// Search for any pixel belonging to a line.
// Use 32 x 4 block for the search.
ivec2 p = ivec2(gl_LocalInvocationID) + ivec2(0, 128);
vec4 c = imageLoad(img, p);
// Any of the pixels found by a thread will do as a starting point.
if (c != bg)
stack[0] = p;
barrier();
if (gl_LocalInvocationIndex == 0 && stack[0] != ivec2(-1))
{
imageStore(img, stack[0], marked);
stackPtr++;
}
barrier();
while (!done)
{
if (gl_LocalInvocationIndex == 0 && stackPtr != 0)
pixel = popMarkedPixel();
barrier();
if (gl_LocalInvocationID.x < 3 && gl_LocalInvocationID.y < 3)
{
ivec2 p = pixel + ivec2(gl_LocalInvocationID) - ivec2(1);
if (p.x >= 0 && p.y >= 0 && p.x < w && p.y < h)
{
vec4 c = imageLoad(img, p);
if (c != marked && c != bg)
{
pushMarkedPixel(p);
}
}
}
barrier();
if (gl_LocalInvocationIndex == 0 && stackPtr < 1)
done = true;
barrier();
}
}
END
BUFFER position DATA_TYPE R8G8_SNORM DATA
-120 -120
-119 120
120 119
10 20
-80 20
-80 95
-83 95
-83 -95
-85 95
END
BUFFER texture FORMAT R8G8B8A8_UNORM
BUFFER framebuffer FORMAT B8G8R8A8_UNORM
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
VERTEX_DATA position LOCATION 0
BIND BUFFER texture AS color LOCATION 0
FRAMEBUFFER_SIZE 256 256
END
PIPELINE graphics tex_pipeline
ATTACH vert_shader
ATTACH frag_shader_tex
BIND BUFFER texture AS storage_image DESCRIPTOR_SET 0 BINDING 0
FRAMEBUFFER_SIZE 256 256
BIND BUFFER framebuffer AS color LOCATION 0
END
PIPELINE compute verification_pipeline
ATTACH compute_shader
BIND BUFFER texture AS storage_image DESCRIPTOR_SET 0 BINDING 0
FRAMEBUFFER_SIZE 256 256
END
CLEAR_COLOR pipeline 0 0 0 255
CLEAR pipeline
RUN pipeline DRAW_ARRAY AS LINE_STRIP START_IDX 0 COUNT 9
RUN verification_pipeline 1 1 1
RUN tex_pipeline DRAW_RECT POS 0 0 SIZE 256 256
# Everything should be clear color since the checker consumes
# the drawn pixels if they are continuous.
EXPECT framebuffer IDX 0 0 SIZE 256 255 EQ_RGBA 0 0 0 255