Add geometry shader tests
authorArkadiusz Sarwa <arkadiusz.sarwa@mobica.com>
Tue, 27 Sep 2016 09:10:05 +0000 (11:10 +0200)
committerPyry Haulos <phaulos@google.com>
Fri, 11 Nov 2016 16:13:13 +0000 (08:13 -0800)
New tests:
- dEQP-VK.geometry.*

Fixes #63

Change-Id: If1da0ce5e171ca6cb7396421f2fb8ffbcc55ce88

96 files changed:
android/cts/master/vk-master.txt
external/vulkancts/data/vulkan/data/geometry/line_strip.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/line_strip_adjacency.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/line_strip_emit_0_end_0.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/line_strip_emit_0_end_1.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/line_strip_emit_0_end_2.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/line_strip_emit_1_end_1.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/line_strip_emit_1_end_2.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/line_strip_emit_2_end_1.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/line_strip_emit_2_end_2.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/line_strip_emit_2_end_2_emit_2_end_0.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/lines.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/lines_adjacency.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/lines_to_points.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/lines_to_triangles.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/output_0_and_128.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/output_10.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/output_100_and_10.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/output_10_and_100.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/output_128.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/output_128_and_0.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/output_max.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/output_vary_by_attribute.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/output_vary_by_attribute_instancing.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/output_vary_by_texture.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/output_vary_by_texture_instancing.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/output_vary_by_uniform.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/output_vary_by_uniform_instancing.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/point_size.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/points.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/points_emit_0_end_0.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/points_emit_0_end_1.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/points_emit_0_end_2.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/points_emit_1_end_1.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/points_emit_1_end_2.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/points_to_lines.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/points_to_triangles.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/primitive_id.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/primitive_id_in.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/primitive_id_in_restarted.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/triangle_fan.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/triangle_strip.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_0_end_0.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_0_end_1.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_0_end_2.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_1_end_1.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_1_end_2.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_2_end_1.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_2_end_2.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_3_end_1.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_3_end_2.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_3_end_2_emit_3_end_0.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/triangles.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/triangles_adjacency.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/triangles_to_lines.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/triangles_to_points.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/vertex_count_0.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/vertex_count_1.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/vertex_count_10.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/vertex_count_11.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/vertex_count_12.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/vertex_count_2.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/vertex_count_3.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/vertex_count_4.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/vertex_count_5.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/vertex_count_6.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/vertex_count_7.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/vertex_count_8.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/vertex_count_9.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/vertex_no_op_geometry_out_1.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/vertex_out_0_geometry_out_1.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/vertex_out_0_geometry_out_2.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/vertex_out_1_geometry_out_0.png [new file with mode: 0644]
external/vulkancts/data/vulkan/data/geometry/vertex_out_1_geometry_out_2.png [new file with mode: 0644]
external/vulkancts/modules/vulkan/CMakeLists.txt
external/vulkancts/modules/vulkan/geometry/CMakeLists.txt [new file with mode: 0644]
external/vulkancts/modules/vulkan/geometry/vktGeometryBasicClass.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/geometry/vktGeometryBasicClass.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/geometry/vktGeometryBasicGeometryShaderTests.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/geometry/vktGeometryBasicGeometryShaderTests.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/geometry/vktGeometryEmitGeometryShaderTests.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/geometry/vktGeometryEmitGeometryShaderTests.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/geometry/vktGeometryInputGeometryShaderTests.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/geometry/vktGeometryInputGeometryShaderTests.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/geometry/vktGeometryInstancedRenderingTests.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/geometry/vktGeometryInstancedRenderingTests.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/geometry/vktGeometryLayeredRenderingTests.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/geometry/vktGeometryLayeredRenderingTests.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/geometry/vktGeometryTests.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/geometry/vktGeometryTests.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/geometry/vktGeometryTestsUtil.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/geometry/vktGeometryTestsUtil.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/geometry/vktGeometryVaryingGeometryShaderTests.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/geometry/vktGeometryVaryingGeometryShaderTests.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/vktTestPackage.cpp
external/vulkancts/mustpass/1.0.2/vk-default.txt

