Added tests for line continuity
authorAri Suonpaa <ari.suonpaa@siru.fi>
Fri, 6 Mar 2020 08:19:59 +0000 (10:19 +0200)
committerAlexander Galazin <Alexander.Galazin@arm.com>
Thu, 9 Apr 2020 07:02:18 +0000 (03:02 -0400)
The current tests verify line rasterization results
quite loosely because of differences in implementations.
However a line with missing pixels were still passing
the tests. This adds separate tests that catch such
rasterization errors.

Amber has been updated to add polygon mode support.

New tests:

dEQP-VK.rasterization.line_continuity.line-strip
dEQP-VK.rasterization.line_continuity.polygon-mode-lines

VK-GL-CTS issue: 2024

Components: Vulkan
Change-Id: Ibad1deb85f3a5bbc169723f0d8c00c3192447917

android/cts/master/vk-master-2020-03-01.txt
android/cts/master/vk-master.txt
external/fetch_sources.py
external/vulkancts/data/vulkan/amber/rasterization/line_continuity/line-strip.amber [new file with mode: 0644]
external/vulkancts/data/vulkan/amber/rasterization/line_continuity/polygon-mode-lines.amber [new file with mode: 0644]
external/vulkancts/modules/vulkan/amber/vktAmberTestCase.cpp
external/vulkancts/modules/vulkan/rasterization/vktRasterizationTests.cpp
external/vulkancts/mustpass/master/vk-default-no-waivers.txt
external/vulkancts/mustpass/master/vk-default.txt

index c3bf2f8..5202f0f 100644 (file)
@@ -157404,6 +157404,8 @@ dEQP-VK.rasterization.provoking_vertex.line_list
 dEQP-VK.rasterization.provoking_vertex.line_list_with_adjacency
 dEQP-VK.rasterization.provoking_vertex.line_strip
 dEQP-VK.rasterization.provoking_vertex.line_strip_with_adjacency
+dEQP-VK.rasterization.line_continuity.line-strip
+dEQP-VK.rasterization.line_continuity.polygon-mode-lines
 dEQP-VK.clipping.clip_volume.depth_clip.point_list
 dEQP-VK.clipping.clip_volume.depth_clip.line_list
 dEQP-VK.clipping.clip_volume.depth_clip.line_list_with_adjacency
index fd789ab..2dfb8b5 100644 (file)
@@ -507733,6 +507733,8 @@ dEQP-VK.rasterization.provoking_vertex.line_list
 dEQP-VK.rasterization.provoking_vertex.line_list_with_adjacency
 dEQP-VK.rasterization.provoking_vertex.line_strip
 dEQP-VK.rasterization.provoking_vertex.line_strip_with_adjacency
+dEQP-VK.rasterization.line_continuity.line-strip
+dEQP-VK.rasterization.line_continuity.polygon-mode-lines
 dEQP-VK.clipping.clip_volume.inside.point_list
 dEQP-VK.clipping.clip_volume.inside.line_list
 dEQP-VK.clipping.clip_volume.inside.line_list_with_adjacency
index c830835..f412f7e 100644 (file)
@@ -332,7 +332,7 @@ PACKAGES = [
        GitRepo(
                "https://github.com/google/amber.git",
                None,
-               "ed3e05c945aa7a3559ef616f63a798fede19f363",
+               "93c0348c63675edd1e51e44893d58973b0d144fd",
                "amber"),
 ]
 
