From d5c8a7f813ed59d8c01ef9a8aa9a6087c3f946bf Mon Sep 17 00:00:00 2001 From: Arkadiusz Sarwa Date: Tue, 27 Sep 2016 11:10:05 +0200 Subject: [PATCH] Add geometry shader tests New tests: - dEQP-VK.geometry.* Fixes #63 Change-Id: If1da0ce5e171ca6cb7396421f2fb8ffbcc55ce88 --- android/cts/master/vk-master.txt | 124 ++ .../data/vulkan/data/geometry/line_strip.png | Bin 0 -> 1677 bytes .../vulkan/data/geometry/line_strip_adjacency.png | Bin 0 -> 2054 bytes .../data/geometry/line_strip_emit_0_end_0.png | Bin 0 -> 854 bytes .../data/geometry/line_strip_emit_0_end_1.png | Bin 0 -> 854 bytes .../data/geometry/line_strip_emit_0_end_2.png | Bin 0 -> 854 bytes .../data/geometry/line_strip_emit_1_end_1.png | Bin 0 -> 854 bytes .../data/geometry/line_strip_emit_1_end_2.png | Bin 0 -> 854 bytes .../data/geometry/line_strip_emit_2_end_1.png | Bin 0 -> 1056 bytes .../data/geometry/line_strip_emit_2_end_2.png | Bin 0 -> 1056 bytes .../line_strip_emit_2_end_2_emit_2_end_0.png | Bin 0 -> 1168 bytes .../vulkancts/data/vulkan/data/geometry/lines.png | Bin 0 -> 1339 bytes .../data/vulkan/data/geometry/lines_adjacency.png | Bin 0 -> 1360 bytes .../data/vulkan/data/geometry/lines_to_points.png | Bin 0 -> 1030 bytes .../vulkan/data/geometry/lines_to_triangles.png | Bin 0 -> 1484 bytes .../data/vulkan/data/geometry/output_0_and_128.png | Bin 0 -> 865 bytes .../data/vulkan/data/geometry/output_10.png | Bin 0 -> 863 bytes .../vulkan/data/geometry/output_100_and_10.png | Bin 0 -> 872 bytes .../vulkan/data/geometry/output_10_and_100.png | Bin 0 -> 873 bytes .../data/vulkan/data/geometry/output_128.png | Bin 0 -> 861 bytes .../data/vulkan/data/geometry/output_128_and_0.png | Bin 0 -> 867 bytes .../data/vulkan/data/geometry/output_max.png | Bin 0 -> 861 bytes .../data/geometry/output_vary_by_attribute.png | Bin 0 -> 1322 bytes .../output_vary_by_attribute_instancing.png | Bin 0 -> 1322 bytes .../data/geometry/output_vary_by_texture.png | Bin 0 -> 1312 bytes .../geometry/output_vary_by_texture_instancing.png | Bin 0 -> 1310 bytes .../data/geometry/output_vary_by_uniform.png | Bin 0 -> 1312 bytes .../geometry/output_vary_by_uniform_instancing.png | Bin 0 -> 1310 bytes .../data/vulkan/data/geometry/point_size.png | Bin 0 -> 916 bytes .../vulkancts/data/vulkan/data/geometry/points.png | Bin 0 -> 1046 bytes .../vulkan/data/geometry/points_emit_0_end_0.png | Bin 0 -> 854 bytes .../vulkan/data/geometry/points_emit_0_end_1.png | Bin 0 -> 854 bytes .../vulkan/data/geometry/points_emit_0_end_2.png | Bin 0 -> 854 bytes .../vulkan/data/geometry/points_emit_1_end_1.png | Bin 0 -> 864 bytes .../vulkan/data/geometry/points_emit_1_end_2.png | Bin 0 -> 864 bytes .../data/vulkan/data/geometry/points_to_lines.png | Bin 0 -> 1368 bytes .../vulkan/data/geometry/points_to_triangles.png | Bin 0 -> 1484 bytes .../data/vulkan/data/geometry/primitive_id.png | Bin 0 -> 1027 bytes .../data/vulkan/data/geometry/primitive_id_in.png | Bin 0 -> 2026 bytes .../data/geometry/primitive_id_in_restarted.png | Bin 0 -> 1422 bytes .../data/vulkan/data/geometry/triangle_fan.png | Bin 0 -> 2197 bytes .../data/vulkan/data/geometry/triangle_strip.png | Bin 0 -> 2107 bytes .../data/geometry/triangle_strip_emit_0_end_0.png | Bin 0 -> 854 bytes .../data/geometry/triangle_strip_emit_0_end_1.png | Bin 0 -> 854 bytes .../data/geometry/triangle_strip_emit_0_end_2.png | Bin 0 -> 854 bytes .../data/geometry/triangle_strip_emit_1_end_1.png | Bin 0 -> 854 bytes .../data/geometry/triangle_strip_emit_1_end_2.png | Bin 0 -> 854 bytes .../data/geometry/triangle_strip_emit_2_end_1.png | Bin 0 -> 854 bytes .../data/geometry/triangle_strip_emit_2_end_2.png | Bin 0 -> 854 bytes .../data/geometry/triangle_strip_emit_3_end_1.png | Bin 0 -> 1206 bytes .../data/geometry/triangle_strip_emit_3_end_2.png | Bin 0 -> 1206 bytes .../triangle_strip_emit_3_end_2_emit_3_end_0.png | Bin 0 -> 1552 bytes .../data/vulkan/data/geometry/triangles.png | Bin 0 -> 1443 bytes .../vulkan/data/geometry/triangles_adjacency.png | Bin 0 -> 1445 bytes .../vulkan/data/geometry/triangles_to_lines.png | Bin 0 -> 1350 bytes .../vulkan/data/geometry/triangles_to_points.png | Bin 0 -> 1036 bytes .../data/vulkan/data/geometry/vertex_count_0.png | Bin 0 -> 854 bytes .../data/vulkan/data/geometry/vertex_count_1.png | Bin 0 -> 854 bytes .../data/vulkan/data/geometry/vertex_count_10.png | Bin 0 -> 1694 bytes .../data/vulkan/data/geometry/vertex_count_11.png | Bin 0 -> 1694 bytes .../data/vulkan/data/geometry/vertex_count_12.png | Bin 0 -> 1894 bytes .../data/vulkan/data/geometry/vertex_count_2.png | Bin 0 -> 854 bytes .../data/vulkan/data/geometry/vertex_count_3.png | Bin 0 -> 854 bytes .../data/vulkan/data/geometry/vertex_count_4.png | Bin 0 -> 854 bytes .../data/vulkan/data/geometry/vertex_count_5.png | Bin 0 -> 854 bytes .../data/vulkan/data/geometry/vertex_count_6.png | Bin 0 -> 1181 bytes .../data/vulkan/data/geometry/vertex_count_7.png | Bin 0 -> 1181 bytes .../data/vulkan/data/geometry/vertex_count_8.png | Bin 0 -> 1447 bytes .../data/vulkan/data/geometry/vertex_count_9.png | Bin 0 -> 1447 bytes .../data/geometry/vertex_no_op_geometry_out_1.png | Bin 0 -> 1253 bytes .../data/geometry/vertex_out_0_geometry_out_1.png | Bin 0 -> 1103 bytes .../data/geometry/vertex_out_0_geometry_out_2.png | Bin 0 -> 1103 bytes .../data/geometry/vertex_out_1_geometry_out_0.png | Bin 0 -> 1103 bytes .../data/geometry/vertex_out_1_geometry_out_2.png | Bin 0 -> 1814 bytes external/vulkancts/modules/vulkan/CMakeLists.txt | 3 + .../modules/vulkan/geometry/CMakeLists.txt | 31 + .../vulkan/geometry/vktGeometryBasicClass.cpp | 217 ++++ .../vulkan/geometry/vktGeometryBasicClass.hpp | 66 ++ .../vktGeometryBasicGeometryShaderTests.cpp | 1181 ++++++++++++++++++++ .../vktGeometryBasicGeometryShaderTests.hpp | 39 + .../vktGeometryEmitGeometryShaderTests.cpp | 262 +++++ .../vktGeometryEmitGeometryShaderTests.hpp | 39 + .../vktGeometryInputGeometryShaderTests.cpp | 304 +++++ .../vktGeometryInputGeometryShaderTests.hpp | 39 + .../vktGeometryInstancedRenderingTests.cpp | 704 ++++++++++++ .../vktGeometryInstancedRenderingTests.hpp | 40 + .../geometry/vktGeometryLayeredRenderingTests.cpp | 1073 ++++++++++++++++++ .../geometry/vktGeometryLayeredRenderingTests.hpp | 40 + .../modules/vulkan/geometry/vktGeometryTests.cpp | 60 + .../modules/vulkan/geometry/vktGeometryTests.hpp | 39 + .../vulkan/geometry/vktGeometryTestsUtil.cpp | 765 +++++++++++++ .../vulkan/geometry/vktGeometryTestsUtil.hpp | 209 ++++ .../vktGeometryVaryingGeometryShaderTests.cpp | 284 +++++ .../vktGeometryVaryingGeometryShaderTests.hpp | 39 + .../vulkancts/modules/vulkan/vktTestPackage.cpp | 2 + external/vulkancts/mustpass/1.0.2/vk-default.txt | 124 ++ 96 files changed, 5684 insertions(+) create mode 100644 external/vulkancts/data/vulkan/data/geometry/line_strip.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/line_strip_adjacency.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/line_strip_emit_0_end_0.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/line_strip_emit_0_end_1.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/line_strip_emit_0_end_2.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/line_strip_emit_1_end_1.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/line_strip_emit_1_end_2.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/line_strip_emit_2_end_1.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/line_strip_emit_2_end_2.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/line_strip_emit_2_end_2_emit_2_end_0.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/lines.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/lines_adjacency.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/lines_to_points.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/lines_to_triangles.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/output_0_and_128.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/output_10.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/output_100_and_10.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/output_10_and_100.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/output_128.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/output_128_and_0.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/output_max.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/output_vary_by_attribute.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/output_vary_by_attribute_instancing.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/output_vary_by_texture.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/output_vary_by_texture_instancing.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/output_vary_by_uniform.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/output_vary_by_uniform_instancing.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/point_size.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/points.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/points_emit_0_end_0.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/points_emit_0_end_1.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/points_emit_0_end_2.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/points_emit_1_end_1.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/points_emit_1_end_2.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/points_to_lines.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/points_to_triangles.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/primitive_id.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/primitive_id_in.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/primitive_id_in_restarted.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/triangle_fan.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/triangle_strip.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_0_end_0.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_0_end_1.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_0_end_2.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_1_end_1.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_1_end_2.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_2_end_1.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_2_end_2.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_3_end_1.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_3_end_2.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_3_end_2_emit_3_end_0.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/triangles.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/triangles_adjacency.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/triangles_to_lines.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/triangles_to_points.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/vertex_count_0.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/vertex_count_1.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/vertex_count_10.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/vertex_count_11.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/vertex_count_12.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/vertex_count_2.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/vertex_count_3.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/vertex_count_4.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/vertex_count_5.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/vertex_count_6.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/vertex_count_7.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/vertex_count_8.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/vertex_count_9.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/vertex_no_op_geometry_out_1.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/vertex_out_0_geometry_out_1.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/vertex_out_0_geometry_out_2.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/vertex_out_1_geometry_out_0.png create mode 100644 external/vulkancts/data/vulkan/data/geometry/vertex_out_1_geometry_out_2.png create mode 100644 external/vulkancts/modules/vulkan/geometry/CMakeLists.txt create mode 100644 external/vulkancts/modules/vulkan/geometry/vktGeometryBasicClass.cpp create mode 100644 external/vulkancts/modules/vulkan/geometry/vktGeometryBasicClass.hpp create mode 100644 external/vulkancts/modules/vulkan/geometry/vktGeometryBasicGeometryShaderTests.cpp create mode 100644 external/vulkancts/modules/vulkan/geometry/vktGeometryBasicGeometryShaderTests.hpp create mode 100644 external/vulkancts/modules/vulkan/geometry/vktGeometryEmitGeometryShaderTests.cpp create mode 100644 external/vulkancts/modules/vulkan/geometry/vktGeometryEmitGeometryShaderTests.hpp create mode 100644 external/vulkancts/modules/vulkan/geometry/vktGeometryInputGeometryShaderTests.cpp create mode 100644 external/vulkancts/modules/vulkan/geometry/vktGeometryInputGeometryShaderTests.hpp create mode 100644 external/vulkancts/modules/vulkan/geometry/vktGeometryInstancedRenderingTests.cpp create mode 100644 external/vulkancts/modules/vulkan/geometry/vktGeometryInstancedRenderingTests.hpp create mode 100644 external/vulkancts/modules/vulkan/geometry/vktGeometryLayeredRenderingTests.cpp create mode 100644 external/vulkancts/modules/vulkan/geometry/vktGeometryLayeredRenderingTests.hpp create mode 100644 external/vulkancts/modules/vulkan/geometry/vktGeometryTests.cpp create mode 100644 external/vulkancts/modules/vulkan/geometry/vktGeometryTests.hpp create mode 100644 external/vulkancts/modules/vulkan/geometry/vktGeometryTestsUtil.cpp create mode 100644 external/vulkancts/modules/vulkan/geometry/vktGeometryTestsUtil.hpp create mode 100644 external/vulkancts/modules/vulkan/geometry/vktGeometryVaryingGeometryShaderTests.cpp create mode 100644 external/vulkancts/modules/vulkan/geometry/vktGeometryVaryingGeometryShaderTests.hpp diff --git a/android/cts/master/vk-master.txt b/android/cts/master/vk-master.txt index 27858d9..5236ee0 100644 --- a/android/cts/master/vk-master.txt +++ b/android/cts/master/vk-master.txt @@ -122513,3 +122513,127 @@ dEQP-VK.texture.shadow.2d_array.linear_mipmap_linear.never_d32_sfloat dEQP-VK.texture.shadow.2d_array.linear_mipmap_linear.never_d16_unorm_s8_uint dEQP-VK.texture.shadow.2d_array.linear_mipmap_linear.never_d24_unorm_s8_uint dEQP-VK.texture.shadow.2d_array.linear_mipmap_linear.never_d32_sfloat_s8_uint +dEQP-VK.geometry.input.basic_primitive.points +dEQP-VK.geometry.input.basic_primitive.lines +dEQP-VK.geometry.input.basic_primitive.line_strip +dEQP-VK.geometry.input.basic_primitive.triangles +dEQP-VK.geometry.input.basic_primitive.triangle_strip +dEQP-VK.geometry.input.basic_primitive.triangle_fan +dEQP-VK.geometry.input.basic_primitive.lines_adjacency +dEQP-VK.geometry.input.basic_primitive.line_strip_adjacency +dEQP-VK.geometry.input.basic_primitive.triangles_adjacency +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_0 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_1 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_2 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_3 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_4 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_5 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_6 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_7 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_8 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_9 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_10 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_11 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_12 +dEQP-VK.geometry.input.conversion.triangles_to_points +dEQP-VK.geometry.input.conversion.lines_to_points +dEQP-VK.geometry.input.conversion.points_to_lines +dEQP-VK.geometry.input.conversion.triangles_to_lines +dEQP-VK.geometry.input.conversion.points_to_triangles +dEQP-VK.geometry.input.conversion.lines_to_triangles +dEQP-VK.geometry.basic.output_10 +dEQP-VK.geometry.basic.output_128 +dEQP-VK.geometry.basic.output_10_and_100 +dEQP-VK.geometry.basic.output_100_and_10 +dEQP-VK.geometry.basic.output_0_and_128 +dEQP-VK.geometry.basic.output_128_and_0 +dEQP-VK.geometry.basic.output_vary_by_attribute +dEQP-VK.geometry.basic.output_vary_by_uniform +dEQP-VK.geometry.basic.output_vary_by_texture +dEQP-VK.geometry.basic.output_vary_by_attribute_instancing +dEQP-VK.geometry.basic.output_vary_by_uniform_instancing +dEQP-VK.geometry.basic.output_vary_by_texture_instancing +dEQP-VK.geometry.basic.point_size +dEQP-VK.geometry.basic.primitive_id_in +dEQP-VK.geometry.basic.primitive_id_in_restarted +dEQP-VK.geometry.basic.primitive_id +dEQP-VK.geometry.layered.1d_array.render_to_default_layer +dEQP-VK.geometry.layered.1d_array.render_to_one +dEQP-VK.geometry.layered.1d_array.render_to_all +dEQP-VK.geometry.layered.1d_array.render_different_content +dEQP-VK.geometry.layered.1d_array.fragment_layer +dEQP-VK.geometry.layered.1d_array.invocation_per_layer +dEQP-VK.geometry.layered.1d_array.multiple_layers_per_invocation +dEQP-VK.geometry.layered.2d_array.render_to_default_layer +dEQP-VK.geometry.layered.2d_array.render_to_one +dEQP-VK.geometry.layered.2d_array.render_to_all +dEQP-VK.geometry.layered.2d_array.render_different_content +dEQP-VK.geometry.layered.2d_array.fragment_layer +dEQP-VK.geometry.layered.2d_array.invocation_per_layer +dEQP-VK.geometry.layered.2d_array.multiple_layers_per_invocation +dEQP-VK.geometry.layered.cube.render_to_default_layer +dEQP-VK.geometry.layered.cube.render_to_one +dEQP-VK.geometry.layered.cube.render_to_all +dEQP-VK.geometry.layered.cube.render_different_content +dEQP-VK.geometry.layered.cube.fragment_layer +dEQP-VK.geometry.layered.cube.invocation_per_layer +dEQP-VK.geometry.layered.cube.multiple_layers_per_invocation +dEQP-VK.geometry.layered.cube_array.render_to_default_layer +dEQP-VK.geometry.layered.cube_array.render_to_one +dEQP-VK.geometry.layered.cube_array.render_to_all +dEQP-VK.geometry.layered.cube_array.render_different_content +dEQP-VK.geometry.layered.cube_array.fragment_layer +dEQP-VK.geometry.layered.cube_array.invocation_per_layer +dEQP-VK.geometry.layered.cube_array.multiple_layers_per_invocation +dEQP-VK.geometry.instanced.draw_1_instances_1_geometry_invocations +dEQP-VK.geometry.instanced.draw_1_instances_2_geometry_invocations +dEQP-VK.geometry.instanced.draw_1_instances_8_geometry_invocations +dEQP-VK.geometry.instanced.draw_1_instances_32_geometry_invocations +dEQP-VK.geometry.instanced.draw_1_instances_64_geometry_invocations +dEQP-VK.geometry.instanced.draw_1_instances_127_geometry_invocations +dEQP-VK.geometry.instanced.draw_2_instances_1_geometry_invocations +dEQP-VK.geometry.instanced.draw_2_instances_2_geometry_invocations +dEQP-VK.geometry.instanced.draw_2_instances_8_geometry_invocations +dEQP-VK.geometry.instanced.draw_2_instances_32_geometry_invocations +dEQP-VK.geometry.instanced.draw_2_instances_64_geometry_invocations +dEQP-VK.geometry.instanced.draw_2_instances_127_geometry_invocations +dEQP-VK.geometry.instanced.draw_4_instances_1_geometry_invocations +dEQP-VK.geometry.instanced.draw_4_instances_2_geometry_invocations +dEQP-VK.geometry.instanced.draw_4_instances_8_geometry_invocations +dEQP-VK.geometry.instanced.draw_4_instances_32_geometry_invocations +dEQP-VK.geometry.instanced.draw_4_instances_64_geometry_invocations +dEQP-VK.geometry.instanced.draw_4_instances_127_geometry_invocations +dEQP-VK.geometry.instanced.draw_8_instances_1_geometry_invocations +dEQP-VK.geometry.instanced.draw_8_instances_2_geometry_invocations +dEQP-VK.geometry.instanced.draw_8_instances_8_geometry_invocations +dEQP-VK.geometry.instanced.draw_8_instances_32_geometry_invocations +dEQP-VK.geometry.instanced.draw_8_instances_64_geometry_invocations +dEQP-VK.geometry.instanced.draw_8_instances_127_geometry_invocations +dEQP-VK.geometry.varying.vertex_no_op_geometry_out_1 +dEQP-VK.geometry.varying.vertex_out_0_geometry_out_1 +dEQP-VK.geometry.varying.vertex_out_0_geometry_out_2 +dEQP-VK.geometry.varying.vertex_out_1_geometry_out_0 +dEQP-VK.geometry.varying.vertex_out_1_geometry_out_2 +dEQP-VK.geometry.emit.points_emit_0_end_0 +dEQP-VK.geometry.emit.points_emit_0_end_1 +dEQP-VK.geometry.emit.points_emit_1_end_1 +dEQP-VK.geometry.emit.points_emit_0_end_2 +dEQP-VK.geometry.emit.points_emit_1_end_2 +dEQP-VK.geometry.emit.line_strip_emit_0_end_0 +dEQP-VK.geometry.emit.line_strip_emit_0_end_1 +dEQP-VK.geometry.emit.line_strip_emit_1_end_1 +dEQP-VK.geometry.emit.line_strip_emit_2_end_1 +dEQP-VK.geometry.emit.line_strip_emit_0_end_2 +dEQP-VK.geometry.emit.line_strip_emit_1_end_2 +dEQP-VK.geometry.emit.line_strip_emit_2_end_2 +dEQP-VK.geometry.emit.line_strip_emit_2_end_2_emit_2_end_0 +dEQP-VK.geometry.emit.triangle_strip_emit_0_end_0 +dEQP-VK.geometry.emit.triangle_strip_emit_0_end_1 +dEQP-VK.geometry.emit.triangle_strip_emit_1_end_1 +dEQP-VK.geometry.emit.triangle_strip_emit_2_end_1 +dEQP-VK.geometry.emit.triangle_strip_emit_3_end_1 +dEQP-VK.geometry.emit.triangle_strip_emit_0_end_2 +dEQP-VK.geometry.emit.triangle_strip_emit_1_end_2 +dEQP-VK.geometry.emit.triangle_strip_emit_2_end_2 +dEQP-VK.geometry.emit.triangle_strip_emit_3_end_2 +dEQP-VK.geometry.emit.triangle_strip_emit_3_end_2_emit_3_end_0 diff --git a/external/vulkancts/data/vulkan/data/geometry/line_strip.png b/external/vulkancts/data/vulkan/data/geometry/line_strip.png new file mode 100644 index 0000000000000000000000000000000000000000..26e096ea802d933e6cc23bbd8c4a8870e4370857 GIT binary patch literal 1677 zcmd5-TToM16g@XyAUuK;Fr_$zObfvWAhi(`A_RH2LO?|nkOa|^YAcAL7(lot7Fs}P zu@(zRP^V}W3JL{5!ovzULP-P)j!xo5rHKVYB1m|Iq&Ja%cly_#^O!TUXRW>0TIZX{ zh!BFAy%_+25EdG^3jhc^LI7`!ZSiT>J_W#dPgtP;o|BcYBu~<=1lt8ig-$Fp_qQtV zU$TRD@O)1lJ@C`#E&XLv2w~wsHw<{D0JZ^m3b5J<$QJT57&VtZ%gf1j0Oq8{=vhj&%JK2DXalX< zeV|AuCfOKh?sWpax$JYMfF~h=JAO?!?k84X-MiXoJ1H*4GkivKBE2rbD|@mT&^)zV zA-lOuB5Wouow&rEw0*TB-agsZ@8Tj5-$q@fR1=1T;D*bLfT(6yPu zV_Og6F3k1mVq|d5OBV~0c};TA>Q%og*f;Bc-_&6#{Ce4^J!74G;H6(DN!)nb6m3;9 zi#5YK^F{f2s8As7F+v~k{lz|Bkl!J7GK^F5O!%Q>{ZxHfnq*sCL-#zxOh4PyQkCF4 zd{===;B&Vgj7hgfHfY_zlta?Cr(M76w&uNrYATqrdruU z@{xxoRkWIAqiNV~_yv{aHK*}@PjRBMroY%2w zvB<}Sr(M)8c6O?^q~YoOAIz8P1N?4G*X632T2ZBo4EIPDgBZVZdvs;(sbpefPe}!` zYUTk5fvb~XV3$pPPHoCjws#-ghpj+MGRz|sFB&Mc(V)B zZuZA|V{!%+BCof0ogqi&=Qvt;YG<62A^R5fI4NRI`#DwqW^9_ z6Y_Q<#`oM<@iwP-UUYuN@kp_quC@HF-K*fKd!zH6*}S9QGYO-D(`du65U&1UGQ?B% zE_1pE8%+C5RC0C*u;=_48Oa!&Qb=E3vw+y*A3Nu^3pca;Tl&K3Sb|Xd=9$HSQ+rh< z@YJUY5^=U|X|1l`TJJ;ZZwh7=;IKzjg4Y-ZuJyMYe7BjPWBf^OT^))yb`MPw)_$7E;LFh#wiJkfR;Ws(W==hO8<-tnL(m$g@TX0zLlfup0hm7}?;e z^u+5uUY_K=uJ0UT+Y*mf;cEL6$pu{58G)qJ)dsZ0x@Vf-*-ioFiRw)v17^%0Y@Vvq zawYYUzlwBk3}vq0S{ic(d!Cy%Ez-<(zC+BapqUL!G;4Q!L0Is8(d26b%DC>?g>8-$ zaJ^xvrQ1-=Hd&pLzmlQ!s9s&Op%lj6Hc69G;sX7AWWhF;aa{hUZ45>(kCt2<+|(g0 z6*dywm}(ywiEGay%NH8!rY;K;)K{_lY@0`>P{A;%kW3YzY>LgLC+)B32(V%IDRAk8{vSULhxg@uB&21jEoZ_r4tE>rw z&6F*dvLFF zd!sf0K-bg5{TKi!iC@yG_s|E1efkhdBLjNxcB`+P-wUWNP zSUYYjprJ!o*ke_j?YN;v38&q6Stuh*wJdc*lR007w-d- zF86^{<+TSr^0s*;UcdS&-af;gQ&|)B((JY_*4wXpKHu*81ZrVrUl+F~Bz=e+(w>3& zjrb4n(=X2}*y4b1WSy}cv;`LMdatsKG5{%5aUMYcdY(jLIXV(@RIDCU&yIYZ{CJ}o zXIBc{0C8IAf=a#F89P>kDI4X%Pn>c@tpn{^e!M%6DP26smd}zGl%~j10x=v7;;K5Qx z6oRt3wwL}~Z!%(hp&mp{rAo*dy_yvNT8;HG1Aw`!XgQGtj!zx@y@8=}*952@ z0?cWj(qrBPepo#^XO?y;%fVwPKm;7aP22KwjmV8y%4r5J>y=?qW#fAAzySPsZvU`E+! z8ogI@5Z82#0pXUzpcXvjkU|gEf_lURA~L*|<5U9hHOdGdVDxGBL~hS@fIlURxCk~} zn5wGM2M05c38M9kw=hmI2{EPfQWlo9bKg#U-2hb}bSy~OpLS$;e(1vzv<=P7;lcv1 zGt0EG;=Z?yrfJg+$T+<;oncOZ(+k$>=D3C))+BaQ*;Lg|G}8h1f`z5@ZQ{QEiC z*K8(fqkP>*qILTuU$}k!_8ruP|K{Rte_vkQM=Lyr6($nolOF zN`;3T6Zf|OvkVzo`0?rx_QN{J{rPFH#ZBkmvd%M~_CZhYI8pIyn7d{C|f72;dW zV&_j`TU|0kCb92(FJHN7WODe@N#f*D5O0d(o1-Y}FB~vMGs})hU^^V&YAu4m;4EQc z9r!U4c4Dj@393udjB(Nm>^-J{(?L7efMy%7hng(_)?vYp#e2J_8RvWAba4shsNw3b z54e)X6_(7ex%aOo2>!_2&9R!qUQh=!^ynU(d1Ni-e2>4Ls(OeAu{V_eEmVtU)=Rpl zy2(g>J83^ZGx}4R>fM-wDAB0Q@AlxX_ckeUdK3C!wVyrE8%3*B1+n9*<-Ct3kok9Z z+&H%4>3me5H>LcpqJ10a_+_d)PR)Vxm#TIv&{4G1P5)dEt7NVqUQ0sPMT3-$ANy~Y zK;NHjjtriFg9~yG?O56tjv@|@V!YGMv?uKiij)LT0#zOOX@6$nh!Zt}g>lyYX;Qm7I-LMi@+E@jnr z6ywwj!6F2aQ>nFscVv73DC$soe(Ow8pG6L z)6LaOgm~jhg*uhiTnUPT658_3_ino>)-plDyhbfAd zsABNIzM2^wuZB+fD;2V<&&-6v@4*r^Ln9war#01D5d2K~D5mv7bO=33K>yn>a9YFC c|1MOR*^Kk9!xdAv5WWM?gFfyJZlSq<0a#Inr2qf` literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_0_end_0.png b/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_0_end_0.png new file mode 100644 index 0000000000000000000000000000000000000000..fc45c5022ddb5f6c6d023d3104c385823a054467 GIT binary patch literal 854 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{Sx*(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_0_end_1.png b/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_0_end_1.png new file mode 100644 index 0000000000000000000000000000000000000000..fc45c5022ddb5f6c6d023d3104c385823a054467 GIT binary patch literal 854 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{Sx*(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_0_end_2.png b/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_0_end_2.png new file mode 100644 index 0000000000000000000000000000000000000000..fc45c5022ddb5f6c6d023d3104c385823a054467 GIT binary patch literal 854 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{Sx*(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_1_end_1.png b/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_1_end_1.png new file mode 100644 index 0000000000000000000000000000000000000000..fc45c5022ddb5f6c6d023d3104c385823a054467 GIT binary patch literal 854 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{Sx*(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_1_end_2.png b/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_1_end_2.png new file mode 100644 index 0000000000000000000000000000000000000000..fc45c5022ddb5f6c6d023d3104c385823a054467 GIT binary patch literal 854 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{Sx*(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_2_end_1.png b/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_2_end_1.png new file mode 100644 index 0000000000000000000000000000000000000000..22e374daf6fb8d73d613dacdb77aad0a7427fd1a GIT binary patch literal 1056 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJFd=bkQ(Ar*7p-f+yj?I6PH zsCDA+`ZH^USlWb73!Rko3!mFC`+oEBhm*w8agfO&Z#j>F8UL5kYz^C-t$vg5|rX< z*QGJ}9QtV7#Ncz_qj49f!Gyi%GnfoI!skoQU|_bWOH*VJFaC4p2+Izj^*t;PnBr>F zQkmwQ`Dkp+Xfg3|dYRe*&NsF1oEZ3?U48E7)4*(5_s)%h@6nH)%EAwPzuA?mG30-E zRa~xipj*aXTcAPQqAo0vsit}F`7D+Po^iEdDNHs8KW^4y{L%C{Jyq?1{f*xu90%0* z{0f=DAa7CU#qvPEZ@!dp!shQUPq80Z?SC`*_O{wD?hMI4*oShm-_H=DHCOL==2lT) P&S&s+^>bP0l+XkKCXEn# literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_2_end_2.png b/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_2_end_2.png new file mode 100644 index 0000000000000000000000000000000000000000..22e374daf6fb8d73d613dacdb77aad0a7427fd1a GIT binary patch literal 1056 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJFd=bkQ(Ar*7p-f+yj?I6PH zsCDA+`ZH^USlWb73!Rko3!mFC`+oEBhm*w8agfO&Z#j>F8UL5kYz^C-t$vg5|rX< z*QGJ}9QtV7#Ncz_qj49f!Gyi%GnfoI!skoQU|_bWOH*VJFaC4p2+Izj^*t;PnBr>F zQkmwQ`Dkp+Xfg3|dYRe*&NsF1oEZ3?U48E7)4*(5_s)%h@6nH)%EAwPzuA?mG30-E zRa~xipj*aXTcAPQqAo0vsit}F`7D+Po^iEdDNHs8KW^4y{L%C{Jyq?1{f*xu90%0* z{0f=DAa7CU#qvPEZ@!dp!shQUPq80Z?SC`*_O{wD?hMI4*oShm-_H=DHCOL==2lT) P&S&s+^>bP0l+XkKCXEn# literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_2_end_2_emit_2_end_0.png b/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_2_end_2_emit_2_end_0.png new file mode 100644 index 0000000000000000000000000000000000000000..c983ed7dcbb28f63601a3458a9a7d41876ce60db GIT binary patch literal 1168 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJEia8DPk3ccAx!Py{l%H&2rdKdp?qp>&Kzf$vuTU3NMe}6=%5P&Y<8kibx272T8{Z@6>X} z3o&pAGwirfDD(JZ#hqG72p=SL;?4a3$s7zzI2l^NC?=uxuYDVX!z>1e84L$bhW-2_ z@64d!3$^lri}u_9hAa%1SQrkmF!*h{_58mC6GJ8wLn0WdM-=|=S7ex=#vq`^@L^G? z{r}?v3?9NDyMd_U;HlsBJd6z{j12~i4eD$E{e)WtvP-z^2GAuAw+dy-|uX7qU)~LAvP2Pd(uT&OLlCs&-(}o4?<0 znQmd)upn06?cRBoh@QjeXR;(H^8L3h`*+v3f%V4k7*__h?VoSA|DMSpT>N9_EC!!b z59c3#_x&KtjGn#ctvL_4l-1uhkQYu6;`?92_1%R*EuiAUjLDn@%GL9Ca~|;B^L1t; zX9072ecjY*6^8t<$_)|CoFCM_*%=Epn18qy@BOlFCWE-PtZXk@JI6b-n!24(k`OrO|hWvsbH>WcEX+FGv|0i2B#(fFzgB2L&YwQ=yFl7Aq z;6tzygS^Eb+ppDmOgz=|*VQn*%4fJGm)!ICT{pwKhxX7YgGAgABY(3p&3UbD$Pl*- QSkf?fy85}Sb4q9e0O40lA^-pY literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/lines.png b/external/vulkancts/data/vulkan/data/geometry/lines.png new file mode 100644 index 0000000000000000000000000000000000000000..1664be81ce38c07f310b1a2c4a77cfff85f2a28d GIT binary patch literal 1339 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD%CQlc~kcv5P@1D-P?IGY0 zm}T()|LHlc$wvfJ+@<#JsyH7h*&#mHHC8Mo$R_vpwtR<6_V4W&KG-oaBn}4jf8TG0 z)wlNlsj0fH`CunY!tdf6_H*lgm|JwkFw{wvt+341E4qKnyzs$|8V(Myi$Czbwr7Pp zy`b^yd@jZY14fI-ulze19Bz2$v6lVTUGwtccBcQiH`dX~5U&izbtA`AcSZ~Hp`zcYh^4+!ns@Gn@IK|qaRzt7%ZhizFBEMD7x7hvEJ zZpeN2>;0?qdx4HB;%8>ue-o+!q79R*yZQa^ZSj^hIj?p`IzP%jc)s>~(S)n)nLzIK zhs*_MXE%hIe7$p~=mo=_Pjmiz-RCp_@`_)aXIRE}>`Jlm`Gw33e|#9W?acmirFb(R zW5b3Th8S1P)9eXa4<88v9dU_qMwRH?s=RBH`53NnGPG10a?*L$p-dY(J|CQEq!N7oEIVVwkt+vhR^{3K5GYu%6665+nG6myK#0e< zw0BAL{mr z)g%VHAKP$Vk)eBsiP3bqMX|YC*44h9uCd0G;oh5KopqH-b^AYkk9%0WV14Da`{hh) zyczE0yo!)`k^DhXp@s8+fcDz|+c*4M?+c0)wi#7l(`%UyT#opET^$sa-LrT7+x_dj z0*Jk#HYe)n?5TG-cNo0>UtIJ3j;kTV)&J&#*X>fi{@ndK?X_hNgUmHu=2)43xt}E& z*u!LAL<2*YlcDnJ*ZSKm43}6MwtTt@VF6QU!S;zyJap$)EmrJ~-V~XoUZd1jZ={ uHMDR1cOIAmpCu}AY-WUn`p_nC)W2qYA|xeZ=>;ql89ZJ6T-G@yGywn^jrL*y literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/lines_adjacency.png b/external/vulkancts/data/vulkan/data/geometry/lines_adjacency.png new file mode 100644 index 0000000000000000000000000000000000000000..9a397778715ee70cb00b0d1e764f9b2b8580ab03 GIT binary patch literal 1360 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD%aZeY=kcv5P?;b3=>>=V1 zSlRXef9lz!1!|s_VLhs=qrcA)W!2g9;BMX0Egy0tr=I{xJ-ojCvK{LlcPob1bMNoA{b9UgmJfp*@9(|)Uw>JyAjrVX`~9xi?RV-)j-B(F z9A+>8QBA_%uZDWB;bg@Bo0CDN0+G*=U+3?!FdSk@5b~?<`!H>G zgK~Uv?Dg~W-<3%}oqX_P8UKN68|GI|s+Ikg`qSpa_kT4an~n&^@f|p^ez{%ouJx~9 zeNlh@l%dDQh)qha`n9tI|E2_;I<5^7|6d9*a8yS#tod&+?++W$`8x6p8r9w){<1G1 z{<{wh7Jn0CZvGdmnRdDU^?~U^*ir3z0o#*FXw@iJSOR0 z|3w&H0iAiRzE1({do>2(4gZQo7#j>2CFWe7uguBN!pX2(`sZ)aA7^|IG@jk?Px{+V z&I1SBr2oy|H&cV_vjBtHU&$BqSu)$!w*Kd2n9cL0w334(k?BC*n*X1{fm8PI%Y0bK zd@y?be-9{R9&9g-jZIWluN3~U+xjijhjO6mT{R3fTg7VLUt+9y_HYV&q)6;9$%e+Z z<9f0T4-6S2*8DF4y5=eKgD+rj0~3`u`+;Bnu~rNLJM^zztNO!5UhyoG`>46wQz~gA!qMz&lD9}I1i}I`6uHDjd`_%zt1(87!pCqz~Z&N zJ1~fgMQ6m;?7d`j>RQqJS+6DL=kPEY>nt(rC2Sx`t*Z%9e{9g)UOAKq9 ifix&Nj3Pt`{N;W&=Yi4FQgcv&$>8bg=d#Wzp$P!>$A4 z*#7^&rHn%p^8}BCvg5H|8{Zs!*|YfO?LwLF%pO&dwG0Wej12~Z0#!WN_lu!m(d~zl z?Q8C^EGYYMkcA;}Cnv)X1qJ~%Y-pPbLl}P|zc*7s^v8w%0%}=xvJKj`nPt4fbB?Ae zaC}x*XyIhQh7Op&`#$q`pt1j1Ei*>NH(xj%ViV$*vnRB3n;onCF)N$_k6ws@2Oh3t zh<(T8FoTof5DPB!VDd)ogU;vAR)sYxo&ox0I^TgS7b{-voOxWEp(VD8iJ=aww}67v zcn@4Dy}j~znmJ%tRV&UtwHd0v$ZVmPih&o%w$mTVGx^TQziLw{Xw8VzHB8PkI2%rXI{gh4Za&!J6dWRRPEEUckEJ2_ZPh`y z8TU9C{C8iPo_5{fuX#D60w^G{hXX|X!2FHDcKy2<1k#uWNxCNA85_czSz~58r|okA P=5Gd1S3j3^P6rYb$7{=doI6#q0JBu(cQ_vx9Lfb(KS^;6e5UFJo62Vb-h|t72Q7IiLRO?h~ z*KK&EG0bA*qe}MbCCBNi(^E@BkFHauX z$Gim31xpqHfM?>SxUB%l{D}a?WnMCJuLuB~&m_jhq!v^@?$_n6OrS;gv<*2N*)1mn zCr_P1WC_`W!mvcUSqIeAdzI3Ihq?$Nf)Gv#zxe3NCIOj3jwM8`yWj z)HJD9^N^`?c8d9ulzJOXzmIkI1UTV!L$M*STLxDbd68^1CWZs0l}&ljw-7NtMSh9% zzCx2^4~;F9w8|i!NhK|<#{;pm5ziTWTC2KO`1zNm z9$@ufD(O$Q)pk~v^Rt~aeN%5Ky^r`FTqRhnWoaZy;J(0<_g{r1Suj z3^+fyh&8g=dO3d?x2)>dER^*kI6Ay@&+KeXtgBg@L@n9(XbLRr7w2>0)m{1ssTa9j z=$kce>dc)1_$&!C8+SEL?Ajp88Qp~8KQ-z?L^%R21~av(z^GEuc?Lq*(3%Q;<<09- z9t!q0g1zGMMaE(YA$RPy5Yr7Sm@Y>&59nZx`IjCRm%misRCkF}rH7d0CtQ9xAyiOE zfr_EO(>PIt8MKi}*LnvrB_|x!oFjA}h;lIe65$>$vaF&@^j!XFLim>(S*&98-f7ff zxROW;6Ip(sOSWv`D+%E?H}bdFksQNM5^}c4f+7afoslw5{>)_2H?ej&q> zSIp@tiGi8xpRV%ru`QH%rcnptA#8sz+WgV5am?~;umY?*ON$tY;RJj5PYe%LtYrCn zD5}wj#goZU@V5KL`6t>XPu@p0M6dd=dgi&ec^B?7Uq!+J#h?$(5S*O*W2}v^?bO|PVDzUNxmh$NbQ&_awYje&+90V?C%{)f&2zj zhd&g_Da($6b>A>c3f4V7;wZ$N5Qm2$<_lP+4`S{JdX<5au_s6_!zo4?2o(DNADjE5 XS^QpImEh(4N<(5iFRtc8{HwnKzLXTD literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/output_0_and_128.png b/external/vulkancts/data/vulkan/data/geometry/output_0_and_128.png new file mode 100644 index 0000000000000000000000000000000000000000..860a6cb2b9edb89f9eae658995a0e03a0da6f79f GIT binary patch literal 865 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{4Nn)xkcv5PuPqcjV8FxT zXgT>`bXf)0hJ$a7HoBWf8E<4T-|V@t(1C5Dc*dnS@9Ykw8y8zYG=Kk=;ei};gTW{o4S|st0vnhm4zd1MNvysF P%s335u6{1-oD!M1AMMVqoxe^>bP0l+XkKDxtCR literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/output_128.png b/external/vulkancts/data/vulkan/data/geometry/output_128.png new file mode 100644 index 0000000000000000000000000000000000000000..c29ccc0a1fa6100e29e92cffa6529de23edf1c41 GIT binary patch literal 861 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{6;Bt(kcv5PuPhWi;K0Lt z(Bkj+HxJf7FfQKh@kYtxW&` literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/output_128_and_0.png b/external/vulkancts/data/vulkan/data/geometry/output_128_and_0.png new file mode 100644 index 0000000000000000000000000000000000000000..35aa909013b5e0c7be7980fc718e9388d3c2eb58 GIT binary patch literal 867 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{El(H6kcv5PuWjT#V8Fv- zsQvr>nkzF8F!sH@kYtxW&` literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/output_vary_by_attribute.png b/external/vulkancts/data/vulkan/data/geometry/output_vary_by_attribute.png new file mode 100644 index 0000000000000000000000000000000000000000..e3d6953d8a69fb78d087dd6776b1d80a2a6c6b49 GIT binary patch literal 1322 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJEikDe}$Ar*7p-aXxS+l|51 zQR~G2|3;fRM0|Mqze;Sn`6`&TBJn`O&YkW3l7ZWEZ-3+U`1Se~Gs8M%1_3paQTL7S zwYSUj%O9I=KWoise{J!>`+3_P-487nYT*C;E;5eihb-d{2KV?|-Hhc-1{*iOf7!~w z&v@9z#DzgEbxw~0gRqok-NH;^1{Vb%2DRd=60Qq88Pt+mdej&u&q(}ZEW@14$?#v9 zNtelhaq(jgU(1LgVTiuZ44jeAHNrD=!~&+c$_cPa8g1^nUi6W zuo}p2kH`7K4W5!}${Yudoa<{i@!<7A`y&(c`OIqGu{>bjE6lw3c{$62!+$l|+|DaA zZJ1Ddzjxkr4u+PWnhY(RbVPq^zcSu=d;8yq`**h8ZcuLQyS>eJH)<>VLQs!+Ob2!3~0s<$wM^pykJZ;6-2;gU$OZ z3^Ar|f(_5-h%qR){M7wDyMc+Nf38qN}Qu749=`yy#N2-YrlPi7#BRgc+*az$vK}fCeL_nxZYRi?X2x}5*g1Jek=&M z;(vV4kE;#Q4A)AoMAm$~&BU0Xn;yGQU#jV8J&(tUj_U76=kcqoW4QBQKkti%_%10A zmIl|@TC+F>miBv07MBmDf8=2}#KLfhkN-fRA z)#vwx|NsAi({C@+j;xkr{O2wIiY0uJ=#`&m{zUS?ia;s*J!vWWMyXG_-{~ zZ}{=yy$$n%hf^KhkL}N0$Dr}+U6z6gP|bqu#`oWTYce(%oM!+g`%y$u2)vPJSiR$k UNJwV^unc7IboFyt=akR{08e|Xng9R* literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/output_vary_by_attribute_instancing.png b/external/vulkancts/data/vulkan/data/geometry/output_vary_by_attribute_instancing.png new file mode 100644 index 0000000000000000000000000000000000000000..d08fb348e9027dd4285b5b3c7a0d6fc62a529d11 GIT binary patch literal 1322 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJEikDe}$Ar*7p-o5LW6e;0) zF?spD|5M*~_jMYsWi9&m&HT8>t5rd&g4a@*x$ys8>u#(%moxk;fGlSGT%UA7kVit@Bw^t|2)kz63 zq}}=*SChfP(h%8aw~wE@@j1hc$34g29iAs&z?4uM-dl7aQ$e=jyT19H?Tq0Wr()mr zitoGoXXh`bId5OT*#Fzwa6v*1L!H#0#sB?yW@M!>)LH*>|7UNQAhe#zCiDG{15=N& z9&mVAxR|Nn+7H(@&0{PN-UN0r2={Ov5Ory|+RM?Pc<8;3e8cMF^ zOBi_g<2L6oyfgc^J65jZ$R+ z{+NG1^Hq44-gG<0oZGg3jK}uRc%Nr{@O9x&hMe151r7eS*51iGbp2rmkXtG!z!3J# zvO!$Jezml4!{*}|e|!wo7;cx{)99VA>BgFHyGMAQp&o;~u!NfAXRQO}-zrKEyqK9) z!(dmf#^&blsKqe&C}qF@ z>Ena`TfWaOmatnd)WH2lkm+$cKU2ZR^rVC@Z+saP&P;AVNdd^IVF20R^mDWio@;Yy RiU*c~44$rjF6*2UngDwXn|=TQ literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/output_vary_by_texture.png b/external/vulkancts/data/vulkan/data/geometry/output_vary_by_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..0e655b7689e193a9d8cee04252e5a116a054ec4b GIT binary patch literal 1312 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJEi=bkQ(Ar*7p-o2f7+fBqF zaMg?d|2O>#(C}q4-!(&qFMU1h6U7Eb!DDmIDyDjE&%OOldcv3MH`y8HxHBmDkc`9% z_y7ORf3NU%joO1$Tj?LSbI%kO#4;5a&Y$=6Xv2Dr1FUcMZWU*iV@XJIkH5^#n8(z% zGqZ!i=Tw1F6N692lMmd!vl$ea5}6EUZf*-?nZ=Tz)HdNFOM;Lw&wrld2O^jb=({X% zWl&3aVbRUtFoQ7iIk5b5kr?BQBRYaJo?1vaGyFLC;XB6xmvb@>hwrN}Og8N3QDNxt zn*p-iLF%6wQ&<>h+_)$xAX#Jk!}ZP2lLy)6vor2k;GdN6;%65_%$@l_Mx`5r zSkZpzs(Z=|0?%R@IE3kle*b>M{Nw!J*7-YS>qG*IZpY2u(_Hg>=~0G#ua_{q`8mmn zVZM}1!{RtEmIuPj%m$BATNv&czKCrIoZTawpMHRqm*c>Tg(8duQcS3@n}N@0zbpUbLJsvFCpK zzmNYP-Ji(CAbI}Wx1$1YYB&S#2N>K6=1o?wj}8Y>x(nuJLh-2VF-I|W^etv@v~@Hs0zcH7jHIyMD*lcsE=;oblsfX!AS99x1QG{O=_ygg?A^X!7U7x`XeTWK5T|$=ekk zy4=v8c=vInUNisw!bgt}*z>=)HZ=IMVY;Us|ABzRl7CbcS~wX%=O;W&3|nmEp96;S6ow|J!adZdkEb{A*V8e+34ev(uaZ&19JH;hj=^?Facg z%nA?ZHm>6VDH8Zn&%Mv&2S1a;HLm+_zsE8$B)(%LCLxci!50EI?2~pCKkcmh`W0C6 OF?hQAxvXlV}rpcq9_Cu zUVq+ipDI5)+2KsN`k&(~w?C3&Y3OnH{}RMu!>aIbru)uI%8Rra+^WAnnOA43z|gbh zyQi%w3)2A&_xWcoJ3Xjo=qWs=d~=JtcQ}L2`&GgfhpswUG0d;8c`7gb?&5^qb9QLY zH~Sw~%Y5$J^B4PnTN^G&s9~s+`ma9rAJTl{^> zyHii=O>fB7ah?Bh{nK5|;62jQ`44Q1m1cY#fBkx9@IG#L8&(6SxWLMJ|0fGF?&$ik zVHe0RJ;%-i{jwqVdGDnkGm}CXww<+jDEXMFz@#y8lAu2Gzm)#z9KG{a9%Fw{e*VaT z7n&Zd56b_GGcR7QCe3iboKex2LBR(HI-}3Fv(^2d`8N5Gg!($M2S)E@$_x|anF@B< z@^2UTAjfENHn2UCrD86_oJT#*IxIHlS2MI*uU>C;?la4Sfb{+#mWn% zs^vW=LkkEUsJN#A;T*`bxwJ_Rltv}ahH}~qH^fTHWD7EI2shll`&8?J-u7l|VGz$b z=I@K@ug}v(nF?mCcFXu<nU`&)>C#(C}q4-!(&qFMU1h6U7Eb!DDmIDyDjE&%OOldcv3MH`y8HxHBmDkc`9% z_y7ORf3NU%joO1$Tj?LSbI%kO#4;5a&Y$=6Xv2Dr1FUcMZWU*iV@XJIkH5^#n8(z% zGqZ!i=Tw1F6N692lMmd!vl$ea5}6EUZf*-?nZ=Tz)HdNFOM;Lw&wrld2O^jb=({X% zWl&3aVbRUtFoQ7iIk5b5kr?BQBRYaJo?1vaGyFLC;XB6xmvb@>hwrN}Og8N3QDNxt zn*p-iLF%6wQ&<>h+_)$xAX#Jk!}ZP2lLy)6vor2k;GdN6;%65_%$@l_Mx`5r zSkZpzs(Z=|0?%R@IE3kle*b>M{Nw!J*7-YS>qG*IZpY2u(_Hg>=~0G#ua_{q`8mmn zVZM}1!{RtEmIuPj%m$BATNv&czKCrIoZTawpMHRqm*c>Tg(8duQcS3@n}N@0zbpUbLJsvFCpK zzmNYP-Ji(CAbI}Wx1$1YYB&S#2N>K6=1o?wj}8Y>x(nuJLh-2VF-I|W^etv@v~@Hs0zcH7jHIyMD*lcsE=;oblsfX!AS99x1QG{O=_ygg?A^X!7U7x`XeTWK5T|$=ekk zy4=v8c=vInUNisw!bgt}*z>=)HZ=IMVY;Us|ABzRl7CbcS~wX%=O;W&3|nmEp96;S6ow|J!adZdkEb{A*V8e+34ev(uaZ&19JH;hj=^?Facg z%nA?ZHm>6VDH8Zn&%Mv&2S1a;HLm+_zsE8$B)(%LCLxci!50EI?2~pCKkcmh`W0C6 OF?hQAxvXlV}rpcq9_Cu zUVq+ipDI5)+2KsN`k&(~w?C3&Y3OnH{}RMu!>aIbru)uI%8Rra+^WAnnOA43z|gbh zyQi%w3)2A&_xWcoJ3Xjo=qWs=d~=JtcQ}L2`&GgfhpswUG0d;8c`7gb?&5^qb9QLY zH~Sw~%Y5$J^B4PnTN^G&s9~s+`ma9rAJTl{^> zyHii=O>fB7ah?Bh{nK5|;62jQ`44Q1m1cY#fBkx9@IG#L8&(6SxWLMJ|0fGF?&$ik zVHe0RJ;%-i{jwqVdGDnkGm}CXww<+jDEXMFz@#y8lAu2Gzm)#z9KG{a9%Fw{e*VaT z7n&Zd56b_GGcR7QCe3iboKex2LBR(HI-}3Fv(^2d`8N5Gg!($M2S)E@$_x|anF@B< z@^2UTAjfENHn2UCrD86_oJT#*IxIHlS2MI*uU>C;?la4Sfb{+#mWn% zs^vW=LkkEUsJN#A;T*`bxwJ_Rltv}ahH}~qH^fTHWD7EI2shll`&8?J-u7l|VGz$b z=I@K@ug}v(nF?mCcFXu<nU`&)>Cu)pvNh{w!@4ThBdSm)#Mu!;;4mW1btgYs% zP?5$L@{#xJtyUL_N*scR79`Au6q&f&dUtg-kDd?%hqduzVTM361`gq&iGH)l{uTY? Uc0B4DFt;&yy85}Sb4q9e0E;D#PXGV_ literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/points.png b/external/vulkancts/data/vulkan/data/geometry/points.png new file mode 100644 index 0000000000000000000000000000000000000000..c1a7d47155affd291c49a6e883c98802e2420bb3 GIT binary patch literal 1046 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJFdyPhtNAr*7p-gV4-Y#_kk zsQLf@=5HIOC-7f8Hqmur>{mu^jw_OEhb!)HdwZi{$@+`@3_Z#W0&2qxnVB#gKf%ww zt@g8=(==s552j=#3mj1D<-MoppRt{LMB9-H&Ij5pr@ zS|GgMt!m<;V?f=11O*PUFknLuW^eAc-yp^KgRwHfG^|lE=OyO>5B~Kt85Dplh6-Qo zb}HydGh`o15S6&JNti)_VFG2*z?go&@xlK?3>-k?aiC=nyaVhGYkf%Rd;6ZBcU=P0j5A#N z`|m$HpUBi;Ak5Ihi5>MP2Y;|LV^loDa^Ud{hIh&gHCL?lKkr*#@HCUJk3k>}s2QhU zfKmw()9a2EgI$RyL)bKxUNKz5(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/points_emit_0_end_1.png b/external/vulkancts/data/vulkan/data/geometry/points_emit_0_end_1.png new file mode 100644 index 0000000000000000000000000000000000000000..fc45c5022ddb5f6c6d023d3104c385823a054467 GIT binary patch literal 854 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{Sx*(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/points_emit_0_end_2.png b/external/vulkancts/data/vulkan/data/geometry/points_emit_0_end_2.png new file mode 100644 index 0000000000000000000000000000000000000000..fc45c5022ddb5f6c6d023d3104c385823a054467 GIT binary patch literal 854 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{Sx*(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/points_emit_1_end_1.png b/external/vulkancts/data/vulkan/data/geometry/points_emit_1_end_1.png new file mode 100644 index 0000000000000000000000000000000000000000..c50c0fdfd418db3db95401b242e6937e387c7007 GIT binary patch literal 864 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{bx#+^kcv5PuWb}$aO5~* z@b35fnflEKf>>uiczE^<--Iu*{0#3n7+N?-(P#*e7y?U~H|)MH{NT!L$#90im;4N` fSQrisQB=2DgYDOhgG(xaIfud1)z4*}Q$iB}8HB#N literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/points_emit_1_end_2.png b/external/vulkancts/data/vulkan/data/geometry/points_emit_1_end_2.png new file mode 100644 index 0000000000000000000000000000000000000000..c50c0fdfd418db3db95401b242e6937e387c7007 GIT binary patch literal 864 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{bx#+^kcv5PuWb}$aO5~* z@b35fnflEKf>>uiczE^<--Iu*{0#3n7+N?-(P#*e7y?U~H|)MH{NT!L$#90im;4N` fSQrisQB=2DgYDOhgG(xaIfud1)z4*}Q$iB}8HB#N literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/points_to_lines.png b/external/vulkancts/data/vulkan/data/geometry/points_to_lines.png new file mode 100644 index 0000000000000000000000000000000000000000..40460f80e0d4bba0bb23cf503bfad9d3130fc6eb GIT binary patch literal 1368 zcmds1YfO`86h8gRmKL$JV>W7l6=Wrg%oR0&7HQpJTx77wFpkPv)RlBx1ud6V`oXxw z6ern_S%uPOI>Qzw7egu&Yyrh376I!MvYk=x?7LG+nR%P>gSD90T1KPMqeRCcyioi_=5qIp#L4*gTKYLif>AD zmdSuS`yjs8WP3!8vRxv@2`8jd(@o=H$+q^!6#cJ9{OY^25z&jLA`XeK1itABiGz(u zmB2~|R^cRU#`6T}P?2tY?!J7*EETU7O^)yd6(v2woQ0S)S4$GP``c&o;vRK|oM(Qz zz2=m;qbx{2K8$~C#|IKHf!(+}_w?hZpXZ$`BVF&)-09XxPB4~|r1CHMaP@jDHo~Al zJypM<84qp%0|(0r13DWrcVgucNa>I(Gu83Frl43wMlYqc=l4r#dPnA%IT95#)o2_O zq)KtJ)}3{7UV$=q&q(J1v{XF@GrkG*uLIFpb*~IGL>W;bVBwwm9r!BXA719rm(EjR z*zdoCCAt{@XKj^k3Io|MgSTrIvNKZ(myc^gS_O7nAXnuc`eet7#9DAt2~w+Ua(v&k zOE#%)jAWI!g55B9d(CiA>$Zf?)lPf*lf8m}(~LKVLDQ#eHUtk)tqFo#o~e_m zP~Xp(=ZEfDIkskN1N(!%au}7jn>iD-8SY9smY`7QDZt0P+eushHAP!^i)Bn0PWS5mZ?JYDi>8-hwB)+V2C(0nIrD?@ z?9?0s>E5qpa%Epx^juq>dSE1p@0%wyWEbY#;Z0(C>jqEFTBqg`C1nxP&-feI9~gD9 z9o7E#ZT*{+KhFy6p|z{~*ubplpL^T!oC1n#b6SEeX3T}>dezX2r#-q%pD)wF6k)-4 zuD1{!i^kr$qe44Ba|FX(1~8pJQF%A;UO%*JuW*IAx*A6_h)tgJws2NGp(7PqMQg$) z@VZ?I-Fq!~wU-FZp7u-;#vw$o9uiS@`KG}a@^|1rPu_-m-``t&uYz4#h3Jo3X{xs3 zfzcOK5S}RL86TW-=xC(5?NRfmOBr-8^%i`cnhl+!E?t6G7ttmuUPSk;p7KbRf_vX3 zue$4egyn_?Ab~$tC?zEdc|Z^ts;wMjI~5FZPmZcB;j95kmj&O9fCPaOlheU#1pY;D zA$rAX0(LG8T6|qxs@v9#AEUtKJpq1sY+n*Lxs*2(HZE4i5gQXylQI&ozALKx3p*I= ARR910 literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/points_to_triangles.png b/external/vulkancts/data/vulkan/data/geometry/points_to_triangles.png new file mode 100644 index 0000000000000000000000000000000000000000..69caa8e562473c3b80765cd7c0a5c30dce3d8410 GIT binary patch literal 1484 zcmds%?N3v86vxlKec*y+6cmOaQbAERQ3;e5AB(oZ3hO%5Y=mly1B5tf6=>?n=%wAL z0t;j)aSk0*oOKaI>y(FfR+wbjYTKb~Whh*lI0V!p<3X{myJi1?FZOD$&M!H?N00{|hP2w-%wNDk}s0BChWe#$OY!;=RCg?D+2Dt?W3zLNG! z#7(t5x~8SJVd;2<-*SEJ3}-`6Pg-nl9Ir{*d=qJmKyVofx2T};1?ob;Vt|&xCT)(b1B-=f=>>t0D5wgtMK~95Z`{Zd#uA2P$!{q5{&bjfPZ+nRr^T z*3TUcb*gG}uxBfej$q4tjm}KmcgbLwTR>ICfHpZyIljfk#I2_{JxGgp8*OZ_`cD^q zx3dlyL^}0T&AS+B2|R^6e36_qIjY^#D)3r^(NkbMK|(Ec55GlT#P}v?`d`B`>yUt= ziC7mcv^sla2Wr1!=zglE5<54e#Xk#e5mcE%q%PYE>vLP%wNRW+)xQJu7^eF;6kBV( zL_Dfq0Q41p5|SmG@DfF#67tXS5KT#mG$-y1E!6V3TkdeJfW#uD!vx%*5$}re%+VEK9DQ&0ocGElLD6hn8n%VixxZgE8xDp|fN&}fkljgJJ z#^K&s0koa=QO_;&MoNCy#Ub7KFWAK} z-Mty{JLtQ_H7VYki|>3HXa3e+58@Mu>#KSCj^;SC(tZXM3%W@ra+LXC{pXhpQlYKy zl6K436Kf&uPh|pMcCTC=0}8^@S`)@baDPL?WT|AHEZo{MeXhlG9)rhWN7`&muPhWY z`GU|-wlRU5J(V&P<=u#A8i|utH1mM)Phh-?M(_Yjkmh{O{b!g__V0#&1ESgY+pTR( QCz;Y96o~jOTV8X0MFdk?>ibgKlyKX+VanA z{6E{MKsb*Af_x6v6-(!^+l5OO7 zd^~KZC){9otv&Bg!5nYagr0i#{67V2EWg!vu;)E0GG};D%EE968Tr-ou&jT0^QM$J zgOZJPv@%0WMcFrdMulUWH=k!|P&j|?pAf?$8*Ayq$qF9D%=AkE6ecxr0y3SJdjJ1( zn`bgH-O>(6<~d5&w==ZlNN)SMox|bG=0@rIeg>Acymx=hW>I+c`9bgg>^{S?I(fEt khj>xL2syk48{3XSpOMG#?c3Mcz|76y>FVdQ&MBb@01?>|F8}}l literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/primitive_id_in.png b/external/vulkancts/data/vulkan/data/geometry/primitive_id_in.png new file mode 100644 index 0000000000000000000000000000000000000000..ca373920c4cce474389faf1100c54e4ad1f838ab GIT binary patch literal 2026 zcmbuA{Z|uL8prR9112DlA=m~e0zsh^R^w9M7n5RA#HuK`f`*p(QY_knMMMNiCUrqr zg0uxHMIbr#U^q~LE{7)djfvRA;!CLPma_;ZI$Pm1xFKa}2OBec^B-)_{`9?fp6By@ zzW1ED=hpAsk>TSN|M{KP(S2p_1>P zI2mE8Uoz*r^zoU$SDTkxlGqRGuAlGwbDl1HOpS`4TjsI=F9U?N0g(V9WGFCT;3GD` zxPTQ2INSb*!r(RGk4+`EF$p^O`kmQ0bnr_%b<)e~h2%Y09Bu%I*<|TE1Nm6eX7Jh1 zr)P8*Oh`XYyxSoiW*z$rh6>^OW&7#&L=y;HUmF!GpG%YlWW0NoG=*scVZl3 z|B(Uvo?@N1x`rj@65&5JF^*h5$wtTDzUmOl#aPl7aOH^5WfJ0uFNY|8-pDvg^6S7} zOw-_^M#iGU8o=v`<<2!86%x?iPMwtF)$9OE(X&GN$KJjO3)S^xye?aD*<9c#UmE2JO`Rbpp0^&j0H#B#e=MLl zuA$MQTzPKRInhJV;#ZJHN7dTIR{bxNgxcA(q%wNkSaU32orun zFhPSBK3W!mTJGUQwwNduTZPXoUZ-nxeiKUFDsvf1j};NV<-v=qk9UE8cVO?$jcpj1 zk?*~C3e_L?*WeU0IgPw3!Fuk~Oq>GVK%{r0%l_0AM8@4%PfCo;L{Jnl(BY{kX|;3% z=&l1=9%KJul_;7|h8vlwD{i>rJK7>mbr-V&nT@s?^xBhJ;(+t;mkRgzur7ysC>L5Q zWk$s#xf?(OnfNMCO#se1;GBFG43me!|F&>IO5{#+-Z#-g-LGtGj8=J>rwB=Q0}1<` zONTrlkk{duY<(F5vR%f4f(8~vJMRB!`s>&y5=hPOxZr8Za^6!y(s6o^yi9E{N|_&H zgP;0p5z5R5eMLN|5g_IW2kKhT*X!P|12KK>eI)3++G=aKHYleo4PgF@(LXjSgy>*% zt#`b8UU5+DKj>fAfz)1o9%Z=z=6i3JHYyb8;E-Q2OC>x5)+T*ZNSVVyv~T|uJ;V}y znrKUK{R#c}>G{@RMI^GNtZG?@IYN|SZQS4Ul>Pq4@Bby{L(QD44>@2{SV>CX3WD4aL#)%Jiavjck+Q4}=rTRt2GLOvZIB_jv2y;0s@vJjv&q zobx%~Wv0@LV5xK$g8XL&jS!*B!G$&VQK%Q1wgvDTEBD8vBA~(sRNd>l**lX z-(oycLOCDnYx?D+DyLy~I-@G%)uM-d6@15L{C*lRuGZO@V^#JQWDZpemPWA~Kx zq%|+#pm?P!abk5XQkgji^J@!>;w8`QhA*K&Vsk|{so$p9y1NuhXG57Mn2Pe7D3tuC z1%hL7D7m8vd}E~MMv1oR%0}b0H;CxnWR%0<(Xp6k)A;dZl%RK!8fO^)Jb#|Be;tsN zf5+p4{W4TB2PU;J@M#)TtY>;@9JswjEMW&|Ja=0jOJ|+WTC*nkbDi#8(+r)P>S-$!5Tt3?{uGl}x zH;=BzOlv;pa2jJ~9gPp|iHIR`d>3u?o#Iqmik%H51c7r>l3#Ita_sUS}aCff~TS&AwJM;>t zRS}vV%09&ha=?((ZBpWK5>;h~w4Aog4Xt6FH7c_agSlOD8mE(}_69}cr%AN`lE{4| zN_bD?aT4XZ3@ksll!_8vUImT6w7}6HeoI#iU&OO7m7Ze4ZWFA1ZX=zJ2PC#p>BH7& zM8PNvQV9RzyA8~bwNbGqa)_92x!K0@>p4*JL4kzx6%prVbCT48H=dn7aGD7RP0(`m z1=8vJDxck5csxrjB&LbM6X*0*g1O^m@x%b;!#a`GVD7YvtO4_p=S0?ldA)R~d1>oP znc$_^!otRn!$AWaY5!H%?=VR|b8S8IdNh*EY~Su_^e?*Lk7edgIu=N4YtguZcDxBG z<(?LQP{F*T8vcoYk^FGU)w#_v0N>k3+WiNUnG2&uxat&6q9!b$c;r7h_tNT9FWm3l S=-e&-vrt`W)DP>dJ%0nsMh7SW literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/triangle_fan.png b/external/vulkancts/data/vulkan/data/geometry/triangle_fan.png new file mode 100644 index 0000000000000000000000000000000000000000..720b717e93201b63fbdc697912441d813af73ec5 GIT binary patch literal 2197 zcmd6p`B&4&8pbEd7YIbe$PyM6lxlh{R$0XWB~(J7h!SKMNN`~hE(TcwhUJSCkjoOW z78Q_05!q?9a!mjwM1)pl5fA|rKtM#0H7r3&XuN;H{pFr>f0{YxnR%ag<~e6Rlj(Y# ztg51`0sv5TaM4Kk$z|= zZ*OEu%LmkORHd8GV5Xhf!c})@`n7MN?zT_1UTT1s3y6mhFbxTsA#hn4KC|#zT`nmaOH2M>@}}hy0YI7yHl|r2Fp(V<^$1%ATU*NZ;-X^NPnB z^hY4d6L4JJl)B{PvPhzN!w@37-qk^FHT{STSK$T*{RN`m0&F5IyJr#QjkF=s$h$U_ z_P}liDEYpE(x%ELe86(Lg;Vhwqsty`BxNpL61e;=(hwwH;-MgYnoGXF9rIQ~ZLT2XBybU}h8uU3L z8Mr4n(9K8vH=$>(`N520+wTPVwC)y&wvcLP&|8C|y?*xaRFh&?l=IvQ+y3!ZVwjeN z5kC>Y@mPfShO%IGJ6aP9_ZeM`!|wxvs&dfSfT0HyAC`khLCw!DL?WavTO4sZaBtdN zVxG0+PvXqRsdVy{mTun1q?6P7n!)wU0WiZstk1Qar9SW_5VF|8#)wHD>94i2sT9*q(|Lcp9E9@=JR3)Ab3?n{n)3qOfo~OG@K`%W)T@Pq z_Zl92SenOTy6-q(B9CZ^AG!IL#F+K3??{TAx^)t5Wm-*FX?2?(9L!J_-Xu4B+(prE zkTw^m@j0mrBqdJWhv#N4Jy$R6l<7!Bc`ogW+hpfVyY!o*bZGvRC3v`3tVKjlItye%?m_HE(hRSaz_t z#F6io0EQ~Ir_JWrHa&gXigmpW9uY7}?JryPS;zz@Ad?Oke>rX3KTYBEQ7CC3oW6XY z!zam@e!trqjdLlHN){*^pLc#yzgCW&4$mu0Npcr!xX1X3SY$Y-qwz)k-KhLYAPT%A zey`0t9xcDn2DmaeiBS}q~aUBh6qBz;QDelf;#VC!!lp$~CL0Mi_ z^3369b!;0xD&%d%Qwp_q+#HTwI01f`3=6~{q-P{2`WBEo4(|a9jw)VQn7ZFqlsfXV}jQlhG6R zITaf_;g7@RRxR(v@3=M*x7z|>1ddb!a7{3r!KoxeGCrgtrG~c40JL83I|Gq$BhO;JXpYpx7c%e zwtk1vk}pI{Q_r_jhlRyGQ8zT?YKAdy}x|cBu8DcW&n)n@``EjnFU?2m;Z%*6lnFgba(n?lYpn? zo%KYk;EBJik%CV~^8|?Ybz4n)R(zEmu(&8(SwGwHO2UWWlm2V}J|Cb=RFcc`cgh72 zjs&i+4Ohe{3o<5-_k|WT>P4h01hAd}>djM=$Cu(Ks9_}picLoGYpY>b64?>(@)a%(ts+>XW=r{5L zwRoUUAC;fLT<%uXwecCMCWF|KvqA32`LwzdbqiaCO)fQc`|?Zsw>(NMO)I{{;6}Th z>u_|jK*cQXTJ@?m7+XXODon0fZbeL9mp2vY(7G4s_is;mVCbBWk5%zQ|2Q@? zX9a)!<)7DebYetd5Dg#3gxqkO*D6g-rg*l2rd=7~%ZcVw+1Z3yn>f{xqnTby<|Q3} zl#dOif`sO_fTqDq_ud4Z?Tt)!{z}w@(3z>?=;cl0DJ+XHdjT!jx*fMxP^wd5eX1mP z{p42&)9`b%$nLorSY}c}7A6m|6`1XcKfu|>JYU^Q> nji-3behg?9A^tZc-@wU!*4){2#HU35-2hIcb(k}lE({!}v literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/triangle_strip.png b/external/vulkancts/data/vulkan/data/geometry/triangle_strip.png new file mode 100644 index 0000000000000000000000000000000000000000..c4fa315b0f30582e4e61584518c66484de2358d4 GIT binary patch literal 2107 zcmdT``#Y5T7GLk{WrkeFW$!%*vrU-Yu|qm;g%NT~XtQ%SuI0F#o=QZScR0ChLfNI{ zGPWJbb?dkrhS8HyJWuVZPA;Q3YLm$=gyy{M|6u=ke)@jb^Q`q*pU+zBS>JEA=P@S* zISn}gP;hZ}I1YdiR|Lp1#1VMrZWI6+b#busPAYjn@v8Yvt1{Ee__{oDF+A`_A1{W}v3U%$)nHWc(7szl4FDDlm=$*BHV3|IdttWf(ajQAjMF z>v+7f{JSGB-r`L!UGmy1Gb(zlI{MT6dSf@W-Kz~8w2E80l4I&ydNX@k+9mSFu0>8b zJ>4`;GMG@cb3*lx&Wgf)i1WeS0ku*|?QXVMH(l+iFen&f)CGWUBWgx(T9b&+X;Ivt zf5jBqJxZQ9EsV^EM5UL)y{vbM;+}YFO$z8LjkJ+VE*-*0GU}i?&s#X35fZdarbIX8 z9g=hCjHibB5}>lP!rk!kDf1ZiQdj1wwGw{5 zDSS)$Y z3lEEbNjiO!mTIlqw3brfRpW#g-61DAaEmLDL91hajhcBHJ?O^nDuy6o)r&TiVDF)) zg9J~~S(_e?MP)K0W??TIzRA-_{hC%e8Yd{PmC8&@`l+HCF@3S}nsRxjW=L8zcsot> zZs-#E#fmj@-0u7=I#%qlJ$)wv%q&%z%8^p1KYH;s(hL}yxKKzJnQ-J>NvxbU>7{eC zQcY{EG{KX?>q^X+8(Yux;9yb!#X}F+uaW}_`sT8S;-pjC65f)^8jgb5C@j#F4n3}v z8Vi3r{YZO9oqtu2H*5QqwH4H>$NH{p01UfgtQAeXUWIYb0sKv8KDgfkko>q80!VCb z@p0tTW4@s443cCZ<9%X3_>iW0oNX?cdWKE4TJ^qeT{UWn`sAw%E_G!wFFJlP*}j;( z8p<{Jpie)tcT=6I?_=92(m)F)p3q14_nV^y%+YoA{)32feTs*aLw`)gCD!oy6Wm2AI&5sd)w`Kcexsk2u=*l0HkeT)&73a9O0V9GJ~aqq{uRLCEeJwL}Vp)(;_(799dVB*D0Y9-C_Mbd_Y%u~ zIZ@O}(&y6YIYv1$J~DX50Lgk1RLa3<_+#ZMWn`G0`YqT|Ll$Y^(k?Jf1FZS)uY0w( zIeI8%q|M80GFKNKwZD2=2-vw9FDAvp9@2_!QZFmVN*|lackg?;nq_hE;9!K$SuKS8 zkIx%xvL8$Q4{SeI!I^pTDODzxJ5}_IC3R5K2Tnw1td9}YN9!ny1R?8$-SWwXC|s6hvOF$Tj?V4n-xJxOl<^;&1Y-|rpj2?7 ze8Qi+K-)d~qX?UH+B5GQt8m}mZk>YjKPsmD+r;wB-1(wjVk>c*^Dc9q5Jk&5zb<~T zEYUzI-a^~YGUmh_7|t_Fui#mMPM|Vur7v?x5h3rJzZcTgC4j< zYN?73WDy{PR(rLj!&GsH=DeT8SgsqW41EbKtC^iha6Rl6aQVTswxX0t?pb8%0>;Xs z3&e|T9fU=;FHHyIT=IYcjJxhx)C2iQez+=RsB+pd{1sWSgW+z}k2f)V*g}??56sY3 z^z5yU7GYIQi%}Ogm8j^iMUbS1#n7A1q9$ahuFqTUvrAm>y)g>ZVP>X2l(bsD?onnK zBHUe-w+rF4LgIP>hR3%axfqxI&rP-x!mYhyVm4_a3q@zD^Bv*s;@e7`G5!VAe`9Ju z7smU8Y-NmOLhp9$bf6pCf*X2LevK(PU_2t!sk>|c^I9i++L$sC!7Gg5EoxtsVVe7i zbNw2-NCYxZpcePGIe6XgOT%CylIIr1TQtS+Z-p7(EpsDziy^XK20(u0ecr9PM~ amX2WIO_TS(O5YQo0&sCW=Fo7MmG(b6j%7ap literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_0_end_0.png b/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_0_end_0.png new file mode 100644 index 0000000000000000000000000000000000000000..fc45c5022ddb5f6c6d023d3104c385823a054467 GIT binary patch literal 854 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{Sx*(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_0_end_1.png b/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_0_end_1.png new file mode 100644 index 0000000000000000000000000000000000000000..fc45c5022ddb5f6c6d023d3104c385823a054467 GIT binary patch literal 854 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{Sx*(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_0_end_2.png b/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_0_end_2.png new file mode 100644 index 0000000000000000000000000000000000000000..fc45c5022ddb5f6c6d023d3104c385823a054467 GIT binary patch literal 854 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{Sx*(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_1_end_1.png b/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_1_end_1.png new file mode 100644 index 0000000000000000000000000000000000000000..fc45c5022ddb5f6c6d023d3104c385823a054467 GIT binary patch literal 854 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{Sx*(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_1_end_2.png b/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_1_end_2.png new file mode 100644 index 0000000000000000000000000000000000000000..fc45c5022ddb5f6c6d023d3104c385823a054467 GIT binary patch literal 854 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{Sx*(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_2_end_1.png b/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_2_end_1.png new file mode 100644 index 0000000000000000000000000000000000000000..fc45c5022ddb5f6c6d023d3104c385823a054467 GIT binary patch literal 854 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{Sx*(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_2_end_2.png b/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_2_end_2.png new file mode 100644 index 0000000000000000000000000000000000000000..fc45c5022ddb5f6c6d023d3104c385823a054467 GIT binary patch literal 854 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{Sx*(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_3_end_1.png b/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_3_end_1.png new file mode 100644 index 0000000000000000000000000000000000000000..1faf7ca5c982919c47b1434a7447e51858d43da8 GIT binary patch literal 1206 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJEiT2B|pkcv5PZ$uZ}HV|NN z)cU@E^QVa+H~nsIRQ<@9u*=_J;tj#9{M*~^nk&4#ewCjg#+^aIXA}+U5IFSi`|q;- z_t)3)=&3LSzGshT*~OypVsoQ-+L- zEpT1n$RPIpltTA`UvC)1wtoL`i+jyU-ULVYKgGLw*LX6B6+c8UNaFll#n3 z-UOw^{QtL|{n)cdu)*_;NrbU&_FM*^gkz1fKF;iZ!@#!fl)z2yp3}Su0jqibZ(I8{ zI!u{?IjS%r?2oUuK*PZ`HX7Rhw?*D$&!my`#^-ac@0}KDp*?ZvU9R|O&AN!x(o#W5o_oSizytUPIhB-$L{}ZLzw4Fl$Auc2Eq46=sMoK|z+RB>{rOzE!+Z(ud@n8Euzq{Ywn6xC zz1;gMd!`M{?4N4x{j_6w;L7)?bkFbWHyLeCK9ug>d!YCZ!@Pta#~;tOac7WwvY_|$ z_R2X7HU}7`=jVTsux^kqSn(`H|AVc0L%zhn%AaNTg&Y1CG(3AQ{ck=)&B23_?fE}V ztsCksbh0;#|2V<>K=$x{yZb+s8GoEU_~OIb`y2elF{r5}E)%Z*M#R literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_3_end_2.png b/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_3_end_2.png new file mode 100644 index 0000000000000000000000000000000000000000..1faf7ca5c982919c47b1434a7447e51858d43da8 GIT binary patch literal 1206 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJEiT2B|pkcv5PZ$uZ}HV|NN z)cU@E^QVa+H~nsIRQ<@9u*=_J;tj#9{M*~^nk&4#ewCjg#+^aIXA}+U5IFSi`|q;- z_t)3)=&3LSzGshT*~OypVsoQ-+L- zEpT1n$RPIpltTA`UvC)1wtoL`i+jyU-ULVYKgGLw*LX6B6+c8UNaFll#n3 z-UOw^{QtL|{n)cdu)*_;NrbU&_FM*^gkz1fKF;iZ!@#!fl)z2yp3}Su0jqibZ(I8{ zI!u{?IjS%r?2oUuK*PZ`HX7Rhw?*D$&!my`#^-ac@0}KDp*?ZvU9R|O&AN!x(o#W5o_oSizytUPIhB-$L{}ZLzw4Fl$Auc2Eq46=sMoK|z+RB>{rOzE!+Z(ud@n8Euzq{Ywn6xC zz1;gMd!`M{?4N4x{j_6w;L7)?bkFbWHyLeCK9ug>d!YCZ!@Pta#~;tOac7WwvY_|$ z_R2X7HU}7`=jVTsux^kqSn(`H|AVc0L%zhn%AaNTg&Y1CG(3AQ{ck=)&B23_?fE}V ztsCksbh0;#|2V<>K=$x{yZb+s8GoEU_~OIb`y2elF{r5}E)%Z*M#R literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_3_end_2_emit_3_end_0.png b/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_3_end_2_emit_3_end_0.png new file mode 100644 index 0000000000000000000000000000000000000000..b493c289bb6843b02414098b9f468d6762d93b29 GIT binary patch literal 1552 zcmd^<`%hB`9L2x4x0IqZbSj}xq%0(`_+UjI79+F@T9JoDMwy0N6;mVi@cjRx_7>vgCI+71K-m6cXO1`eq_q!ze$)jwnV>GMrazBwo7hjSz~ zMaWp;w*mkd3A^I=0wAsv0Xofv%#yP?0B(Z`@!LL=>8JkcKH0yUsp*R-9wBS*sB`5_ zG518jYDm5J%Abqx_w1RF(nHhRyqOaj(>^d41k5A|)PaDDD8&@GMFq77P*(#z_HNHtY^~20qsq;u4&NcrJ^W-3smQ5T zVV=}udC#KC&Qih8uY4sFn!}xG^U^t+VHJGymBwb6NrT{UXFqoOmhlpTZ_8m5>kwt! z1Kv_P1&`nP1u0oetdoHKQoTFbL&MkXR5%S>mj*X}+w=jg5liW2(Bbq~q_h(I8dbWB zTpx(I=w>6a-V3V*Jo&r};ouPdVa<91ERlAef535`3dHXBUgA^ zg!Gy$^CNc79?+?6g>j(HfA)BaZyA~$_anZg1`doP|12A)hfA(ydSclW=HD$U&PEE2 z^shVT_v)vXdP!Bsygf#~Rzq%$QZf~1>@n>~Cl<;UC^Ouz-{D&18)-%_HvZgF`eS38 z2aBj!O2&7rjqDgS^h~sD?H5Ah>DlcPs3zJ+n@x~Em9hH-e*tnR@93=R$!XYeWbfiFV7AnZ#pg(1^iHJY~L4+vf`f>@qAd73^5$&%&L7Cqum8t5(5s8PM5Et z^qxS981jR(UR47jF}s;1D6igTG_^%Hg8m+Z(B&QqMR-Tpi=`JHmFkg*mpK*MgQ_ce z!0;s&u4(c;1VIJEFRq@Rq6^T1p%>Sh^LZ%mc*C5(*{voUrf!g? znB4*{BU{Ce@v)nVBzRqfn*LPC8e!OacVE@QOq2vhuI_vMGSj-AjfZHka?1+?)ru7y t^|!q8qNEm7$6IFkdPKlw{}*d49 literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/triangles.png b/external/vulkancts/data/vulkan/data/geometry/triangles.png new file mode 100644 index 0000000000000000000000000000000000000000..ebfe79a633040b810ba9e6aedac0c66b472a47e5 GIT binary patch literal 1443 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJFNEKe85kcv5P?_TV?Wg*dU zG2rd*{YKTHrKfmU)0~oiTf47XwYNLy|9s{{vrli!z0T|LtMnTy!*f9f4q+Oj-|ydW zOC0_BY`^~U7*-i=$%fmB?W=qk;v}nf+l$V8&%k3^GmVqsL!=hNc^lS>pam+T4Y|e- zJ_PD99FRZBaHpE zY-c!Q_Ga8dm-W<(3@o@89W`j>nf3=v5TN3|hr-bEKGHpn>f8I8YzrBV< zB6H)p4Ug+n&#g`?$>%qd34{q;>X3^(R8d%yNzd2lglOT;^*Y(<~-4@Ek}e76Zk% zL<_U`97hJWq!U0-`Z!2bh%-v`BtG|GGEfkFpuuEdVfbJ!OG3bAzJFh)zX~A=3 z`(5cTk&i>4=rH(iT)qCJJA<6jpVvYRazzQ5u}lYodA`kJX}H^Qq=uzox#Wkh91Qw` zjaxYwb_=vwax&-}zj-adu+Np{ngYY084_o_8GdY&WdHx`AwM7U#trqlZ+>3-DhFh; z?7s2+2gd=SxSJQ>{;THzhB3qG4V(A-F+`kN%+Yb=J`2MkmWHP{p3YZi(0RFqz>vX{eM~fqeBtfPoD3n$9sWCJccC;#kdquC ztprB6n~X}j_%$U4o0J#VpIW1M9^|y;z(|&3e4yG^qYHM}X_<(qc7_kSY<0X$2l_h? t?qO-jH~#VYbCLkZXBMC|)4_yPa` literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/triangles_adjacency.png b/external/vulkancts/data/vulkan/data/geometry/triangles_adjacency.png new file mode 100644 index 0000000000000000000000000000000000000000..14e87ed902a8a5d2c64f6b6a6d34bdc36a178864 GIT binary patch literal 1445 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJFN98VX=kcv5P?|K*A_7HGz z%t(4ypL*_8V!zHm6`|Mzr)?bdL)JU8dH=Yv?d>K;&;M)e7&i1VILsgy-PpgHf5WZk z^__npl>LOU54;!m?2(B-c`&603?Utfbkz%(v~5A{14c6@xeJ%(Z1+j5p84ZDK>i~Qix z(f;Unlfg$uWjFU5UFil*9$RhI{me6t91_yzJix#3??+D>oXb5k@(=pWH9AmI=}qv_{C1s)EPL0@uJ(d48h|3decvr?ewvg z-E%zpKDR;XoOQgvjpwrMpS^tO>+77$=Z@BTW!i<&N-oob&yyj%!|1HB9Xko`FaUx-(IHN?? zt3#KzeEwiu$93ki%L5x7X2%)*ppeCfrp2-S`m_JNy6#RNJL%^WIS*VBFUYz5W^-ZQ za=rsk4pu$O$*aHj6qGcKE!uh(1+ypIe#ZB0@$*?#b>|*_VVrTMU~`lbL-74w%&S$I zHslt!--#}d&=hVs$z!#836sIswbmQFv>0xil|R^9+Adne_~Y^x#o1+Y=kz5Rn!i;o zt}osBi=nyFkmLTRs|Wl!UWeD8dF^j{ePuagMX!6_chSS|pZ&6Ae6VU||JU<#PQ9&< z{$$P2cQ#;uA49>_C#|Z26}*fOmT|_vsl8t4zfYd=!3Lfm=Q$b5ed8j88s`f#$Ze{+ zFu!!o<#oyoGV>Du+c7>!oGd==*_Tn_s}k_#j%XE#Y40v&}p#iSrl~ zd^TLE1j^?>K zC{&m;HW)BU9PmA_#bj{gIY$RmwE#%DSBi=0|^WFoZ`& zSlQoa1ZMPttBbeqy8V9#OT%oQ?>jjeT7Z57O6oH{P-Oc%2b7B%+JSta$2Hsj#Q^!B kI477_@aLpqDf^qB<3-Gi@3oQ-fWmdKI;Vst0L>xb0ssI2 literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/triangles_to_lines.png b/external/vulkancts/data/vulkan/data/geometry/triangles_to_lines.png new file mode 100644 index 0000000000000000000000000000000000000000..6a43f3dfbb959b54ef7b527e9f3fe05283e790c4 GIT binary patch literal 1350 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD%UQZXtkcv5P@1D)O?Iz(6 zxa!64{YJYpnxfXNnV+F@_QSl*TuJ&Ijm6KIeY=+D-u}kx@$2wUZ&@Lcz^U;?|hzlXnutigYkQp{x|P_ z@AKdM`~07oMLPcM3C|`MPhVVrSh?RN3nzqbCyKr3e)dEc5J_}Nd6J#NC? z`GGMkE#Sb3==nH*A}I8LC_(X9y&J@aV)Y05o9}mSzxCt)*J;nD_U%@aWZ=KvQ~LJv zmLJc{elXnmU2yhIn&q>_HS_+wzQ9^F1pEjDr`QWfk%whGJ3}Q*&(@n$~6@3`Q62Cteg*lh;Sbdx;gMtqTsipsUJ{2f& zhwF^M{rpU`t!o?^)XX0{?fUws$y{fxGsBLT6Yt(N?cU14U> zvlFBL{1;@HmTvgp66`(?!+-O^A!zjG-+y(e(JB)E^+AFSM|b4Uo_L4T!mzuR=kfpZ zED1v2?bfPs^>6-Buf`z%t=jQ^@uXWPC43p|&NMxn4346RmXGtp1wfivZ~Uzkg(m44 zbAX~kpybeY%Y3```Xh52glE_O`Tz1KD`P}EgHO(~qwlXq9amwv^W}t!(eEpVEUz={ zIN4;U$Cx0o`+pTQ02>s0{%3gTe~DWM4feM{pZ literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/triangles_to_points.png b/external/vulkancts/data/vulkan/data/geometry/triangles_to_points.png new file mode 100644 index 0000000000000000000000000000000000000000..281a37c9006b3ac48ee00c0b3324fccec3664d5b GIT binary patch literal 1036 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJFd%bqTdAr*7p-gfM}Z6Ltl zsQLf@=As+keA&v4Q&rt#zcL-%aLYNlLhg8>tiz@CSNR#%C^HDC(H7~)td?h}J5c#! zo%1wKhC@P(29FMWmtj=UF=S-8FU-J!9W@-*Qi%;~R6N7NkjR7^c{6Qz{qAGw+g~Z~ z&(>s>J*Rr=Y9udm^N%&sXysAZ!yP#V`UW+m$`N9e{3YsGLu2U2RriE^!M9QH3guG zA04}yHqT^`cyG0D--$ogK-anBjHJYz+(Px)4Zv`C@bS-~y=n~HKa>9Ph_}WSvosh8 z;|ffM?VBUb+8J_kUUjE@E#q5#0Hj}cKi_#!aN^blj2-!nZdS8lkpPT`;g4?QGks5( V>pe9-0GP`eJYD@<);T3K0RXS(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/vertex_count_1.png b/external/vulkancts/data/vulkan/data/geometry/vertex_count_1.png new file mode 100644 index 0000000000000000000000000000000000000000..fc45c5022ddb5f6c6d023d3104c385823a054467 GIT binary patch literal 854 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{Sx*(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/vertex_count_10.png b/external/vulkancts/data/vulkan/data/geometry/vertex_count_10.png new file mode 100644 index 0000000000000000000000000000000000000000..9cac87ee267605108acc50df0afb5b97049142a6 GIT binary patch literal 1694 zcmchY`#02S9LJyUcLp<>5am)X6GPIBMi+^S!a);FB|~XU4Awb0G_x*6ad^(1*R}yxe>6p1JpgBtPprOK}a|Zq-by+ z`>#&SB~631jx_bWbEK{dEfUo8EDpUuEBKX3GgaQ5(SW;hA;<_Q;toQ|@7GE$!T!}S z`K(rEt`Y_6!|PhJ{Ft2nS;H_@f(ot zeNn6xoMp{6hA;yX!{{0{4xd%|+cCHiU#_r+4cb_2I|xI7i@kxdjh?w5*cI~q6Fj)@ zh0u(UGZ@&%2#M#G(p2Yj6d3}WzCpTc!DnG?>2=S9C2yR+Miu?#!4XI^{XQ@+p+xDk8x)Ot)IR$`h-WH z3U#>Ml+GH-Oy8l#kyq?XTzNVEVxSe$@K!1iGoR>A>`s7u=~thlD5Evw8$mYelM*Jk z4KACA-8ovn0krSeCpJ~}f?#Wnz@`Ep$xW@NWv+j@c`D$N>M2rzocy~Jt)z1ru@+@A zM8eEl%lEyhkyzEShN5$7d%Au6LE=^v@afg8%>JOz$2KqE6ntqDbCbps@!l~}nNGNK z%nD(0i+UVj#o;7H^ZCVH-wSmLhNwme)3_w08dfOu=Ya5oeRj!AH;#`hk9xE&!O@b&HfF34Cdo9_^HuIpflK4V9yH!pSs_AE z<_r<7&fpE%;x!OPGF*BkMy{r)F`;`t4J`pFXFNV2LMjy7U|9^yido zB?lgyL?czflj3hgEKMBIVCeo&Xe6#_BE^C&BfRuKh2{SNWc&$Bh@X7` literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/vertex_count_11.png b/external/vulkancts/data/vulkan/data/geometry/vertex_count_11.png new file mode 100644 index 0000000000000000000000000000000000000000..9cac87ee267605108acc50df0afb5b97049142a6 GIT binary patch literal 1694 zcmchY`#02S9LJyUcLp<>5am)X6GPIBMi+^S!a);FB|~XU4Awb0G_x*6ad^(1*R}yxe>6p1JpgBtPprOK}a|Zq-by+ z`>#&SB~631jx_bWbEK{dEfUo8EDpUuEBKX3GgaQ5(SW;hA;<_Q;toQ|@7GE$!T!}S z`K(rEt`Y_6!|PhJ{Ft2nS;H_@f(ot zeNn6xoMp{6hA;yX!{{0{4xd%|+cCHiU#_r+4cb_2I|xI7i@kxdjh?w5*cI~q6Fj)@ zh0u(UGZ@&%2#M#G(p2Yj6d3}WzCpTc!DnG?>2=S9C2yR+Miu?#!4XI^{XQ@+p+xDk8x)Ot)IR$`h-WH z3U#>Ml+GH-Oy8l#kyq?XTzNVEVxSe$@K!1iGoR>A>`s7u=~thlD5Evw8$mYelM*Jk z4KACA-8ovn0krSeCpJ~}f?#Wnz@`Ep$xW@NWv+j@c`D$N>M2rzocy~Jt)z1ru@+@A zM8eEl%lEyhkyzEShN5$7d%Au6LE=^v@afg8%>JOz$2KqE6ntqDbCbps@!l~}nNGNK z%nD(0i+UVj#o;7H^ZCVH-wSmLhNwme)3_w08dfOu=Ya5oeRj!AH;#`hk9xE&!O@b&HfF34Cdo9_^HuIpflK4V9yH!pSs_AE z<_r<7&fpE%;x!OPGF*BkMy{r)F`;`t4J`pFXFNV2LMjy7U|9^yido zB?lgyL?czflj3hgEKMBIVCeo&Xe6#_BE^C&BfRuKh2{SNWc&$Bh@X7` literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/vertex_count_12.png b/external/vulkancts/data/vulkan/data/geometry/vertex_count_12.png new file mode 100644 index 0000000000000000000000000000000000000000..9a627f1b13a5d14673d9e5dd8135479648718fe1 GIT binary patch literal 1894 zcmcgt`#aNn9RGZ`VK^;^ic?EYMG8ZX5;NXek7Xo)VT zi!`~!;&DqWEnO_-&@9G|F0$M*#%Mb87xbLxIZr>m-_QH@dfu=1^Ss_C1N=$zj20UK z0OtAnYzYJa(zy^o>+1|H{uUDe0|(zN8+RsM9Foi9SGX=Xw&OydHbO=d@v>IU?rpB9 zzAG)hW?L42b3i4-IHWC(x@ZtEP%c9P6&frs1GY9GU_1CL4-lOpI1&NGD3EFRzb0l< z)nN4t^RH?7YxNqa(ExXTX;=qJ@uV$vqR3k^0_Fw2Etp|wt#wMLz zNM6dQB8`x(+Q6<0XI~->yIS{Va~+Aw)5-g<`WIIaIXn7#<^;Cnuh$Z(Ol zGex_j9W`i0c;Xo{#>|s$3NPhP%VWPrOsEoS)Geyl5r`Kxp=JcBm)HZ>Xr~#bU%GkR^MOP8TzO~Lb0jaViM#N~QK#+# z#_Z8SC8-ChVPw~5!M3BASPhzYNNCg0=M^Op_)bPaK8=jS-c}C!*^Nq;pX3>L++LK~ z>pu3$@LuS_8a4at;dm$eu#zDX(rN4P?T&#%nd#Wc*EE4N$5opI0_7WgL2;Xx^^4lL`;bnLhn6IC#2RO;C`R&Hj#&3xB>+q>wm*O9Isrtz>uDhA z8qb)*aRTy{6kcW&O5rt^4l6Am-l1p>-Z1X+ctn^!5p&?#;8SU?R|m>UldL8&>oxl~ z=I{rl+n-ALUDX)k*y#)SE(d`DKk3Em`^Xr#N0rL%J)Q141e}kOHd*4nKB9{No(Au_ z*^VS*sXxNI=2z%~8`dCnq*r!(@a`(RORn0?RpbTrf7l!Zf<5PEyt{2AvZy`99#OOw zvvW#u;7XyqWUmUpucLPLJW=ub5+u3d&EBkv4=w`7+>{y{PMLEh>+QktD|%DglrB>O z_UX@^zwrik~lM&l+|Y{+t|pYABQ1m$|$&+b7`+==&Y(x})V$YRCh z@tz5hsZ5E8dp>AgpjDM09A!nEgF=RG`sJ->=+n#B&N25=z^*8I18CdA8g7IV*rP13 z4k+Xweg6XI{g#bIbF25focxfl&F!huyy#br%aSfO5shoA1B7qSxtnL--e7zuvz^-7 zUORPpIve<6L;B<>D<5Sz%Yd)82FCdndlscq5GKs`-r>pWV1$V+=g+|YzGTFmJQ>+- zre76?Fxgk-9loDFYYiR*o?pYkoiT%tt#qKb+2bkTVdDQzbHSn6adQmPyH?}a_js*@tJhfd(S=pd@w~^*;eF3Ouz+2CZ_ zO~T-lg=~%&TC}pf&ahXzC{^7&k4^@GdX8aA^OAS;3L3)cm3+xMH-un#mos%d5#b~& zT{1Q-!8@A}j0QJ?ht`g7s$|U8i>cx(Ge?9{6u^uc6yS-fz%l2>IY zT7K5tj#J$ts6-QaBrl^IING(p#l4zKq$5owDc3XG^0E3Ekp#pyWf!a8*M*y(&I zVu^xd&3@+?0*Y|zlS*tA(BknOl>d8tm;Z>NMT&39HFZHh=jr|@@b&iJQnqP##=pJV B8!Z3; literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/vertex_count_2.png b/external/vulkancts/data/vulkan/data/geometry/vertex_count_2.png new file mode 100644 index 0000000000000000000000000000000000000000..fc45c5022ddb5f6c6d023d3104c385823a054467 GIT binary patch literal 854 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{Sx*(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/vertex_count_3.png b/external/vulkancts/data/vulkan/data/geometry/vertex_count_3.png new file mode 100644 index 0000000000000000000000000000000000000000..fc45c5022ddb5f6c6d023d3104c385823a054467 GIT binary patch literal 854 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{Sx*(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/vertex_count_4.png b/external/vulkancts/data/vulkan/data/geometry/vertex_count_4.png new file mode 100644 index 0000000000000000000000000000000000000000..fc45c5022ddb5f6c6d023d3104c385823a054467 GIT binary patch literal 854 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{Sx*(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/vertex_count_5.png b/external/vulkancts/data/vulkan/data/geometry/vertex_count_5.png new file mode 100644 index 0000000000000000000000000000000000000000..fc45c5022ddb5f6c6d023d3104c385823a054467 GIT binary patch literal 854 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD{Sx*(P#*azz~oxQDXW(IVG$gm|qw?UHx3vIVCg! E0PwDVApigX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/vertex_count_6.png b/external/vulkancts/data/vulkan/data/geometry/vertex_count_6.png new file mode 100644 index 0000000000000000000000000000000000000000..09a4b8169388546f4c350097205008513b93818b GIT binary patch literal 1181 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJEi6i*k&kcv5P?*``Ga$s=1 zSa|f`_BVAdqP(h0JZ8-NF>iB2M%_Kx=72rDhTj-f{?4jpNRVS}Fd!FgIQ@qCOxbV! ziQ6@oH&_NS{&@F)zO=pRa=r#}xdX|||M5MTDSh{?|HYNe3^rxI7D-JNiHEPpi8V}3S7R!;?>(QP?$sHVrd8W(S!UQ8D!13~ zwPDac|0a&5rE!z znW^9@pzpx(u;u;y`<hAhZL!&Qdw0vPhF=!j-rFpYF*u79vDYTQJXXCpQ@^iDV8W+pWWLR_N z!c0}shH7VHyHi1o63KTD-k+C!wYW%cC&QoItrORl$(_@eWN>cgzYUbTf10V?%Z`yj zo`vBM6;MLq?+?$!`if`PGOXj7TQ1z-IZtx8xnz-uJfngSgIeM0%}k6Da{>xf7-yW= zG1Hepty+Y!@j(U?Ln6}#26NlZ90!#0loh!4G&4BNV9+_T_WbVL!~Pc(PYW}&aE>Cf cLf|i3a=Ag)ZkN0=V6nsC>FVdQ&MBb@06b=R_5c6? literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/vertex_count_7.png b/external/vulkancts/data/vulkan/data/geometry/vertex_count_7.png new file mode 100644 index 0000000000000000000000000000000000000000..09a4b8169388546f4c350097205008513b93818b GIT binary patch literal 1181 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJEi6i*k&kcv5P?*``Ga$s=1 zSa|f`_BVAdqP(h0JZ8-NF>iB2M%_Kx=72rDhTj-f{?4jpNRVS}Fd!FgIQ@qCOxbV! ziQ6@oH&_NS{&@F)zO=pRa=r#}xdX|||M5MTDSh{?|HYNe3^rxI7D-JNiHEPpi8V}3S7R!;?>(QP?$sHVrd8W(S!UQ8D!13~ zwPDac|0a&5rE!z znW^9@pzpx(u;u;y`<hAhZL!&Qdw0vPhF=!j-rFpYF*u79vDYTQJXXCpQ@^iDV8W+pWWLR_N z!c0}shH7VHyHi1o63KTD-k+C!wYW%cC&QoItrORl$(_@eWN>cgzYUbTf10V?%Z`yj zo`vBM6;MLq?+?$!`if`PGOXj7TQ1z-IZtx8xnz-uJfngSgIeM0%}k6Da{>xf7-yW= zG1Hepty+Y!@j(U?Ln6}#26NlZ90!#0loh!4G&4BNV9+_T_WbVL!~Pc(PYW}&aE>Cf cLf|i3a=Ag)ZkN0=V6nsC>FVdQ&MBb@06b=R_5c6? literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/vertex_count_8.png b/external/vulkancts/data/vulkan/data/geometry/vertex_count_8.png new file mode 100644 index 0000000000000000000000000000000000000000..ab83eec0ed255fd51afe13fad6923dfc4cfc8586 GIT binary patch literal 1447 zcmeH{Z!p^j7{{OdE7H=GVp~gf$fk?P?T$LkSsRNikrmx!8LDdRbpEs{NhyA;r?=}) zI@&}IiDN}}mYEzCEJ7C+^|wo??u~bQx4X~X^E}_@?z!iA?z!jd zGc1}t{tY|;*wZ7Z(Euo`ivrtyRugx*F$DmZL8rcdmS43p)01(8MhNSPx@EC^u1jVM zeZ{9DScb0eKVv*M9A4vS;aXfy z;{f()FvGC=QMfJ`81~%{u&^0_0yaW${OB4lXQY)B*d^KzYccPF^gSFusD}8uRSRx% zc2Lub!=i#fDCxKY6OO2LJxFjzWHtvg?mh09NnxGLCd&;n1Fj-> zvY_ouW~OOmA15ba={(9Ruo4>cQY#6>;q_Yrc+z3aFTYRiKaI}njqctiFUyCqey<#} z`n?NZgm-T548Cjzri$4>9vfFK@)w=dANws--+UXbUvCjWr=Rg1@|1I`j^pl*XhnLd zOImMPWJOVZLkOz9s@re@OD&4!YiS5w)S@YtN?Z`_#h0Gw-;yZl?!z173W&Y7{Hx&H z;tHp4#Jp-c=YYovE^FNKD}F2}?c{3fhc#Cv+gOU0SCD5J@a7Vc>YcAVDwTDL7$Uqy znzFMT94xa_b2fZOOT86;=*#fx_CI;;Zrg1t={?Jq1ZeArW? zRa`1%0G?opvD z+r~^fgtY3&Td~~8YB4t%O%aEuiq7t43hv<59ImT*E-q%_Z;}$aPNr+?hwg8cq1vC< zMw+udf1lHMERQh!k2}UJ%pRplahv5b-l&Xwsf`Ks?y8?Q^|!Yi5}(y6Fbw@|J9V;4 zWqdTMJ#~!a=`DjMe_oFpJLyIos9N&0IhOofYu%~Z`1Az1r}YYT;*AAzYuALJbo<_N1iK_l7@TGMI;wt80yE=w>ZX zIMb6T(a^xw35lG3Bo2cTC%l9X0WH&dB2?x(ql%tR?w)xf@N#nwA;&{M2s_Njp%4n{ zwO`_;vBo5VS+wCQK;i`om>#O04MD3Lj+$A9K!^DN7bph{Mb5P?91ojVxD zf+MUZjg5Hi#?wPZca662XVTKhn?TT62f2#27XP1rZJ^l#E}y3DEZkLoXMMmx4`)&3 IrxJ_*0RbQ{8vpo??u~bQx4X~X^E}_@?z!iA?z!jd zGc1}t{tY|;*wZ7Z(Euo`ivrtyRugx*F$DmZL8rcdmS43p)01(8MhNSPx@EC^u1jVM zeZ{9DScb0eKVv*M9A4vS;aXfy z;{f()FvGC=QMfJ`81~%{u&^0_0yaW${OB4lXQY)B*d^KzYccPF^gSFusD}8uRSRx% zc2Lub!=i#fDCxKY6OO2LJxFjzWHtvg?mh09NnxGLCd&;n1Fj-> zvY_ouW~OOmA15ba={(9Ruo4>cQY#6>;q_Yrc+z3aFTYRiKaI}njqctiFUyCqey<#} z`n?NZgm-T548Cjzri$4>9vfFK@)w=dANws--+UXbUvCjWr=Rg1@|1I`j^pl*XhnLd zOImMPWJOVZLkOz9s@re@OD&4!YiS5w)S@YtN?Z`_#h0Gw-;yZl?!z173W&Y7{Hx&H z;tHp4#Jp-c=YYovE^FNKD}F2}?c{3fhc#Cv+gOU0SCD5J@a7Vc>YcAVDwTDL7$Uqy znzFMT94xa_b2fZOOT86;=*#fx_CI;;Zrg1t={?Jq1ZeArW? zRa`1%0G?opvD z+r~^fgtY3&Td~~8YB4t%O%aEuiq7t43hv<59ImT*E-q%_Z;}$aPNr+?hwg8cq1vC< zMw+udf1lHMERQh!k2}UJ%pRplahv5b-l&Xwsf`Ks?y8?Q^|!Yi5}(y6Fbw@|J9V;4 zWqdTMJ#~!a=`DjMe_oFpJLyIos9N&0IhOofYu%~Z`1Az1r}YYT;*AAzYuALJbo<_N1iK_l7@TGMI;wt80yE=w>ZX zIMb6T(a^xw35lG3Bo2cTC%l9X0WH&dB2?x(ql%tR?w)xf@N#nwA;&{M2s_Njp%4n{ zwO`_;vBo5VS+wCQK;i`om>#O04MD3Lj+$A9K!^DN7bph{Mb5P?91ojVxD zf+MUZjg5Hi#?wPZca662XVTKhn?TT62f2#27XP1rZJ^l#E}y3DEZkLoXMMmx4`)&3 IrxJ_*0RbQ{8vpLT~|p96$TO1lYrPwCjj{`}@22*`|01&+na{|9xt<>&?j6y7vd# zZ#DjC#$s1}+Bf&>nH2w6IDujg5$FH-yBqNK9o<~&`^j_vLt^4xsyey1f=Jmrcn0*sQg4tJ~M3_AWrJLCUP@>Gf z0Yzu_WhgzYI1Z(k6$hah%pZo5VEzc$5Sl3+q)*GFAW8GB*wRv(Vc{O;$8j&3?pu=X zpa{N1?;b?$MO8XEx1Ao;VSY_uPoQ)rdN&3?8$1_8XC~5*@@h&=qr8DqlPIsH)HtjL zN{zzmq*NZ|T1sV6Rw*@zay_NE?;wZ!I&!$*O3pakMdXaaT|rJB?j~}waCeb22rEcV zKP;K#X;|w?o`j{5%=fP*neV@x7n>K?ME;4-pva6@F@hFeee2;3$rPQz`bB0rHr{si0(^7-m+@*P|Y2cA@+v8CK8 zg=6e|8@>&dezSBd`3bzNlcaEA70*nQB&8p%;AtMFTKKW{KmZrk$0GPN(90P19vVuc z)RxTiHY9VrE0b4w?<7ZfE0S5>{^T(4l4OQ=G%5TdQ~0bY{9;r1geiQ^6n@qeUNVL6 zGKIgW3;$dfzDgH9t_z>hg@2_BU#SZp(}llM5b{Mq7!<^6xFFs~W^<*v$9+HBUb6+C gE7Gd;Z-#q8+V!yVe6At$o&UZNk0qjo?vt1P04QUF0{{R3 literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/vertex_out_0_geometry_out_1.png b/external/vulkancts/data/vulkan/data/geometry/vertex_out_0_geometry_out_1.png new file mode 100644 index 0000000000000000000000000000000000000000..f071c179e488612f57e97a18edf2fcfbc3f84f16 GIT binary patch literal 1103 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD1F;5rAkcv5P?|SA*JBqL# zoc8c{d}LgtK??7Z8)v1A9&za%On)&RuwY_H97RNizJD_qx!Efm5@)z<`0u$O!?L75=T#Ye4*!_%&tSIk*Zca%^3Dtr=YAX)WN0(`w~?hG zv8UdKF@fXp{APxngssdAKAv}GsL*;mznkHM$uWC*#s```^?pnTp7zwoF>Tm!lfU7Z zy*c9pqht2=j1Pp4?Pp_rP;zWPALE0NWBbJzBW~odJ3Nl>XDHx$96y=igTdqY=?otP z9>>pS_>g>Tza3-5l@~xO-a9hvnEmm+GsBMVkMCU>cFg?v-ko7b=g0S+3}Rp2fE0K$ z{FwCdy)VO$DIeeaGyItF(VT2U;W3{xO`B;h4M{L*cRe zY7E?#zZo+Aa5zl)SS-UdA?42>RR+Uj=l8QH9Qje{&mi{k1>=PuKRXy$B<$x4Hk_5T zj~8s{m9)Pv*x)N^zg?h#^-eW|NnM^Q!)(L4cZv+sKoZC{sH<~gFiZIJX9|PQyWK$7 zedb_{nDOzm24e)!9yZ2^2_K7rUhnx>tj0Lw#&4j4Vl&2wmXF1(j1dhVi$xh{%=uWn sbo%38|7WwPJ>_ON#4?ItA@GmkUV)(DE8dMoz=DFo)78&qol`;+0ND#s%K!iX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/vertex_out_0_geometry_out_2.png b/external/vulkancts/data/vulkan/data/geometry/vertex_out_0_geometry_out_2.png new file mode 100644 index 0000000000000000000000000000000000000000..f071c179e488612f57e97a18edf2fcfbc3f84f16 GIT binary patch literal 1103 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD1F;5rAkcv5P?|SA*JBqL# zoc8c{d}LgtK??7Z8)v1A9&za%On)&RuwY_H97RNizJD_qx!Efm5@)z<`0u$O!?L75=T#Ye4*!_%&tSIk*Zca%^3Dtr=YAX)WN0(`w~?hG zv8UdKF@fXp{APxngssdAKAv}GsL*;mznkHM$uWC*#s```^?pnTp7zwoF>Tm!lfU7Z zy*c9pqht2=j1Pp4?Pp_rP;zWPALE0NWBbJzBW~odJ3Nl>XDHx$96y=igTdqY=?otP z9>>pS_>g>Tza3-5l@~xO-a9hvnEmm+GsBMVkMCU>cFg?v-ko7b=g0S+3}Rp2fE0K$ z{FwCdy)VO$DIeeaGyItF(VT2U;W3{xO`B;h4M{L*cRe zY7E?#zZo+Aa5zl)SS-UdA?42>RR+Uj=l8QH9Qje{&mi{k1>=PuKRXy$B<$x4Hk_5T zj~8s{m9)Pv*x)N^zg?h#^-eW|NnM^Q!)(L4cZv+sKoZC{sH<~gFiZIJX9|PQyWK$7 zedb_{nDOzm24e)!9yZ2^2_K7rUhnx>tj0Lw#&4j4Vl&2wmXF1(j1dhVi$xh{%=uWn sbo%38|7WwPJ>_ON#4?ItA@GmkUV)(DE8dMoz=DFo)78&qol`;+0ND#s%K!iX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/vertex_out_1_geometry_out_0.png b/external/vulkancts/data/vulkan/data/geometry/vertex_out_1_geometry_out_0.png new file mode 100644 index 0000000000000000000000000000000000000000..f071c179e488612f57e97a18edf2fcfbc3f84f16 GIT binary patch literal 1103 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJD1F;5rAkcv5P?|SA*JBqL# zoc8c{d}LgtK??7Z8)v1A9&za%On)&RuwY_H97RNizJD_qx!Efm5@)z<`0u$O!?L75=T#Ye4*!_%&tSIk*Zca%^3Dtr=YAX)WN0(`w~?hG zv8UdKF@fXp{APxngssdAKAv}GsL*;mznkHM$uWC*#s```^?pnTp7zwoF>Tm!lfU7Z zy*c9pqht2=j1Pp4?Pp_rP;zWPALE0NWBbJzBW~odJ3Nl>XDHx$96y=igTdqY=?otP z9>>pS_>g>Tza3-5l@~xO-a9hvnEmm+GsBMVkMCU>cFg?v-ko7b=g0S+3}Rp2fE0K$ z{FwCdy)VO$DIeeaGyItF(VT2U;W3{xO`B;h4M{L*cRe zY7E?#zZo+Aa5zl)SS-UdA?42>RR+Uj=l8QH9Qje{&mi{k1>=PuKRXy$B<$x4Hk_5T zj~8s{m9)Pv*x)N^zg?h#^-eW|NnM^Q!)(L4cZv+sKoZC{sH<~gFiZIJX9|PQyWK$7 zedb_{nDOzm24e)!9yZ2^2_K7rUhnx>tj0Lw#&4j4Vl&2wmXF1(j1dhVi$xh{%=uWn sbo%38|7WwPJ>_ON#4?ItA@GmkUV)(DE8dMoz=DFo)78&qol`;+0ND#s%K!iX literal 0 HcmV?d00001 diff --git a/external/vulkancts/data/vulkan/data/geometry/vertex_out_1_geometry_out_2.png b/external/vulkancts/data/vulkan/data/geometry/vertex_out_1_geometry_out_2.png new file mode 100644 index 0000000000000000000000000000000000000000..43eee1c59cfad61697b4a6ab239283d1cb6e5ef6 GIT binary patch literal 1814 zcmeHI>r;|>6#l(0s2G}QtEALcTiOmmYMAB~O0z6AD{DD-?4%$aA-oO3xPd9(XG zzj*)v_k=BRI{|=D7XmnE)a=U9v-?jOD5e;bf3wk`s=z5*;r1j}v$dJu%LV9OX%((HsdT%hDg|HoiZ^+MWa=4)!R1GVWOJ96yIL8?oFOi%;p>@P1@86Q`YjQssyIL>j;pi?cT&QpAj-zfQ zdo?5&EUtQZ#{{#h3)<$geeIzO5jn-Em1x_=L#mKdD#n@X;%M?lKni;gvom!>&h4mC z@d?whWuStX4XwXbtPY{de1Py!on$yc?5(@F$YLYk<-yKCOS@E7G9c3;2jGa+HDREa)tzH z^-jauZDo(Ai1rVzbpFYFqxqT-k~D$uG)Z-5&VkgUA8Q;-b%&(Mj^W8JkD3x3onLn` zU!)ogpNN&I{o$1Qk^PRaW?kgWeePD;alZgikzVFBJZUM~MGLiNtOVZq!(&9k5EL@^ zrFK_LurX5s$!QFKsZTMEemFh@tZ4~cKe<{~lL$y(2bYW!ZQl(yGTe9( zkl;;`!X8UDXDWgj-;-_ZEC@{vIt^<^H4W}GhZl0C!#1DQQmo#gj!HEjQ2qd?T;r30 zizr+p$abf3T}(;`4#%C0^WURXGF0S;4yI2wAT+3NQ3aw*w&bI zb58vwkjkpZOLx4y?? + +namespace vkt +{ +namespace geometry +{ +using namespace vk; +using tcu::IVec2; +using tcu::Vec4; +using tcu::TestStatus; +using tcu::TestContext; +using tcu::TestCaseGroup; +using de::MovePtr; +using std::string; +using std::vector; +using std::size_t; + +static const int TEST_CANVAS_SIZE = 256; + +GeometryExpanderRenderTestInstance::GeometryExpanderRenderTestInstance (Context& context, + const VkPrimitiveTopology primitiveType, + const char* name) + : TestInstance (context) + , m_primitiveType (primitiveType) + , m_name (name) +{ + checkGeometryShaderSupport(context.getInstanceInterface(), context.getPhysicalDevice()); +} + +tcu::TestStatus GeometryExpanderRenderTestInstance::iterate (void) +{ + const DeviceInterface& vk = m_context.getDeviceInterface(); + const VkDevice device = m_context.getDevice(); + const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); + const VkQueue queue = m_context.getUniversalQueue(); + Allocator& memAlloc = m_context.getDefaultAllocator(); + const IVec2 resolution = IVec2(TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); + const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; + const Image colorAttachmentImage ( + vk, + device, + memAlloc, + makeImageCreateInfo(resolution, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT), + MemoryRequirement::Any + ); + const Unique renderPass (makeRenderPass(vk, device, colorFormat)); + + const Move pipelineLayout (createPipelineLayout(vk, device)); + const VkImageSubresourceRange colorSubRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); + const Unique colorAttachmentView (makeImageView(vk, device, *colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubRange)); + const Unique framebuffer (makeFramebuffer(vk, device, *renderPass, *colorAttachmentView, resolution.x(), resolution.y(), 1u)); + const Unique cmdPool (makeCommandPool(vk, device, queueFamilyIndex)); + const Unique cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); + + const VkDeviceSize vertexDataSizeBytes = sizeInBytes(m_vertexPosData) + sizeInBytes(m_vertexAttrData); + const deUint32 vertexPositionsOffset = 0u; + const deUint32 vertexAtrrOffset = static_cast(sizeof(Vec4)); + const string geometryShaderName = (m_context.getBinaryCollection().contains("geometry_pointsize") && checkPointSize (m_context.getInstanceInterface(), m_context.getPhysicalDevice()))? + "geometry_pointsize" : "geometry"; + + const Unique pipeline (GraphicsPipelineBuilder() + .setRenderSize (resolution) + .setShader (vk, device, VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("vertex"), DE_NULL) + .setShader (vk, device, VK_SHADER_STAGE_GEOMETRY_BIT, m_context.getBinaryCollection().get(geometryShaderName), DE_NULL) + .setShader (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("fragment"), DE_NULL) + .addVertexBinding (makeVertexInputBindingDescription(0u, 2u*vertexAtrrOffset, VK_VERTEX_INPUT_RATE_VERTEX)) + .addVertexAttribute (makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, vertexPositionsOffset)) + .addVertexAttribute (makeVertexInputAttributeDescription(1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, vertexAtrrOffset)) + .setPrimitiveTopology (m_primitiveType) + .build (vk, device, *pipelineLayout, *renderPass)); + + const VkDeviceSize colorBufferSizeBytes = resolution.x()*resolution.y() * tcu::getPixelSize(mapVkFormat(colorFormat)); + const Buffer colorBuffer (vk, device, memAlloc, makeBufferCreateInfo(colorBufferSizeBytes, + VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible); + const Buffer vertexBuffer (vk, device, memAlloc, makeBufferCreateInfo(vertexDataSizeBytes, + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT ), MemoryRequirement::HostVisible); + { + const Allocation& alloc = vertexBuffer.getAllocation(); + struct DataVec4 + { + Vec4 pos; + Vec4 color; + }; + + DataVec4* const pData = static_cast(alloc.getHostPtr()); + for(int ndx = 0; ndx < m_numDrawVertices; ++ndx) + { + pData[ndx].pos = m_vertexPosData[ndx]; + pData[ndx].color = m_vertexAttrData[ndx]; + } + flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), vertexDataSizeBytes); + // No barrier needed, flushed memory is automatically visible + } + + // Draw commands + beginCommandBuffer(vk, *cmdBuffer); + + // Change color attachment image layout + { + const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier( + (VkAccessFlags)0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + *colorAttachmentImage, colorSubRange); + + vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, + 0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentLayoutBarrier); + } + + // Begin render pass + { + const VkRect2D renderArea = { + makeOffset2D(0, 0), + makeExtent2D(resolution.x(), resolution.y()), + }; + const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f); + beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor); + } + + vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); + { + const VkBuffer buffers[] = { vertexBuffer.get()}; + const VkDeviceSize offsets[] = { vertexPositionsOffset }; + vk.cmdBindVertexBuffers(*cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(buffers), buffers, offsets); + } + + bindDescriptorSets(vk, device, memAlloc, *cmdBuffer, *pipelineLayout); + + drawCommand (*cmdBuffer); + endRenderPass(vk, *cmdBuffer); + + // Copy render result to a host-visible buffer + { + const VkImageMemoryBarrier colorAttachmentPreCopyBarrier = makeImageMemoryBarrier( + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + *colorAttachmentImage, colorSubRange); + + vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, + 0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentPreCopyBarrier); + } + { + const VkBufferImageCopy copyRegion = makeBufferImageCopy(makeExtent3D(resolution.x(), resolution.y(), 0), makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u)); + vk.cmdCopyImageToBuffer(*cmdBuffer, *colorAttachmentImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ©Region); + } + + { + const VkBufferMemoryBarrier postCopyBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, colorBufferSizeBytes); + + vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, + 0u, DE_NULL, 1u, &postCopyBarrier, 0u, DE_NULL); + } + + endCommandBuffer(vk, *cmdBuffer); + submitCommandsAndWait(vk, device, queue, *cmdBuffer); + + { + // Log the result image. + const Allocation& colorBufferAlloc = colorBuffer.getAllocation(); + invalidateMappedMemoryRange(vk, device, colorBufferAlloc.getMemory(), colorBufferAlloc.getOffset(), colorBufferSizeBytes); + const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), resolution.x(), resolution.y(), 1, colorBufferAlloc.getHostPtr()); + + if (!compareWithFileImage(m_context, imagePixelAccess, m_name)) + return TestStatus::fail("Fail"); + } + + return TestStatus::pass("Pass"); +} + +Move GeometryExpanderRenderTestInstance::createPipelineLayout (const DeviceInterface& vk, const VkDevice device) +{ + return makePipelineLayout(vk, device); +} + +void GeometryExpanderRenderTestInstance::drawCommand (const VkCommandBuffer& cmdBuffer) +{ + const DeviceInterface& vk = m_context.getDeviceInterface(); + vk.cmdDraw(cmdBuffer, static_cast(m_numDrawVertices), 1u, 0u, 0u); +} + +} // geometry +} // vkt diff --git a/external/vulkancts/modules/vulkan/geometry/vktGeometryBasicClass.hpp b/external/vulkancts/modules/vulkan/geometry/vktGeometryBasicClass.hpp new file mode 100644 index 0000000..4154eab --- /dev/null +++ b/external/vulkancts/modules/vulkan/geometry/vktGeometryBasicClass.hpp @@ -0,0 +1,66 @@ +#ifndef _VKTGEOMETRYBASICCLASS_HPP +#define _VKTGEOMETRYBASICCLASS_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * + * 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. + * + *//*! + * \file + * \brief Geometry Basic Class + *//*--------------------------------------------------------------------*/ + +#include "tcuDefs.hpp" +#include "vktTestCase.hpp" +#include "vkTypeUtil.hpp" +#include "vkRef.hpp" +#include "vktGeometryTestsUtil.hpp" + +namespace vkt +{ +namespace geometry +{ + +class GeometryExpanderRenderTestInstance : public TestInstance +{ +public: + GeometryExpanderRenderTestInstance (Context& context, + const vk::VkPrimitiveTopology primitiveType, + const char* name); + + tcu::TestStatus iterate (void); + +protected: + virtual vk::Move createPipelineLayout (const vk::DeviceInterface& vk, const vk::VkDevice device); + virtual void bindDescriptorSets (const vk::DeviceInterface& /*vk*/, + const vk::VkDevice /*device*/, + vk::Allocator& /*memAlloc*/, + const vk::VkCommandBuffer& /*cmdBuffer*/, + const vk::VkPipelineLayout& /*pipelineLayout*/){}; + virtual void drawCommand (const vk::VkCommandBuffer& cmdBuffer); + + const vk::VkPrimitiveTopology m_primitiveType; + const std::string m_name; + int m_numDrawVertices; + std::vector m_vertexPosData; + std::vector m_vertexAttrData; + +}; + +} // geometry +} // vkt + +#endif // _VKTGEOMETRYBASICCLASS_HPP diff --git a/external/vulkancts/modules/vulkan/geometry/vktGeometryBasicGeometryShaderTests.cpp b/external/vulkancts/modules/vulkan/geometry/vktGeometryBasicGeometryShaderTests.cpp new file mode 100644 index 0000000..291ec43 --- /dev/null +++ b/external/vulkancts/modules/vulkan/geometry/vktGeometryBasicGeometryShaderTests.cpp @@ -0,0 +1,1181 @@ +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * Copyright (c) 2016 The Android Open Source Project + * + * 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. + * + *//*! + * \file + * \brief Basic Geometry Shader Tests + *//*--------------------------------------------------------------------*/ + +#include "vktGeometryBasicGeometryShaderTests.hpp" +#include "vktGeometryBasicClass.hpp" +#include "vktGeometryTestsUtil.hpp" + +#include "gluTextureUtil.hpp" +#include "glwEnums.hpp" +#include "vkDefs.hpp" +#include "vktTestCase.hpp" +#include "vktTestCaseUtil.hpp" +#include "vkImageUtil.hpp" +#include "vkTypeUtil.hpp" +#include "vkPrograms.hpp" +#include "vkBuilderUtil.hpp" +#include "vkRefUtil.hpp" +#include "vkQueryUtil.hpp" +#include "vkMemUtil.hpp" +#include "tcuTextureUtil.hpp" + +#include + +using namespace vk; + +namespace vkt +{ +namespace geometry +{ +namespace +{ +using tcu::TestStatus; +using tcu::TestContext; +using tcu::TestCaseGroup; +using de::MovePtr; +using std::string; +using std::vector; + +enum VaryingSource +{ + READ_ATTRIBUTE = 0, + READ_UNIFORM, + READ_TEXTURE, + + READ_LAST +}; +enum ShaderInstancingMode +{ + MODE_WITHOUT_INSTANCING = 0, + MODE_WITH_INSTANCING, + + MODE_LAST +}; +enum +{ + EMIT_COUNT_VERTEX_0 = 6, + EMIT_COUNT_VERTEX_1 = 0, + EMIT_COUNT_VERTEX_2 = -1, + EMIT_COUNT_VERTEX_3 = 10, +}; +enum VariableTest +{ + TEST_POINT_SIZE = 0, + TEST_PRIMITIVE_ID_IN, + TEST_PRIMITIVE_ID, + TEST_LAST +}; + +void uploadImage (Context& context, + const tcu::ConstPixelBufferAccess& access, + VkImage destImage) +{ + const DeviceInterface& vk = context.getDeviceInterface(); + const VkDevice device = context.getDevice(); + const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); + const VkQueue queue = context.getUniversalQueue(); + Allocator& memAlloc = context.getDefaultAllocator(); + const VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + const deUint32 bufferSize = access.getWidth() * access.getHeight() * access.getDepth() * access.getFormat().getPixelSize(); + Move buffer; + de::MovePtr bufferAlloc; + Move cmdPool; + Move cmdBuffer; + Move fence; + + // Create source buffer + { + const VkBufferCreateInfo bufferParams = + { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkBufferCreateFlags flags; + bufferSize, // VkDeviceSize size; + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // VkBufferUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 0u, // deUint32 queueFamilyIndexCount; + DE_NULL, // const deUint32* pQueueFamilyIndices; + }; + buffer = createBuffer(vk, device, &bufferParams); + bufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, device, *buffer), MemoryRequirement::HostVisible); + VK_CHECK(vk.bindBufferMemory(device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset())); + } + + // Create command pool and buffer + { + const VkCommandPoolCreateInfo cmdPoolParams = + { + VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCommandPoolCreateFlags flags; + queueFamilyIndex, // deUint32 queueFamilyIndex; + }; + cmdPool = createCommandPool(vk, device, &cmdPoolParams); + + const VkCommandBufferAllocateInfo cmdBufferAllocateInfo = + { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + *cmdPool, // VkCommandPool commandPool; + VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level; + 1u, // deUint32 bufferCount; + }; + cmdBuffer = allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo); + } + + // Create fence + { + const VkFenceCreateInfo fenceParams = + { + VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u // VkFenceCreateFlags flags; + }; + + fence = createFence(vk, device, &fenceParams); + } + + // Barriers for copying buffer to image + const VkBufferMemoryBarrier preBufferBarrier = + { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_ACCESS_HOST_WRITE_BIT, // VkAccessFlags srcAccessMask; + VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; + VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; + *buffer, // VkBuffer buffer; + 0u, // VkDeviceSize offset; + bufferSize // VkDeviceSize size; + }; + + const VkImageMemoryBarrier preImageBarrier = + { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkAccessFlags srcAccessMask; + VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout; + VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; + destImage, // VkImage image; + { // VkImageSubresourceRange subresourceRange; + aspectMask, // VkImageAspect aspect; + 0u, // deUint32 baseMipLevel; + 1u, // deUint32 mipLevels; + 0u, // deUint32 baseArraySlice; + 1u // deUint32 arraySize; + } + }; + + const VkImageMemoryBarrier postImageBarrier = + { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; + VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask; + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout; + VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; + destImage, // VkImage image; + { // VkImageSubresourceRange subresourceRange; + aspectMask, // VkImageAspect aspect; + 0u, // deUint32 baseMipLevel; + 1u, // deUint32 mipLevels; + 0u, // deUint32 baseArraySlice; + 1u // deUint32 arraySize; + } + }; + + const VkCommandBufferBeginInfo cmdBufferBeginInfo = + { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags; + (const VkCommandBufferInheritanceInfo*)DE_NULL, + }; + + // Get copy regions and write buffer data + const VkBufferImageCopy copyRegions = + { + 0u, // VkDeviceSize bufferOffset; + (deUint32)access.getWidth(), // deUint32 bufferRowLength; + (deUint32)access.getHeight(), // deUint32 bufferImageHeight; + { // VkImageSubresourceLayers imageSubresource; + aspectMask, // VkImageAspectFlags aspectMask; + (deUint32)0u, // uint32_t mipLevel; + (deUint32)0u, // uint32_t baseArrayLayer; + 1u // uint32_t layerCount; + }, + { 0u, 0u, 0u }, // VkOffset3D imageOffset; + { // VkExtent3D imageExtent; + (deUint32)access.getWidth(), + (deUint32)access.getHeight(), + (deUint32)access.getDepth() + } + }; + + { + const tcu::PixelBufferAccess destAccess (access.getFormat(), access.getSize(), bufferAlloc->getHostPtr()); + tcu::copy(destAccess, access); + flushMappedMemoryRange(vk, device, bufferAlloc->getMemory(), bufferAlloc->getOffset(), bufferSize); + } + + // Copy buffer to image + VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo)); + vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &preBufferBarrier, 1, &preImageBarrier); + vk.cmdCopyBufferToImage(*cmdBuffer, *buffer, destImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Regions); + vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier); + VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); + + const VkSubmitInfo submitInfo = + { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // deUint32 waitSemaphoreCount; + DE_NULL, // const VkSemaphore* pWaitSemaphores; + DE_NULL, // const VkPipelineStageFlags* pWaitDstStageMask; + 1u, // deUint32 commandBufferCount; + &cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers; + 0u, // deUint32 signalSemaphoreCount; + DE_NULL // const VkSemaphore* pSignalSemaphores; + }; + + VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence)); + VK_CHECK(vk.waitForFences(device, 1, &fence.get(), true, ~(0ull) /* infinity */)); +} + +class GeometryOutputCountTestInstance : public GeometryExpanderRenderTestInstance +{ +public: + GeometryOutputCountTestInstance (Context& context, + const VkPrimitiveTopology primitiveType, + const int primitiveCount, + const char* name); + void genVertexAttribData (void); +private: + const int m_primitiveCount; +}; + +GeometryOutputCountTestInstance::GeometryOutputCountTestInstance (Context& context, + const VkPrimitiveTopology primitiveType, + const int primitiveCount, + const char* name) + : GeometryExpanderRenderTestInstance (context, primitiveType, name) + , m_primitiveCount (primitiveCount) + +{ + genVertexAttribData(); +} + +void GeometryOutputCountTestInstance::genVertexAttribData (void) +{ + m_vertexPosData.resize(m_primitiveCount); + m_vertexAttrData.resize(m_primitiveCount); + + for (int ndx = 0; ndx < m_primitiveCount; ++ndx) + { + m_vertexPosData[ndx] = tcu::Vec4(-1.0f, ((float)ndx) / (float)m_primitiveCount * 2.0f - 1.0f, 0.0f, 1.0f); + m_vertexAttrData[ndx] = (ndx % 2 == 0) ? tcu::Vec4(1, 1, 1, 1) : tcu::Vec4(1, 0, 0, 1); + } + m_numDrawVertices = m_primitiveCount; +} + +class VaryingOutputCountTestInstance : public GeometryExpanderRenderTestInstance +{ +public: + VaryingOutputCountTestInstance (Context& context, + const char* name, + const VkPrimitiveTopology primitiveType, + const VaryingSource test, + const ShaderInstancingMode mode); + void genVertexAttribData (void); +protected: + Move createPipelineLayout (const DeviceInterface& vk, const VkDevice device); + void bindDescriptorSets (const DeviceInterface& vk, + const VkDevice device, + Allocator& memAlloc, + const VkCommandBuffer& cmdBuffer, + const VkPipelineLayout& pipelineLayout); +private: + void genVertexDataWithoutInstancing (void); + void genVertexDataWithInstancing (void); + + const VaryingSource m_test; + const ShaderInstancingMode m_mode; + const deInt32 m_maxEmitCount; + Move m_descriptorPool; + Move m_descriptorSetLayout; + Move m_descriptorSet; + Move m_buffer; + Move m_texture; + Move m_imageView; + Move m_sampler; + de::MovePtr m_allocation; +}; + +VaryingOutputCountTestInstance::VaryingOutputCountTestInstance (Context& context, + const char* name, + const VkPrimitiveTopology primitiveType, + const VaryingSource test, + const ShaderInstancingMode mode) + : GeometryExpanderRenderTestInstance (context, primitiveType, name) + , m_test (test) + , m_mode (mode) + , m_maxEmitCount (128) +{ + genVertexAttribData (); +} + +void VaryingOutputCountTestInstance::genVertexAttribData (void) +{ + if (m_mode == MODE_WITHOUT_INSTANCING) + genVertexDataWithoutInstancing(); + else if (m_mode == MODE_WITH_INSTANCING) + genVertexDataWithInstancing(); + else + DE_ASSERT(false); +} + +Move VaryingOutputCountTestInstance::createPipelineLayout (const DeviceInterface& vk, const VkDevice device) +{ + if (m_test == READ_UNIFORM) + { + m_descriptorSetLayout = DescriptorSetLayoutBuilder() + .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_GEOMETRY_BIT) + .build(vk, device); + m_descriptorPool = DescriptorPoolBuilder() + .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) + .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); + m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout); + + return makePipelineLayout(vk, device, *m_descriptorSetLayout); + } + else if (m_test == READ_TEXTURE) + { + const tcu::Vec4 data[4] = + { + tcu::Vec4(255, 0, 0, 0), + tcu::Vec4(0, 255, 0, 0), + tcu::Vec4(0, 0, 255, 0), + tcu::Vec4(0, 0, 0, 255) + }; + const tcu::UVec2 viewportSize (4, 1); + const tcu::TextureFormat texFormat = glu::mapGLInternalFormat(GL_RGBA8); + const VkFormat format = mapTextureFormat(texFormat); + const VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + Allocator& memAlloc = m_context.getDefaultAllocator(); + tcu::TextureLevel texture (texFormat, static_cast(viewportSize.x()), static_cast(viewportSize.y())); + + // Fill with data + { + tcu::PixelBufferAccess access = texture.getAccess(); + for (int x = 0; x < texture.getWidth(); ++x) + access.setPixel(data[x], x, 0); + } + // Create image + const VkImageCreateInfo imageParams = + { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0, // VkImageCreateFlags flags; + VK_IMAGE_TYPE_2D, // VkImageType imageType; + format, // VkFormat format; + { // VkExtent3D extent; + viewportSize.x(), + viewportSize.y(), + 1u, + }, + 1u, // deUint32 mipLevels; + 1u, // deUint32 arrayLayers; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; + imageUsageFlags, // VkImageUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 0u, // deUint32 queueFamilyIndexCount; + DE_NULL, // const deUint32* pQueueFamilyIndices; + VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout; + }; + + m_texture = createImage(vk, device, &imageParams); + m_allocation = memAlloc.allocate(getImageMemoryRequirements(vk, device, *m_texture), MemoryRequirement::Any); + VK_CHECK(vk.bindImageMemory(device, *m_texture, m_allocation->getMemory(), m_allocation->getOffset())); + uploadImage(m_context, texture.getAccess(), *m_texture); + + m_descriptorSetLayout = DescriptorSetLayoutBuilder() + .addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_GEOMETRY_BIT) + .build(vk, device); + m_descriptorPool = DescriptorPoolBuilder() + .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) + .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); + m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout); + + return makePipelineLayout(vk, device, *m_descriptorSetLayout); + } + else + return makePipelineLayout(vk, device); +} + +void VaryingOutputCountTestInstance::bindDescriptorSets (const DeviceInterface& vk, const VkDevice device, Allocator& memAlloc, + const VkCommandBuffer& cmdBuffer, const VkPipelineLayout& pipelineLayout) +{ + if (m_test == READ_UNIFORM) + { + const deInt32 emitCount[4] = { 6, 0, m_maxEmitCount, 10 }; + const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(sizeof(emitCount), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + m_buffer = createBuffer(vk, device, &bufferCreateInfo); + m_allocation = memAlloc.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), MemoryRequirement::HostVisible); + + VK_CHECK(vk.bindBufferMemory(device, *m_buffer, m_allocation->getMemory(), m_allocation->getOffset())); + { + deMemcpy(m_allocation->getHostPtr(), &emitCount[0], sizeof(emitCount)); + flushMappedMemoryRange(vk, device, m_allocation->getMemory(), m_allocation->getOffset(), sizeof(emitCount)); + + const VkDescriptorBufferInfo bufferDescriptorInfo = makeDescriptorBufferInfo(*m_buffer, 0ull, sizeof(emitCount)); + + DescriptorSetUpdateBuilder() + .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufferDescriptorInfo) + .update(vk, device); + vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0u, 1u, &*m_descriptorSet, 0u, DE_NULL); + } + } + else if (m_test == READ_TEXTURE) + { + const tcu::TextureFormat texFormat = glu::mapGLInternalFormat(GL_RGBA8); + const VkFormat format = mapTextureFormat(texFormat); + const VkSamplerCreateInfo samplerParams = + { + VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkSamplerCreateFlags flags; + VK_FILTER_NEAREST, // VkFilter magFilter; + VK_FILTER_NEAREST, // VkFilter minFilter; + VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode; + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU; + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV; + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW; + 0.0f, // float mipLodBias; + VK_FALSE, // VkBool32 anisotropyEnable; + 1.0f, // float maxAnisotropy; + false, // VkBool32 compareEnable; + VK_COMPARE_OP_NEVER, // VkCompareOp compareOp; + 0.0f, // float minLod; + 0.0f, // float maxLod; + VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor; + false // VkBool32 unnormalizedCoordinates; + }; + m_sampler = createSampler(vk, device, &samplerParams); + const VkImageViewCreateInfo viewParams = + { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; + NULL, // const voide* pNext; + 0u, // VkImageViewCreateFlags flags; + *m_texture, // VkImage image; + VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; + format, // VkFormat format; + makeComponentMappingRGBA(), // VkChannelMapping channels; + { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; + 0u, // deUint32 baseMipLevel; + 1u, // deUint32 mipLevels; + 0, // deUint32 baseArraySlice; + 1u // deUint32 arraySize; + }, // VkImageSubresourceRange subresourceRange; + }; + m_imageView = createImageView(vk, device, &viewParams); + const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo (*m_sampler, *m_imageView, VK_IMAGE_LAYOUT_GENERAL); + DescriptorSetUpdateBuilder() + .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descriptorImageInfo) + .update(vk, device); + vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0u, 1u, &*m_descriptorSet, 0u, DE_NULL); + } +} + +void VaryingOutputCountTestInstance::genVertexDataWithoutInstancing (void) +{ + m_numDrawVertices = 4; + m_vertexPosData.resize(m_numDrawVertices); + m_vertexAttrData.resize(m_numDrawVertices); + + m_vertexPosData[0] = tcu::Vec4( 0.5f, 0.0f, 0.0f, 1.0f); + m_vertexPosData[1] = tcu::Vec4( 0.0f, 0.5f, 0.0f, 1.0f); + m_vertexPosData[2] = tcu::Vec4(-0.7f, -0.1f, 0.0f, 1.0f); + m_vertexPosData[3] = tcu::Vec4(-0.1f, -0.7f, 0.0f, 1.0f); + + if (m_test == READ_ATTRIBUTE) + { + m_vertexAttrData[0] = tcu::Vec4(((EMIT_COUNT_VERTEX_0 == -1) ? ((float)m_maxEmitCount) : ((float)EMIT_COUNT_VERTEX_0)), 0.0f, 0.0f, 0.0f); + m_vertexAttrData[1] = tcu::Vec4(((EMIT_COUNT_VERTEX_1 == -1) ? ((float)m_maxEmitCount) : ((float)EMIT_COUNT_VERTEX_1)), 0.0f, 0.0f, 0.0f); + m_vertexAttrData[2] = tcu::Vec4(((EMIT_COUNT_VERTEX_2 == -1) ? ((float)m_maxEmitCount) : ((float)EMIT_COUNT_VERTEX_2)), 0.0f, 0.0f, 0.0f); + m_vertexAttrData[3] = tcu::Vec4(((EMIT_COUNT_VERTEX_3 == -1) ? ((float)m_maxEmitCount) : ((float)EMIT_COUNT_VERTEX_3)), 0.0f, 0.0f, 0.0f); + } + else + { + m_vertexAttrData[0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f); + m_vertexAttrData[1] = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f); + m_vertexAttrData[2] = tcu::Vec4(2.0f, 0.0f, 0.0f, 0.0f); + m_vertexAttrData[3] = tcu::Vec4(3.0f, 0.0f, 0.0f, 0.0f); + } +} + +void VaryingOutputCountTestInstance::genVertexDataWithInstancing (void) +{ + m_numDrawVertices = 1; + m_vertexPosData.resize(m_numDrawVertices); + m_vertexAttrData.resize(m_numDrawVertices); + + m_vertexPosData[0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f); + + if (m_test == READ_ATTRIBUTE) + { + const int emitCounts[] = + { + (EMIT_COUNT_VERTEX_0 == -1) ? (m_maxEmitCount) : (EMIT_COUNT_VERTEX_0), + (EMIT_COUNT_VERTEX_1 == -1) ? (m_maxEmitCount) : (EMIT_COUNT_VERTEX_1), + (EMIT_COUNT_VERTEX_2 == -1) ? (m_maxEmitCount) : (EMIT_COUNT_VERTEX_2), + (EMIT_COUNT_VERTEX_3 == -1) ? (m_maxEmitCount) : (EMIT_COUNT_VERTEX_3), + }; + + m_vertexAttrData[0] = tcu::Vec4((float)emitCounts[0], (float)emitCounts[1], (float)emitCounts[2], (float)emitCounts[3]); + } + else + { + // not used + m_vertexAttrData[0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f); + } +} + +class BuiltinVariableRenderTestInstance: public GeometryExpanderRenderTestInstance +{ +public: + BuiltinVariableRenderTestInstance (Context& context, + const char* name, + const VariableTest test, + const bool indicesTest); + void genVertexAttribData (void); + void createIndicesBuffer (void); + +protected: + void drawCommand (const VkCommandBuffer& cmdBuffer); + +private: + const bool m_indicesTest; + std::vector m_indices; + Move m_indicesBuffer; + MovePtr m_allocation; +}; + +BuiltinVariableRenderTestInstance::BuiltinVariableRenderTestInstance (Context& context, const char* name, const VariableTest test, const bool indicesTest) + : GeometryExpanderRenderTestInstance (context, (test == TEST_PRIMITIVE_ID_IN) ? VK_PRIMITIVE_TOPOLOGY_LINE_STRIP : VK_PRIMITIVE_TOPOLOGY_POINT_LIST, name) + , m_indicesTest (indicesTest) +{ + genVertexAttribData(); +} + +void BuiltinVariableRenderTestInstance::genVertexAttribData (void) +{ + m_numDrawVertices = 5; + + m_vertexPosData.resize(m_numDrawVertices); + m_vertexPosData[0] = tcu::Vec4( 0.5f, 0.0f, 0.0f, 1.0f); + m_vertexPosData[1] = tcu::Vec4( 0.0f, 0.5f, 0.0f, 1.0f); + m_vertexPosData[2] = tcu::Vec4(-0.7f, -0.1f, 0.0f, 1.0f); + m_vertexPosData[3] = tcu::Vec4(-0.1f, -0.7f, 0.0f, 1.0f); + m_vertexPosData[4] = tcu::Vec4( 0.5f, 0.0f, 0.0f, 1.0f); + + m_vertexAttrData.resize(m_numDrawVertices); + m_vertexAttrData[0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f); + m_vertexAttrData[1] = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f); + m_vertexAttrData[2] = tcu::Vec4(2.0f, 0.0f, 0.0f, 0.0f); + m_vertexAttrData[3] = tcu::Vec4(3.0f, 0.0f, 0.0f, 0.0f); + m_vertexAttrData[4] = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f); + + if (m_indicesTest) + { + // Only used by primitive ID restart test + m_indices.resize(m_numDrawVertices); + m_indices[0] = 1; + m_indices[1] = 4; + m_indices[2] = 0xFFFF; // restart + m_indices[3] = 2; + m_indices[4] = 1; + createIndicesBuffer(); + } +} + +void BuiltinVariableRenderTestInstance::createIndicesBuffer (void) +{ + // Create vertex indices buffer + const DeviceInterface& vk = m_context.getDeviceInterface(); + const VkDevice device = m_context.getDevice(); + Allocator& memAlloc = m_context.getDefaultAllocator(); + const VkDeviceSize indexBufferSize = m_indices.size() * sizeof(deUint16); + const VkBufferCreateInfo indexBufferParams = + { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkBufferCreateFlags flags; + indexBufferSize, // VkDeviceSize size; + VK_BUFFER_USAGE_INDEX_BUFFER_BIT, // VkBufferUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 0u, // deUint32 queueFamilyCount; + DE_NULL // const deUint32* pQueueFamilyIndices; + }; + + m_indicesBuffer = createBuffer(vk, device, &indexBufferParams); + m_allocation = memAlloc.allocate(getBufferMemoryRequirements(vk, device, *m_indicesBuffer), MemoryRequirement::HostVisible); + VK_CHECK(vk.bindBufferMemory(device, *m_indicesBuffer, m_allocation->getMemory(), m_allocation->getOffset())); + // Load indices into buffer + deMemcpy(m_allocation->getHostPtr(), &m_indices[0], (size_t)indexBufferSize); + flushMappedMemoryRange(vk, device, m_allocation->getMemory(), m_allocation->getOffset(), indexBufferSize); +} + +void BuiltinVariableRenderTestInstance::drawCommand (const VkCommandBuffer& cmdBuffer) +{ + const DeviceInterface& vk = m_context.getDeviceInterface(); + if (m_indicesTest) + { + vk.cmdBindIndexBuffer(cmdBuffer, *m_indicesBuffer, 0, VK_INDEX_TYPE_UINT16); + vk.cmdDrawIndexed(cmdBuffer, static_cast(m_indices.size()), 1, 0, 0, 0); + } + else + vk.cmdDraw(cmdBuffer, static_cast(m_numDrawVertices), 1u, 0u, 0u); +} + +class GeometryOutputCountTest : public TestCase +{ +public: + GeometryOutputCountTest (TestContext& testCtx, + const char* name, + const char* description, + const vector pattern); + + void initPrograms (SourceCollections& sourceCollections) const; + virtual TestInstance* createInstance (Context& context) const; + +protected: + const vector m_pattern; +}; + +GeometryOutputCountTest::GeometryOutputCountTest (TestContext& testCtx, const char* name, const char* description, const vector pattern) + : TestCase (testCtx, name, description) + , m_pattern (pattern) +{ + +} + +void GeometryOutputCountTest::initPrograms (SourceCollections& sourceCollections) const +{ + { + std::ostringstream src; + src << "#version 310 es\n" + <<"layout(location = 0) in highp vec4 a_position;\n" + <<"layout(location = 1) in highp vec4 a_color;\n" + <<"layout(location = 0) out highp vec4 v_geom_FragColor;\n" + <<"void main (void)\n" + <<"{\n" + <<" gl_Position = a_position;\n" + <<" v_geom_FragColor = a_color;\n" + <<"}\n"; + sourceCollections.glslSources.add("vertex") << glu::VertexSource(src.str()); + } + + { + const int max_vertices = m_pattern.size() == 2 ? std::max(m_pattern[0], m_pattern[1]) : m_pattern[0]; + + std::ostringstream src; + src << "#version 310 es\n" + << "#extension GL_EXT_geometry_shader : require\n" + << "#extension GL_OES_texture_storage_multisample_2d_array : require\n" + << "layout(points) in;\n" + << "layout(triangle_strip, max_vertices = " << max_vertices << ") out;\n" + << "layout(location = 0) in highp vec4 v_geom_FragColor[];\n" + << "layout(location = 0) out highp vec4 v_frag_FragColor;\n" + << "void main (void)\n" + << "{\n" + << " const highp float rowHeight = 2.0 / float(" << m_pattern.size() << ");\n" + << " const highp float colWidth = 2.0 / float(" << max_vertices << ");\n"; + + if (m_pattern.size() == 2) + src << " highp int emitCount = (gl_PrimitiveIDIn == 0) ? (" << m_pattern[0] << ") : (" << m_pattern[1] << ");\n"; + else + src << " highp int emitCount = " << m_pattern[0] << ";\n"; + src << " for (highp int ndx = 0; ndx < emitCount / 2; ndx++)\n" + << " {\n" + << " gl_Position = gl_in[0].gl_Position + vec4(float(ndx) * 2.0 * colWidth, 0.0, 0.0, 0.0);\n" + << " v_frag_FragColor = v_geom_FragColor[0];\n" + << " EmitVertex();\n" + + << " gl_Position = gl_in[0].gl_Position + vec4(float(ndx) * 2.0 * colWidth, rowHeight, 0.0, 0.0);\n" + << " v_frag_FragColor = v_geom_FragColor[0];\n" + << " EmitVertex();\n" + + << " }\n" + << "}\n"; + sourceCollections.glslSources.add("geometry") << glu::GeometrySource(src.str()); + } + + { + std::ostringstream src; + src << "#version 310 es\n" + <<"layout(location = 0) out mediump vec4 fragColor;\n" + <<"layout(location = 0) in mediump vec4 v_frag_FragColor;\n" + <<"void main (void)\n" + <<"{\n" + <<" fragColor = v_frag_FragColor;\n" + <<"}\n"; + sourceCollections.glslSources.add("fragment") << glu::FragmentSource(src.str()); + } +} + +TestInstance* GeometryOutputCountTest::createInstance (Context& context) const +{ + return new GeometryOutputCountTestInstance (context, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, static_cast(m_pattern.size()), getName()); +} + +class VaryingOutputCountCase : public TestCase +{ +public: + VaryingOutputCountCase (TestContext& testCtx, + const char* name, + const char* description, + const VaryingSource test, + const ShaderInstancingMode mode); + void initPrograms (SourceCollections& sourceCollections) const; + virtual TestInstance* createInstance (Context& context) const; +protected: + const VaryingSource m_test; + const ShaderInstancingMode m_mode; +}; + +VaryingOutputCountCase::VaryingOutputCountCase (TestContext& testCtx, const char* name, const char* description, const VaryingSource test, const ShaderInstancingMode mode) + : TestCase (testCtx, name, description) + , m_test (test) + , m_mode (mode) +{ +} + +void VaryingOutputCountCase::initPrograms (SourceCollections& sourceCollections) const +{ + { + std::ostringstream src; + switch(m_test) + { + case READ_ATTRIBUTE: + case READ_TEXTURE: + src << "#version 310 es\n" + << "layout(location = 0) in highp vec4 a_position;\n" + << "layout(location = 1) in highp vec4 a_emitCount;\n" + << "layout(location = 0) out highp vec4 v_geom_emitCount;\n" + << "void main (void)\n" + << "{\n" + << " gl_Position = a_position;\n" + << " v_geom_emitCount = a_emitCount;\n" + << "}\n"; + break; + case READ_UNIFORM: + src << "#version 310 es\n" + << "layout(location = 0) in highp vec4 a_position;\n" + << "layout(location = 1) in highp vec4 a_vertexNdx;\n" + << "layout(location = 0) out highp vec4 v_geom_vertexNdx;\n" + << "void main (void)\n" + << "{\n" + << " gl_Position = a_position;\n" + << " v_geom_vertexNdx = a_vertexNdx;\n" + << "}\n"; + break; + default: + DE_ASSERT(0); + break; + } + sourceCollections.glslSources.add("vertex") << glu::VertexSource(src.str()); + } + + { + const bool instanced = MODE_WITH_INSTANCING == m_mode; + std::ostringstream src; + src << "#version 310 es\n" + << "#extension GL_EXT_geometry_shader : require\n" + << "#extension GL_OES_texture_storage_multisample_2d_array : require\n"; + if (instanced) + src << "layout(points, invocations=4) in;\n"; + else + src << "layout(points) in;\n"; + + switch(m_test) + { + case READ_ATTRIBUTE: + src << "layout(triangle_strip, max_vertices = 128) out;\n" + << "layout(location = 0) in highp vec4 v_geom_emitCount[];\n" + << "layout(location = 0) out highp vec4 v_frag_FragColor;\n" + << "void main (void)\n" + << "{\n" + << " highp vec4 attrEmitCounts = v_geom_emitCount[0];\n" + << " mediump int emitCount = int(attrEmitCounts[" << ((instanced) ? ("gl_InvocationID") : ("0")) << "]);\n" + << " highp vec4 color = vec4((emitCount < 10) ? (0.0) : (1.0), (emitCount > 10) ? (0.0) : (1.0), 1.0, 1.0);\n" + << " highp vec4 basePos = " << ((instanced) ? ("gl_in[0].gl_Position + 0.5 * vec4(cos(float(gl_InvocationID)), sin(float(gl_InvocationID)), 0.0, 0.0)") : ("gl_in[0].gl_Position")) << ";\n" + << " for (mediump int i = 0; i < emitCount / 2; i++)\n" + << " {\n" + << " highp float angle = (float(i) + 0.5) / float(emitCount / 2) * 3.142;\n" + << " gl_Position = basePos + vec4(cos(angle), sin(angle), 0.0, 0.0) * 0.15;\n" + << " v_frag_FragColor = color;\n" + << " EmitVertex();\n" + << " gl_Position = basePos + vec4(cos(angle), -sin(angle), 0.0, 0.0) * 0.15;\n" + << " v_frag_FragColor = color;\n" + << " EmitVertex();\n" + << " }\n" + <<"}\n"; + break; + case READ_UNIFORM: + src << "layout(triangle_strip, max_vertices = 128) out;\n" + << "layout(location = 0) in highp vec4 v_geom_vertexNdx[];\n" + << "layout(binding = 0) readonly uniform Input {\n" + << " ivec4 u_emitCount;\n" + << "} emit;\n" + << "layout(location = 0) out highp vec4 v_frag_FragColor;\n" + << "void main (void)\n" + << "{\n" + << " mediump int primitiveNdx = " << ((instanced) ? ("gl_InvocationID") : ("int(v_geom_vertexNdx[0].x)")) << ";\n" + << " mediump int emitCount = emit.u_emitCount[primitiveNdx];\n" + << "\n" + << " const highp vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n" + << " const highp vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n" + << " const highp vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);\n" + << " const highp vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n" + << " const highp vec4 colors[4] = vec4[4](red, green, blue, yellow);\n" + << " highp vec4 color = colors[int(primitiveNdx)];\n" + << "\n" + << " highp vec4 basePos = " << ((instanced) ? ("gl_in[0].gl_Position + 0.5 * vec4(cos(float(gl_InvocationID)), sin(float(gl_InvocationID)), 0.0, 0.0)") : ("gl_in[0].gl_Position")) << ";\n" + << " for (mediump int i = 0; i < emitCount / 2; i++)\n" + << " {\n" + << " highp float angle = (float(i) + 0.5) / float(emitCount / 2) * 3.142;\n" + << " gl_Position = basePos + vec4(cos(angle), sin(angle), 0.0, 0.0) * 0.15;\n" + << " v_frag_FragColor = color;\n" + << " EmitVertex();\n" + << " gl_Position = basePos + vec4(cos(angle), -sin(angle), 0.0, 0.0) * 0.15;\n" + << " v_frag_FragColor = color;\n" + << " EmitVertex();\n" + << " }\n" + <<"}\n"; + break; + case READ_TEXTURE: + src << "layout(triangle_strip, max_vertices = 128) out;\n" + << "layout(location = 0) in highp vec4 v_geom_vertexNdx[];\n" + << "layout(binding = 0) uniform highp sampler2D u_sampler;\n" + << "layout(location = 0) out highp vec4 v_frag_FragColor;\n" + << "void main (void)\n" + << "{\n" + << " highp float primitiveNdx = " << ((instanced) ? ("float(gl_InvocationID)") : ("v_geom_vertexNdx[0].x")) << ";\n" + << " highp vec2 texCoord = vec2(1.0 / 8.0 + primitiveNdx / 4.0, 0.5);\n" + << " highp vec4 texColor = texture(u_sampler, texCoord);\n" + << " mediump int emitCount = 0;\n" + << " if (texColor.x > 0.0)\n" + << " emitCount += 6;\n" + << " if (texColor.y > 0.0)\n" + << " emitCount += 0;\n" + << " if (texColor.z > 0.0)\n" + << " emitCount += 128;\n" + << " if (texColor.w > 0.0)\n" + << " emitCount += 10;\n" + << " const highp vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n" + << " const highp vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n" + << " const highp vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);\n" + << " const highp vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n" + << " const highp vec4 colors[4] = vec4[4](red, green, blue, yellow);\n" + << " highp vec4 color = colors[int(primitiveNdx)];\n" + << " highp vec4 basePos = "<< ((instanced) ? ("gl_in[0].gl_Position + 0.5 * vec4(cos(float(gl_InvocationID)), sin(float(gl_InvocationID)), 0.0, 0.0)") : ("gl_in[0].gl_Position")) << ";\n" + << " for (mediump int i = 0; i < emitCount / 2; i++)\n" + << " {\n" + << " highp float angle = (float(i) + 0.5) / float(emitCount / 2) * 3.142;\n" + << " gl_Position = basePos + vec4(cos(angle), sin(angle), 0.0, 0.0) * 0.15;\n" + << " v_frag_FragColor = color;\n" + << " EmitVertex();\n" + << " gl_Position = basePos + vec4(cos(angle), -sin(angle), 0.0, 0.0) * 0.15;\n" + << " v_frag_FragColor = color;\n" + << " EmitVertex();\n" + << " }\n" + <<"}\n"; + break; + default: + DE_ASSERT(0); + break; + } + sourceCollections.glslSources.add("geometry") << glu::GeometrySource(src.str()); + } + + { + std::ostringstream src; + src << "#version 310 es\n" + << "layout(location = 0) out mediump vec4 fragColor;\n" + << "layout(location = 0) in mediump vec4 v_frag_FragColor;\n" + << "void main (void)\n" + << "{\n" + << " fragColor = v_frag_FragColor;\n" + << "}\n"; + sourceCollections.glslSources.add("fragment") << glu::FragmentSource(src.str()); + } +} + +TestInstance* VaryingOutputCountCase::createInstance (Context& context) const +{ + return new VaryingOutputCountTestInstance (context, getName(), VK_PRIMITIVE_TOPOLOGY_POINT_LIST, m_test, m_mode); +} + +class BuiltinVariableRenderTest : public TestCase +{ +public: + BuiltinVariableRenderTest (TestContext& testCtx, + const char* name, + const char* desc, + const VariableTest test, + const bool flag = false); + void initPrograms (SourceCollections& sourceCollections) const; + virtual TestInstance* createInstance (Context& context) const; +protected: + const VariableTest m_test; + const bool m_flag; +}; + +BuiltinVariableRenderTest::BuiltinVariableRenderTest (TestContext& testCtx, const char* name, const char* description, const VariableTest test, const bool flag) + : TestCase (testCtx, name, description) + , m_test (test) + , m_flag (flag) +{ +} + +void BuiltinVariableRenderTest::initPrograms (SourceCollections& sourceCollections) const +{ + { + std::ostringstream src; + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" + << "out gl_PerVertex\n" + <<" {\n" + << " vec4 gl_Position;\n" + << " float gl_PointSize;\n" + << "};\n" + << "layout(location = 0) in vec4 a_position;\n"; + switch(m_test) + { + case TEST_POINT_SIZE: + src << "layout(location = 1) in vec4 a_pointSize;\n" + << "layout(location = 0) out vec4 v_geom_pointSize;\n" + << "void main (void)\n" + << "{\n" + << " gl_Position = a_position;\n" + << " gl_PointSize = 1.0;\n" + << " v_geom_pointSize = a_pointSize;\n" + << "}\n"; + break; + case TEST_PRIMITIVE_ID_IN: + src << "void main (void)\n" + << "{\n" + << " gl_Position = a_position;\n" + << "}\n"; + break; + case TEST_PRIMITIVE_ID: + src << "layout(location = 1) in vec4 a_primitiveID;\n" + << "layout(location = 0) out vec4 v_geom_primitiveID;\n" + << "void main (void)\n" + << "{\n" + << " gl_Position = a_position;\n" + << " v_geom_primitiveID = a_primitiveID;\n" + << "}\n"; + break; + default: + DE_ASSERT(0); + break; + } + sourceCollections.glslSources.add("vertex") << glu::VertexSource(src.str()); + } + + { + std::ostringstream src; + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" + << "in gl_PerVertex\n" + <<"{\n" + << " vec4 gl_Position;\n" + << " float gl_PointSize;\n" + << "} gl_in[];\n" + << "out gl_PerVertex\n" + <<"{\n" + << " vec4 gl_Position;\n" + << " float gl_PointSize;\n" + << "};\n"; + switch(m_test) + { + case TEST_POINT_SIZE: + src << "#extension GL_EXT_geometry_point_size : require\n" + << "layout(points) in;\n" + << "layout(points, max_vertices = 1) out;\n" + << "layout(location = 0) in vec4 v_geom_pointSize[];\n" + << "layout(location = 0) out vec4 v_frag_FragColor;\n" + << "void main (void)\n" + << "{\n" + << " gl_Position = gl_in[0].gl_Position;\n" + << " gl_PointSize = v_geom_pointSize[0].x + 1.0;\n" + << " v_frag_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n" + << " EmitVertex();\n" + << "}\n"; + break; + case TEST_PRIMITIVE_ID_IN: + src << "layout(lines) in;\n" + << "layout(triangle_strip, max_vertices = 10) out;\n" + << "layout(location = 0) out vec4 v_frag_FragColor;\n" + << "void main (void)\n" + << "{\n" + << " const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n" + << " const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n" + << " const vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);\n" + << " const vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n" + << " const vec4 colors[4] = vec4[4](red, green, blue, yellow);\n" + << " for (float percent=0.00; percent < 0.30; percent+=0.10)\n" + "{\n" + << " gl_Position = gl_in[0].gl_Position * vec4(1.0+percent, 1.0+percent, 1.0, 1.0);\n" + << " v_frag_FragColor = colors[gl_PrimitiveIDIn % 4];\n" + << " EmitVertex();\n" + << " gl_Position = gl_in[1].gl_Position * vec4(1.0+percent, 1.0+percent, 1.0, 1.0);\n" + << " v_frag_FragColor = colors[gl_PrimitiveIDIn % 4];\n" + << " EmitVertex();\n" + << " }\n" + << "}\n"; + break; + case TEST_PRIMITIVE_ID: + src << "layout(points, invocations=1) in;\n" + << "layout(triangle_strip, max_vertices = 3) out;\n" + << "layout(location = 0) in vec4 v_geom_primitiveID[];\n" + << "void main (void)\n" + << "{\n" + << " gl_Position = gl_in[0].gl_Position + vec4(0.05, 0.0, 0.0, 0.0);\n" + << " gl_PrimitiveID = int(floor(v_geom_primitiveID[0].x)) + 3;\n" + << " EmitVertex();\n" + << " gl_Position = gl_in[0].gl_Position - vec4(0.05, 0.0, 0.0, 0.0);\n" + << " gl_PrimitiveID = int(floor(v_geom_primitiveID[0].x)) + 3;\n" + << " EmitVertex();\n" + << " gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.05, 0.0, 0.0);\n" + << " gl_PrimitiveID = int(floor(v_geom_primitiveID[0].x)) + 3;\n" + << " EmitVertex();\n" + << "}\n"; + break; + default: + DE_ASSERT(0); + break; + } + sourceCollections.glslSources.add("geometry") << glu::GeometrySource(src.str()); + } + + { + std::ostringstream src; + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"; + switch(m_test) + { + case TEST_POINT_SIZE: + src << "layout(location = 0) out vec4 fragColor;\n" + << "layout(location = 0) in vec4 v_frag_FragColor;\n" + << "void main (void)\n" + << "{\n" + << " fragColor = v_frag_FragColor;\n" + << "}\n"; + break; + case TEST_PRIMITIVE_ID_IN: + src << "layout(location = 0) out vec4 fragColor;\n" + << "layout(location = 0) in vec4 v_frag_FragColor;\n" + << "void main (void)\n" + << "{\n" + << " fragColor = v_frag_FragColor;\n" + << "}\n"; + break; + case TEST_PRIMITIVE_ID: + src << "layout(location = 0) out vec4 fragColor;\n" + << "void main (void)\n" + << "{\n" + << " const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n" + << " const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n" + << " const vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);\n" + << " const vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n" + << " const vec4 colors[4] = vec4[4](yellow, red, green, blue);\n" + << " fragColor = colors[gl_PrimitiveID % 4];\n" + << "}\n"; + break; + default: + DE_ASSERT(0); + break; + } + sourceCollections.glslSources.add("fragment") << glu::FragmentSource(src.str()); + } +} + +TestInstance* BuiltinVariableRenderTest::createInstance (Context& context) const +{ + if (m_test == TEST_POINT_SIZE && !checkPointSize(context.getInstanceInterface(), context.getPhysicalDevice())) + TCU_THROW(NotSupportedError, "Missing feature: pointSize"); + return new BuiltinVariableRenderTestInstance(context, getName(), m_test, m_flag); +} + +inline vector createPattern (int count) +{ + vector pattern; + pattern.push_back(count); + return pattern; +} + +inline vector createPattern (int count0, int count1) +{ + vector pattern; + pattern.push_back(count0); + pattern.push_back(count1); + return pattern; +} + +} // anonymous + +TestCaseGroup* createBasicGeometryShaderTests (TestContext& testCtx) +{ + MovePtr basicGroup (new tcu::TestCaseGroup(testCtx, "basic", "Basic tests.")); + + basicGroup->addChild(new GeometryOutputCountTest (testCtx, "output_10", "Output 10 vertices", createPattern(10))); + basicGroup->addChild(new GeometryOutputCountTest (testCtx, "output_128", "Output 128 vertices", createPattern(128))); + basicGroup->addChild(new GeometryOutputCountTest (testCtx, "output_10_and_100", "Output 10 and 100 vertices in two invocations", createPattern(10, 100))); + basicGroup->addChild(new GeometryOutputCountTest (testCtx, "output_100_and_10", "Output 100 and 10 vertices in two invocations", createPattern(100, 10))); + basicGroup->addChild(new GeometryOutputCountTest (testCtx, "output_0_and_128", "Output 0 and 128 vertices in two invocations", createPattern(0, 128))); + basicGroup->addChild(new GeometryOutputCountTest (testCtx, "output_128_and_0", "Output 128 and 0 vertices in two invocations", createPattern(128, 0))); + + basicGroup->addChild(new VaryingOutputCountCase (testCtx, "output_vary_by_attribute", "Output varying number of vertices", READ_ATTRIBUTE, MODE_WITHOUT_INSTANCING)); + basicGroup->addChild(new VaryingOutputCountCase (testCtx, "output_vary_by_uniform", "Output varying number of vertices", READ_UNIFORM, MODE_WITHOUT_INSTANCING)); + basicGroup->addChild(new VaryingOutputCountCase (testCtx, "output_vary_by_texture", "Output varying number of vertices", READ_TEXTURE, MODE_WITHOUT_INSTANCING)); + basicGroup->addChild(new VaryingOutputCountCase (testCtx, "output_vary_by_attribute_instancing", "Output varying number of vertices", READ_ATTRIBUTE, MODE_WITH_INSTANCING)); + basicGroup->addChild(new VaryingOutputCountCase (testCtx, "output_vary_by_uniform_instancing", "Output varying number of vertices", READ_UNIFORM, MODE_WITH_INSTANCING)); + basicGroup->addChild(new VaryingOutputCountCase (testCtx, "output_vary_by_texture_instancing", "Output varying number of vertices", READ_TEXTURE, MODE_WITH_INSTANCING)); + + basicGroup->addChild(new BuiltinVariableRenderTest (testCtx, "point_size", "test gl_PointSize", TEST_POINT_SIZE)); + basicGroup->addChild(new BuiltinVariableRenderTest (testCtx, "primitive_id_in", "test gl_PrimitiveIDIn", TEST_PRIMITIVE_ID_IN)); + basicGroup->addChild(new BuiltinVariableRenderTest (testCtx, "primitive_id_in_restarted", "test gl_PrimitiveIDIn with primitive restart", TEST_PRIMITIVE_ID_IN, true)); + basicGroup->addChild(new BuiltinVariableRenderTest (testCtx, "primitive_id", "test gl_PrimitiveID", TEST_PRIMITIVE_ID)); + + return basicGroup.release(); +} + +} // geometry +} // vkt diff --git a/external/vulkancts/modules/vulkan/geometry/vktGeometryBasicGeometryShaderTests.hpp b/external/vulkancts/modules/vulkan/geometry/vktGeometryBasicGeometryShaderTests.hpp new file mode 100644 index 0000000..eadb2f1 --- /dev/null +++ b/external/vulkancts/modules/vulkan/geometry/vktGeometryBasicGeometryShaderTests.hpp @@ -0,0 +1,39 @@ +#ifndef _VKTGEOMETRYBASICGEOMETRYSHADERTESTS_HPP +#define _VKTGEOMETRYBASICGEOMETRYSHADERTESTS_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * + * 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. + * + *//*! + * \file + * \brief Basic Geometry Shader Tests + *//*--------------------------------------------------------------------*/ + +#include "tcuDefs.hpp" +#include "vktTestCase.hpp" + +namespace vkt +{ +namespace geometry +{ + +tcu::TestCaseGroup* createBasicGeometryShaderTests (tcu::TestContext& testCtx); + +} // geometry +} // vkt + +#endif // _VKTGEOMETRYBASICGEOMETRYSHADERTESTS_HPP diff --git a/external/vulkancts/modules/vulkan/geometry/vktGeometryEmitGeometryShaderTests.cpp b/external/vulkancts/modules/vulkan/geometry/vktGeometryEmitGeometryShaderTests.cpp new file mode 100644 index 0000000..edf9942 --- /dev/null +++ b/external/vulkancts/modules/vulkan/geometry/vktGeometryEmitGeometryShaderTests.cpp @@ -0,0 +1,262 @@ +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * Copyright (c) 2016 The Android Open Source Project + * + * 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. + * + *//*! + * \file + * \brief Emit Geometry Shader Tests + *//*--------------------------------------------------------------------*/ + +#include "vktGeometryEmitGeometryShaderTests.hpp" +#include "vktGeometryBasicClass.hpp" +#include "vktGeometryTestsUtil.hpp" + +#include "vkDefs.hpp" +#include "vktTestCase.hpp" +#include "vktTestCaseUtil.hpp" +#include "vkImageUtil.hpp" +#include "vkTypeUtil.hpp" +#include "vkPrograms.hpp" +#include "vkBuilderUtil.hpp" + +#include "vkRefUtil.hpp" +#include "vkQueryUtil.hpp" +#include "vkMemUtil.hpp" + +#include + +using namespace vk; + +namespace vkt +{ +namespace geometry +{ +namespace +{ +using std::string; +using de::MovePtr; +using tcu::Vec4; +using tcu::TestStatus; +using tcu::TestContext; +using tcu::TestCaseGroup; + +typedef enum VertexOutputs {VERTEXT_NO_OP = -1,VERTEXT_ZERO, VERTEXT_ONE} VertexOut; +typedef enum GeometryOutputs {GEOMETRY_ZERO, GEOMETRY_ONE, GEOMETRY_TWO} GeometryOut; + +struct EmitTestSpec +{ + VkPrimitiveTopology primitiveTopology; + int emitCountA; //!< primitive A emit count + int endCountA; //!< primitive A end count + int emitCountB; //!< + int endCountB; //!< + string name; + string desc; +}; + +class GeometryEmitTestInstance : public GeometryExpanderRenderTestInstance +{ +public: + GeometryEmitTestInstance (Context& context, + const char* name); + void genVertexAttribData (void); +}; + +GeometryEmitTestInstance::GeometryEmitTestInstance (Context& context, const char* name) + : GeometryExpanderRenderTestInstance (context, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, name) +{ + genVertexAttribData(); +} + +void GeometryEmitTestInstance::genVertexAttribData (void) +{ + m_numDrawVertices = 1; + m_vertexPosData.resize(m_numDrawVertices); + m_vertexPosData[0] = Vec4(0, 0, 0, 1); + + m_vertexAttrData.resize(m_numDrawVertices); + m_vertexAttrData[0] = Vec4(1, 1, 1, 1); +} + +class EmitTest : public TestCase +{ +public: + EmitTest (TestContext& testCtx, + const EmitTestSpec& emitTestSpec); + + void initPrograms (SourceCollections& sourceCollections) const; + virtual TestInstance* createInstance (Context& context) const; + +protected: + string shaderGeometry (bool pointSize) const; + const EmitTestSpec m_emitTestSpec; +}; + +EmitTest::EmitTest (TestContext& testCtx, const EmitTestSpec& emitTestSpec) + : TestCase (testCtx, emitTestSpec.name, emitTestSpec.desc) + , m_emitTestSpec (emitTestSpec) + +{ + +} + +void EmitTest::initPrograms (SourceCollections& sourceCollections) const +{ + { + std::ostringstream src; + src << "#version 310 es\n" + << "layout(location = 0) in highp vec4 a_position;\n" + << "layout(location = 1) in highp vec4 a_color;\n" + << "layout(location = 0) out highp vec4 v_geom_FragColor;\n" + << "void main (void)\n" + << "{\n" + << " gl_Position = a_position;\n" + << " v_geom_FragColor = a_color;\n" + << "}\n"; + sourceCollections.glslSources.add("vertex") << glu::VertexSource(src.str()); + } + + { + sourceCollections.glslSources.add("geometry") << glu::GeometrySource(shaderGeometry(false)); + if(m_emitTestSpec.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST) + sourceCollections.glslSources.add("geometry_pointsize") << glu::GeometrySource(shaderGeometry(true)); + } + + { + std::ostringstream src; + src << "#version 310 es\n" + << "layout(location = 0) out mediump vec4 fragColor;\n" + << "layout(location = 0) in mediump vec4 v_frag_FragColor;\n" + << "void main (void)\n" + << "{\n" + << " fragColor = v_frag_FragColor;\n" + <<"}\n"; + sourceCollections.glslSources.add("fragment") << glu::FragmentSource(src.str()); + } +} + +TestInstance* EmitTest::createInstance (Context& context) const +{ + return new GeometryEmitTestInstance(context, getName()); +} + +string EmitTest::shaderGeometry (bool pointSize) const +{ + std::ostringstream src; + src << "#version 310 es\n" + << "#extension GL_EXT_geometry_shader : require\n"; + if (pointSize) + src <<"#extension GL_EXT_geometry_point_size : require\n"; + src << "layout(points) in;\n" + << "layout(" << outputTypeToGLString(m_emitTestSpec.primitiveTopology) << ", max_vertices = " << (m_emitTestSpec.emitCountA + m_emitTestSpec.emitCountB +1) << ") out;\n" + << "layout(location = 0) in highp vec4 v_geom_FragColor[];\n" + << "layout(location = 0) out highp vec4 v_frag_FragColor;\n" + << "void main (void)\n" + << "{\n" + << " const highp vec4 position0 = vec4(-0.5, 0.5, 0.0, 0.0);\n" + << " const highp vec4 position1 = vec4( 0.0, 0.1, 0.0, 0.0);\n" + << " const highp vec4 position2 = vec4( 0.5, 0.5, 0.0, 0.0);\n" + << " const highp vec4 position3 = vec4( 0.7, -0.2, 0.0, 0.0);\n" + << " const highp vec4 position4 = vec4( 0.2, 0.2, 0.0, 0.0);\n" + << " const highp vec4 position5 = vec4( 0.4, -0.3, 0.0, 0.0);\n"; + for (int i = 0; i < m_emitTestSpec.emitCountA; ++i) + { + if (pointSize) + src << " gl_PointSize = 1.0;\n"; + src << " gl_Position = gl_in[0].gl_Position + position" << i << ";\n" + " gl_PrimitiveID = gl_PrimitiveIDIn;\n" + " v_frag_FragColor = v_geom_FragColor[0];\n" + " EmitVertex();\n" + "\n"; + } + + for (int i = 0; i < m_emitTestSpec.endCountA; ++i) + src << " EndPrimitive();\n"; + + for (int i = 0; i < m_emitTestSpec.emitCountB; ++i) + { + if (pointSize) + src << " gl_PointSize = 1.0;\n"; + src << " gl_Position = gl_in[0].gl_Position + position" << (m_emitTestSpec.emitCountA + i) << ";\n" + " gl_PrimitiveID = gl_PrimitiveIDIn;\n" + " v_frag_FragColor = v_geom_FragColor[0];\n" + " EmitVertex();\n" + "\n"; + } + + for (int i = 0; i < m_emitTestSpec.endCountB; ++i) + src << " EndPrimitive();\n"; + src << "}\n"; + return src.str(); +} + +} // anonymous + +TestCaseGroup* createEmitGeometryShaderTests (TestContext& testCtx) +{ + MovePtr emitGroup (new TestCaseGroup(testCtx, "emit", "Different emit counts.")); + + // emit different amounts + { + EmitTestSpec emitTests[] = + { + { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, 0, 0, 0, "points" , ""}, + { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, 1, 0, 0, "points" , ""}, + { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 1, 1, 0, 0, "points" , ""}, + { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, 2, 0, 0, "points" , ""}, + { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 1, 2, 0, 0, "points" , ""}, + { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 0, 0, 0, 0, "line_strip" , ""}, + { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 0, 1, 0, 0, "line_strip" , ""}, + { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 1, 1, 0, 0, "line_strip" , ""}, + { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 2, 1, 0, 0, "line_strip" , ""}, + { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 0, 2, 0, 0, "line_strip" , ""}, + { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 1, 2, 0, 0, "line_strip" , ""}, + { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 2, 2, 0, 0, "line_strip" , ""}, + { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 2, 2, 2, 0, "line_strip" , ""}, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, 0, 0, 0, "triangle_strip", ""}, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, 1, 0, 0, "triangle_strip", ""}, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 1, 1, 0, 0, "triangle_strip", ""}, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 2, 1, 0, 0, "triangle_strip", ""}, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 3, 1, 0, 0, "triangle_strip", ""}, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, 2, 0, 0, "triangle_strip", ""}, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 1, 2, 0, 0, "triangle_strip", ""}, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 2, 2, 0, 0, "triangle_strip", ""}, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 3, 2, 0, 0, "triangle_strip", ""}, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 3, 2, 3, 0, "triangle_strip", ""}, + }; + + for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(emitTests); ++ndx) + { + emitTests[ndx].name = std::string(emitTests[ndx].name) + "_emit_" + de::toString(emitTests[ndx].emitCountA) + "_end_" + de::toString(emitTests[ndx].endCountA); + emitTests[ndx].desc = std::string(emitTests[ndx].name) + " output, emit " + de::toString(emitTests[ndx].emitCountA) + " vertices, call EndPrimitive " + de::toString(emitTests[ndx].endCountA) + " times"; + + if (emitTests[ndx].emitCountB) + { + emitTests[ndx].name += "_emit_" + de::toString(emitTests[ndx].emitCountB) + "_end_" + de::toString(emitTests[ndx].endCountB); + emitTests[ndx].desc += ", emit " + de::toString(emitTests[ndx].emitCountB) + " vertices, call EndPrimitive " + de::toString(emitTests[ndx].endCountB) + " times"; + } + + emitGroup->addChild(new EmitTest(testCtx, emitTests[ndx])); + } + } + + return emitGroup.release(); +} + +} // geometry +} // vkt diff --git a/external/vulkancts/modules/vulkan/geometry/vktGeometryEmitGeometryShaderTests.hpp b/external/vulkancts/modules/vulkan/geometry/vktGeometryEmitGeometryShaderTests.hpp new file mode 100644 index 0000000..fbc93dd --- /dev/null +++ b/external/vulkancts/modules/vulkan/geometry/vktGeometryEmitGeometryShaderTests.hpp @@ -0,0 +1,39 @@ +#ifndef _VKTGEOMETRYEMITGEOMETRYSHADERTESTS_HPP +#define _VKTGEOMETRYEMITGEOMETRYSHADERTESTS_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * + * 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. + * + *//*! + * \file + * \brief Emit Geometry Shader Tests + *//*--------------------------------------------------------------------*/ + +#include "tcuDefs.hpp" +#include "vktTestCase.hpp" + +namespace vkt +{ +namespace geometry +{ + +tcu::TestCaseGroup* createEmitGeometryShaderTests (tcu::TestContext& testCtx); + +} // geometry +} // vkt + +#endif // _VKTGEOMETRYEMITGEOMETRYSHADERTESTS_HPP diff --git a/external/vulkancts/modules/vulkan/geometry/vktGeometryInputGeometryShaderTests.cpp b/external/vulkancts/modules/vulkan/geometry/vktGeometryInputGeometryShaderTests.cpp new file mode 100644 index 0000000..b5a6315 --- /dev/null +++ b/external/vulkancts/modules/vulkan/geometry/vktGeometryInputGeometryShaderTests.cpp @@ -0,0 +1,304 @@ +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * Copyright (c) 2016 The Android Open Source Project + * + * 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. + * + *//*! + * \file + * \brief Input Geometry Shader Tests + *//*--------------------------------------------------------------------*/ + +#include "vktGeometryInputGeometryShaderTests.hpp" +#include "vktGeometryBasicClass.hpp" +#include "vktGeometryTestsUtil.hpp" + +#include "vkDefs.hpp" +#include "vktTestCase.hpp" +#include "vktTestCaseUtil.hpp" +#include "vkImageUtil.hpp" +#include "vkTypeUtil.hpp" +#include "vkPrograms.hpp" +#include "vkBuilderUtil.hpp" + +#include "vkRefUtil.hpp" +#include "vkQueryUtil.hpp" +#include "vkMemUtil.hpp" + +#include + +using namespace vk; + +namespace vkt +{ +namespace geometry +{ +namespace +{ +using tcu::Vec4; +using tcu::TestStatus; +using tcu::TestContext; +using tcu::TestCaseGroup; +using de::MovePtr; +using std::string; +using std::vector; + +class GeometryInputTestInstance : public GeometryExpanderRenderTestInstance +{ +public: + GeometryInputTestInstance (Context& context, + const VkPrimitiveTopology primitiveType, + const char* name); + + GeometryInputTestInstance (Context& context, + const VkPrimitiveTopology primitiveType, + const char* name, + const int numDrawVertices); + + void genVertexAttribData (void); +}; + +GeometryInputTestInstance::GeometryInputTestInstance (Context& context, + const VkPrimitiveTopology primitiveType, + const char* name) + : GeometryExpanderRenderTestInstance (context, primitiveType, name) +{ + genVertexAttribData(); +} + +GeometryInputTestInstance::GeometryInputTestInstance (Context& context, + const VkPrimitiveTopology primitiveType, + const char* name, + const int numDrawVertices) + : GeometryExpanderRenderTestInstance (context, primitiveType, name) +{ + genVertexAttribData(); + m_numDrawVertices = numDrawVertices; +} + +void GeometryInputTestInstance::genVertexAttribData (void) +{ + // Create 1 X 2 grid in triangle strip adjacent - order + const float scale = 0.3f; + const Vec4 offset (-0.5f, -0.2f, 0.0f, 1.0f); + m_numDrawVertices = 12; + + m_vertexPosData.resize(m_numDrawVertices); + m_vertexPosData[ 0] = Vec4( 0, 0, 0.0f, 0.0f) * scale + offset; + m_vertexPosData[ 1] = Vec4(-1, -1, 0.0f, 0.0f) * scale + offset; + m_vertexPosData[ 2] = Vec4( 0, -1, 0.0f, 0.0f) * scale + offset; + m_vertexPosData[ 3] = Vec4( 1, 1, 0.0f, 0.0f) * scale + offset; + m_vertexPosData[ 4] = Vec4( 1, 0, 0.0f, 0.0f) * scale + offset; + m_vertexPosData[ 5] = Vec4( 0, -2, 0.0f, 0.0f) * scale + offset; + m_vertexPosData[ 6] = Vec4( 1, -1, 0.0f, 0.0f) * scale + offset; + m_vertexPosData[ 7] = Vec4( 2, 1, 0.0f, 0.0f) * scale + offset; + m_vertexPosData[ 8] = Vec4( 2, 0, 0.0f, 0.0f) * scale + offset; + m_vertexPosData[ 9] = Vec4( 1, -2, 0.0f, 0.0f) * scale + offset; + m_vertexPosData[10] = Vec4( 2, -1, 0.0f, 0.0f) * scale + offset; + m_vertexPosData[11] = Vec4( 3, 0, 0.0f, 0.0f) * scale + offset; + + // Red and white + m_vertexAttrData.resize(m_numDrawVertices); + for (int i = 0; i < m_numDrawVertices; ++i) + m_vertexAttrData[i] = (i % 2 == 0) ? Vec4(1, 1, 1, 1) : Vec4(1, 0, 0, 1); +} + +class GeometryExpanderRenderTest : public TestCase +{ +public: + GeometryExpanderRenderTest (TestContext& testCtx, + const PrimitiveTestSpec& inputPrimitives); + + void initPrograms (SourceCollections& sourceCollections) const; + virtual TestInstance* createInstance (Context& context) const; + +protected: + string shaderGeometry (bool pointSize) const; + const VkPrimitiveTopology m_primitiveType; + const VkPrimitiveTopology m_outputType; +}; + +GeometryExpanderRenderTest::GeometryExpanderRenderTest (TestContext& testCtx, const PrimitiveTestSpec& inputPrimitives) + : TestCase (testCtx, inputPrimitives.name, inputPrimitives.name) + , m_primitiveType (inputPrimitives.primitiveType) + , m_outputType (inputPrimitives.outputType) +{ + +} + +void GeometryExpanderRenderTest::initPrograms (SourceCollections& sourceCollections) const +{ + { + std::ostringstream src; + src << "#version 310 es\n" + <<"layout(location = 0) in highp vec4 a_position;\n" + <<"layout(location = 1) in highp vec4 a_color;\n" + <<"layout(location = 0) out highp vec4 v_geom_FragColor;\n" + <<"void main (void)\n" + <<"{\n" + <<" gl_Position = a_position;\n" + <<" v_geom_FragColor = a_color;\n" + <<"}\n"; + sourceCollections.glslSources.add("vertex") << glu::VertexSource(src.str()); + } + + { + sourceCollections.glslSources.add("geometry") << glu::GeometrySource(shaderGeometry(false)); + if (m_outputType == VK_PRIMITIVE_TOPOLOGY_POINT_LIST) + sourceCollections.glslSources.add("geometry_pointsize") << glu::GeometrySource(shaderGeometry(true)); + } + + { + std::ostringstream src; + src << "#version 310 es\n" + <<"layout(location = 0) out highp vec4 fragColor;\n" + <<"layout(location = 0) in highp vec4 v_frag_FragColor;\n" + <<"void main (void)\n" + <<"{\n" + <<" fragColor = v_frag_FragColor;\n" + <<"}\n"; + sourceCollections.glslSources.add("fragment") << glu::FragmentSource(src.str()); + } +} + +TestInstance* GeometryExpanderRenderTest::createInstance (Context& context) const +{ + return new GeometryInputTestInstance(context, m_primitiveType, getName()); +} + +string GeometryExpanderRenderTest::shaderGeometry (bool pointSize) const +{ + std::ostringstream src; + src << "#version 310 es\n" + << "#extension GL_EXT_geometry_shader : require\n"; + if (pointSize) + src <<"#extension GL_EXT_geometry_point_size : require\n"; + src << "layout(" << inputTypeToGLString(m_primitiveType) << ") in;\n" + << "layout(" << outputTypeToGLString(m_outputType) << ", max_vertices = " << calcOutputVertices(m_primitiveType) << ") out;\n" + << "layout(location = 0) in highp vec4 v_geom_FragColor[];\n" + << "layout(location = 0) out highp vec4 v_frag_FragColor;\n" + << "\n" + << "void main (void)\n" + << "{\n" + << " const highp vec4 offset0 = vec4(-0.07, -0.01, 0.0, 0.0);\n" + << " const highp vec4 offset1 = vec4( 0.03, -0.03, 0.0, 0.0);\n" + << " const highp vec4 offset2 = vec4(-0.01, 0.08, 0.0, 0.0);\n" + << " highp vec4 yoffset = float(gl_PrimitiveIDIn) * vec4(0.02, 0.1, 0.0, 0.0);\n" + << "\n" + << " for (highp int ndx = 0; ndx < gl_in.length(); ndx++)\n" + << " {\n"; + if (pointSize) + src << " gl_PointSize = 1.0;\n"; + src << " gl_Position = gl_in[ndx].gl_Position + offset0 + yoffset;\n" + << " v_frag_FragColor = v_geom_FragColor[ndx];\n" + << " EmitVertex();\n" + << "\n"; + if (pointSize) + src << " gl_PointSize = 1.0;\n"; + src << " gl_Position = gl_in[ndx].gl_Position + offset1 + yoffset;\n" + << " v_frag_FragColor = v_geom_FragColor[ndx];\n" + << " EmitVertex();\n" + << "\n"; + if (pointSize) + src << " gl_PointSize = 1.0;\n"; + src << " gl_Position = gl_in[ndx].gl_Position + offset2 + yoffset;\n" + << " v_frag_FragColor = v_geom_FragColor[ndx];\n" + << " EmitVertex();\n" + << " EndPrimitive();\n" + << " }\n" + << "}\n"; + return src.str(); +} + +class TriangleStripAdjacencyVertexCountTest : public GeometryExpanderRenderTest +{ +public: + TriangleStripAdjacencyVertexCountTest (TestContext& testCtx, const PrimitiveTestSpec& inputPrimitives, const int numInputVertices); + virtual TestInstance* createInstance (Context& context) const; +private: + const int m_numInputVertices; +}; + +TriangleStripAdjacencyVertexCountTest::TriangleStripAdjacencyVertexCountTest (TestContext& testCtx, const PrimitiveTestSpec& inputPrimitives, const int numInputVertices) + : GeometryExpanderRenderTest (testCtx, inputPrimitives) + , m_numInputVertices (numInputVertices) +{ +} + +TestInstance* TriangleStripAdjacencyVertexCountTest::createInstance (Context& context) const +{ + return new GeometryInputTestInstance(context, m_primitiveType, getName(), m_numInputVertices); +} + +} // anonymous + +TestCaseGroup* createInputGeometryShaderTests (TestContext& testCtx) +{ + MovePtr inputPrimitiveGroup (new TestCaseGroup(testCtx, "input", "Different input primitives.")); + MovePtr basicPrimitiveGroup (new TestCaseGroup(testCtx, "basic_primitive", "Basic Primitive geometry tests")); + MovePtr triStripAdjacencyGroup (new TestCaseGroup(testCtx, "triangle_strip_adjacency", "Different triangle_strip_adjacency vertex counts.")); + MovePtr conversionPrimitiveGroup (new TestCaseGroup(testCtx, "conversion", "Different input and output primitives.")); + + const PrimitiveTestSpec inputPrimitives[] = + { + { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, "points", VK_PRIMITIVE_TOPOLOGY_POINT_LIST }, + { VK_PRIMITIVE_TOPOLOGY_LINE_LIST, "lines", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP }, + { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, "line_strip", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP }, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, "triangles", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP }, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, "triangle_strip", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP }, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, "triangle_fan", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP }, + { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, "lines_adjacency", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP }, + { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, "line_strip_adjacency", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP }, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, "triangles_adjacency", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP } + }; + + // more basic types + for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(inputPrimitives); ++ndx) + basicPrimitiveGroup->addChild(new GeometryExpanderRenderTest(testCtx, inputPrimitives[ndx])); + + // triangle strip adjacency with different vertex counts + for (int vertexCount = 0; vertexCount <= 12; ++vertexCount) + { + const string name = "vertex_count_" + de::toString(vertexCount); + const PrimitiveTestSpec primitives = { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, name.c_str(), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP }; + + triStripAdjacencyGroup->addChild(new TriangleStripAdjacencyVertexCountTest(testCtx, primitives, vertexCount)); + } + + // different type conversions + { + static const PrimitiveTestSpec conversionPrimitives[] = + { + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, "triangles_to_points", VK_PRIMITIVE_TOPOLOGY_POINT_LIST }, + { VK_PRIMITIVE_TOPOLOGY_LINE_LIST, "lines_to_points", VK_PRIMITIVE_TOPOLOGY_POINT_LIST }, + { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, "points_to_lines", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP }, + { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, "triangles_to_lines", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP }, + { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, "points_to_triangles", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP}, + { VK_PRIMITIVE_TOPOLOGY_LINE_LIST, "lines_to_triangles", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP} + }; + + for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(conversionPrimitives); ++ndx) + conversionPrimitiveGroup->addChild(new GeometryExpanderRenderTest(testCtx, conversionPrimitives[ndx])); + } + + inputPrimitiveGroup->addChild(basicPrimitiveGroup.release()); + inputPrimitiveGroup->addChild(triStripAdjacencyGroup.release()); + inputPrimitiveGroup->addChild(conversionPrimitiveGroup.release()); + return inputPrimitiveGroup.release(); +} + +} // geometry +} // vkt diff --git a/external/vulkancts/modules/vulkan/geometry/vktGeometryInputGeometryShaderTests.hpp b/external/vulkancts/modules/vulkan/geometry/vktGeometryInputGeometryShaderTests.hpp new file mode 100644 index 0000000..fab8fac --- /dev/null +++ b/external/vulkancts/modules/vulkan/geometry/vktGeometryInputGeometryShaderTests.hpp @@ -0,0 +1,39 @@ +#ifndef _VKTGEOMETRYINPUTGEOMETRYSHADERTESTS_HPP +#define _VKTGEOMETRYINPUTGEOMETRYSHADERTESTS_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * + * 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. + * + *//*! + * \file + * \brief Input Geometry Shader Tests + *//*--------------------------------------------------------------------*/ + +#include "tcuDefs.hpp" +#include "vktTestCase.hpp" + +namespace vkt +{ +namespace geometry +{ + +tcu::TestCaseGroup* createInputGeometryShaderTests (tcu::TestContext& testCtx); + +} // geometry +} // vkt + +#endif // _VKTGEOMETRYINPUTGEOMETRYSHADERTESTS_HPP diff --git a/external/vulkancts/modules/vulkan/geometry/vktGeometryInstancedRenderingTests.cpp b/external/vulkancts/modules/vulkan/geometry/vktGeometryInstancedRenderingTests.cpp new file mode 100644 index 0000000..278994f --- /dev/null +++ b/external/vulkancts/modules/vulkan/geometry/vktGeometryInstancedRenderingTests.cpp @@ -0,0 +1,704 @@ +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * Copyright (c) 2014 The Android Open Source Project + * + * 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. + * + *//*! + * \file + * \brief Geometry shader instanced rendering tests + *//*--------------------------------------------------------------------*/ + +#include "vktGeometryInstancedRenderingTests.hpp" +#include "vktTestCase.hpp" +#include "vktTestCaseUtil.hpp" +#include "vktGeometryTestsUtil.hpp" + +#include "vkPrograms.hpp" +#include "vkQueryUtil.hpp" +#include "vkMemUtil.hpp" +#include "vkRefUtil.hpp" +#include "vkTypeUtil.hpp" +#include "vkImageUtil.hpp" + +#include "tcuTextureUtil.hpp" +#include "tcuImageCompare.hpp" + +#include "deRandom.hpp" +#include "deMath.h" + +namespace vkt +{ +namespace geometry +{ +namespace +{ +using namespace vk; +using de::MovePtr; +using de::UniquePtr; +using tcu::Vec4; +using tcu::UVec2; + +struct TestParams +{ + int numDrawInstances; + int numInvocations; +}; + +VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const VkExtent3D size, const VkImageUsageFlags usage) +{ + const VkImageCreateInfo imageParams = + { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkImageCreateFlags)0, // VkImageCreateFlags flags; + VK_IMAGE_TYPE_2D, // VkImageType imageType; + format, // VkFormat format; + size, // VkExtent3D extent; + 1u, // deUint32 mipLevels; + 1u, // deUint32 arrayLayers; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; + usage, // VkImageUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 0u, // deUint32 queueFamilyIndexCount; + DE_NULL, // const deUint32* pQueueFamilyIndices; + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + }; + return imageParams; +} + +Move makeRenderPass (const DeviceInterface& vk, + const VkDevice device, + const VkFormat colorFormat) +{ + const VkAttachmentDescription colorAttachmentDescription = + { + (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; + colorFormat, // VkFormat format; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; + VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; + }; + + const VkAttachmentReference colorAttachmentRef = + { + 0u, // deUint32 attachment; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; + }; + + const VkSubpassDescription subpassDescription = + { + (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; + VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; + 0u, // deUint32 inputAttachmentCount; + DE_NULL, // const VkAttachmentReference* pInputAttachments; + 1u, // deUint32 colorAttachmentCount; + &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments; + DE_NULL, // const VkAttachmentReference* pResolveAttachments; + DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; + 0u, // deUint32 preserveAttachmentCount; + DE_NULL // const deUint32* pPreserveAttachments; + }; + + const VkRenderPassCreateInfo renderPassInfo = + { + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; + 1u, // deUint32 attachmentCount; + &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments; + 1u, // deUint32 subpassCount; + &subpassDescription, // const VkSubpassDescription* pSubpasses; + 0u, // deUint32 dependencyCount; + DE_NULL // const VkSubpassDependency* pDependencies; + }; + + return createRenderPass(vk, device, &renderPassInfo); +} + +Move makeGraphicsPipeline (const DeviceInterface& vk, + const VkDevice device, + const VkPipelineLayout pipelineLayout, + const VkRenderPass renderPass, + const VkShaderModule vertexModule, + const VkShaderModule geometryModule, + const VkShaderModule fragmentModule, + const VkExtent2D renderSize) +{ + const VkVertexInputBindingDescription vertexInputBindingDescription = + { + 0u, // uint32_t binding; + sizeof(Vec4), // uint32_t stride; + VK_VERTEX_INPUT_RATE_INSTANCE, // VkVertexInputRate inputRate; + }; + + const VkVertexInputAttributeDescription vertexInputAttributeDescription = + { + 0u, // uint32_t location; + 0u, // uint32_t binding; + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; + 0u, // uint32_t offset; + }; + + const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; + 1u, // uint32_t vertexBindingDescriptionCount; + &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; + 1u, // uint32_t vertexAttributeDescriptionCount; + &vertexInputAttributeDescription, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; + }; + + const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags; + VK_PRIMITIVE_TOPOLOGY_POINT_LIST, // VkPrimitiveTopology topology; + VK_FALSE, // VkBool32 primitiveRestartEnable; + }; + + const VkViewport viewport = makeViewport( + 0.0f, 0.0f, + static_cast(renderSize.width), static_cast(renderSize.height), + 0.0f, 1.0f); + const VkRect2D scissor = + { + makeOffset2D(0, 0), + makeExtent2D(renderSize.width, renderSize.height), + }; + + const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags; + 1u, // uint32_t viewportCount; + &viewport, // const VkViewport* pViewports; + 1u, // uint32_t scissorCount; + &scissor, // const VkRect2D* pScissors; + }; + + const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags; + VK_FALSE, // VkBool32 depthClampEnable; + VK_FALSE, // VkBool32 rasterizerDiscardEnable; + VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; + VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; + VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; + VK_FALSE, // VkBool32 depthBiasEnable; + 0.0f, // float depthBiasConstantFactor; + 0.0f, // float depthBiasClamp; + 0.0f, // float depthBiasSlopeFactor; + 1.0f, // float lineWidth; + }; + + const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; + VK_FALSE, // VkBool32 sampleShadingEnable; + 0.0f, // float minSampleShading; + DE_NULL, // const VkSampleMask* pSampleMask; + VK_FALSE, // VkBool32 alphaToCoverageEnable; + VK_FALSE // VkBool32 alphaToOneEnable; + }; + + const VkStencilOpState stencilOpState = makeStencilOpState( + VK_STENCIL_OP_KEEP, // stencil fail + VK_STENCIL_OP_KEEP, // depth & stencil pass + VK_STENCIL_OP_KEEP, // depth only fail + VK_COMPARE_OP_ALWAYS, // compare op + 0u, // compare mask + 0u, // write mask + 0u); // reference + + VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags; + VK_FALSE, // VkBool32 depthTestEnable; + VK_FALSE, // VkBool32 depthWriteEnable; + VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; + VK_FALSE, // VkBool32 depthBoundsTestEnable; + VK_FALSE, // VkBool32 stencilTestEnable; + stencilOpState, // VkStencilOpState front; + stencilOpState, // VkStencilOpState back; + 0.0f, // float minDepthBounds; + 1.0f, // float maxDepthBounds; + }; + + const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = + { + VK_FALSE, // VkBool32 blendEnable; + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; + VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; + VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; + colorComponentsAll, // VkColorComponentFlags colorWriteMask; + }; + + const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; + VK_FALSE, // VkBool32 logicOpEnable; + VK_LOGIC_OP_COPY, // VkLogicOp logicOp; + 1u, // deUint32 attachmentCount; + &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; + { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; + }; + + const VkPipelineShaderStageCreateInfo pShaderStages[] = + { + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; + vertexModule, // VkShaderModule module; + "main", // const char* pName; + DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; + }, + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_GEOMETRY_BIT, // VkShaderStageFlagBits stage; + geometryModule, // VkShaderModule module; + "main", // const char* pName; + DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; + }, + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; + fragmentModule, // VkShaderModule module; + "main", // const char* pName; + DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; + }, + }; + + const VkGraphicsPipelineCreateInfo graphicsPipelineInfo = + { + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; + DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount; + pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages; + &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; + DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; + &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState; + &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; + &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; + &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; + &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; + DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; + pipelineLayout, // VkPipelineLayout layout; + renderPass, // VkRenderPass renderPass; + 0u, // deUint32 subpass; + DE_NULL, // VkPipeline basePipelineHandle; + 0, // deInt32 basePipelineIndex; + }; + + return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo); +} + +void draw (Context& context, + const UVec2& renderSize, + const VkFormat colorFormat, + const Vec4& clearColor, + const VkBuffer colorBuffer, + const int numDrawInstances, + const std::vector& perInstanceAttribute) +{ + const DeviceInterface& vk = context.getDeviceInterface(); + const VkDevice device = context.getDevice(); + const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); + const VkQueue queue = context.getUniversalQueue(); + Allocator& allocator = context.getDefaultAllocator(); + + const VkImageSubresourceRange colorSubresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)); + const VkExtent3D colorImageExtent (makeExtent3D(renderSize.x(), renderSize.y(), 1u)); + const VkExtent2D renderExtent (makeExtent2D(renderSize.x(), renderSize.y())); + + const Unique colorImage (makeImage (vk, device, makeImageCreateInfo(colorFormat, colorImageExtent, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT))); + const UniquePtr colorImageAlloc (bindImage (vk, device, allocator, *colorImage, MemoryRequirement::Any)); + const Unique colorAttachment (makeImageView (vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange)); + + const VkDeviceSize vertexBufferSize = sizeInBytes(perInstanceAttribute); + const Unique vertexBuffer (makeBuffer(vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))); + const UniquePtr vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible)); + + const Unique vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u)); + const Unique geometryModule (createShaderModule (vk, device, context.getBinaryCollection().get("geom"), 0u)); + const Unique fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u)); + + const Unique renderPass (makeRenderPass (vk, device, colorFormat)); + const Unique framebuffer (makeFramebuffer (vk, device, *renderPass, *colorAttachment, renderSize.x(), renderSize.y(), 1u)); + const Unique pipelineLayout (makePipelineLayout (vk, device)); + const Unique pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule, renderExtent)); + + const Unique cmdPool (makeCommandPool (vk, device, queueFamilyIndex)); + const Unique cmdBuffer (makeCommandBuffer (vk, device, *cmdPool)); + + // Initialize vertex data + { + deMemcpy(vertexBufferAlloc->getHostPtr(), &perInstanceAttribute[0], (size_t)vertexBufferSize); + flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize); + } + + beginCommandBuffer(vk, *cmdBuffer); + + const VkClearValue clearValue = makeClearValueColor(clearColor); + const VkRect2D renderArea = + { + makeOffset2D(0, 0), + renderExtent, + }; + const VkRenderPassBeginInfo renderPassBeginInfo = + { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + *renderPass, // VkRenderPass renderPass; + *framebuffer, // VkFramebuffer framebuffer; + renderArea, // VkRect2D renderArea; + 1u, // uint32_t clearValueCount; + &clearValue, // const VkClearValue* pClearValues; + }; + vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + + vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); + { + const VkDeviceSize offset = 0ull; + vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &offset); + } + vk.cmdDraw(*cmdBuffer, 1u, static_cast(numDrawInstances), 0u, 0u); + vk.cmdEndRenderPass(*cmdBuffer); + + // Prepare color image for copy + { + const VkImageMemoryBarrier barriers[] = + { + { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask; + VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; + VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; + *colorImage, // VkImage image; + colorSubresourceRange, // VkImageSubresourceRange subresourceRange; + }, + }; + + vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, + 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers); + } + // Color image -> host buffer + { + const VkBufferImageCopy region = + { + 0ull, // VkDeviceSize bufferOffset; + 0u, // uint32_t bufferRowLength; + 0u, // uint32_t bufferImageHeight; + makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u), // VkImageSubresourceLayers imageSubresource; + makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; + colorImageExtent, // VkExtent3D imageExtent; + }; + + vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer, 1u, ®ion); + } + // Buffer write barrier + { + const VkBufferMemoryBarrier barriers[] = + { + { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; + VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; + VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; + colorBuffer, // VkBuffer buffer; + 0ull, // VkDeviceSize offset; + VK_WHOLE_SIZE, // VkDeviceSize size; + }, + }; + + vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, + 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u); + } + + VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); + submitCommandsAndWait(vk, device, queue, *cmdBuffer); +} + +std::vector generatePerInstancePosition (const int numInstances) +{ + de::Random rng(1234); + std::vector positions; + + for (int i = 0; i < numInstances; ++i) + { + const float flipX = rng.getBool() ? 1.0f : -1.0f; + const float flipY = rng.getBool() ? 1.0f : -1.0f; + const float x = flipX * rng.getFloat(0.1f, 0.9f); // x mustn't be 0.0, because we are using sign() in the shader + const float y = flipY * rng.getFloat(0.0f, 0.7f); + + positions.push_back(Vec4(x, y, 0.0f, 1.0f)); + } + + return positions; +} + +//! Get a rectangle region of an image, using NDC coordinates (i.e. [-1, 1] range). +//! Result rect is cropped in either dimension to be inside the bounds of the image. +tcu::PixelBufferAccess getSubregion (tcu::PixelBufferAccess image, const float x, const float y, const float size) +{ + const float w = static_cast(image.getWidth()); + const float h = static_cast(image.getHeight()); + const float x1 = w * (x + 1.0f) * 0.5f; + const float y1 = h * (y + 1.0f) * 0.5f; + const float sx = w * size * 0.5f; + const float sy = h * size * 0.5f; + const float x2 = x1 + sx; + const float y2 = y1 + sy; + + // Round and clamp only after all of the above. + const int ix1 = std::max(deRoundFloatToInt32(x1), 0); + const int ix2 = std::min(deRoundFloatToInt32(x2), image.getWidth()); + const int iy1 = std::max(deRoundFloatToInt32(y1), 0); + const int iy2 = std::min(deRoundFloatToInt32(y2), image.getHeight()); + + return tcu::getSubregion(image, ix1, iy1, ix2 - ix1, iy2 - iy1); +} + +//! Must be in sync with the geometry shader code. +void generateReferenceImage(tcu::PixelBufferAccess image, const Vec4& clearColor, const std::vector& perInstancePosition, const int numInvocations) +{ + tcu::clear(image, clearColor); + + for (std::vector::const_iterator iterPosition = perInstancePosition.begin(); iterPosition != perInstancePosition.end(); ++iterPosition) + for (int invocationNdx = 0; invocationNdx < numInvocations; ++invocationNdx) + { + const float x = iterPosition->x(); + const float y = iterPosition->y(); + const float modifier = (numInvocations > 1 ? static_cast(invocationNdx) / static_cast(numInvocations - 1) : 0.0f); + const Vec4 color (deFloatAbs(x), deFloatAbs(y), 0.2f + 0.8f * modifier, 1.0f); + const float size = 0.05f + 0.03f * modifier; + const float dx = (deFloatSign(-x) - x) / static_cast(numInvocations); + const float xOffset = static_cast(invocationNdx) * dx; + const float yOffset = 0.3f * deFloatSin(12.0f * modifier); + + tcu::PixelBufferAccess rect = getSubregion(image, x + xOffset - size, y + yOffset - size, size + size); + tcu::clear(rect, color); + } +} + +void initPrograms (SourceCollections& programCollection, const TestParams params) +{ + // Vertex shader + { + std::ostringstream src; + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" + << "\n" + << "layout(location = 0) in vec4 in_position;\n" + << "\n" + << "out gl_PerVertex {\n" + << " vec4 gl_Position;\n" + << "};\n" + << "\n" + << "void main(void)\n" + << "{\n" + << " gl_Position = in_position;\n" + << "}\n"; + + programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); + } + + // Geometry shader + { + // The shader must be in sync with reference image rendering routine. + + std::ostringstream src; + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" + << "\n" + << "layout(points, invocations = " << params.numInvocations << ") in;\n" + << "layout(triangle_strip, max_vertices = 4) out;\n" + << "\n" + << "layout(location = 0) out vec4 out_color;\n" + << "\n" + << "in gl_PerVertex {\n" + << " vec4 gl_Position;\n" + << "} gl_in[];\n" + << "\n" + << "out gl_PerVertex {\n" + << " vec4 gl_Position;\n" + << "};\n" + << "\n" + << "void main(void)\n" + << "{\n" + << " const vec4 pos = gl_in[0].gl_Position;\n" + << " const float modifier = " << (params.numInvocations > 1 ? "float(gl_InvocationID) / float(" + de::toString(params.numInvocations - 1) + ")" : "0.0") << ";\n" + << " const vec4 color = vec4(abs(pos.x), abs(pos.y), 0.2 + 0.8 * modifier, 1.0);\n" + << " const float size = 0.05 + 0.03 * modifier;\n" + << " const float dx = (sign(-pos.x) - pos.x) / float(" << params.numInvocations << ");\n" + << " const vec4 offsetPos = pos + vec4(float(gl_InvocationID) * dx,\n" + << " 0.3 * sin(12.0 * modifier),\n" + << " 0.0,\n" + << " 0.0);\n" + << "\n" + << " gl_Position = offsetPos + vec4(-size, -size, 0.0, 0.0);\n" + << " out_color = color;\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = offsetPos + vec4(-size, size, 0.0, 0.0);\n" + << " out_color = color;\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = offsetPos + vec4( size, -size, 0.0, 0.0);\n" + << " out_color = color;\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = offsetPos + vec4( size, size, 0.0, 0.0);\n" + << " out_color = color;\n" + << " EmitVertex();\n" + << "}\n"; + + programCollection.glslSources.add("geom") << glu::GeometrySource(src.str()); + } + + // Fragment shader + { + std::ostringstream src; + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" + << "\n" + << "layout(location = 0) in vec4 in_color;\n" + << "layout(location = 0) out vec4 o_color;\n" + << "\n" + << "void main(void)\n" + << "{\n" + << " o_color = in_color;\n" + << "}\n"; + + programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); + } +} + +tcu::TestStatus test (Context& context, const TestParams params) +{ + const DeviceInterface& vk = context.getDeviceInterface(); + const InstanceInterface& vki = context.getInstanceInterface(); + const VkDevice device = context.getDevice(); + const VkPhysicalDevice physDevice = context.getPhysicalDevice(); + Allocator& allocator = context.getDefaultAllocator(); + + checkGeometryShaderSupport(vki, physDevice, params.numInvocations); + + const UVec2 renderSize (128u, 128u); + const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; + const Vec4 clearColor = Vec4(0.0f, 0.0f, 0.0f, 1.0f); + + const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)); + const Unique colorBuffer (makeBuffer(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT))); + const UniquePtr colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible)); + + const std::vector perInstancePosition = generatePerInstancePosition(params.numDrawInstances); + + { + context.getTestContext().getLog() + << tcu::TestLog::Message << "Rendering " << params.numDrawInstances << " instance(s) of colorful quads." << tcu::TestLog::EndMessage + << tcu::TestLog::Message << "Drawing " << params.numInvocations << " quad(s), each drawn by a geometry shader invocation." << tcu::TestLog::EndMessage; + } + + zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize); + draw(context, renderSize, colorFormat, clearColor, *colorBuffer, params.numDrawInstances, perInstancePosition); + + // Compare result + { + invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSize); + const tcu::ConstPixelBufferAccess result(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, colorBufferAlloc->getHostPtr()); + + tcu::TextureLevel reference(mapVkFormat(colorFormat), renderSize.x(), renderSize.y()); + generateReferenceImage(reference.getAccess(), clearColor, perInstancePosition, params.numInvocations); + + if (!tcu::fuzzyCompare(context.getTestContext().getLog(), "Image Compare", "Image Compare", reference.getAccess(), result, 0.01f, tcu::COMPARE_LOG_RESULT)) + return tcu::TestStatus::fail("Rendered image is incorrect"); + else + return tcu::TestStatus::pass("OK"); + } +} + +} // anonymous + +//! \note CTS requires shaders to be known ahead of time (some platforms use precompiled shaders), so we can't query a limit at runtime and generate +//! a shader based on that. This applies to number of GS invocations which can't be injected into the shader. +tcu::TestCaseGroup* createInstancedRenderingTests (tcu::TestContext& testCtx) +{ + MovePtr group(new tcu::TestCaseGroup(testCtx, "instanced", "Instanced rendering tests.")); + + const int drawInstanceCases[] = + { + 1, 2, 4, 8, + }; + const int invocationCases[] = + { + 1, 2, 8, 32, // required by the Vulkan spec + 64, 127, // larger than the minimum, but perhaps some implementations support it, so we'll try + }; + + for (const int* pNumDrawInstances = drawInstanceCases; pNumDrawInstances != drawInstanceCases + DE_LENGTH_OF_ARRAY(drawInstanceCases); ++pNumDrawInstances) + for (const int* pNumInvocations = invocationCases; pNumInvocations != invocationCases + DE_LENGTH_OF_ARRAY(invocationCases); ++pNumInvocations) + { + std::ostringstream caseName; + caseName << "draw_" << *pNumDrawInstances << "_instances_" << *pNumInvocations << "_geometry_invocations"; + + const TestParams params = + { + *pNumDrawInstances, + *pNumInvocations, + }; + + addFunctionCaseWithPrograms(group.get(), caseName.str(), "", initPrograms, test, params); + } + + return group.release(); +} + +} // geometry +} // vkt diff --git a/external/vulkancts/modules/vulkan/geometry/vktGeometryInstancedRenderingTests.hpp b/external/vulkancts/modules/vulkan/geometry/vktGeometryInstancedRenderingTests.hpp new file mode 100644 index 0000000..5aaeea0 --- /dev/null +++ b/external/vulkancts/modules/vulkan/geometry/vktGeometryInstancedRenderingTests.hpp @@ -0,0 +1,40 @@ +#ifndef _VKTGEOMETRYINSTANCEDRENDERINGTESTS_HPP +#define _VKTGEOMETRYINSTANCEDRENDERINGTESTS_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * Copyright (c) 2014 The Android Open Source Project + * + * 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. + * + *//*! + * \file + * \brief Geometry shader instanced rendering tests + *//*--------------------------------------------------------------------*/ + +#include "tcuDefs.hpp" +#include "tcuTestCase.hpp" + +namespace vkt +{ +namespace geometry +{ + +tcu::TestCaseGroup* createInstancedRenderingTests (tcu::TestContext& testCtx); + +} // geometry +} // vkt + +#endif // _VKTGEOMETRYINSTANCEDRENDERINGTESTS_HPP diff --git a/external/vulkancts/modules/vulkan/geometry/vktGeometryLayeredRenderingTests.cpp b/external/vulkancts/modules/vulkan/geometry/vktGeometryLayeredRenderingTests.cpp new file mode 100644 index 0000000..d5e10e9 --- /dev/null +++ b/external/vulkancts/modules/vulkan/geometry/vktGeometryLayeredRenderingTests.cpp @@ -0,0 +1,1073 @@ +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * Copyright (c) 2014 The Android Open Source Project + * + * 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. + * + *//*! + * \file + * \brief Geometry shader layered rendering tests + *//*--------------------------------------------------------------------*/ + +#include "vktGeometryLayeredRenderingTests.hpp" +#include "vktTestCase.hpp" +#include "vktTestCaseUtil.hpp" +#include "vktGeometryTestsUtil.hpp" + +#include "vkPrograms.hpp" +#include "vkStrUtil.hpp" +#include "vkQueryUtil.hpp" +#include "vkMemUtil.hpp" +#include "vkRefUtil.hpp" +#include "vkTypeUtil.hpp" +#include "vkImageUtil.hpp" + +#include "deStringUtil.hpp" +#include "deUniquePtr.hpp" + +#include "tcuTextureUtil.hpp" +#include "tcuVectorUtil.hpp" + +namespace vkt +{ +namespace geometry +{ +namespace +{ +using namespace vk; +using de::MovePtr; +using de::UniquePtr; +using tcu::Vec4; +using tcu::IVec3; + +enum TestType +{ + TEST_TYPE_DEFAULT_LAYER, // !< draw to default layer + TEST_TYPE_SINGLE_LAYER, // !< draw to single layer + TEST_TYPE_ALL_LAYERS, // !< draw all layers + TEST_TYPE_DIFFERENT_CONTENT, // !< draw different content to different layers + TEST_TYPE_LAYER_ID, // !< draw to all layers, verify gl_Layer fragment input + TEST_TYPE_INVOCATION_PER_LAYER, // !< draw to all layers, one invocation per layer + TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION, // !< draw to all layers, multiple invocations write to multiple layers +}; + +struct ImageParams +{ + VkImageViewType viewType; + VkExtent3D size; + deUint32 numLayers; +}; + +struct TestParams +{ + TestType testType; + ImageParams image; +}; + +static const float s_colors[][4] = +{ + { 1.0f, 1.0f, 1.0f, 1.0f }, // white + { 1.0f, 0.0f, 0.0f, 1.0f }, // red + { 0.0f, 1.0f, 0.0f, 1.0f }, // green + { 0.0f, 0.0f, 1.0f, 1.0f }, // blue + { 1.0f, 1.0f, 0.0f, 1.0f }, // yellow + { 1.0f, 0.0f, 1.0f, 1.0f }, // magenta +}; + +deUint32 getTargetLayer (const ImageParams& imageParams) +{ + if (imageParams.viewType == VK_IMAGE_VIEW_TYPE_3D) + return imageParams.size.depth / 2; + else + return imageParams.numLayers / 2; +} + +std::string getShortImageViewTypeName (const VkImageViewType imageViewType) +{ + std::string s(getImageViewTypeName(imageViewType)); + return de::toLower(s.substr(19)); +} + +VkImageType getImageType (const VkImageViewType viewType) +{ + switch (viewType) + { + case VK_IMAGE_VIEW_TYPE_1D: + case VK_IMAGE_VIEW_TYPE_1D_ARRAY: + return VK_IMAGE_TYPE_1D; + + case VK_IMAGE_VIEW_TYPE_2D: + case VK_IMAGE_VIEW_TYPE_2D_ARRAY: + case VK_IMAGE_VIEW_TYPE_CUBE: + case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: + return VK_IMAGE_TYPE_2D; + + case VK_IMAGE_VIEW_TYPE_3D: + return VK_IMAGE_TYPE_3D; + + default: + DE_ASSERT(0); + return VK_IMAGE_TYPE_LAST; + } +} + +inline bool isCubeImageViewType (const VkImageViewType viewType) +{ + return viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY; +} + +VkImageCreateInfo makeImageCreateInfo (const VkImageCreateFlags flags, const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const VkImageUsageFlags usage) +{ + const VkImageCreateInfo imageParams = + { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + flags, // VkImageCreateFlags flags; + type, // VkImageType imageType; + format, // VkFormat format; + size, // VkExtent3D extent; + 1u, // deUint32 mipLevels; + numLayers, // deUint32 arrayLayers; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; + usage, // VkImageUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 0u, // deUint32 queueFamilyIndexCount; + DE_NULL, // const deUint32* pQueueFamilyIndices; + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + }; + return imageParams; +} + +Move makeRenderPass (const DeviceInterface& vk, + const VkDevice device, + const VkFormat colorFormat) +{ + const VkAttachmentDescription colorAttachmentDescription = + { + (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; + colorFormat, // VkFormat format; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; + VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; + }; + + const VkAttachmentReference colorAttachmentRef = + { + 0u, // deUint32 attachment; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; + }; + + const VkSubpassDescription subpassDescription = + { + (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; + VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; + 0u, // deUint32 inputAttachmentCount; + DE_NULL, // const VkAttachmentReference* pInputAttachments; + 1u, // deUint32 colorAttachmentCount; + &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments; + DE_NULL, // const VkAttachmentReference* pResolveAttachments; + DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; + 0u, // deUint32 preserveAttachmentCount; + DE_NULL // const deUint32* pPreserveAttachments; + }; + + const VkRenderPassCreateInfo renderPassInfo = + { + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; + 1u, // deUint32 attachmentCount; + &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments; + 1u, // deUint32 subpassCount; + &subpassDescription, // const VkSubpassDescription* pSubpasses; + 0u, // deUint32 dependencyCount; + DE_NULL // const VkSubpassDependency* pDependencies; + }; + + return createRenderPass(vk, device, &renderPassInfo); +} + +Move makeGraphicsPipeline (const DeviceInterface& vk, + const VkDevice device, + const VkPipelineLayout pipelineLayout, + const VkRenderPass renderPass, + const VkShaderModule vertexModule, + const VkShaderModule geometryModule, + const VkShaderModule fragmentModule, + const VkExtent2D renderSize) +{ + const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; + 0u, // uint32_t vertexBindingDescriptionCount; + DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; + 0u, // uint32_t vertexAttributeDescriptionCount; + DE_NULL, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; + }; + + const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags; + VK_PRIMITIVE_TOPOLOGY_POINT_LIST, // VkPrimitiveTopology topology; + VK_FALSE, // VkBool32 primitiveRestartEnable; + }; + + const VkViewport viewport = makeViewport( + 0.0f, 0.0f, + static_cast(renderSize.width), static_cast(renderSize.height), + 0.0f, 1.0f); + const VkRect2D scissor = + { + makeOffset2D(0, 0), + makeExtent2D(renderSize.width, renderSize.height), + }; + + const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags; + 1u, // uint32_t viewportCount; + &viewport, // const VkViewport* pViewports; + 1u, // uint32_t scissorCount; + &scissor, // const VkRect2D* pScissors; + }; + + const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags; + VK_FALSE, // VkBool32 depthClampEnable; + VK_FALSE, // VkBool32 rasterizerDiscardEnable; + VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; + VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; + VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; + VK_FALSE, // VkBool32 depthBiasEnable; + 0.0f, // float depthBiasConstantFactor; + 0.0f, // float depthBiasClamp; + 0.0f, // float depthBiasSlopeFactor; + 1.0f, // float lineWidth; + }; + + const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; + VK_FALSE, // VkBool32 sampleShadingEnable; + 0.0f, // float minSampleShading; + DE_NULL, // const VkSampleMask* pSampleMask; + VK_FALSE, // VkBool32 alphaToCoverageEnable; + VK_FALSE // VkBool32 alphaToOneEnable; + }; + + const VkStencilOpState stencilOpState = makeStencilOpState( + VK_STENCIL_OP_KEEP, // stencil fail + VK_STENCIL_OP_KEEP, // depth & stencil pass + VK_STENCIL_OP_KEEP, // depth only fail + VK_COMPARE_OP_ALWAYS, // compare op + 0u, // compare mask + 0u, // write mask + 0u); // reference + + VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags; + VK_FALSE, // VkBool32 depthTestEnable; + VK_FALSE, // VkBool32 depthWriteEnable; + VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; + VK_FALSE, // VkBool32 depthBoundsTestEnable; + VK_FALSE, // VkBool32 stencilTestEnable; + stencilOpState, // VkStencilOpState front; + stencilOpState, // VkStencilOpState back; + 0.0f, // float minDepthBounds; + 1.0f, // float maxDepthBounds; + }; + + const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = + { + VK_FALSE, // VkBool32 blendEnable; + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; + VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; + VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; + VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; + VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; + colorComponentsAll, // VkColorComponentFlags colorWriteMask; + }; + + const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; + VK_FALSE, // VkBool32 logicOpEnable; + VK_LOGIC_OP_COPY, // VkLogicOp logicOp; + 1u, // deUint32 attachmentCount; + &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; + { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; + }; + + const VkPipelineShaderStageCreateInfo pShaderStages[] = + { + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; + vertexModule, // VkShaderModule module; + "main", // const char* pName; + DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; + }, + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_GEOMETRY_BIT, // VkShaderStageFlagBits stage; + geometryModule, // VkShaderModule module; + "main", // const char* pName; + DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; + }, + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; + fragmentModule, // VkShaderModule module; + "main", // const char* pName; + DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; + }, + }; + + const VkGraphicsPipelineCreateInfo graphicsPipelineInfo = + { + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; + DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount; + pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages; + &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; + DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; + &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState; + &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; + &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; + &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; + &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; + DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; + pipelineLayout, // VkPipelineLayout layout; + renderPass, // VkRenderPass renderPass; + 0u, // deUint32 subpass; + DE_NULL, // VkPipeline basePipelineHandle; + 0, // deInt32 basePipelineIndex; + }; + + return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo); +} + +//! Convenience wrapper to access 1D, 2D, and 3D image layers/slices in a uniform way. +class LayeredImageAccess +{ +public: + static LayeredImageAccess create (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData) + { + if (type == VK_IMAGE_TYPE_1D) + return LayeredImageAccess(format, size.width, numLayers, pData); + else + return LayeredImageAccess(type, format, size, numLayers, pData); + } + + inline tcu::ConstPixelBufferAccess getLayer (const int layer) const + { + return tcu::getSubregion(m_wholeImage, 0, (m_1dModifier * layer), ((~m_1dModifier & 1) * layer), m_width, m_height, 1); + } + + inline int getNumLayersOrSlices (void) const + { + return m_layers; + } + +private: + // Specialized for 1D images. + LayeredImageAccess (const VkFormat format, const deUint32 width, const deUint32 numLayers, const void* pData) + : m_width (static_cast(width)) + , m_height (1) + , m_1dModifier (1) + , m_layers (numLayers) + , m_wholeImage (tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_layers, 1, pData)) + { + } + + LayeredImageAccess (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData) + : m_width (static_cast(size.width)) + , m_height (static_cast(size.height)) + , m_1dModifier (0) + , m_layers (static_cast(type == VK_IMAGE_TYPE_3D ? size.depth : numLayers)) + , m_wholeImage (tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_height, m_layers, pData)) + { + } + + const int m_width; + const int m_height; + const int m_1dModifier; + const int m_layers; + const tcu::ConstPixelBufferAccess m_wholeImage; +}; + +inline bool compareColors (const Vec4& colorA, const Vec4& colorB, const Vec4& threshold) +{ + return tcu::allEqual( + tcu::lessThan(tcu::abs(colorA - colorB), threshold), + tcu::BVec4(true, true, true, true)); +} + +bool verifyImageSingleColoredRow (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image, const float rowWidthRatio, const tcu::Vec4& barColor) +{ + DE_ASSERT(rowWidthRatio > 0.0f); + + const Vec4 black (0.0f, 0.0f, 0.0f, 1.0f); + const Vec4 green (0.0f, 1.0f, 0.0f, 1.0f); + const Vec4 red (1.0f, 0.0f, 0.0f, 1.0f); + const Vec4 threshold (0.02f); + const int barLength = static_cast(rowWidthRatio * static_cast(image.getWidth())); + const int barLengthThreshold = 1; + tcu::TextureLevel errorMask (image.getFormat(), image.getWidth(), image.getHeight()); + tcu::PixelBufferAccess errorMaskAccess = errorMask.getAccess(); + + tcu::clear(errorMask.getAccess(), green); + + log << tcu::TestLog::Message + << "Expecting all pixels with distance less or equal to (about) " << barLength + << " pixels from left border to be of color " << barColor.swizzle(0, 1, 2) << "." + << tcu::TestLog::EndMessage; + + bool allPixelsOk = true; + + for (int y = 0; y < image.getHeight(); ++y) + for (int x = 0; x < image.getWidth(); ++x) + { + const Vec4 color = image.getPixel(x, y); + const bool isBlack = compareColors(color, black, threshold); + const bool isColor = compareColors(color, barColor, threshold); + + bool isOk; + + if (x <= barLength - barLengthThreshold) + isOk = isColor; + else if (x >= barLength + barLengthThreshold) + isOk = isBlack; + else + isOk = isColor || isBlack; + + allPixelsOk &= isOk; + + if (!isOk) + errorMaskAccess.setPixel(red, x, y); + } + + if (allPixelsOk) + { + log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage + << tcu::TestLog::ImageSet("LayerContent", "Layer content") + << tcu::TestLog::Image("Layer", "Layer", image) + << tcu::TestLog::EndImageSet; + return true; + } + else + { + log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage + << tcu::TestLog::ImageSet("LayerContent", "Layer content") + << tcu::TestLog::Image("Layer", "Layer", image) + << tcu::TestLog::Image("ErrorMask", "Errors", errorMask) + << tcu::TestLog::EndImageSet; + return false; + } + + log << tcu::TestLog::Image("LayerContent", "Layer content", image); + + return allPixelsOk; +} + +bool verifyEmptyImage (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image) +{ + log << tcu::TestLog::Message << "Expecting empty image" << tcu::TestLog::EndMessage; + + const Vec4 black (0.0f, 0.0f, 0.0f, 1.0f); + const Vec4 threshold (0.02f); + + for (int y = 0; y < image.getHeight(); ++y) + for (int x = 0; x < image.getWidth(); ++x) + { + const Vec4 color = image.getPixel(x, y); + + if (!compareColors(color, black, threshold)) + { + log << tcu::TestLog::Message + << "Found (at least) one bad pixel at " << x << "," << y << ". Pixel color is not background color." + << tcu::TestLog::EndMessage + << tcu::TestLog::ImageSet("LayerContent", "Layer content") + << tcu::TestLog::Image("Layer", "Layer", image) + << tcu::TestLog::EndImageSet; + return false; + } + } + + log << tcu::TestLog::Message << "Image is valid" << tcu::TestLog::EndMessage; + + return true; +} + +bool verifyLayerContent (tcu::TestLog& log, const TestType testType, const tcu::ConstPixelBufferAccess image, const int layerNdx, const int numLayers) +{ + const Vec4 white (1.0f, 1.0f, 1.0f, 1.0f); + const int targetLayer = numLayers / 2; + const float variableBarRatio = static_cast(layerNdx) / static_cast(numLayers); + + switch (testType) + { + case TEST_TYPE_DEFAULT_LAYER: + if (layerNdx == 0) + return verifyImageSingleColoredRow(log, image, 0.5f, white); + else + return verifyEmptyImage(log, image); + + case TEST_TYPE_SINGLE_LAYER: + if (layerNdx == targetLayer) + return verifyImageSingleColoredRow(log, image, 0.5f, white); + else + return verifyEmptyImage(log, image); + + case TEST_TYPE_ALL_LAYERS: + case TEST_TYPE_INVOCATION_PER_LAYER: + return verifyImageSingleColoredRow(log, image, 0.5f, s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]); + + case TEST_TYPE_DIFFERENT_CONTENT: + case TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION: + if (layerNdx == 0) + return verifyEmptyImage(log, image); + else + return verifyImageSingleColoredRow(log, image, variableBarRatio, white); + + case TEST_TYPE_LAYER_ID: + { + // This code must be in sync with the fragment shader. + const tcu::Vec4 layerColor( (layerNdx % 2) == 1 ? 1.0f : 0.5f, + ((layerNdx/2) % 2) == 1 ? 1.0f : 0.5f, + layerNdx == 0 ? 1.0f : 0.0f, + 1.0f); + return verifyImageSingleColoredRow(log, image, 0.5f, layerColor); + } + + default: + DE_ASSERT(0); + return false; + }; +} + +std::string getLayerDescription (const VkImageViewType viewType, const int layer) +{ + std::ostringstream str; + const int numCubeFaces = 6; + + if (isCubeImageViewType(viewType)) + str << "cube " << (layer / numCubeFaces) << ", face " << (layer % numCubeFaces); + else if (viewType == VK_IMAGE_VIEW_TYPE_3D) + str << "slice z = " << layer; + else + str << "layer " << layer; + + return str.str(); +} + +bool verifyResults (tcu::TestLog& log, const TestParams& params, const VkFormat colorFormat, const void* resultData) +{ + const LayeredImageAccess image = LayeredImageAccess::create(getImageType(params.image.viewType), colorFormat, params.image.size, params.image.numLayers, resultData); + + int numGoodLayers = 0; + + for (int layerNdx = 0; layerNdx < image.getNumLayersOrSlices(); ++layerNdx) + { + const tcu::ConstPixelBufferAccess layerImage = image.getLayer(layerNdx); + + log << tcu::TestLog::Message << "Verifying " << getLayerDescription(params.image.viewType, layerNdx) << tcu::TestLog::EndMessage; + + if (verifyLayerContent(log, params.testType, layerImage, layerNdx, image.getNumLayersOrSlices())) + ++numGoodLayers; + } + + return numGoodLayers == image.getNumLayersOrSlices(); +} + +std::string toGlsl (const Vec4& v) +{ + std::ostringstream str; + str << "vec4("; + for (int i = 0; i < 4; ++i) + str << (i != 0 ? ", " : "") << de::floatToString(v[i], 1); + str << ")"; + return str.str(); +} + +void initPrograms (SourceCollections& programCollection, const TestParams params) +{ + const bool geomOutputColor = (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_INVOCATION_PER_LAYER); + + // Vertex shader + { + std::ostringstream src; + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" + << "\n" + << "void main(void)\n" + << "{\n" + << "}\n"; + + programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); + } + + // Geometry shader + { + const int maxVertices = (params.testType == TEST_TYPE_DIFFERENT_CONTENT) ? (params.image.numLayers + 1) * params.image.numLayers : + (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_LAYER_ID) ? params.image.numLayers * 4 : + (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION) ? 6 : 4; + + std::ostringstream src; + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" + << "\n"; + + if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION) + src << "layout(points, invocations = " << params.image.numLayers << ") in;\n"; + else + src << "layout(points) in;\n"; + + src << "layout(triangle_strip, max_vertices = " << maxVertices << ") out;\n" + << "\n" + << (geomOutputColor ? "layout(location = 0) out vec4 vert_color;\n\n" : "") + << "out gl_PerVertex {\n" + << " vec4 gl_Position;\n" + << "};\n" + << "\n" + << "void main(void)\n" + << "{\n"; + + std::ostringstream colorTable; + { + const int numColors = DE_LENGTH_OF_ARRAY(s_colors); + + colorTable << " const vec4 colors[" << numColors << "] = vec4[" << numColors << "]("; + + const std::string padding(colorTable.str().length(), ' '); + + for (int i = 0; i < numColors; ++i) + colorTable << (i != 0 ? ",\n" + padding : "") << toGlsl(s_colors[i]); + + colorTable << ");\n"; + } + + if (params.testType == TEST_TYPE_DEFAULT_LAYER) + { + src << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n" + << " EmitVertex();\n"; + } + else if (params.testType == TEST_TYPE_SINGLE_LAYER) + { + const deUint32 targetLayer = getTargetLayer(params.image); + + src << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" + << " gl_Layer = " << targetLayer << ";\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" + << " gl_Layer = " << targetLayer << ";\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n" + << " gl_Layer = " << targetLayer << ";\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n" + << " gl_Layer = " << targetLayer << ";\n" + << " EmitVertex();\n"; + } + else if (params.testType == TEST_TYPE_ALL_LAYERS) + { + src << colorTable.str() + << "\n" + << " for (int layerNdx = 0; layerNdx < " << params.image.numLayers << "; ++layerNdx) {\n" + << " const int colorNdx = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n" + << "\n" + << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" + << " gl_Layer = layerNdx;\n" + << " vert_color = colors[colorNdx];\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" + << " gl_Layer = layerNdx;\n" + << " vert_color = colors[colorNdx];\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n" + << " gl_Layer = layerNdx;\n" + << " vert_color = colors[colorNdx];\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n" + << " gl_Layer = layerNdx;\n" + << " vert_color = colors[colorNdx];\n" + << " EmitVertex();\n" + << " EndPrimitive();\n" + << " };\n"; + } + else if (params.testType == TEST_TYPE_LAYER_ID) + { + src << " for (int layerNdx = 0; layerNdx < " << params.image.numLayers << "; ++layerNdx) {\n" + << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" + << " gl_Layer = layerNdx;\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" + << " gl_Layer = layerNdx;\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n" + << " gl_Layer = layerNdx;\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n" + << " gl_Layer = layerNdx;\n" + << " EmitVertex();\n" + << " EndPrimitive();\n" + << " };\n"; + } + else if (params.testType == TEST_TYPE_DIFFERENT_CONTENT) + { + src << " for (int layerNdx = 0; layerNdx < " << params.image.numLayers << "; ++layerNdx) {\n" + << " for (int colNdx = 0; colNdx <= layerNdx; ++colNdx) {\n" + << " const float posX = float(colNdx) / float(" << params.image.numLayers << ") * 2.0 - 1.0;\n" + << "\n" + << " gl_Position = vec4(posX, 1.0, 0.0, 1.0);\n" + << " gl_Layer = layerNdx;\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = vec4(posX, -1.0, 0.0, 1.0);\n" + << " gl_Layer = layerNdx;\n" + << " EmitVertex();\n" + << " }\n" + << " EndPrimitive();\n" + << " }\n"; + } + else if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER) + { + src << colorTable.str() + << " const int colorNdx = gl_InvocationID % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n" + << "\n" + << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" + << " gl_Layer = gl_InvocationID;\n" + << " vert_color = colors[colorNdx];\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" + << " gl_Layer = gl_InvocationID;\n" + << " vert_color = colors[colorNdx];\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n" + << " gl_Layer = gl_InvocationID;\n" + << " vert_color = colors[colorNdx];\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n" + << " gl_Layer = gl_InvocationID;\n" + << " vert_color = colors[colorNdx];\n" + << " EmitVertex();\n" + << " EndPrimitive();\n"; + } + else if (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION) + { + src << " const int layerA = gl_InvocationID;\n" + << " const int layerB = (gl_InvocationID + 1) % " << params.image.numLayers << ";\n" + << " const float aEnd = float(layerA) / float(" << params.image.numLayers << ") * 2.0 - 1.0;\n" + << " const float bEnd = float(layerB) / float(" << params.image.numLayers << ") * 2.0 - 1.0;\n" + << "\n" + << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" + << " gl_Layer = layerA;\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" + << " gl_Layer = layerA;\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = vec4(aEnd, -1.0, 0.0, 1.0);\n" + << " gl_Layer = layerA;\n" + << " EmitVertex();\n" + << " EndPrimitive();\n" + << "\n" + << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" + << " gl_Layer = layerB;\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = vec4(bEnd, 1.0, 0.0, 1.0);\n" + << " gl_Layer = layerB;\n" + << " EmitVertex();\n" + << "\n" + << " gl_Position = vec4(bEnd, -1.0, 0.0, 1.0);\n" + << " gl_Layer = layerB;\n" + << " EmitVertex();\n" + << " EndPrimitive();\n"; + } + else + DE_ASSERT(0); + + src << "}\n"; // end main + + programCollection.glslSources.add("geom") << glu::GeometrySource(src.str()); + } + + // Fragment shader + { + std::ostringstream src; + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" + << "\n" + << "layout(location = 0) out vec4 o_color;\n" + << (geomOutputColor ? "layout(location = 0) in vec4 vert_color;\n" : "") + << "\n" + << "void main(void)\n" + << "{\n"; + + if (params.testType == TEST_TYPE_LAYER_ID) + { + // This code must be in sync with verifyLayerContent() + src << " o_color = vec4( (gl_Layer % 2) == 1 ? 1.0 : 0.5,\n" + << " ((gl_Layer/2) % 2) == 1 ? 1.0 : 0.5,\n" + << " gl_Layer == 0 ? 1.0 : 0.0,\n" + << " 1.0);\n"; + } + else if (geomOutputColor) + src << " o_color = vert_color;\n"; + else + src << " o_color = vec4(1.0);\n"; + + src << "}\n"; + + programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); + } +} + +tcu::TestStatus test (Context& context, const TestParams params) +{ + const DeviceInterface& vk = context.getDeviceInterface(); + const InstanceInterface& vki = context.getInstanceInterface(); + const VkDevice device = context.getDevice(); + const VkPhysicalDevice physDevice = context.getPhysicalDevice(); + const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); + const VkQueue queue = context.getUniversalQueue(); + Allocator& allocator = context.getDefaultAllocator(); + + checkGeometryShaderSupport(vki, physDevice); + + const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; + const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers); + const Vec4 clearColor = Vec4(0.0f, 0.0f, 0.0f, 1.0f); + const VkDeviceSize colorBufferSize = params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * tcu::getPixelSize(mapVkFormat(colorFormat)); + const VkImageCreateFlags imageCreateFlags = (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0); + + const Unique colorImage (makeImage (vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size, + params.image.numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT))); + const UniquePtr colorImageAlloc (bindImage (vk, device, allocator, *colorImage, MemoryRequirement::Any)); + const Unique colorAttachment (makeImageView (vk, device, *colorImage, params.image.viewType, colorFormat, colorSubresourceRange)); + const Unique colorBuffer (makeBuffer (vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT))); + const UniquePtr colorBufferAlloc (bindBuffer (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible)); + + const Unique vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u)); + const Unique geometryModule (createShaderModule (vk, device, context.getBinaryCollection().get("geom"), 0u)); + const Unique fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u)); + + const Unique renderPass (makeRenderPass (vk, device, colorFormat)); + const Unique framebuffer (makeFramebuffer (vk, device, *renderPass, *colorAttachment, params.image.size.width, params.image.size.height, params.image.numLayers)); + const Unique pipelineLayout (makePipelineLayout (vk, device)); + const Unique pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule, + makeExtent2D(params.image.size.width, params.image.size.height))); + const Unique cmdPool (makeCommandPool (vk, device, queueFamilyIndex)); + const Unique cmdBuffer (makeCommandBuffer (vk, device, *cmdPool)); + + zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize); + + beginCommandBuffer(vk, *cmdBuffer); + + const VkClearValue clearValue = makeClearValueColor(clearColor); + const VkRect2D renderArea = + { + makeOffset2D(0, 0), + makeExtent2D(params.image.size.width, params.image.size.height), + }; + const VkRenderPassBeginInfo renderPassBeginInfo = + { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + *renderPass, // VkRenderPass renderPass; + *framebuffer, // VkFramebuffer framebuffer; + renderArea, // VkRect2D renderArea; + 1u, // uint32_t clearValueCount; + &clearValue, // const VkClearValue* pClearValues; + }; + vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + + vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); + vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u); + vk.cmdEndRenderPass(*cmdBuffer); + + // Prepare color image for copy + { + const VkImageMemoryBarrier barriers[] = + { + { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask; + VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; + VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; + *colorImage, // VkImage image; + colorSubresourceRange, // VkImageSubresourceRange subresourceRange; + }, + }; + + vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, + 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers); + } + // Color image -> host buffer + { + const VkBufferImageCopy region = + { + 0ull, // VkDeviceSize bufferOffset; + 0u, // uint32_t bufferRowLength; + 0u, // uint32_t bufferImageHeight; + makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, params.image.numLayers), // VkImageSubresourceLayers imageSubresource; + makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; + params.image.size, // VkExtent3D imageExtent; + }; + + vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion); + } + // Buffer write barrier + { + const VkBufferMemoryBarrier barriers[] = + { + { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; + VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; + VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; + *colorBuffer, // VkBuffer buffer; + 0ull, // VkDeviceSize offset; + VK_WHOLE_SIZE, // VkDeviceSize size; + }, + }; + + vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, + 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u); + } + + VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); + submitCommandsAndWait(vk, device, queue, *cmdBuffer); + + invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSize); + + if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr())) + return tcu::TestStatus::fail("Rendered images are incorrect"); + else + return tcu::TestStatus::pass("OK"); +} + +} // anonymous + +tcu::TestCaseGroup* createLayeredRenderingTests (tcu::TestContext& testCtx) +{ + MovePtr group(new tcu::TestCaseGroup(testCtx, "layered", "Layered rendering tests.")); + + const struct + { + TestType test; + const char* name; + const char* description; + } testTypes[] = + { + { TEST_TYPE_DEFAULT_LAYER, "render_to_default_layer", "Render to the default layer" }, + { TEST_TYPE_SINGLE_LAYER, "render_to_one", "Render to one layer" }, + { TEST_TYPE_ALL_LAYERS, "render_to_all", "Render to all layers" }, + { TEST_TYPE_DIFFERENT_CONTENT, "render_different_content", "Render different data to different layers" }, + { TEST_TYPE_LAYER_ID, "fragment_layer", "Read gl_Layer in fragment shader" }, + { TEST_TYPE_INVOCATION_PER_LAYER, "invocation_per_layer", "Render to multiple layers with multiple invocations, one invocation per layer" }, + { TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION, "multiple_layers_per_invocation", "Render to multiple layers with multiple invocations, multiple layers per invocation", }, + }; + + const ImageParams imageParams[] = + { + { VK_IMAGE_VIEW_TYPE_1D_ARRAY, { 64, 1, 1 }, 4 }, + { VK_IMAGE_VIEW_TYPE_2D_ARRAY, { 64, 64, 1 }, 4 }, + { VK_IMAGE_VIEW_TYPE_CUBE, { 64, 64, 1 }, 6 }, + { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, { 64, 64, 1 }, 2*6 }, + // No support for rendering to 3d image slices in Vulkan 1.0 + }; + + for (int imageParamNdx = 0; imageParamNdx < DE_LENGTH_OF_ARRAY(imageParams); ++imageParamNdx) + { + MovePtr viewTypeGroup(new tcu::TestCaseGroup(testCtx, getShortImageViewTypeName(imageParams[imageParamNdx].viewType).c_str(), "")); + + for (int testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx) + { + const TestParams params = + { + testTypes[testTypeNdx].test, + imageParams[imageParamNdx], + }; + addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, initPrograms, test, params); + } + + group->addChild(viewTypeGroup.release()); + } + + return group.release(); +} + +} // geometry +} // vkt diff --git a/external/vulkancts/modules/vulkan/geometry/vktGeometryLayeredRenderingTests.hpp b/external/vulkancts/modules/vulkan/geometry/vktGeometryLayeredRenderingTests.hpp new file mode 100644 index 0000000..da43466 --- /dev/null +++ b/external/vulkancts/modules/vulkan/geometry/vktGeometryLayeredRenderingTests.hpp @@ -0,0 +1,40 @@ +#ifndef _VKTGEOMETRYLAYEREDRENDERINGTESTS_HPP +#define _VKTGEOMETRYLAYEREDRENDERINGTESTS_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * Copyright (c) 2014 The Android Open Source Project + * + * 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. + * + *//*! + * \file + * \brief Geometry shader layered rendering tests + *//*--------------------------------------------------------------------*/ + +#include "tcuDefs.hpp" +#include "tcuTestCase.hpp" + +namespace vkt +{ +namespace geometry +{ + +tcu::TestCaseGroup* createLayeredRenderingTests (tcu::TestContext& testCtx); + +} // geometry +} // vkt + +#endif // _VKTGEOMETRYLAYEREDRENDERINGTESTS_HPP diff --git a/external/vulkancts/modules/vulkan/geometry/vktGeometryTests.cpp b/external/vulkancts/modules/vulkan/geometry/vktGeometryTests.cpp new file mode 100644 index 0000000..2afe7b5 --- /dev/null +++ b/external/vulkancts/modules/vulkan/geometry/vktGeometryTests.cpp @@ -0,0 +1,60 @@ +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * + * 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. + * + *//*! + * \file + * \brief Geometry Shader Tests + *//*--------------------------------------------------------------------*/ + +#include "vktGeometryTests.hpp" +#include "vktGeometryBasicGeometryShaderTests.hpp" +#include "vktGeometryInputGeometryShaderTests.hpp" +#include "vktGeometryLayeredRenderingTests.hpp" +#include "vktGeometryInstancedRenderingTests.hpp" +#include "vktGeometryVaryingGeometryShaderTests.hpp" +#include "vktGeometryEmitGeometryShaderTests.hpp" +#include "vktTestGroupUtil.hpp" + +namespace vkt +{ +namespace geometry +{ +namespace +{ + +void createChildren (tcu::TestCaseGroup* geometryTests) +{ + tcu::TestContext& testCtx = geometryTests->getTestContext(); + + geometryTests->addChild(createInputGeometryShaderTests (testCtx)); + geometryTests->addChild(createBasicGeometryShaderTests (testCtx)); + geometryTests->addChild(createLayeredRenderingTests (testCtx)); + geometryTests->addChild(createInstancedRenderingTests (testCtx)); + geometryTests->addChild(createVaryingGeometryShaderTests (testCtx)); + geometryTests->addChild(createEmitGeometryShaderTests (testCtx)); +} + +} // anonymous + +tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx) +{ + return createTestGroup(testCtx, "geometry", "Geometry shader tests", createChildren); +} + +} // geometry +} // vkt diff --git a/external/vulkancts/modules/vulkan/geometry/vktGeometryTests.hpp b/external/vulkancts/modules/vulkan/geometry/vktGeometryTests.hpp new file mode 100644 index 0000000..b2c18c0 --- /dev/null +++ b/external/vulkancts/modules/vulkan/geometry/vktGeometryTests.hpp @@ -0,0 +1,39 @@ +#ifndef _VKTGEOMETRYTESTS_HPP +#define _VKTGEOMETRYTESTS_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * + * 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. + * + *//*! + * \file + * \brief Geometry Shader Tests + *//*--------------------------------------------------------------------*/ + +#include "tcuDefs.hpp" +#include "tcuTestCase.hpp" + +namespace vkt +{ +namespace geometry +{ + +tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx); + +} // geometry +} // vkt + +#endif // _VKTGEOMETRYTESTS_HPP diff --git a/external/vulkancts/modules/vulkan/geometry/vktGeometryTestsUtil.cpp b/external/vulkancts/modules/vulkan/geometry/vktGeometryTestsUtil.cpp new file mode 100644 index 0000000..0c8f63f --- /dev/null +++ b/external/vulkancts/modules/vulkan/geometry/vktGeometryTestsUtil.cpp @@ -0,0 +1,765 @@ +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2014 The Android Open Source Project + * Copyright (c) 2016 The Khronos Group Inc. + * + * 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. + * + *//*! + * \file + * \brief Geometry Utilities + *//*--------------------------------------------------------------------*/ + +#include "vktGeometryTestsUtil.hpp" +#include "vkTypeUtil.hpp" +#include "vkDefs.hpp" +#include "tcuImageCompare.hpp" + +#include "tcuImageIO.hpp" + +#include "deMath.h" + +using namespace vk; + +namespace vkt +{ +namespace geometry +{ + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::setShader (const DeviceInterface& vk, + const VkDevice device, + const VkShaderStageFlagBits stage, + const ProgramBinary& binary, + const VkSpecializationInfo* specInfo) +{ + VkShaderModule module; + switch (stage) + { + case (VK_SHADER_STAGE_VERTEX_BIT): + DE_ASSERT(m_vertexShaderModule.get() == DE_NULL); + m_vertexShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0); + module = *m_vertexShaderModule; + break; + + case (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT): + DE_ASSERT(m_tessControlShaderModule.get() == DE_NULL); + m_tessControlShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0); + module = *m_tessControlShaderModule; + break; + + case (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT): + DE_ASSERT(m_tessEvaluationShaderModule.get() == DE_NULL); + m_tessEvaluationShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0); + module = *m_tessEvaluationShaderModule; + break; + + case (VK_SHADER_STAGE_GEOMETRY_BIT): + DE_ASSERT(m_geometryShaderModule.get() == DE_NULL); + m_geometryShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0); + module = *m_geometryShaderModule; + break; + + case (VK_SHADER_STAGE_FRAGMENT_BIT): + DE_ASSERT(m_fragmentShaderModule.get() == DE_NULL); + m_fragmentShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0); + module = *m_fragmentShaderModule; + break; + + default: + DE_FATAL("Invalid shader stage"); + return *this; + } + + const VkPipelineShaderStageCreateInfo pipelineShaderStageInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; + stage, // VkShaderStageFlagBits stage; + module, // VkShaderModule module; + "main", // const char* pName; + specInfo, // const VkSpecializationInfo* pSpecializationInfo; + }; + + m_shaderStageFlags |= stage; + m_shaderStages.push_back(pipelineShaderStageInfo); + + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::setVertexInputSingleAttribute (const VkFormat vertexFormat, const deUint32 stride) +{ + const VkVertexInputBindingDescription bindingDesc = + { + 0u, // uint32_t binding; + stride, // uint32_t stride; + VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate; + }; + const VkVertexInputAttributeDescription attributeDesc = + { + 0u, // uint32_t location; + 0u, // uint32_t binding; + vertexFormat, // VkFormat format; + 0u, // uint32_t offset; + }; + + m_vertexInputBindings.clear(); + m_vertexInputBindings.push_back(bindingDesc); + + m_vertexInputAttributes.clear(); + m_vertexInputAttributes.push_back(attributeDesc); + + return *this; +} + +template +inline const T* dataPointer (const std::vector& vec) +{ + return (vec.size() != 0 ? &vec[0] : DE_NULL); +} + +Move GraphicsPipelineBuilder::build (const DeviceInterface& vk, + const VkDevice device, + const VkPipelineLayout pipelineLayout, + const VkRenderPass renderPass) +{ + const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; + static_cast(m_vertexInputBindings.size()), // uint32_t vertexBindingDescriptionCount; + dataPointer(m_vertexInputBindings), // const VkVertexInputBindingDescription* pVertexBindingDescriptions; + static_cast(m_vertexInputAttributes.size()), // uint32_t vertexAttributeDescriptionCount; + dataPointer(m_vertexInputAttributes), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; + }; + + const VkPrimitiveTopology topology = (m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST + : m_primitiveTopology; + + VkBool32 primitiveRestartEnable = VK_TRUE; + switch(m_primitiveTopology) + { + case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: + case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: + primitiveRestartEnable = VK_FALSE; + break; + default: + break; + }; + + const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags; + topology, // VkPrimitiveTopology topology; + primitiveRestartEnable, // VkBool32 primitiveRestartEnable; + }; + + const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineTessellationStateCreateFlags)0, // VkPipelineTessellationStateCreateFlags flags; + m_patchControlPoints, // uint32_t patchControlPoints; + }; + + const VkViewport viewport = makeViewport( + 0.0f, 0.0f, + static_cast(m_renderSize.x()), static_cast(m_renderSize.y()), + 0.0f, 1.0f); + + const VkRect2D scissor = { + makeOffset2D(0, 0), + makeExtent2D(m_renderSize.x(), m_renderSize.y()), + }; + + const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags; + 1u, // uint32_t viewportCount; + &viewport, // const VkViewport* pViewports; + 1u, // uint32_t scissorCount; + &scissor, // const VkRect2D* pScissors; + }; + + const bool isRasterizationDisabled = ((m_shaderStageFlags & VK_SHADER_STAGE_FRAGMENT_BIT) == 0); + const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags; + VK_FALSE, // VkBool32 depthClampEnable; + isRasterizationDisabled, // VkBool32 rasterizerDiscardEnable; + VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; + m_cullModeFlags, // VkCullModeFlags cullMode; + m_frontFace, // VkFrontFace frontFace; + VK_FALSE, // VkBool32 depthBiasEnable; + 0.0f, // float depthBiasConstantFactor; + 0.0f, // float depthBiasClamp; + 0.0f, // float depthBiasSlopeFactor; + 1.0f, // float lineWidth; + }; + + const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; + VK_FALSE, // VkBool32 sampleShadingEnable; + 0.0f, // float minSampleShading; + DE_NULL, // const VkSampleMask* pSampleMask; + VK_FALSE, // VkBool32 alphaToCoverageEnable; + VK_FALSE // VkBool32 alphaToOneEnable; + }; + + const VkStencilOpState stencilOpState = makeStencilOpState( + VK_STENCIL_OP_KEEP, // stencil fail + VK_STENCIL_OP_KEEP, // depth & stencil pass + VK_STENCIL_OP_KEEP, // depth only fail + VK_COMPARE_OP_NEVER, // compare op + 0u, // compare mask + 0u, // write mask + 0u); // reference + + const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags; + VK_FALSE, // VkBool32 depthTestEnable; + VK_FALSE, // VkBool32 depthWriteEnable; + VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; + VK_FALSE, // VkBool32 depthBoundsTestEnable; + VK_FALSE, // VkBool32 stencilTestEnable; + stencilOpState, // VkStencilOpState front; + stencilOpState, // VkStencilOpState back; + 0.0f, // float minDepthBounds; + 1.0f, // float maxDepthBounds; + }; + + const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = + { + m_blendEnable, // VkBool32 blendEnable; + VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcColorBlendFactor; + VK_BLEND_FACTOR_ONE, // VkBlendFactor dstColorBlendFactor; + VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; + VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcAlphaBlendFactor; + VK_BLEND_FACTOR_ONE, // VkBlendFactor dstAlphaBlendFactor; + VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; + colorComponentsAll, // VkColorComponentFlags colorWriteMask; + }; + + const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; + VK_FALSE, // VkBool32 logicOpEnable; + VK_LOGIC_OP_COPY, // VkLogicOp logicOp; + 1u, // deUint32 attachmentCount; + &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; + { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; + }; + + const VkGraphicsPipelineCreateInfo graphicsPipelineInfo = + { + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; + static_cast(m_shaderStages.size()), // deUint32 stageCount; + &m_shaderStages[0], // const VkPipelineShaderStageCreateInfo* pStages; + &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; + (m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? &pipelineTessellationStateInfo : DE_NULL), // const VkPipelineTessellationStateCreateInfo* pTessellationState; + (isRasterizationDisabled ? DE_NULL : &pipelineViewportStateInfo), // const VkPipelineViewportStateCreateInfo* pViewportState; + &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; + (isRasterizationDisabled ? DE_NULL : &pipelineMultisampleStateInfo), // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; + (isRasterizationDisabled ? DE_NULL : &pipelineDepthStencilStateInfo), // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; + (isRasterizationDisabled ? DE_NULL : &pipelineColorBlendStateInfo), // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; + DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; + pipelineLayout, // VkPipelineLayout layout; + renderPass, // VkRenderPass renderPass; + 0u, // deUint32 subpass; + DE_NULL, // VkPipeline basePipelineHandle; + 0, // deInt32 basePipelineIndex; + }; + + return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo); +} + +std::string inputTypeToGLString (const VkPrimitiveTopology& inputType) +{ + switch (inputType) + { + case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: + return "points"; + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: + return "lines"; + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: + return "lines_adjacency"; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: + return "triangles"; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: + return "triangles_adjacency"; + default: + DE_ASSERT(DE_FALSE); + return "error"; + } +} + +std::string outputTypeToGLString (const VkPrimitiveTopology& outputType) +{ + switch (outputType) + { + case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: + return "points"; + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: + return "line_strip"; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: + return "triangle_strip"; + default: + DE_ASSERT(DE_FALSE); + return "error"; + } +} + +size_t calcOutputVertices (const VkPrimitiveTopology& inputType) +{ + switch (inputType) + { + case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: + return 1 * 3; + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: + return 2 * 3; + case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: + case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: + return 4 * 3; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: + return 3 * 3; + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: + return 6 * 3; + default: + DE_ASSERT(DE_FALSE); + return 0; + } +} + +VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize bufferSize, + const VkBufferUsageFlags usage) +{ + const VkBufferCreateInfo bufferCreateInfo = + { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkBufferCreateFlags)0, // VkBufferCreateFlags flags; + bufferSize, // VkDeviceSize size; + usage, // VkBufferUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 0u, // deUint32 queueFamilyIndexCount; + DE_NULL, // const deUint32* pQueueFamilyIndices; + }; + return bufferCreateInfo; +} + +VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage, const deUint32 numArrayLayers) +{ + const VkImageCreateInfo imageInfo = + { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkImageCreateFlags)0, // VkImageCreateFlags flags; + VK_IMAGE_TYPE_2D, // VkImageType imageType; + format, // VkFormat format; + makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent; + 1u, // uint32_t mipLevels; + numArrayLayers, // uint32_t arrayLayers; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; + usage, // VkImageUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 0u, // uint32_t queueFamilyIndexCount; + DE_NULL, // const uint32_t* pQueueFamilyIndices; + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + }; + return imageInfo; +} + +Move makeDescriptorSet (const DeviceInterface& vk, + const VkDevice device, + const VkDescriptorPool descriptorPool, + const VkDescriptorSetLayout setLayout) +{ + const VkDescriptorSetAllocateInfo info = + { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + descriptorPool, // VkDescriptorPool descriptorPool; + 1u, // deUint32 descriptorSetCount; + &setLayout, // const VkDescriptorSetLayout* pSetLayouts; + }; + return allocateDescriptorSet(vk, device, &info); +} + +Move makeRenderPass (const DeviceInterface& vk, const VkDevice device, const VkFormat colorFormat) +{ + const VkAttachmentDescription colorAttachmentDescription = + { + (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; + colorFormat, // VkFormat format; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; + VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout; + }; + + const VkAttachmentReference colorAttachmentReference = + { + 0u, // deUint32 attachment; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; + }; + + const VkAttachmentReference depthAttachmentReference = + { + VK_ATTACHMENT_UNUSED, // deUint32 attachment; + VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout layout; + }; + + const VkSubpassDescription subpassDescription = + { + (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; + VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; + 0u, // deUint32 inputAttachmentCount; + DE_NULL, // const VkAttachmentReference* pInputAttachments; + 1u, // deUint32 colorAttachmentCount; + &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments; + DE_NULL, // const VkAttachmentReference* pResolveAttachments; + &depthAttachmentReference, // const VkAttachmentReference* pDepthStencilAttachment; + 0u, // deUint32 preserveAttachmentCount; + DE_NULL // const deUint32* pPreserveAttachments; + }; + + const VkRenderPassCreateInfo renderPassInfo = + { + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; + 1u, // deUint32 attachmentCount; + &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments; + 1u, // deUint32 subpassCount; + &subpassDescription, // const VkSubpassDescription* pSubpasses; + 0u, // deUint32 dependencyCount; + DE_NULL // const VkSubpassDependency* pDependencies; + }; + + return createRenderPass(vk, device, &renderPassInfo); +} + +Move makeImageView (const DeviceInterface& vk, + const VkDevice vkDevice, + const VkImage image, + const VkImageViewType viewType, + const VkFormat format, + const VkImageSubresourceRange subresourceRange) +{ + const VkImageViewCreateInfo imageViewParams = + { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkImageViewCreateFlags)0, // VkImageViewCreateFlags flags; + image, // VkImage image; + viewType, // VkImageViewType viewType; + format, // VkFormat format; + makeComponentMappingRGBA(), // VkComponentMapping components; + subresourceRange, // VkImageSubresourceRange subresourceRange; + }; + return createImageView(vk, vkDevice, &imageViewParams); +} + +VkBufferImageCopy makeBufferImageCopy (const VkExtent3D extent, + const VkImageSubresourceLayers subresourceLayers) +{ + const VkBufferImageCopy copyParams = + { + 0ull, // VkDeviceSize bufferOffset; + 0u, // deUint32 bufferRowLength; + 0u, // deUint32 bufferImageHeight; + subresourceLayers, // VkImageSubresourceLayers imageSubresource; + makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; + extent, // VkExtent3D imageExtent; + }; + return copyParams; +} + +Move makePipelineLayout (const DeviceInterface& vk, + const VkDevice device, + const VkDescriptorSetLayout descriptorSetLayout) +{ + const VkPipelineLayoutCreateInfo info = + { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags; + (descriptorSetLayout != DE_NULL ? 1u : 0u), // deUint32 setLayoutCount; + (descriptorSetLayout != DE_NULL ? &descriptorSetLayout : DE_NULL), // const VkDescriptorSetLayout* pSetLayouts; + 0u, // deUint32 pushConstantRangeCount; + DE_NULL, // const VkPushConstantRange* pPushConstantRanges; + }; + return createPipelineLayout(vk, device, &info); +} + +Move makeFramebuffer (const DeviceInterface& vk, + const VkDevice device, + const VkRenderPass renderPass, + const VkImageView colorAttachment, + const deUint32 width, + const deUint32 height, + const deUint32 layers) +{ + const VkFramebufferCreateInfo framebufferInfo = { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags; + renderPass, // VkRenderPass renderPass; + 1u, // uint32_t attachmentCount; + &colorAttachment, // const VkImageView* pAttachments; + width, // uint32_t width; + height, // uint32_t height; + layers, // uint32_t layers; + }; + + return createFramebuffer(vk, device, &framebufferInfo); +} + +Move makeCommandPool (const DeviceInterface& vk, const VkDevice device, const deUint32 queueFamilyIndex) +{ + const VkCommandPoolCreateInfo info = + { + VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags; + queueFamilyIndex, // deUint32 queueFamilyIndex; + }; + return createCommandPool(vk, device, &info); +} + +Move makeCommandBuffer (const DeviceInterface& vk, const VkDevice device, const VkCommandPool commandPool) +{ + const VkCommandBufferAllocateInfo info = + { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + commandPool, // VkCommandPool commandPool; + VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level; + 1u, // deUint32 commandBufferCount; + }; + return allocateCommandBuffer(vk, device, &info); +} + +VkImageMemoryBarrier makeImageMemoryBarrier (const VkAccessFlags srcAccessMask, + const VkAccessFlags dstAccessMask, + const VkImageLayout oldLayout, + const VkImageLayout newLayout, + const VkImage image, + const VkImageSubresourceRange subresourceRange) +{ + const VkImageMemoryBarrier barrier = + { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + srcAccessMask, // VkAccessFlags outputMask; + dstAccessMask, // VkAccessFlags inputMask; + oldLayout, // VkImageLayout oldLayout; + newLayout, // VkImageLayout newLayout; + VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; + image, // VkImage image; + subresourceRange, // VkImageSubresourceRange subresourceRange; + }; + return barrier; +} + +VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags srcAccessMask, + const VkAccessFlags dstAccessMask, + const VkBuffer buffer, + const VkDeviceSize offset, + const VkDeviceSize bufferSizeBytes) +{ + const VkBufferMemoryBarrier barrier = + { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + srcAccessMask, // VkAccessFlags srcAccessMask; + dstAccessMask, // VkAccessFlags dstAccessMask; + VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; + buffer, // VkBuffer buffer; + offset, // VkDeviceSize offset; + bufferSizeBytes, // VkDeviceSize size; + }; + return barrier; +} + +void beginRenderPass (const DeviceInterface& vk, + const VkCommandBuffer commandBuffer, + const VkRenderPass renderPass, + const VkFramebuffer framebuffer, + const VkRect2D& renderArea, + const tcu::Vec4& clearColor) +{ + const VkClearValue clearValue = makeClearValueColor(clearColor); + + const VkRenderPassBeginInfo renderPassBeginInfo = { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + renderPass, // VkRenderPass renderPass; + framebuffer, // VkFramebuffer framebuffer; + renderArea, // VkRect2D renderArea; + 1u, // uint32_t clearValueCount; + &clearValue, // const VkClearValue* pClearValues; + }; + + vk.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); +} + +void endRenderPass (const DeviceInterface& vk, + const VkCommandBuffer commandBuffer) +{ + vk.cmdEndRenderPass(commandBuffer); +} + +void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer) +{ + const VkCommandBufferBeginInfo info = + { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags; + DE_NULL, // const VkCommandBufferInheritanceInfo* pInheritanceInfo; + }; + VK_CHECK(vk.beginCommandBuffer(commandBuffer, &info)); +} + +void endCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer) +{ + VK_CHECK(vk.endCommandBuffer(commandBuffer)); +} + +void submitCommandsAndWait (const DeviceInterface& vk, + const VkDevice device, + const VkQueue queue, + const VkCommandBuffer commandBuffer) +{ + const VkFenceCreateInfo fenceInfo = + { + VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkFenceCreateFlags)0, // VkFenceCreateFlags flags; + }; + const Unique fence(createFence(vk, device, &fenceInfo)); + + const VkSubmitInfo submitInfo = + { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // uint32_t waitSemaphoreCount; + DE_NULL, // const VkSemaphore* pWaitSemaphores; + DE_NULL, // const VkPipelineStageFlags* pWaitDstStageMask; + 1u, // uint32_t commandBufferCount; + &commandBuffer, // const VkCommandBuffer* pCommandBuffers; + 0u, // uint32_t signalSemaphoreCount; + DE_NULL, // const VkSemaphore* pSignalSemaphores; + }; + VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence)); + VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull)); +} + +bool compareWithFileImage (Context& context, const tcu::ConstPixelBufferAccess& resultImage, std::string testName) +{ + tcu::TextureLevel referenceImage; + std::string fileName="vulkan/data/geometry/"+testName+".png"; + tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), fileName.c_str()); + + if (tcu::fuzzyCompare(context.getTestContext().getLog(), "ImageComparison", "Image Comparison", + referenceImage.getAccess(), resultImage, 0.001f, tcu::COMPARE_LOG_RESULT)) + return tcu::intThresholdPositionDeviationCompare(context.getTestContext().getLog(), "ImageComparison", "Image Comparison", + referenceImage.getAccess(), resultImage, tcu::UVec4(1u, 1u, 1u, 1u), tcu::IVec3(2,2,2), false, tcu::COMPARE_LOG_RESULT); + else + return false; +} + +de::MovePtr bindImage (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkImage image, const MemoryRequirement requirement) +{ + de::MovePtr alloc = allocator.allocate(getImageMemoryRequirements(vk, device, image), requirement); + VK_CHECK(vk.bindImageMemory(device, image, alloc->getMemory(), alloc->getOffset())); + return alloc; +} + +de::MovePtr bindBuffer (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkBuffer buffer, const MemoryRequirement requirement) +{ + de::MovePtr alloc(allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), requirement)); + VK_CHECK(vk.bindBufferMemory(device, buffer, alloc->getMemory(), alloc->getOffset())); + return alloc; +} + +void zeroBuffer (const DeviceInterface& vk, const VkDevice device, const Allocation& alloc, const VkDeviceSize size) +{ + deMemset(alloc.getHostPtr(), 0, static_cast(size)); + flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), size); +} + +VkBool32 checkPointSize (const InstanceInterface& vki, const VkPhysicalDevice physDevice) +{ + const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures (vki, physDevice); + return features.shaderTessellationAndGeometryPointSize; +} + +void checkGeometryShaderSupport (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const int numGeometryShaderInvocations) +{ + const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures (vki, physDevice); + const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physDevice).limits; + + if (!features.geometryShader) + TCU_THROW(NotSupportedError, "Missing feature: geometryShader"); + + if (numGeometryShaderInvocations != 0 && limits.maxGeometryShaderInvocations < static_cast(numGeometryShaderInvocations)) + TCU_THROW(NotSupportedError, ("Unsupported limit: maxGeometryShaderInvocations < " + de::toString(numGeometryShaderInvocations)).c_str()); +} + +} //geometry +} //vkt diff --git a/external/vulkancts/modules/vulkan/geometry/vktGeometryTestsUtil.hpp b/external/vulkancts/modules/vulkan/geometry/vktGeometryTestsUtil.hpp new file mode 100644 index 0000000..43e72a5 --- /dev/null +++ b/external/vulkancts/modules/vulkan/geometry/vktGeometryTestsUtil.hpp @@ -0,0 +1,209 @@ +#ifndef _VKTGEOMETRYTESTSUTIL_HPP +#define _VKTGEOMETRYTESTSUTIL_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2014 The Android Open Source Project + * Copyright (c) 2016 The Khronos Group Inc. + * + * 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. + * + *//*! + * \file + * \brief Geometry Utilities + *//*--------------------------------------------------------------------*/ + +#include "vkDefs.hpp" +#include "vkMemUtil.hpp" +#include "vkRef.hpp" +#include "vkPrograms.hpp" +#include "vkRefUtil.hpp" +#include "vkQueryUtil.hpp" +#include "vktTestCase.hpp" + +#include "tcuVector.hpp" + +#include "deStringUtil.hpp" +#include "deUniquePtr.hpp" + +namespace vkt +{ +namespace geometry +{ + +struct PrimitiveTestSpec +{ + vk::VkPrimitiveTopology primitiveType; + const char* name; + vk::VkPrimitiveTopology outputType; +}; + +class Buffer +{ +public: + Buffer (const vk::DeviceInterface& vk, + const vk::VkDevice device, + vk::Allocator& allocator, + const vk::VkBufferCreateInfo& bufferCreateInfo, + const vk::MemoryRequirement memoryRequirement) + + : m_buffer (createBuffer(vk, device, &bufferCreateInfo)) + , m_allocation (allocator.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), memoryRequirement)) + { + VK_CHECK(vk.bindBufferMemory(device, *m_buffer, m_allocation->getMemory(), m_allocation->getOffset())); + } + + const vk::VkBuffer& get (void) const { return *m_buffer; } + const vk::VkBuffer& operator* (void) const { return get(); } + vk::Allocation& getAllocation (void) const { return *m_allocation; } + +private: + const vk::Unique m_buffer; + const de::UniquePtr m_allocation; + + // "deleted" + Buffer (const Buffer&); + Buffer& operator= (const Buffer&); +}; + +class Image +{ +public: + Image (const vk::DeviceInterface& vk, + const vk::VkDevice device, + vk::Allocator& allocator, + const vk::VkImageCreateInfo& imageCreateInfo, + const vk::MemoryRequirement memoryRequirement) + + : m_image (createImage(vk, device, &imageCreateInfo)) + , m_allocation (allocator.allocate(getImageMemoryRequirements(vk, device, *m_image), memoryRequirement)) + { + VK_CHECK(vk.bindImageMemory(device, *m_image, m_allocation->getMemory(), m_allocation->getOffset())); + } + + const vk::VkImage& get (void) const { return *m_image; } + const vk::VkImage& operator* (void) const { return get(); } + vk::Allocation& getAllocation (void) const { return *m_allocation; } + +private: + const vk::Unique m_image; + const de::UniquePtr m_allocation; + + // "deleted" + Image (const Image&); + Image& operator= (const Image&); +}; + +class GraphicsPipelineBuilder +{ +public: + GraphicsPipelineBuilder (void) : m_renderSize (0, 0) + , m_shaderStageFlags (0u) + , m_cullModeFlags (vk::VK_CULL_MODE_NONE) + , m_frontFace (vk::VK_FRONT_FACE_COUNTER_CLOCKWISE) + , m_patchControlPoints (1u) + , m_blendEnable (false) + , m_primitiveTopology (vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST) {} + + GraphicsPipelineBuilder& setRenderSize (const tcu::IVec2& size) { m_renderSize = size; return *this; } + GraphicsPipelineBuilder& setShader (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkShaderStageFlagBits stage, const vk::ProgramBinary& binary, const vk::VkSpecializationInfo* specInfo); + GraphicsPipelineBuilder& setPatchControlPoints (const deUint32 controlPoints) { m_patchControlPoints = controlPoints; return *this; } + GraphicsPipelineBuilder& setCullModeFlags (const vk::VkCullModeFlags cullModeFlags) { m_cullModeFlags = cullModeFlags; return *this; } + GraphicsPipelineBuilder& setFrontFace (const vk::VkFrontFace frontFace) { m_frontFace = frontFace; return *this; } + GraphicsPipelineBuilder& setBlend (const bool enable) { m_blendEnable = enable; return *this; } + + //! Applies only to pipelines without tessellation shaders. + GraphicsPipelineBuilder& setPrimitiveTopology (const vk::VkPrimitiveTopology topology) { m_primitiveTopology = topology; return *this; } + + GraphicsPipelineBuilder& addVertexBinding (const vk::VkVertexInputBindingDescription vertexBinding) { m_vertexInputBindings.push_back(vertexBinding); return *this; } + GraphicsPipelineBuilder& addVertexAttribute (const vk::VkVertexInputAttributeDescription vertexAttribute) { m_vertexInputAttributes.push_back(vertexAttribute); return *this; } + + //! Basic vertex input configuration (uses biding 0, location 0, etc.) + GraphicsPipelineBuilder& setVertexInputSingleAttribute (const vk::VkFormat vertexFormat, const deUint32 stride); + + vk::Move build (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkPipelineLayout pipelineLayout, const vk::VkRenderPass renderPass); + +private: + tcu::IVec2 m_renderSize; + vk::Move m_vertexShaderModule; + vk::Move m_fragmentShaderModule; + vk::Move m_geometryShaderModule; + vk::Move m_tessControlShaderModule; + vk::Move m_tessEvaluationShaderModule; + std::vector m_shaderStages; + std::vector m_vertexInputBindings; + std::vector m_vertexInputAttributes; + vk::VkShaderStageFlags m_shaderStageFlags; + vk::VkCullModeFlags m_cullModeFlags; + vk::VkFrontFace m_frontFace; + deUint32 m_patchControlPoints; + bool m_blendEnable; + vk::VkPrimitiveTopology m_primitiveTopology; + + GraphicsPipelineBuilder (const GraphicsPipelineBuilder&); // "deleted" + GraphicsPipelineBuilder& operator= (const GraphicsPipelineBuilder&); +}; + +template +inline std::size_t sizeInBytes (const std::vector& vec) +{ + return vec.size() * sizeof(vec[0]); +} + +std::string inputTypeToGLString (const vk::VkPrimitiveTopology& inputType); +std::string outputTypeToGLString (const vk::VkPrimitiveTopology& outputType); +std::size_t calcOutputVertices (const vk::VkPrimitiveTopology& inputType); + +vk::VkBufferCreateInfo makeBufferCreateInfo (const vk::VkDeviceSize bufferSize, const vk::VkBufferUsageFlags usage); +vk::VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const vk::VkFormat format, const vk::VkImageUsageFlags usage, const deUint32 numArrayLayers = 1u); +vk::Move makeDescriptorSet (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkDescriptorPool descriptorPool, const vk::VkDescriptorSetLayout setLayout); +vk::Move makeRenderPass (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkFormat colorFormat); +vk::Move makeImageView (const vk::DeviceInterface& vk, const vk::VkDevice vkDevice, const vk::VkImage image, const vk::VkImageViewType viewType, const vk::VkFormat format, const vk::VkImageSubresourceRange subresourceRange); +vk::VkBufferImageCopy makeBufferImageCopy (const vk::VkExtent3D extent, const vk::VkImageSubresourceLayers subresourceLayers); +vk::Move makePipelineLayout (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkDescriptorSetLayout descriptorSetLayout = DE_NULL); +vk::Move makeFramebuffer (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkRenderPass renderPass, const vk::VkImageView colorAttachment, const deUint32 width, const deUint32 height, const deUint32 layers); +vk::Move makeCommandPool (const vk::DeviceInterface& vk, const vk::VkDevice device, const deUint32 queueFamilyIndex); +vk::Move makeCommandBuffer (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkCommandPool commandPool); +vk::VkImageMemoryBarrier makeImageMemoryBarrier (const vk::VkAccessFlags srcAccessMask, const vk::VkAccessFlags dstAccessMask, const vk::VkImageLayout oldLayout, const vk::VkImageLayout newLayout, const vk::VkImage image, const vk::VkImageSubresourceRange subresourceRange); +vk::VkBufferMemoryBarrier makeBufferMemoryBarrier (const vk::VkAccessFlags srcAccessMask, const vk::VkAccessFlags dstAccessMask, const vk::VkBuffer buffer, const vk::VkDeviceSize offset, const vk::VkDeviceSize bufferSizeBytes); +de::MovePtr bindImage (const vk::DeviceInterface& vk, const vk::VkDevice device, vk::Allocator& allocator, const vk::VkImage image, const vk::MemoryRequirement requirement); +de::MovePtr bindBuffer (const vk::DeviceInterface& vk, const vk::VkDevice device, vk::Allocator& allocator, const vk::VkBuffer buffer, const vk::MemoryRequirement requirement); + +void beginRenderPass (const vk::DeviceInterface& vk, const vk::VkCommandBuffer commandBuffer, const vk::VkRenderPass renderPass, const vk::VkFramebuffer framebuffer, const vk::VkRect2D& renderArea, const tcu::Vec4& clearColor); +void endRenderPass (const vk::DeviceInterface& vk, const vk::VkCommandBuffer commandBuffer); +void beginCommandBuffer (const vk::DeviceInterface& vk, const vk::VkCommandBuffer commandBuffer); +void endCommandBuffer (const vk::DeviceInterface& vk, const vk::VkCommandBuffer commandBuffer); +void submitCommandsAndWait (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkQueue queue, const vk::VkCommandBuffer commandBuffer); + +bool compareWithFileImage (Context& context, const tcu::ConstPixelBufferAccess& resultImage, std::string name); + +void zeroBuffer (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::Allocation& alloc, const vk::VkDeviceSize size); + +void checkGeometryShaderSupport (const vk::InstanceInterface& vki, const vk::VkPhysicalDevice physDevice, const int numGeometryShaderInvocations = 0); +vk::VkBool32 checkPointSize (const vk::InstanceInterface& vki, const vk::VkPhysicalDevice physDevice); + +inline vk::Move makeBuffer (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkBufferCreateInfo& createInfo) +{ + return createBuffer(vk, device, &createInfo); +} + +inline vk::Move makeImage (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkImageCreateInfo& createInfo) +{ + return createImage(vk, device, &createInfo); +} + +} //vkt +} //geometry + +#endif // _VKTGEOMETRYTESTSUTIL_HPP diff --git a/external/vulkancts/modules/vulkan/geometry/vktGeometryVaryingGeometryShaderTests.cpp b/external/vulkancts/modules/vulkan/geometry/vktGeometryVaryingGeometryShaderTests.cpp new file mode 100644 index 0000000..6e90fdb --- /dev/null +++ b/external/vulkancts/modules/vulkan/geometry/vktGeometryVaryingGeometryShaderTests.cpp @@ -0,0 +1,284 @@ +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * Copyright (c) 2016 The Android Open Source Project + * + * 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. + * + *//*! + * \file + * \brief Varying Geometry Shader Tests + *//*--------------------------------------------------------------------*/ + +#include "vktGeometryVaryingGeometryShaderTests.hpp" +#include "vktGeometryBasicClass.hpp" +#include "vktGeometryTestsUtil.hpp" + +#include "vkDefs.hpp" +#include "vktTestCase.hpp" +#include "vktTestCaseUtil.hpp" +#include "vkImageUtil.hpp" +#include "vkTypeUtil.hpp" +#include "vkPrograms.hpp" +#include "vkBuilderUtil.hpp" + +#include "vkRefUtil.hpp" +#include "vkQueryUtil.hpp" +#include "vkMemUtil.hpp" + +#include + +using namespace vk; + +namespace vkt +{ +namespace geometry +{ +namespace +{ +using tcu::TestStatus; +using tcu::TestContext; +using tcu::TestCaseGroup; +using std::string; +using de::MovePtr; + +typedef enum VertexOutputs {VERTEXT_NO_OP = -1,VERTEXT_ZERO, VERTEXT_ONE} VertexOut; +typedef enum GeometryOutputs {GEOMETRY_ZERO, GEOMETRY_ONE, GEOMETRY_TWO} GeometryOut; + +struct VaryingTestSpec +{ + VertexOutputs vertexOutputs; + GeometryOutputs geometryOutputs; + const string name; + const string desc; +}; + +class GeometryVaryingTestInstance : public GeometryExpanderRenderTestInstance +{ +public: + GeometryVaryingTestInstance (Context& context, + const char* name); + + void genVertexAttribData (void); +}; + +GeometryVaryingTestInstance::GeometryVaryingTestInstance (Context& context, const char* name) + : GeometryExpanderRenderTestInstance (context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, name) +{ + genVertexAttribData(); +} + +void GeometryVaryingTestInstance::genVertexAttribData (void) +{ + m_numDrawVertices = 3; + m_vertexPosData.resize(m_numDrawVertices); + m_vertexPosData[0] = tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f); + m_vertexPosData[1] = tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f); + m_vertexPosData[2] = tcu::Vec4(0.1f, 0.0f, 0.0f, 1.0f); + + m_vertexAttrData.resize(m_numDrawVertices); + m_vertexAttrData[0] = tcu::Vec4(0.7f, 0.4f, 0.6f, 1.0f); + m_vertexAttrData[1] = tcu::Vec4(0.9f, 0.2f, 0.5f, 1.0f); + m_vertexAttrData[2] = tcu::Vec4(0.1f, 0.8f, 0.3f, 1.0f); +} + +class VaryingTest : public TestCase +{ +public: + VaryingTest (TestContext& testCtx, + const VaryingTestSpec& varyingTestSpec); + + void initPrograms (SourceCollections& sourceCollections) const; + virtual TestInstance* createInstance (Context& context) const; + +protected: + const VaryingTestSpec m_varyingTestSpec; +}; + +VaryingTest::VaryingTest (TestContext& testCtx, const VaryingTestSpec& varyingTestSpec) + : TestCase (testCtx, varyingTestSpec.name, varyingTestSpec.desc) + , m_varyingTestSpec (varyingTestSpec) + +{ + +} + +void VaryingTest::initPrograms (SourceCollections& sourceCollections) const +{ + { + std::ostringstream src; + src << "#version 310 es\n" + <<"layout(location = 0) in highp vec4 a_position;\n" + <<"layout(location = 1) in highp vec4 a_color;\n"; + switch(m_varyingTestSpec.vertexOutputs) + { + case VERTEXT_NO_OP: + src << "void main (void)\n" + << "{\n" + << "}\n"; + break; + case VERTEXT_ZERO: + src << "void main (void)\n" + << "{\n" + << " gl_Position = a_position;\n" + << "}\n"; + break; + case VERTEXT_ONE: + src <<"layout(location = 0) out highp vec4 v_geom_0;\n" + << "void main (void)\n" + << "{\n" + << " gl_Position = a_position;\n" + << " v_geom_0 = a_color;\n" + << "}\n"; + break; + default: + DE_ASSERT(0); + } + sourceCollections.glslSources.add("vertex") << glu::VertexSource(src.str()); + } + + { + std::ostringstream src; + src << "#version 310 es\n" + << "#extension GL_EXT_geometry_shader : require\n" + << "layout(triangles) in;\n" + << "layout(triangle_strip, max_vertices = 3) out;\n"; + + if (m_varyingTestSpec.vertexOutputs == VERTEXT_ONE) + src << "layout(location = 0) in highp vec4 v_geom_0[];\n"; + + if (m_varyingTestSpec.geometryOutputs >= GEOMETRY_ONE) + src << "layout(location = 0) out highp vec4 v_frag_0;\n"; + if (m_varyingTestSpec.geometryOutputs == GEOMETRY_TWO) + src << "layout(location = 1) out highp vec4 v_frag_1;\n"; + + src << "void main (void)\n" + << "{\n" + << " highp vec4 offset = vec4(-0.2, -0.2, 0.0, 0.0);\n" + << " highp vec4 inputColor;\n" + << "\n"; + if (m_varyingTestSpec.vertexOutputs == VERTEXT_ONE) + src << " inputColor = v_geom_0[0];\n"; + else + src << " inputColor = vec4(1.0, 0.0, 0.0, 1.0);\n"; + + if (m_varyingTestSpec.vertexOutputs == VERTEXT_NO_OP) + src << " gl_Position = vec4(0.0, 0.0, 0.0, 1.0) + offset;\n"; + if (m_varyingTestSpec.vertexOutputs >= VERTEXT_ZERO) + src << " gl_Position = gl_in[0].gl_Position + offset;\n"; + + if (m_varyingTestSpec.geometryOutputs == GEOMETRY_ONE) + src << " v_frag_0 = inputColor;\n"; + if (m_varyingTestSpec.geometryOutputs == GEOMETRY_TWO) + src << " v_frag_0 = inputColor * 0.5;\n" + << " v_frag_1 = inputColor.yxzw * 0.5;\n"; + + src << " EmitVertex();\n" + << "\n"; + if (m_varyingTestSpec.vertexOutputs == VERTEXT_ONE) + src << " inputColor = v_geom_0[1];\n"; + else + src << " inputColor = vec4(1.0, 0.0, 0.0, 1.0);\n"; + + if (m_varyingTestSpec.vertexOutputs == VERTEXT_NO_OP) + src << " gl_Position = vec4(1.0, 0.0, 0.0, 1.0) + offset;\n"; + if (m_varyingTestSpec.vertexOutputs >= VERTEXT_ZERO) + src << " gl_Position = gl_in[1].gl_Position + offset;\n"; + + if (m_varyingTestSpec.geometryOutputs == GEOMETRY_ONE) + src << " v_frag_0 = inputColor;\n"; + if (m_varyingTestSpec.geometryOutputs == GEOMETRY_TWO) + src << " v_frag_0 = inputColor * 0.5;\n" + << " v_frag_1 = inputColor.yxzw * 0.5;\n"; + + src << " EmitVertex();\n" + << "\n"; + + if (m_varyingTestSpec.vertexOutputs == VERTEXT_ONE) + src << " inputColor = v_geom_0[2];\n"; + else + src << " inputColor = vec4(1.0, 0.0, 0.0, 1.0);\n"; + + if (m_varyingTestSpec.vertexOutputs == VERTEXT_NO_OP) + src << " gl_Position = vec4(1.0, 1.0, 0.0, 1.0) + offset;\n"; + if (m_varyingTestSpec.vertexOutputs >= VERTEXT_ZERO) + src << " gl_Position = gl_in[2].gl_Position + offset;\n"; + + if (m_varyingTestSpec.geometryOutputs == GEOMETRY_ONE) + src << " v_frag_0 = inputColor;\n"; + if (m_varyingTestSpec.geometryOutputs == GEOMETRY_TWO) + src << " v_frag_0 = inputColor * 0.5;\n" + << " v_frag_1 = inputColor.yxzw * 0.5;\n"; + + src << " EmitVertex();\n" + << "\n" + << " EndPrimitive();\n" + << "}\n"; + sourceCollections.glslSources.add("geometry") << glu::GeometrySource(src.str()); + } + + { + std::ostringstream src; + src << "#version 310 es\n" + <<"layout(location = 0) out highp vec4 fragColor;\n"; + if (m_varyingTestSpec.geometryOutputs >= GEOMETRY_ONE) + src <<"layout(location = 0) in mediump vec4 v_frag_0;\n"; + if (m_varyingTestSpec.geometryOutputs == GEOMETRY_TWO) + src <<"layout(location = 1) in mediump vec4 v_frag_1;\n"; + + src <<"void main (void)\n" + <<"{\n"; + if (m_varyingTestSpec.geometryOutputs == GEOMETRY_ZERO) + src <<"fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"; + if (m_varyingTestSpec.geometryOutputs == GEOMETRY_ONE) + src <<" fragColor = v_frag_0;\n"; + if (m_varyingTestSpec.geometryOutputs == GEOMETRY_TWO) + src <<" fragColor = v_frag_0 + v_frag_1.yxzw;\n"; + src <<"}\n"; + sourceCollections.glslSources.add("fragment") << glu::FragmentSource(src.str()); + } +} + +TestInstance* VaryingTest::createInstance (Context& context) const +{ + return new GeometryVaryingTestInstance(context, getName()); +} + +} // anonymous + +TestCaseGroup* createVaryingGeometryShaderTests (TestContext& testCtx) +{ + MovePtr varyingGroup (new TestCaseGroup(testCtx, "varying", "Test varyings.")); + + // varying + { + static const VaryingTestSpec varyingTests[] = + { + { VERTEXT_NO_OP, GEOMETRY_ONE, "vertex_no_op_geometry_out_1", "vertex_no_op_geometry_out_1" }, + { VERTEXT_ZERO, GEOMETRY_ONE, "vertex_out_0_geometry_out_1", "vertex_out_0_geometry_out_1" }, + { VERTEXT_ZERO, GEOMETRY_TWO, "vertex_out_0_geometry_out_2", "vertex_out_0_geometry_out_2" }, + { VERTEXT_ONE, GEOMETRY_ZERO, "vertex_out_1_geometry_out_0", "vertex_out_1_geometry_out_0" }, + { VERTEXT_ONE, GEOMETRY_TWO, "vertex_out_1_geometry_out_2", "vertex_out_1_geometry_out_2" }, + }; + + for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(varyingTests); ++ndx) + varyingGroup->addChild(new VaryingTest(testCtx, varyingTests[ndx])); + } + + return varyingGroup.release(); +} + +} // geometry +} // vkt diff --git a/external/vulkancts/modules/vulkan/geometry/vktGeometryVaryingGeometryShaderTests.hpp b/external/vulkancts/modules/vulkan/geometry/vktGeometryVaryingGeometryShaderTests.hpp new file mode 100644 index 0000000..4afb8c7 --- /dev/null +++ b/external/vulkancts/modules/vulkan/geometry/vktGeometryVaryingGeometryShaderTests.hpp @@ -0,0 +1,39 @@ +#ifndef _VKTGEOMETRYVARYINGGEOMETRYSHADERTESTS_HPP +#define _VKTGEOMETRYVARYINGGEOMETRYSHADERTESTS_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * + * 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. + * + *//*! + * \file + * \brief Varying Geometry Shader Tests + *//*--------------------------------------------------------------------*/ + +#include "tcuDefs.hpp" +#include "vktTestCase.hpp" + +namespace vkt +{ +namespace geometry +{ + +tcu::TestCaseGroup* createVaryingGeometryShaderTests (tcu::TestContext& testCtx); + +} // geometry +} // vkt + +#endif // _VKTGEOMETRYVARYINGGEOMETRYSHADERTESTS_HPP diff --git a/external/vulkancts/modules/vulkan/vktTestPackage.cpp b/external/vulkancts/modules/vulkan/vktTestPackage.cpp index 7231823..2620deb 100644 --- a/external/vulkancts/modules/vulkan/vktTestPackage.cpp +++ b/external/vulkancts/modules/vulkan/vktTestPackage.cpp @@ -75,6 +75,7 @@ #include "vktClippingTests.hpp" #include "vktFragmentOperationsTests.hpp" #include "vktTextureTests.hpp" +#include "vktGeometryTests.hpp" #include #include @@ -396,6 +397,7 @@ void TestPackage::init (void) addChild(clipping::createTests (m_testCtx)); addChild(FragmentOperations::createTests(m_testCtx)); addChild(texture::createTests (m_testCtx)); + addChild(geometry::createTests (m_testCtx)); } } // vkt diff --git a/external/vulkancts/mustpass/1.0.2/vk-default.txt b/external/vulkancts/mustpass/1.0.2/vk-default.txt index e3c2882..04f36de 100644 --- a/external/vulkancts/mustpass/1.0.2/vk-default.txt +++ b/external/vulkancts/mustpass/1.0.2/vk-default.txt @@ -116088,3 +116088,127 @@ dEQP-VK.texture.shadow.2d_array.linear_mipmap_linear.never_d32_sfloat dEQP-VK.texture.shadow.2d_array.linear_mipmap_linear.never_d16_unorm_s8_uint dEQP-VK.texture.shadow.2d_array.linear_mipmap_linear.never_d24_unorm_s8_uint dEQP-VK.texture.shadow.2d_array.linear_mipmap_linear.never_d32_sfloat_s8_uint +dEQP-VK.geometry.input.basic_primitive.points +dEQP-VK.geometry.input.basic_primitive.lines +dEQP-VK.geometry.input.basic_primitive.line_strip +dEQP-VK.geometry.input.basic_primitive.triangles +dEQP-VK.geometry.input.basic_primitive.triangle_strip +dEQP-VK.geometry.input.basic_primitive.triangle_fan +dEQP-VK.geometry.input.basic_primitive.lines_adjacency +dEQP-VK.geometry.input.basic_primitive.line_strip_adjacency +dEQP-VK.geometry.input.basic_primitive.triangles_adjacency +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_0 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_1 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_2 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_3 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_4 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_5 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_6 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_7 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_8 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_9 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_10 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_11 +dEQP-VK.geometry.input.triangle_strip_adjacency.vertex_count_12 +dEQP-VK.geometry.input.conversion.triangles_to_points +dEQP-VK.geometry.input.conversion.lines_to_points +dEQP-VK.geometry.input.conversion.points_to_lines +dEQP-VK.geometry.input.conversion.triangles_to_lines +dEQP-VK.geometry.input.conversion.points_to_triangles +dEQP-VK.geometry.input.conversion.lines_to_triangles +dEQP-VK.geometry.basic.output_10 +dEQP-VK.geometry.basic.output_128 +dEQP-VK.geometry.basic.output_10_and_100 +dEQP-VK.geometry.basic.output_100_and_10 +dEQP-VK.geometry.basic.output_0_and_128 +dEQP-VK.geometry.basic.output_128_and_0 +dEQP-VK.geometry.basic.output_vary_by_attribute +dEQP-VK.geometry.basic.output_vary_by_uniform +dEQP-VK.geometry.basic.output_vary_by_texture +dEQP-VK.geometry.basic.output_vary_by_attribute_instancing +dEQP-VK.geometry.basic.output_vary_by_uniform_instancing +dEQP-VK.geometry.basic.output_vary_by_texture_instancing +dEQP-VK.geometry.basic.point_size +dEQP-VK.geometry.basic.primitive_id_in +dEQP-VK.geometry.basic.primitive_id_in_restarted +dEQP-VK.geometry.basic.primitive_id +dEQP-VK.geometry.layered.1d_array.render_to_default_layer +dEQP-VK.geometry.layered.1d_array.render_to_one +dEQP-VK.geometry.layered.1d_array.render_to_all +dEQP-VK.geometry.layered.1d_array.render_different_content +dEQP-VK.geometry.layered.1d_array.fragment_layer +dEQP-VK.geometry.layered.1d_array.invocation_per_layer +dEQP-VK.geometry.layered.1d_array.multiple_layers_per_invocation +dEQP-VK.geometry.layered.2d_array.render_to_default_layer +dEQP-VK.geometry.layered.2d_array.render_to_one +dEQP-VK.geometry.layered.2d_array.render_to_all +dEQP-VK.geometry.layered.2d_array.render_different_content +dEQP-VK.geometry.layered.2d_array.fragment_layer +dEQP-VK.geometry.layered.2d_array.invocation_per_layer +dEQP-VK.geometry.layered.2d_array.multiple_layers_per_invocation +dEQP-VK.geometry.layered.cube.render_to_default_layer +dEQP-VK.geometry.layered.cube.render_to_one +dEQP-VK.geometry.layered.cube.render_to_all +dEQP-VK.geometry.layered.cube.render_different_content +dEQP-VK.geometry.layered.cube.fragment_layer +dEQP-VK.geometry.layered.cube.invocation_per_layer +dEQP-VK.geometry.layered.cube.multiple_layers_per_invocation +dEQP-VK.geometry.layered.cube_array.render_to_default_layer +dEQP-VK.geometry.layered.cube_array.render_to_one +dEQP-VK.geometry.layered.cube_array.render_to_all +dEQP-VK.geometry.layered.cube_array.render_different_content +dEQP-VK.geometry.layered.cube_array.fragment_layer +dEQP-VK.geometry.layered.cube_array.invocation_per_layer +dEQP-VK.geometry.layered.cube_array.multiple_layers_per_invocation +dEQP-VK.geometry.instanced.draw_1_instances_1_geometry_invocations +dEQP-VK.geometry.instanced.draw_1_instances_2_geometry_invocations +dEQP-VK.geometry.instanced.draw_1_instances_8_geometry_invocations +dEQP-VK.geometry.instanced.draw_1_instances_32_geometry_invocations +dEQP-VK.geometry.instanced.draw_1_instances_64_geometry_invocations +dEQP-VK.geometry.instanced.draw_1_instances_127_geometry_invocations +dEQP-VK.geometry.instanced.draw_2_instances_1_geometry_invocations +dEQP-VK.geometry.instanced.draw_2_instances_2_geometry_invocations +dEQP-VK.geometry.instanced.draw_2_instances_8_geometry_invocations +dEQP-VK.geometry.instanced.draw_2_instances_32_geometry_invocations +dEQP-VK.geometry.instanced.draw_2_instances_64_geometry_invocations +dEQP-VK.geometry.instanced.draw_2_instances_127_geometry_invocations +dEQP-VK.geometry.instanced.draw_4_instances_1_geometry_invocations +dEQP-VK.geometry.instanced.draw_4_instances_2_geometry_invocations +dEQP-VK.geometry.instanced.draw_4_instances_8_geometry_invocations +dEQP-VK.geometry.instanced.draw_4_instances_32_geometry_invocations +dEQP-VK.geometry.instanced.draw_4_instances_64_geometry_invocations +dEQP-VK.geometry.instanced.draw_4_instances_127_geometry_invocations +dEQP-VK.geometry.instanced.draw_8_instances_1_geometry_invocations +dEQP-VK.geometry.instanced.draw_8_instances_2_geometry_invocations +dEQP-VK.geometry.instanced.draw_8_instances_8_geometry_invocations +dEQP-VK.geometry.instanced.draw_8_instances_32_geometry_invocations +dEQP-VK.geometry.instanced.draw_8_instances_64_geometry_invocations +dEQP-VK.geometry.instanced.draw_8_instances_127_geometry_invocations +dEQP-VK.geometry.varying.vertex_no_op_geometry_out_1 +dEQP-VK.geometry.varying.vertex_out_0_geometry_out_1 +dEQP-VK.geometry.varying.vertex_out_0_geometry_out_2 +dEQP-VK.geometry.varying.vertex_out_1_geometry_out_0 +dEQP-VK.geometry.varying.vertex_out_1_geometry_out_2 +dEQP-VK.geometry.emit.points_emit_0_end_0 +dEQP-VK.geometry.emit.points_emit_0_end_1 +dEQP-VK.geometry.emit.points_emit_1_end_1 +dEQP-VK.geometry.emit.points_emit_0_end_2 +dEQP-VK.geometry.emit.points_emit_1_end_2 +dEQP-VK.geometry.emit.line_strip_emit_0_end_0 +dEQP-VK.geometry.emit.line_strip_emit_0_end_1 +dEQP-VK.geometry.emit.line_strip_emit_1_end_1 +dEQP-VK.geometry.emit.line_strip_emit_2_end_1 +dEQP-VK.geometry.emit.line_strip_emit_0_end_2 +dEQP-VK.geometry.emit.line_strip_emit_1_end_2 +dEQP-VK.geometry.emit.line_strip_emit_2_end_2 +dEQP-VK.geometry.emit.line_strip_emit_2_end_2_emit_2_end_0 +dEQP-VK.geometry.emit.triangle_strip_emit_0_end_0 +dEQP-VK.geometry.emit.triangle_strip_emit_0_end_1 +dEQP-VK.geometry.emit.triangle_strip_emit_1_end_1 +dEQP-VK.geometry.emit.triangle_strip_emit_2_end_1 +dEQP-VK.geometry.emit.triangle_strip_emit_3_end_1 +dEQP-VK.geometry.emit.triangle_strip_emit_0_end_2 +dEQP-VK.geometry.emit.triangle_strip_emit_1_end_2 +dEQP-VK.geometry.emit.triangle_strip_emit_2_end_2 +dEQP-VK.geometry.emit.triangle_strip_emit_3_end_2 +dEQP-VK.geometry.emit.triangle_strip_emit_3_end_2_emit_3_end_0 -- 2.7.4