index 27858d9..5236ee0 100644 (file)
@@ -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 (file)
index 0000000..26e096e
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/line_strip.png differ
diff --git a/external/vulkancts/data/vulkan/data/geometry/line_strip_adjacency.png b/external/vulkancts/data/vulkan/data/geometry/line_strip_adjacency.png
new file mode 100644 (file)
index 0000000..fd4cae3
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/line_strip_adjacency.png differ
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 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_0_end_0.png differ
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 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_0_end_1.png differ
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 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_0_end_2.png differ
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 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_1_end_1.png differ
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 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_1_end_2.png differ
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 (file)
index 0000000..22e374d
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_2_end_1.png differ
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 (file)
index 0000000..22e374d
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_2_end_2.png differ
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 (file)
index 0000000..c983ed7
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/line_strip_emit_2_end_2_emit_2_end_0.png differ
diff --git a/external/vulkancts/data/vulkan/data/geometry/lines.png b/external/vulkancts/data/vulkan/data/geometry/lines.png
new file mode 100644 (file)
index 0000000..1664be8
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/lines.png differ
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 (file)
index 0000000..9a39777
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/lines_adjacency.png differ
diff --git a/external/vulkancts/data/vulkan/data/geometry/lines_to_points.png b/external/vulkancts/data/vulkan/data/geometry/lines_to_points.png
new file mode 100644 (file)
index 0000000..ada60c7
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/lines_to_points.png differ
diff --git a/external/vulkancts/data/vulkan/data/geometry/lines_to_triangles.png b/external/vulkancts/data/vulkan/data/geometry/lines_to_triangles.png
new file mode 100644 (file)
index 0000000..f6ab4dd
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/lines_to_triangles.png differ
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 (file)
index 0000000..860a6cb
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/output_0_and_128.png differ
diff --git a/external/vulkancts/data/vulkan/data/geometry/output_10.png b/external/vulkancts/data/vulkan/data/geometry/output_10.png
new file mode 100644 (file)
index 0000000..26c7c04
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/output_10.png differ
diff --git a/external/vulkancts/data/vulkan/data/geometry/output_100_and_10.png b/external/vulkancts/data/vulkan/data/geometry/output_100_and_10.png
new file mode 100644 (file)
index 0000000..806ab0e
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/output_100_and_10.png differ
diff --git a/external/vulkancts/data/vulkan/data/geometry/output_10_and_100.png b/external/vulkancts/data/vulkan/data/geometry/output_10_and_100.png
new file mode 100644 (file)
index 0000000..09cd801
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/output_10_and_100.png differ
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 (file)
index 0000000..c29ccc0
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/output_128.png differ
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 (file)
index 0000000..35aa909
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/output_128_and_0.png differ
diff --git a/external/vulkancts/data/vulkan/data/geometry/output_max.png b/external/vulkancts/data/vulkan/data/geometry/output_max.png
new file mode 100644 (file)
index 0000000..c29ccc0
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/output_max.png differ
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 (file)
index 0000000..e3d6953
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/output_vary_by_attribute.png differ
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 (file)
index 0000000..d08fb34
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/output_vary_by_attribute_instancing.png differ
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 (file)
index 0000000..0e655b7
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/output_vary_by_texture.png differ
diff --git a/external/vulkancts/data/vulkan/data/geometry/output_vary_by_texture_instancing.png b/external/vulkancts/data/vulkan/data/geometry/output_vary_by_texture_instancing.png
new file mode 100644 (file)
index 0000000..b33b647
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/output_vary_by_texture_instancing.png differ
diff --git a/external/vulkancts/data/vulkan/data/geometry/output_vary_by_uniform.png b/external/vulkancts/data/vulkan/data/geometry/output_vary_by_uniform.png
new file mode 100644 (file)
index 0000000..0e655b7
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/output_vary_by_uniform.png differ
diff --git a/external/vulkancts/data/vulkan/data/geometry/output_vary_by_uniform_instancing.png b/external/vulkancts/data/vulkan/data/geometry/output_vary_by_uniform_instancing.png
new file mode 100644 (file)
index 0000000..b33b647
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/output_vary_by_uniform_instancing.png differ
diff --git a/external/vulkancts/data/vulkan/data/geometry/point_size.png b/external/vulkancts/data/vulkan/data/geometry/point_size.png
new file mode 100644 (file)
index 0000000..cdb848c
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/point_size.png differ
diff --git a/external/vulkancts/data/vulkan/data/geometry/points.png b/external/vulkancts/data/vulkan/data/geometry/points.png
new file mode 100644 (file)
index 0000000..c1a7d47
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/points.png differ
diff --git a/external/vulkancts/data/vulkan/data/geometry/points_emit_0_end_0.png b/external/vulkancts/data/vulkan/data/geometry/points_emit_0_end_0.png
new file mode 100644 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/points_emit_0_end_0.png differ
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 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/points_emit_0_end_1.png differ
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 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/points_emit_0_end_2.png differ
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 (file)
index 0000000..c50c0fd
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/points_emit_1_end_1.png differ
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 (file)
index 0000000..c50c0fd
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/points_emit_1_end_2.png differ
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 (file)
index 0000000..40460f8
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/points_to_lines.png differ
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 (file)
index 0000000..69caa8e
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/points_to_triangles.png differ
diff --git a/external/vulkancts/data/vulkan/data/geometry/primitive_id.png b/external/vulkancts/data/vulkan/data/geometry/primitive_id.png
new file mode 100644 (file)
index 0000000..ddb9442
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/primitive_id.png differ
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 (file)
index 0000000..ca37392
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/primitive_id_in.png differ
diff --git a/external/vulkancts/data/vulkan/data/geometry/primitive_id_in_restarted.png b/external/vulkancts/data/vulkan/data/geometry/primitive_id_in_restarted.png
new file mode 100644 (file)
index 0000000..5dd4dc2
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/primitive_id_in_restarted.png differ
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 (file)
index 0000000..720b717
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/triangle_fan.png differ
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 (file)
index 0000000..c4fa315
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/triangle_strip.png differ
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 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_0_end_0.png differ
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 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_0_end_1.png differ
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 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_0_end_2.png differ
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 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_1_end_1.png differ
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 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_1_end_2.png differ
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 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_2_end_1.png differ
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 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_2_end_2.png differ
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 (file)
index 0000000..1faf7ca
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_3_end_1.png differ
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 (file)
index 0000000..1faf7ca
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_3_end_2.png differ
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 (file)
index 0000000..b493c28
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/triangle_strip_emit_3_end_2_emit_3_end_0.png differ
diff --git a/external/vulkancts/data/vulkan/data/geometry/triangles.png b/external/vulkancts/data/vulkan/data/geometry/triangles.png
new file mode 100644 (file)
index 0000000..ebfe79a
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/triangles.png differ
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 (file)
index 0000000..14e87ed
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/triangles_adjacency.png differ
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 (file)
index 0000000..6a43f3d
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/triangles_to_lines.png differ
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 (file)
index 0000000..281a37c
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/triangles_to_points.png differ
diff --git a/external/vulkancts/data/vulkan/data/geometry/vertex_count_0.png b/external/vulkancts/data/vulkan/data/geometry/vertex_count_0.png
new file mode 100644 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/vertex_count_0.png differ
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 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/vertex_count_1.png differ
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 (file)
index 0000000..9cac87e
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/vertex_count_10.png differ
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 (file)
index 0000000..9cac87e
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/vertex_count_11.png differ
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 (file)
index 0000000..9a627f1
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/vertex_count_12.png differ
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 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/vertex_count_2.png differ
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 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/vertex_count_3.png differ
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 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/vertex_count_4.png differ
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 (file)
index 0000000..fc45c50
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/vertex_count_5.png differ
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 (file)
index 0000000..09a4b81
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/vertex_count_6.png differ
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 (file)
index 0000000..09a4b81
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/vertex_count_7.png differ
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 (file)
index 0000000..ab83eec
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/vertex_count_8.png differ
diff --git a/external/vulkancts/data/vulkan/data/geometry/vertex_count_9.png b/external/vulkancts/data/vulkan/data/geometry/vertex_count_9.png
new file mode 100644 (file)
index 0000000..ab83eec
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/vertex_count_9.png differ
diff --git a/external/vulkancts/data/vulkan/data/geometry/vertex_no_op_geometry_out_1.png b/external/vulkancts/data/vulkan/data/geometry/vertex_no_op_geometry_out_1.png
new file mode 100644 (file)
index 0000000..3b8f7db
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/vertex_no_op_geometry_out_1.png differ
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 (file)
index 0000000..f071c17
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/vertex_out_0_geometry_out_1.png differ
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 (file)
index 0000000..f071c17
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/vertex_out_0_geometry_out_2.png differ
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 (file)
index 0000000..f071c17
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/vertex_out_1_geometry_out_0.png differ
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 (file)
index 0000000..43eee1c
Binary files /dev/null and b/external/vulkancts/data/vulkan/data/geometry/vertex_out_1_geometry_out_2.png differ
index 4261e43..c6804da 100644 (file)
@@ -21,6 +21,7 @@ add_subdirectory(rasterization)
 add_subdirectory(synchronization)
 add_subdirectory(clipping)
 add_subdirectory(fragment_ops)