diff --git a/external/vulkancts/data/vulkan/amber/rasterization/line_continuity/line-strip.amber b/external/vulkancts/data/vulkan/amber/rasterization/line_continuity/line-strip.amber
new file mode 100644 (file)
index 0000000..dc88e12
--- /dev/null
@@ -0,0 +1,182 @@
+#!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
diff --git a/external/vulkancts/data/vulkan/amber/rasterization/line_continuity/polygon-mode-lines.amber b/external/vulkancts/data/vulkan/amber/rasterization/line_continuity/polygon-mode-lines.amber
new file mode 100644 (file)
index 0000000..4bae586
--- /dev/null
@@ -0,0 +1,187 @@
+#!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.
+
+DEVICE_FEATURE fillModeNonSolid
+
+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, 10);
+    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
+   0  120
+ 120 -120
+
+  0     0
+120     0
+ 60   -60
+
+-100  100
+ 110  100
+ 110  103
+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
+  POLYGON_MODE line
+
+  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 TRIANGLE_LIST 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
index 12793b2..299752b 100644 (file)
@@ -88,6 +88,8 @@ static bool isFeatureSupported(const vkt::Context& ctx, const std::string& featu
                return ctx.getDeviceFeatures().geometryShader;
        if (feature == "Features.vertexPipelineStoresAndAtomics")
                return ctx.getDeviceFeatures().vertexPipelineStoresAndAtomics;
+       if (feature == "Features.fillModeNonSolid")
+               return ctx.getDeviceFeatures().fillModeNonSolid;
        if (feature == "VariablePointerFeatures.variablePointersStorageBuffer")
                return ctx.getVariablePointersFeatures().variablePointersStorageBuffer;
        if (feature == "VariablePointerFeatures.variablePointers")
index 173dc2b..bb252c5 100644 (file)
@@ -4437,6 +4437,40 @@ void createRasterizationTests (tcu::TestCaseGroup* rasterizationTests)
                        provokingVertex->addChild(testCase);
                }
        }
+
+       // .line_continuity
+       {
+               tcu::TestCaseGroup* const       lineContinuity  = new tcu::TestCaseGroup(testCtx, "line_continuity", "Test line continuity");
+               static const char                       dataDir[]               = "rasterization/line_continuity";
+
+               struct Case
+               {
+                       std::string     name;
+                       std::string     desc;
+                       bool            requireFillModeNonSolid;
+               };
+
+               static const Case cases[] =
+               {
+                       {       "line-strip",                   "Test line strip drawing produces continuous lines",    false   },
+                       {       "polygon-mode-lines",   "Test triangles drawn with lines are continuous",               true    }
+               };
+
+               rasterizationTests->addChild(lineContinuity);
+
+               for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
+               {
+                       const std::string                       fileName        = cases[i].name + ".amber";
+                       cts_amber::AmberTestCase*       testCase        = cts_amber::createAmberTestCase(testCtx, cases[i].name.c_str(), cases[i].desc.c_str(), dataDir, fileName);
+
+                       if (cases[i].requireFillModeNonSolid)
+                       {
+                               testCase->addRequirement("Features.fillModeNonSolid");
+                       }
+
+                       lineContinuity->addChild(testCase);
+               }
+       }
 }
 
 } // anonymous
index 86d160d..0b7cfb7 100644 (file)
@@ -509693,6 +509693,8 @@ dEQP-VK.rasterization.provoking_vertex.line_list
 dEQP-VK.rasterization.provoking_vertex.line_list_with_adjacency
 dEQP-VK.rasterization.provoking_vertex.line_strip
 dEQP-VK.rasterization.provoking_vertex.line_strip_with_adjacency
+dEQP-VK.rasterization.line_continuity.line-strip
+dEQP-VK.rasterization.line_continuity.polygon-mode-lines
 dEQP-VK.clipping.clip_volume.inside.point_list
 dEQP-VK.clipping.clip_volume.inside.line_list
 dEQP-VK.clipping.clip_volume.inside.line_list_with_adjacency
index 201c0e6..a0590f1 100644 (file)
@@ -509654,6 +509654,8 @@ dEQP-VK.rasterization.provoking_vertex.line_list
 dEQP-VK.rasterization.provoking_vertex.line_list_with_adjacency
 dEQP-VK.rasterization.provoking_vertex.line_strip
 dEQP-VK.rasterization.provoking_vertex.line_strip_with_adjacency
+dEQP-VK.rasterization.line_continuity.line-strip
+dEQP-VK.rasterization.line_continuity.polygon-mode-lines
 dEQP-VK.clipping.clip_volume.inside.point_list
 dEQP-VK.clipping.clip_volume.inside.line_list
 dEQP-VK.clipping.clip_volume.inside.line_list_with_adjacency