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
add_subdirectory(synchronization)
add_subdirectory(clipping)
add_subdirectory(fragment_ops)
+add_subdirectory(geometry)
add_subdirectory(texture)
include_directories(
clipping
fragment_ops
texture
+ geometry
)
set(DEQP_VK_COMMON_SRCS
deqp-vk-clipping
deqp-vk-fragment-ops
deqp-vk-texture
+ deqp-vk-geometry
)
add_library(deqp-vk-common STATIC ${DEQP_VK_COMMON_SRCS})
--- /dev/null
+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})
--- /dev/null
+/*------------------------------------------------------------------------
+ * 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, ©Region);
+ }
+
+ {
+ const VkBufferMemoryBarrier postCopyBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, colorBufferSizeBytes);
+
+ vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
+ 0u, DE_NULL, 1u, &postCopyBarrier, 0u, DE_NULL);
+ }
+
+ endCommandBuffer(vk, *cmdBuffer);
+ submitCommandsAndWait(vk, device, queue, *cmdBuffer);
+
+ {
+ // Log the result image.
+ const Allocation& colorBufferAlloc = colorBuffer.getAllocation();
+ invalidateMappedMemoryRange(vk, device, colorBufferAlloc.getMemory(), colorBufferAlloc.getOffset(), colorBufferSizeBytes);
+ const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), resolution.x(), resolution.y(), 1, colorBufferAlloc.getHostPtr());
+
+ if (!compareWithFileImage(m_context, imagePixelAccess, m_name))
+ return TestStatus::fail("Fail");
+ }
+
+ return TestStatus::pass("Pass");
+}
+
+Move<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
--- /dev/null
+#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
--- /dev/null
+/*------------------------------------------------------------------------
+ * 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, ©Regions);
+ vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
+ VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+
+ const VkSubmitInfo submitInfo =
+ {
+ VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // deUint32 waitSemaphoreCount;
+ DE_NULL, // const VkSemaphore* pWaitSemaphores;
+ DE_NULL, // const VkPipelineStageFlags* pWaitDstStageMask;
+ 1u, // deUint32 commandBufferCount;
+ &cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
+ 0u, // deUint32 signalSemaphoreCount;
+ DE_NULL // const VkSemaphore* pSignalSemaphores;
+ };
+
+ VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
+ VK_CHECK(vk.waitForFences(device, 1, &fence.get(), true, ~(0ull) /* infinity */));
+}
+
+class GeometryOutputCountTestInstance : public GeometryExpanderRenderTestInstance
+{
+public:
+ GeometryOutputCountTestInstance (Context& context,
+ const VkPrimitiveTopology primitiveType,
+ const int primitiveCount,
+ const char* name);
+ void genVertexAttribData (void);
+private:
+ const int m_primitiveCount;
+};
+
+GeometryOutputCountTestInstance::GeometryOutputCountTestInstance (Context& context,
+ const VkPrimitiveTopology primitiveType,
+ const int primitiveCount,
+ const char* name)
+ : GeometryExpanderRenderTestInstance (context, primitiveType, name)
+ , m_primitiveCount (primitiveCount)
+
+{
+ genVertexAttribData();
+}
+
+void GeometryOutputCountTestInstance::genVertexAttribData (void)
+{
+ m_vertexPosData.resize(m_primitiveCount);
+ m_vertexAttrData.resize(m_primitiveCount);
+
+ for (int ndx = 0; ndx < m_primitiveCount; ++ndx)
+ {
+ m_vertexPosData[ndx] = tcu::Vec4(-1.0f, ((float)ndx) / (float)m_primitiveCount * 2.0f - 1.0f, 0.0f, 1.0f);
+ m_vertexAttrData[ndx] = (ndx % 2 == 0) ? tcu::Vec4(1, 1, 1, 1) : tcu::Vec4(1, 0, 0, 1);
+ }
+ m_numDrawVertices = m_primitiveCount;
+}
+
+class VaryingOutputCountTestInstance : public GeometryExpanderRenderTestInstance
+{
+public:
+ VaryingOutputCountTestInstance (Context& context,
+ const char* name,
+ const VkPrimitiveTopology primitiveType,
+ const VaryingSource test,
+ const ShaderInstancingMode mode);
+ void genVertexAttribData (void);
+protected:
+ Move<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
--- /dev/null
+#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
--- /dev/null
+/*------------------------------------------------------------------------
+ * 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
--- /dev/null
+#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
--- /dev/null
+/*------------------------------------------------------------------------
+ * 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
--- /dev/null
+#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
--- /dev/null
+/*------------------------------------------------------------------------
+ * 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, ®ion);
+ }
+ // Buffer write barrier
+ {
+ const VkBufferMemoryBarrier barriers[] =
+ {
+ {
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
+ VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
+ VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
+ VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
+ colorBuffer, // VkBuffer buffer;
+ 0ull, // VkDeviceSize offset;
+ VK_WHOLE_SIZE, // VkDeviceSize size;
+ },
+ };
+
+ vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
+ 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u);
+ }
+
+ VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+ submitCommandsAndWait(vk, device, queue, *cmdBuffer);
+}
+
+std::vector<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
--- /dev/null
+#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
--- /dev/null
+/*------------------------------------------------------------------------
+ * 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, ®ion);
+ }
+ // Buffer write barrier
+ {
+ const VkBufferMemoryBarrier barriers[] =
+ {
+ {
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
+ VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
+ VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
+ VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
+ *colorBuffer, // VkBuffer buffer;
+ 0ull, // VkDeviceSize offset;
+ VK_WHOLE_SIZE, // VkDeviceSize size;
+ },
+ };
+
+ vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
+ 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u);
+ }
+
+ VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+ submitCommandsAndWait(vk, device, queue, *cmdBuffer);
+
+ invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSize);
+
+ if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
+ return tcu::TestStatus::fail("Rendered images are incorrect");
+ else
+ return tcu::TestStatus::pass("OK");
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createLayeredRenderingTests (tcu::TestContext& testCtx)
+{
+ MovePtr<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
--- /dev/null
+#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
--- /dev/null
+/*------------------------------------------------------------------------
+ * 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
--- /dev/null
+#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
--- /dev/null
+/*------------------------------------------------------------------------
+ * 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
--- /dev/null
+#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
--- /dev/null
+/*------------------------------------------------------------------------
+ * 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
--- /dev/null
+#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
#include "vktClippingTests.hpp"
#include "vktFragmentOperationsTests.hpp"
#include "vktTextureTests.hpp"
+#include "vktGeometryTests.hpp"
#include <vector>
#include <sstream>
addChild(clipping::createTests (m_testCtx));
addChild(FragmentOperations::createTests(m_testCtx));
addChild(texture::createTests (m_testCtx));
+ addChild(geometry::createTests (m_testCtx));
}
} // vkt
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