+add_subdirectory(geometry)
 add_subdirectory(texture)
 
 include_directories(
@@ -46,6 +47,7 @@ include_directories(
        clipping
        fragment_ops
        texture
+       geometry
        )
 
 set(DEQP_VK_COMMON_SRCS
@@ -91,6 +93,7 @@ set(DEQP_VK_COMMON_LIBS
        deqp-vk-clipping
        deqp-vk-fragment-ops
        deqp-vk-texture
+       deqp-vk-geometry
        )
 
 add_library(deqp-vk-common STATIC ${DEQP_VK_COMMON_SRCS})
diff --git a/external/vulkancts/modules/vulkan/geometry/CMakeLists.txt b/external/vulkancts/modules/vulkan/geometry/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e7a7b91
--- /dev/null
@@ -0,0 +1,31 @@
+include_directories(..)
+
+set(DEQP_VK_GEOMETRY_SRCS
+       vktGeometryBasicClass.cpp
+       vktGeometryBasicClass.hpp
+       vktGeometryBasicGeometryShaderTests.cpp
+       vktGeometryBasicGeometryShaderTests.hpp
+       vktGeometryEmitGeometryShaderTests.cpp
+       vktGeometryEmitGeometryShaderTests.hpp
+       vktGeometryVaryingGeometryShaderTests.cpp
+       vktGeometryVaryingGeometryShaderTests.hpp
+       vktGeometryInputGeometryShaderTests.cpp
+       vktGeometryInputGeometryShaderTests.hpp
+       vktGeometryInstancedRenderingTests.cpp
+       vktGeometryInstancedRenderingTests.hpp
+       vktGeometryLayeredRenderingTests.cpp
+       vktGeometryLayeredRenderingTests.hpp
+       vktGeometryTests.cpp
+       vktGeometryTests.hpp
+       vktGeometryTestsUtil.cpp
+       vktGeometryTestsUtil.hpp
+       )
+
+set(DEQP_VK_GEOMETRY_LIBS
+       deqp-vk-common
+       tcutil
+       vkutil
+       )
+
+add_library(deqp-vk-geometry STATIC ${DEQP_VK_GEOMETRY_SRCS})
+target_link_libraries(deqp-vk-geometry ${DEQP_VK_GEOMETRY_LIBS})
diff --git a/external/vulkancts/modules/vulkan/geometry/vktGeometryBasicClass.cpp b/external/vulkancts/modules/vulkan/geometry/vktGeometryBasicClass.cpp
new file mode 100644 (file)
index 0000000..74da22a
--- /dev/null
@@ -0,0 +1,217 @@
+/*------------------------------------------------------------------------
+ * 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 Geometry Basic Class
+ *//*--------------------------------------------------------------------*/
+
+#include "vktGeometryBasicClass.hpp"
+
+#include "vkDefs.hpp"
+#include "vktTestCase.hpp"
+#include "vktTestCaseUtil.hpp"
+#include "vkImageUtil.hpp"
+#include "vkPrograms.hpp"
+#include "vkBuilderUtil.hpp"
+#include "vkRefUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkMemUtil.hpp"
+
+#include <string>
+
+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<VkRenderPass>              renderPass                              (makeRenderPass(vk, device, colorFormat));
+
+       const Move<VkPipelineLayout>    pipelineLayout                  (createPipelineLayout(vk, device));
+       const VkImageSubresourceRange   colorSubRange                   = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
+       const Unique<VkImageView>               colorAttachmentView             (makeImageView(vk, device, *colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubRange));
+       const Unique<VkFramebuffer>             framebuffer                             (makeFramebuffer(vk, device, *renderPass, *colorAttachmentView, resolution.x(), resolution.y(), 1u));
+       const Unique<VkCommandPool>             cmdPool                                 (makeCommandPool(vk, device, queueFamilyIndex));
+       const Unique<VkCommandBuffer>   cmdBuffer                               (makeCommandBuffer(vk, device, *cmdPool));
+
+       const VkDeviceSize                              vertexDataSizeBytes             = sizeInBytes(m_vertexPosData) + sizeInBytes(m_vertexAttrData);
+       const deUint32                                  vertexPositionsOffset   = 0u;
+       const deUint32                                  vertexAtrrOffset                = static_cast<deUint32>(sizeof(Vec4));
+       const string                                    geometryShaderName              = (m_context.getBinaryCollection().contains("geometry_pointsize") && checkPointSize (m_context.getInstanceInterface(), m_context.getPhysicalDevice()))?
+                                                                                                                               "geometry_pointsize" : "geometry";
+
+       const Unique<VkPipeline>                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<DataVec4*>(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, &copyRegion);
+       }
+
+       {
+               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<VkPipelineLayout> 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<deUint32>(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 (file)
index 0000000..4154eab
--- /dev/null
@@ -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<vk::VkPipelineLayout>  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<tcu::Vec4>                  m_vertexPosData;
+       std::vector<tcu::Vec4>                  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 (file)
index 0000000..291ec43
--- /dev/null
@@ -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 <string>
+
+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<VkBuffer>                                  buffer;
+       de::MovePtr<Allocation>                 bufferAlloc;
+       Move<VkCommandPool>                             cmdPool;
+       Move<VkCommandBuffer>                   cmdBuffer;
+       Move<VkFence>                                   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, &copyRegions);
+       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<VkPipelineLayout>          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<VkDescriptorPool>          m_descriptorPool;
+       Move<VkDescriptorSetLayout>     m_descriptorSetLayout;
+       Move<VkDescriptorSet>           m_descriptorSet;
+       Move<VkBuffer>                          m_buffer;
+       Move<VkImage>                           m_texture;
+       Move<VkImageView>                       m_imageView;
+       Move<VkSampler>                         m_sampler;
+       de::MovePtr<Allocation>         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<VkPipelineLayout> 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<int>(viewportSize.x()), static_cast<int>(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<deUint16>   m_indices;
+       Move<vk::VkBuffer>              m_indicesBuffer;
+       MovePtr<Allocation>             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<deUint32>(m_indices.size()), 1, 0, 0, 0);
+       }
+       else
+               vk.cmdDraw(cmdBuffer, static_cast<deUint32>(m_numDrawVertices), 1u, 0u, 0u);
+}
+
+class GeometryOutputCountTest : public TestCase
+{
+public:
+                                                       GeometryOutputCountTest (TestContext&           testCtx,
+                                                                                                        const char*            name,
+                                                                                                        const char*            description,
+                                                                                                        const vector<int>      pattern);
+
+       void                                    initPrograms                    (SourceCollections&                     sourceCollections) const;
+       virtual TestInstance*   createInstance                  (Context&                                       context) const;
+
+protected:
+       const vector<int> m_pattern;
+};
+
+GeometryOutputCountTest::GeometryOutputCountTest (TestContext& testCtx, const char* name, const char* description, const vector<int> 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<int>(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<int> createPattern (int count)
+{
+       vector<int>     pattern;
+       pattern.push_back(count);
+       return pattern;
+}
+
+inline vector<int> createPattern (int count0, int count1)
+{
+       vector<int>     pattern;
+       pattern.push_back(count0);
+       pattern.push_back(count1);
+       return pattern;
+}
+
+} // anonymous
+
+TestCaseGroup* createBasicGeometryShaderTests (TestContext& testCtx)
+{
+       MovePtr<TestCaseGroup> 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 (file)
index 0000000..eadb2f1
--- /dev/null
@@ -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 (file)
index 0000000..edf9942
--- /dev/null
@@ -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 <string>
+
+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<TestCaseGroup> 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 (file)
index 0000000..fbc93dd
--- /dev/null
@@ -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 (file)
index 0000000..b5a6315
--- /dev/null
@@ -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 <string>
+
+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<TestCaseGroup> inputPrimitiveGroup              (new TestCaseGroup(testCtx, "input", "Different input primitives."));
+       MovePtr<TestCaseGroup> basicPrimitiveGroup              (new TestCaseGroup(testCtx, "basic_primitive", "Basic Primitive geometry tests"));
+       MovePtr<TestCaseGroup> triStripAdjacencyGroup   (new TestCaseGroup(testCtx, "triangle_strip_adjacency", "Different triangle_strip_adjacency vertex counts."));
+       MovePtr<TestCaseGroup> 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 (file)
index 0000000..fab8fac
--- /dev/null
@@ -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 (file)
index 0000000..278994f
--- /dev/null
@@ -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<VkRenderPass> 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<VkPipeline> 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<float>(renderSize.width), static_cast<float>(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<Vec4>& 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<VkImage>                   colorImage                              (makeImage              (vk, device, makeImageCreateInfo(colorFormat, colorImageExtent, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
+       const UniquePtr<Allocation>             colorImageAlloc                 (bindImage              (vk, device, allocator, *colorImage, MemoryRequirement::Any));
+       const Unique<VkImageView>               colorAttachment                 (makeImageView  (vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
+
+       const VkDeviceSize                              vertexBufferSize                = sizeInBytes(perInstanceAttribute);
+       const Unique<VkBuffer>                  vertexBuffer                    (makeBuffer(vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)));
+       const UniquePtr<Allocation>             vertexBufferAlloc               (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
+
+       const Unique<VkShaderModule>    vertexModule                    (createShaderModule     (vk, device, context.getBinaryCollection().get("vert"), 0u));
+       const Unique<VkShaderModule>    geometryModule                  (createShaderModule     (vk, device, context.getBinaryCollection().get("geom"), 0u));
+       const Unique<VkShaderModule>    fragmentModule                  (createShaderModule     (vk, device, context.getBinaryCollection().get("frag"), 0u));
+
+       const Unique<VkRenderPass>              renderPass                              (makeRenderPass                 (vk, device, colorFormat));
+       const Unique<VkFramebuffer>             framebuffer                             (makeFramebuffer                (vk, device, *renderPass, *colorAttachment, renderSize.x(), renderSize.y(), 1u));
+       const Unique<VkPipelineLayout>  pipelineLayout                  (makePipelineLayout             (vk, device));
+       const Unique<VkPipeline>                pipeline                                (makeGraphicsPipeline   (vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule, renderExtent));
+
+       const Unique<VkCommandPool>             cmdPool                                 (makeCommandPool                (vk, device, queueFamilyIndex));
+       const Unique<VkCommandBuffer>   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<deUint32>(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, &region);
+       }
+       // 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<Vec4> generatePerInstancePosition (const int numInstances)
+{
+       de::Random                      rng(1234);
+       std::vector<Vec4>       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<float>(image.getWidth());
+       const float h   = static_cast<float>(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<Vec4>& perInstancePosition, const int numInvocations)
+{
+       tcu::clear(image, clearColor);
+
+       for (std::vector<Vec4>::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<float>(invocationNdx) / static_cast<float>(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<float>(numInvocations);
+               const float xOffset             = static_cast<float>(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<VkBuffer>                  colorBuffer                     (makeBuffer(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
+       const UniquePtr<Allocation>             colorBufferAlloc        (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
+
+       const std::vector<Vec4>                 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<tcu::TestCaseGroup> 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 (file)
index 0000000..5aaeea0
--- /dev/null
@@ -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 (file)
index 0000000..d5e10e9
--- /dev/null
@@ -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<VkRenderPass> 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<VkPipeline> 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<float>(renderSize.width), static_cast<float>(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<int>(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<int>(size.width))
+               , m_height              (static_cast<int>(size.height))
+               , m_1dModifier  (0)
+               , m_layers              (static_cast<int>(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<int>(rowWidthRatio * static_cast<float>(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<float>(layerNdx) / static_cast<float>(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<VkImage>                   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<Allocation>             colorImageAlloc         (bindImage                              (vk, device, allocator, *colorImage, MemoryRequirement::Any));
+       const Unique<VkImageView>               colorAttachment         (makeImageView                  (vk, device, *colorImage, params.image.viewType, colorFormat, colorSubresourceRange));
+       const Unique<VkBuffer>                  colorBuffer                     (makeBuffer                             (vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
+       const UniquePtr<Allocation>             colorBufferAlloc        (bindBuffer                             (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
+
+       const Unique<VkShaderModule>    vertexModule            (createShaderModule             (vk, device, context.getBinaryCollection().get("vert"), 0u));
+       const Unique<VkShaderModule>    geometryModule          (createShaderModule             (vk, device, context.getBinaryCollection().get("geom"), 0u));
+       const Unique<VkShaderModule>    fragmentModule          (createShaderModule             (vk, device, context.getBinaryCollection().get("frag"), 0u));
+
+       const Unique<VkRenderPass>              renderPass                      (makeRenderPass                 (vk, device, colorFormat));
+       const Unique<VkFramebuffer>             framebuffer                     (makeFramebuffer                (vk, device, *renderPass, *colorAttachment, params.image.size.width,  params.image.size.height, params.image.numLayers));
+       const Unique<VkPipelineLayout>  pipelineLayout          (makePipelineLayout             (vk, device));
+       const Unique<VkPipeline>                pipeline                        (makeGraphicsPipeline   (vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule,
+                                                                                                                                                                makeExtent2D(params.image.size.width, params.image.size.height)));
+       const Unique<VkCommandPool>             cmdPool                         (makeCommandPool                (vk, device, queueFamilyIndex));
+       const Unique<VkCommandBuffer>   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, &region);
+       }
+       // 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<tcu::TestCaseGroup> 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<tcu::TestCaseGroup> 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 (file)
index 0000000..da43466
--- /dev/null
@@ -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 (file)
index 0000000..2afe7b5
--- /dev/null
@@ -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 (file)
index 0000000..b2c18c0
--- /dev/null
@@ -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 (file)
index 0000000..0c8f63f
--- /dev/null
@@ -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<typename T>
+inline const T* dataPointer (const std::vector<T>& vec)
+{
+       return (vec.size() != 0 ? &vec[0] : DE_NULL);
+}
+
+Move<VkPipeline> 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<deUint32>(m_vertexInputBindings.size()),                    // uint32_t                                    vertexBindingDescriptionCount;
+               dataPointer(m_vertexInputBindings),                                                             // const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
+               static_cast<deUint32>(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<float>(m_renderSize.x()), static_cast<float>(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<deUint32>(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<VkDescriptorSet> 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<VkRenderPass> 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<VkImageView> 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<VkPipelineLayout> 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<VkFramebuffer> 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<VkCommandPool> 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<VkCommandBuffer> 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<VkFence> 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<Allocation> bindImage (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkImage image, const MemoryRequirement requirement)
+{
+       de::MovePtr<Allocation> alloc = allocator.allocate(getImageMemoryRequirements(vk, device, image), requirement);
+       VK_CHECK(vk.bindImageMemory(device, image, alloc->getMemory(), alloc->getOffset()));
+       return alloc;
+}
+
+de::MovePtr<Allocation> bindBuffer (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkBuffer buffer, const MemoryRequirement requirement)
+{
+       de::MovePtr<Allocation> 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<std::size_t>(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<deUint32>(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 (file)
index 0000000..43e72a5
--- /dev/null
@@ -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<vk::VkBuffer>          m_buffer;
+       const de::UniquePtr<vk::Allocation>     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<vk::VkImage>           m_image;
+       const de::UniquePtr<vk::Allocation>     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<vk::VkPipeline>        build                                                   (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkPipelineLayout pipelineLayout, const vk::VkRenderPass renderPass);
+
+private:
+       tcu::IVec2                                                                                      m_renderSize;
+       vk::Move<vk::VkShaderModule>                                            m_vertexShaderModule;
+       vk::Move<vk::VkShaderModule>                                            m_fragmentShaderModule;
+       vk::Move<vk::VkShaderModule>                                            m_geometryShaderModule;
+       vk::Move<vk::VkShaderModule>                                            m_tessControlShaderModule;
+       vk::Move<vk::VkShaderModule>                                            m_tessEvaluationShaderModule;
+       std::vector<vk::VkPipelineShaderStageCreateInfo>        m_shaderStages;
+       std::vector<vk::VkVertexInputBindingDescription>        m_vertexInputBindings;
+       std::vector<vk::VkVertexInputAttributeDescription>      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<typename T>
+inline std::size_t sizeInBytes (const std::vector<T>& 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<vk::VkDescriptorSet>  makeDescriptorSet                       (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkDescriptorPool descriptorPool, const vk::VkDescriptorSetLayout setLayout);
+vk::Move<vk::VkRenderPass>             makeRenderPass                          (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkFormat colorFormat);
+vk::Move<vk::VkImageView>              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<vk::VkPipelineLayout> makePipelineLayout                      (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkDescriptorSetLayout descriptorSetLayout = DE_NULL);
+vk::Move<vk::VkFramebuffer>            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<vk::VkCommandPool>            makeCommandPool                         (const vk::DeviceInterface& vk, const vk::VkDevice device, const deUint32 queueFamilyIndex);
+vk::Move<vk::VkCommandBuffer>  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<vk::Allocation>            bindImage                                       (const vk::DeviceInterface& vk, const vk::VkDevice device, vk::Allocator& allocator, const vk::VkImage image, const vk::MemoryRequirement requirement);
+de::MovePtr<vk::Allocation>            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<vk::VkBuffer> makeBuffer (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkBufferCreateInfo& createInfo)
+{
+       return createBuffer(vk, device, &createInfo);
+}
+
+inline vk::Move<vk::VkImage> 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 (file)
index 0000000..6e90fdb
--- /dev/null
@@ -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 <string>
+
+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<TestCaseGroup> 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 (file)
index 0000000..4afb8c7
--- /dev/null
@@ -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
index 7231823..2620deb 100644 (file)
@@ -75,6 +75,7 @@
 #include "vktClippingTests.hpp"
 #include "vktFragmentOperationsTests.hpp"
 #include "vktTextureTests.hpp"
+#include "vktGeometryTests.hpp"
 
 #include <vector>
 #include <sstream>
@@ -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
index e3c2882..04f36de 100644 (file)
@@ -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