Home | History | Annotate | Download | only in geometry
      1 /*------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2016 The Khronos Group Inc.
      6  * Copyright (c) 2014 The Android Open Source Project
      7  *
      8  * Licensed under the Apache License, Version 2.0 (the "License");
      9  * you may not use this file except in compliance with the License.
     10  * You may obtain a copy of the License at
     11  *
     12  *      http://www.apache.org/licenses/LICENSE-2.0
     13  *
     14  * Unless required by applicable law or agreed to in writing, software
     15  * distributed under the License is distributed on an "AS IS" BASIS,
     16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     17  * See the License for the specific language governing permissions and
     18  * limitations under the License.
     19  *
     20  *//*!
     21  * \file
     22  * \brief Geometry shader instanced rendering tests
     23  *//*--------------------------------------------------------------------*/
     24 
     25 #include "vktGeometryInstancedRenderingTests.hpp"
     26 #include "vktTestCase.hpp"
     27 #include "vktTestCaseUtil.hpp"
     28 #include "vktGeometryTestsUtil.hpp"
     29 
     30 #include "vkPrograms.hpp"
     31 #include "vkQueryUtil.hpp"
     32 #include "vkMemUtil.hpp"
     33 #include "vkRefUtil.hpp"
     34 #include "vkTypeUtil.hpp"
     35 #include "vkImageUtil.hpp"
     36 
     37 #include "tcuTextureUtil.hpp"
     38 #include "tcuImageCompare.hpp"
     39 #include "tcuTestLog.hpp"
     40 
     41 #include "deRandom.hpp"
     42 #include "deMath.h"
     43 
     44 namespace vkt
     45 {
     46 namespace geometry
     47 {
     48 namespace
     49 {
     50 using namespace vk;
     51 using de::MovePtr;
     52 using de::UniquePtr;
     53 using tcu::Vec4;
     54 using tcu::UVec2;
     55 
     56 struct TestParams
     57 {
     58 	int	numDrawInstances;
     59 	int	numInvocations;
     60 };
     61 
     62 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const VkExtent3D size, const VkImageUsageFlags usage)
     63 {
     64 	const VkImageCreateInfo imageParams =
     65 	{
     66 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
     67 		DE_NULL,										// const void*				pNext;
     68 		(VkImageCreateFlags)0,							// VkImageCreateFlags		flags;
     69 		VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
     70 		format,											// VkFormat					format;
     71 		size,											// VkExtent3D				extent;
     72 		1u,												// deUint32					mipLevels;
     73 		1u,												// deUint32					arrayLayers;
     74 		VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples;
     75 		VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
     76 		usage,											// VkImageUsageFlags		usage;
     77 		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
     78 		0u,												// deUint32					queueFamilyIndexCount;
     79 		DE_NULL,										// const deUint32*			pQueueFamilyIndices;
     80 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout;
     81 	};
     82 	return imageParams;
     83 }
     84 
     85 Move<VkRenderPass> makeRenderPass (const DeviceInterface&	vk,
     86 								   const VkDevice			device,
     87 								   const VkFormat			colorFormat)
     88 {
     89 	const VkAttachmentDescription colorAttachmentDescription =
     90 	{
     91 		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
     92 		colorFormat,										// VkFormat							format;
     93 		VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
     94 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
     95 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
     96 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
     97 		VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
     98 		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					initialLayout;
     99 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
    100 	};
    101 
    102 	const VkAttachmentReference colorAttachmentRef =
    103 	{
    104 		0u,													// deUint32			attachment;
    105 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
    106 	};
    107 
    108 	const VkSubpassDescription subpassDescription =
    109 	{
    110 		(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags		flags;
    111 		VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
    112 		0u,													// deUint32							inputAttachmentCount;
    113 		DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
    114 		1u,													// deUint32							colorAttachmentCount;
    115 		&colorAttachmentRef,								// const VkAttachmentReference*		pColorAttachments;
    116 		DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
    117 		DE_NULL,											// const VkAttachmentReference*		pDepthStencilAttachment;
    118 		0u,													// deUint32							preserveAttachmentCount;
    119 		DE_NULL												// const deUint32*					pPreserveAttachments;
    120 	};
    121 
    122 	const VkRenderPassCreateInfo renderPassInfo =
    123 	{
    124 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
    125 		DE_NULL,											// const void*						pNext;
    126 		(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
    127 		1u,													// deUint32							attachmentCount;
    128 		&colorAttachmentDescription,						// const VkAttachmentDescription*	pAttachments;
    129 		1u,													// deUint32							subpassCount;
    130 		&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
    131 		0u,													// deUint32							dependencyCount;
    132 		DE_NULL												// const VkSubpassDependency*		pDependencies;
    133 	};
    134 
    135 	return createRenderPass(vk, device, &renderPassInfo);
    136 }
    137 
    138 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&		vk,
    139 									   const VkDevice				device,
    140 									   const VkPipelineLayout		pipelineLayout,
    141 									   const VkRenderPass			renderPass,
    142 									   const VkShaderModule			vertexModule,
    143 									   const VkShaderModule			geometryModule,
    144 									   const VkShaderModule			fragmentModule,
    145 									   const VkExtent2D				renderSize)
    146 {
    147 	const VkVertexInputBindingDescription vertexInputBindingDescription =
    148 	{
    149 		0u,											// uint32_t             binding;
    150 		sizeof(Vec4),								// uint32_t             stride;
    151 		VK_VERTEX_INPUT_RATE_INSTANCE,				// VkVertexInputRate    inputRate;
    152 	};
    153 
    154 	const VkVertexInputAttributeDescription vertexInputAttributeDescription =
    155 	{
    156 		0u,											// uint32_t    location;
    157 		0u,											// uint32_t    binding;
    158 		VK_FORMAT_R32G32B32A32_SFLOAT,				// VkFormat    format;
    159 		0u,											// uint32_t    offset;
    160 	};
    161 
    162 	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
    163 	{
    164 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType                             sType;
    165 		DE_NULL,														// const void*                                 pNext;
    166 		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags       flags;
    167 		1u,																// uint32_t                                    vertexBindingDescriptionCount;
    168 		&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
    169 		1u,																// uint32_t                                    vertexAttributeDescriptionCount;
    170 		&vertexInputAttributeDescription,								// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
    171 	};
    172 
    173 	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
    174 	{
    175 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType                             sType;
    176 		DE_NULL,														// const void*                                 pNext;
    177 		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags     flags;
    178 		VK_PRIMITIVE_TOPOLOGY_POINT_LIST,								// VkPrimitiveTopology                         topology;
    179 		VK_FALSE,														// VkBool32                                    primitiveRestartEnable;
    180 	};
    181 
    182 	const VkViewport viewport = makeViewport(
    183 		0.0f, 0.0f,
    184 		static_cast<float>(renderSize.width), static_cast<float>(renderSize.height),
    185 		0.0f, 1.0f);
    186 	const VkRect2D scissor =
    187 	{
    188 		makeOffset2D(0, 0),
    189 		makeExtent2D(renderSize.width, renderSize.height),
    190 	};
    191 
    192 	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
    193 	{
    194 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType                             sType;
    195 		DE_NULL,														// const void*                                 pNext;
    196 		(VkPipelineViewportStateCreateFlags)0,							// VkPipelineViewportStateCreateFlags          flags;
    197 		1u,																// uint32_t                                    viewportCount;
    198 		&viewport,														// const VkViewport*                           pViewports;
    199 		1u,																// uint32_t                                    scissorCount;
    200 		&scissor,														// const VkRect2D*                             pScissors;
    201 	};
    202 
    203 	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
    204 	{
    205 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType                          sType;
    206 		DE_NULL,														// const void*                              pNext;
    207 		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags  flags;
    208 		VK_FALSE,														// VkBool32                                 depthClampEnable;
    209 		VK_FALSE,														// VkBool32                                 rasterizerDiscardEnable;
    210 		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
    211 		VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
    212 		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
    213 		VK_FALSE,														// VkBool32									depthBiasEnable;
    214 		0.0f,															// float									depthBiasConstantFactor;
    215 		0.0f,															// float									depthBiasClamp;
    216 		0.0f,															// float									depthBiasSlopeFactor;
    217 		1.0f,															// float									lineWidth;
    218 	};
    219 
    220 	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
    221 	{
    222 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
    223 		DE_NULL,														// const void*								pNext;
    224 		(VkPipelineMultisampleStateCreateFlags)0,						// VkPipelineMultisampleStateCreateFlags	flags;
    225 		VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits					rasterizationSamples;
    226 		VK_FALSE,														// VkBool32									sampleShadingEnable;
    227 		0.0f,															// float									minSampleShading;
    228 		DE_NULL,														// const VkSampleMask*						pSampleMask;
    229 		VK_FALSE,														// VkBool32									alphaToCoverageEnable;
    230 		VK_FALSE														// VkBool32									alphaToOneEnable;
    231 	};
    232 
    233 	const VkStencilOpState stencilOpState = makeStencilOpState(
    234 		VK_STENCIL_OP_KEEP,				// stencil fail
    235 		VK_STENCIL_OP_KEEP,				// depth & stencil pass
    236 		VK_STENCIL_OP_KEEP,				// depth only fail
    237 		VK_COMPARE_OP_ALWAYS,			// compare op
    238 		0u,								// compare mask
    239 		0u,								// write mask
    240 		0u);							// reference
    241 
    242 	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
    243 	{
    244 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,		// VkStructureType							sType;
    245 		DE_NULL,														// const void*								pNext;
    246 		(VkPipelineDepthStencilStateCreateFlags)0,						// VkPipelineDepthStencilStateCreateFlags	flags;
    247 		VK_FALSE,														// VkBool32									depthTestEnable;
    248 		VK_FALSE,														// VkBool32									depthWriteEnable;
    249 		VK_COMPARE_OP_LESS,												// VkCompareOp								depthCompareOp;
    250 		VK_FALSE,														// VkBool32									depthBoundsTestEnable;
    251 		VK_FALSE,														// VkBool32									stencilTestEnable;
    252 		stencilOpState,													// VkStencilOpState							front;
    253 		stencilOpState,													// VkStencilOpState							back;
    254 		0.0f,															// float									minDepthBounds;
    255 		1.0f,															// float									maxDepthBounds;
    256 	};
    257 
    258 	const VkColorComponentFlags					colorComponentsAll					= VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
    259 	const VkPipelineColorBlendAttachmentState	pipelineColorBlendAttachmentState	=
    260 	{
    261 		VK_FALSE,						// VkBool32					blendEnable;
    262 		VK_BLEND_FACTOR_ONE,			// VkBlendFactor			srcColorBlendFactor;
    263 		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstColorBlendFactor;
    264 		VK_BLEND_OP_ADD,				// VkBlendOp				colorBlendOp;
    265 		VK_BLEND_FACTOR_ONE,			// VkBlendFactor			srcAlphaBlendFactor;
    266 		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstAlphaBlendFactor;
    267 		VK_BLEND_OP_ADD,				// VkBlendOp				alphaBlendOp;
    268 		colorComponentsAll,				// VkColorComponentFlags	colorWriteMask;
    269 	};
    270 
    271 	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
    272 	{
    273 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,		// VkStructureType								sType;
    274 		DE_NULL,														// const void*									pNext;
    275 		(VkPipelineColorBlendStateCreateFlags)0,						// VkPipelineColorBlendStateCreateFlags			flags;
    276 		VK_FALSE,														// VkBool32										logicOpEnable;
    277 		VK_LOGIC_OP_COPY,												// VkLogicOp									logicOp;
    278 		1u,																// deUint32										attachmentCount;
    279 		&pipelineColorBlendAttachmentState,								// const VkPipelineColorBlendAttachmentState*	pAttachments;
    280 		{ 0.0f, 0.0f, 0.0f, 0.0f },										// float										blendConstants[4];
    281 	};
    282 
    283 	const VkPipelineShaderStageCreateInfo pShaderStages[] =
    284 	{
    285 		{
    286 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
    287 			DE_NULL,													// const void*							pNext;
    288 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
    289 			VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStageFlagBits				stage;
    290 			vertexModule,												// VkShaderModule						module;
    291 			"main",														// const char*							pName;
    292 			DE_NULL,													// const VkSpecializationInfo*			pSpecializationInfo;
    293 		},
    294 		{
    295 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
    296 			DE_NULL,													// const void*							pNext;
    297 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
    298 			VK_SHADER_STAGE_GEOMETRY_BIT,								// VkShaderStageFlagBits				stage;
    299 			geometryModule,												// VkShaderModule						module;
    300 			"main",														// const char*							pName;
    301 			DE_NULL,													// const VkSpecializationInfo*			pSpecializationInfo;
    302 		},
    303 		{
    304 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
    305 			DE_NULL,													// const void*							pNext;
    306 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
    307 			VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlagBits				stage;
    308 			fragmentModule,												// VkShaderModule						module;
    309 			"main",														// const char*							pName;
    310 			DE_NULL,													// const VkSpecializationInfo*			pSpecializationInfo;
    311 		},
    312 	};
    313 
    314 	const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
    315 	{
    316 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
    317 		DE_NULL,											// const void*										pNext;
    318 		(VkPipelineCreateFlags)0,							// VkPipelineCreateFlags							flags;
    319 		DE_LENGTH_OF_ARRAY(pShaderStages),					// deUint32											stageCount;
    320 		pShaderStages,										// const VkPipelineShaderStageCreateInfo*			pStages;
    321 		&vertexInputStateInfo,								// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
    322 		&pipelineInputAssemblyStateInfo,					// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
    323 		DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
    324 		&pipelineViewportStateInfo,							// const VkPipelineViewportStateCreateInfo*			pViewportState;
    325 		&pipelineRasterizationStateInfo,					// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
    326 		&pipelineMultisampleStateInfo,						// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
    327 		&pipelineDepthStencilStateInfo,						// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
    328 		&pipelineColorBlendStateInfo,						// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
    329 		DE_NULL,											// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
    330 		pipelineLayout,										// VkPipelineLayout									layout;
    331 		renderPass,											// VkRenderPass										renderPass;
    332 		0u,													// deUint32											subpass;
    333 		DE_NULL,											// VkPipeline										basePipelineHandle;
    334 		0,													// deInt32											basePipelineIndex;
    335 	};
    336 
    337 	return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
    338 }
    339 
    340 void draw (Context&					context,
    341 		   const UVec2&				renderSize,
    342 		   const VkFormat			colorFormat,
    343 		   const Vec4&				clearColor,
    344 		   const VkBuffer			colorBuffer,
    345 		   const int				numDrawInstances,
    346 		   const std::vector<Vec4>& perInstanceAttribute)
    347 {
    348 	const DeviceInterface&			vk						= context.getDeviceInterface();
    349 	const VkDevice					device					= context.getDevice();
    350 	const deUint32					queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
    351 	const VkQueue					queue					= context.getUniversalQueue();
    352 	Allocator&						allocator				= context.getDefaultAllocator();
    353 
    354 	const VkImageSubresourceRange	colorSubresourceRange	(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
    355 	const VkExtent3D				colorImageExtent		(makeExtent3D(renderSize.x(), renderSize.y(), 1u));
    356 	const VkExtent2D				renderExtent			(makeExtent2D(renderSize.x(), renderSize.y()));
    357 
    358 	const Unique<VkImage>			colorImage				(makeImage		(vk, device, makeImageCreateInfo(colorFormat, colorImageExtent, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
    359 	const UniquePtr<Allocation>		colorImageAlloc			(bindImage		(vk, device, allocator, *colorImage, MemoryRequirement::Any));
    360 	const Unique<VkImageView>		colorAttachment			(makeImageView	(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
    361 
    362 	const VkDeviceSize				vertexBufferSize		= sizeInBytes(perInstanceAttribute);
    363 	const Unique<VkBuffer>			vertexBuffer			(makeBuffer(vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)));
    364 	const UniquePtr<Allocation>		vertexBufferAlloc		(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
    365 
    366 	const Unique<VkShaderModule>	vertexModule			(createShaderModule	(vk, device, context.getBinaryCollection().get("vert"), 0u));
    367 	const Unique<VkShaderModule>	geometryModule			(createShaderModule	(vk, device, context.getBinaryCollection().get("geom"), 0u));
    368 	const Unique<VkShaderModule>	fragmentModule			(createShaderModule	(vk, device, context.getBinaryCollection().get("frag"), 0u));
    369 
    370 	const Unique<VkRenderPass>		renderPass				(makeRenderPass			(vk, device, colorFormat));
    371 	const Unique<VkFramebuffer>		framebuffer				(makeFramebuffer		(vk, device, *renderPass, *colorAttachment, renderSize.x(), renderSize.y(), 1u));
    372 	const Unique<VkPipelineLayout>	pipelineLayout			(makePipelineLayout		(vk, device));
    373 	const Unique<VkPipeline>		pipeline				(makeGraphicsPipeline	(vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule, renderExtent));
    374 
    375 	const Unique<VkCommandPool>		cmdPool					(createCommandPool		(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
    376 	const Unique<VkCommandBuffer>	cmdBuffer				(allocateCommandBuffer	(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
    377 
    378 	// Initialize vertex data
    379 	{
    380 		deMemcpy(vertexBufferAlloc->getHostPtr(), &perInstanceAttribute[0], (size_t)vertexBufferSize);
    381 		flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
    382 	}
    383 
    384 	beginCommandBuffer(vk, *cmdBuffer);
    385 
    386 	const VkClearValue			clearValue	= makeClearValueColor(clearColor);
    387 	const VkRect2D				renderArea	=
    388 	{
    389 		makeOffset2D(0, 0),
    390 		renderExtent,
    391 	};
    392 	const VkRenderPassBeginInfo renderPassBeginInfo =
    393 	{
    394 		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,		// VkStructureType         sType;
    395 		DE_NULL,										// const void*             pNext;
    396 		*renderPass,									// VkRenderPass            renderPass;
    397 		*framebuffer,									// VkFramebuffer           framebuffer;
    398 		renderArea,										// VkRect2D                renderArea;
    399 		1u,												// uint32_t                clearValueCount;
    400 		&clearValue,									// const VkClearValue*     pClearValues;
    401 	};
    402 	vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
    403 
    404 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
    405 	{
    406 		const VkDeviceSize offset = 0ull;
    407 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &offset);
    408 	}
    409 	vk.cmdDraw(*cmdBuffer, 1u, static_cast<deUint32>(numDrawInstances), 0u, 0u);
    410 	vk.cmdEndRenderPass(*cmdBuffer);
    411 
    412 	// Prepare color image for copy
    413 	{
    414 		const VkImageMemoryBarrier barriers[] =
    415 		{
    416 			{
    417 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
    418 				DE_NULL,									// const void*				pNext;
    419 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			outputMask;
    420 				VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			inputMask;
    421 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			oldLayout;
    422 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// VkImageLayout			newLayout;
    423 				VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
    424 				VK_QUEUE_FAMILY_IGNORED,					// deUint32					destQueueFamilyIndex;
    425 				*colorImage,								// VkImage					image;
    426 				colorSubresourceRange,						// VkImageSubresourceRange	subresourceRange;
    427 			},
    428 		};
    429 
    430 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
    431 			0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
    432 	}
    433 	// Color image -> host buffer
    434 	{
    435 		const VkBufferImageCopy region =
    436 		{
    437 			0ull,																	// VkDeviceSize                bufferOffset;
    438 			0u,																		// uint32_t                    bufferRowLength;
    439 			0u,																		// uint32_t                    bufferImageHeight;
    440 			makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),		// VkImageSubresourceLayers    imageSubresource;
    441 			makeOffset3D(0, 0, 0),													// VkOffset3D                  imageOffset;
    442 			colorImageExtent,														// VkExtent3D                  imageExtent;
    443 		};
    444 
    445 		vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer, 1u, &region);
    446 	}
    447 	// Buffer write barrier
    448 	{
    449 		const VkBufferMemoryBarrier barriers[] =
    450 		{
    451 			{
    452 				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// VkStructureType    sType;
    453 				DE_NULL,										// const void*        pNext;
    454 				VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags      srcAccessMask;
    455 				VK_ACCESS_HOST_READ_BIT,						// VkAccessFlags      dstAccessMask;
    456 				VK_QUEUE_FAMILY_IGNORED,						// uint32_t           srcQueueFamilyIndex;
    457 				VK_QUEUE_FAMILY_IGNORED,						// uint32_t           dstQueueFamilyIndex;
    458 				colorBuffer,									// VkBuffer           buffer;
    459 				0ull,											// VkDeviceSize       offset;
    460 				VK_WHOLE_SIZE,									// VkDeviceSize       size;
    461 			},
    462 		};
    463 
    464 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
    465 			0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u);
    466 	}
    467 
    468 	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
    469 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
    470 }
    471 
    472 std::vector<Vec4> generatePerInstancePosition (const int numInstances)
    473 {
    474 	de::Random			rng(1234);
    475 	std::vector<Vec4>	positions;
    476 
    477 	for (int i = 0; i < numInstances; ++i)
    478 	{
    479 		const float flipX	= rng.getBool() ? 1.0f : -1.0f;
    480 		const float flipY	= rng.getBool() ? 1.0f : -1.0f;
    481 		const float x		= flipX * rng.getFloat(0.1f, 0.9f);	// x mustn't be 0.0, because we are using sign() in the shader
    482 		const float y		= flipY * rng.getFloat(0.0f, 0.7f);
    483 
    484 		positions.push_back(Vec4(x, y, 0.0f, 1.0f));
    485 	}
    486 
    487 	return positions;
    488 }
    489 
    490 //! Get a rectangle region of an image, using NDC coordinates (i.e. [-1, 1] range).
    491 //! Result rect is cropped in either dimension to be inside the bounds of the image.
    492 tcu::PixelBufferAccess getSubregion (tcu::PixelBufferAccess image, const float x, const float y, const float size)
    493 {
    494 	const float w	= static_cast<float>(image.getWidth());
    495 	const float h	= static_cast<float>(image.getHeight());
    496 	const float x1	= w * (x + 1.0f) * 0.5f;
    497 	const float y1	= h * (y + 1.0f) * 0.5f;
    498 	const float sx	= w * size * 0.5f;
    499 	const float sy	= h * size * 0.5f;
    500 	const float x2	= x1 + sx;
    501 	const float y2	= y1 + sy;
    502 
    503 	// Round and clamp only after all of the above.
    504 	const int	ix1	= std::max(deRoundFloatToInt32(x1), 0);
    505 	const int	ix2	= std::min(deRoundFloatToInt32(x2), image.getWidth());
    506 	const int	iy1	= std::max(deRoundFloatToInt32(y1), 0);
    507 	const int	iy2	= std::min(deRoundFloatToInt32(y2), image.getHeight());
    508 
    509 	return tcu::getSubregion(image, ix1, iy1, ix2 - ix1, iy2 - iy1);
    510 }
    511 
    512 //! Must be in sync with the geometry shader code.
    513 void generateReferenceImage(tcu::PixelBufferAccess image, const Vec4& clearColor, const std::vector<Vec4>& perInstancePosition, const int numInvocations)
    514 {
    515 	tcu::clear(image, clearColor);
    516 
    517 	for (std::vector<Vec4>::const_iterator iterPosition = perInstancePosition.begin(); iterPosition != perInstancePosition.end(); ++iterPosition)
    518 	for (int invocationNdx = 0; invocationNdx < numInvocations; ++invocationNdx)
    519 	{
    520 		const float x			= iterPosition->x();
    521 		const float y			= iterPosition->y();
    522 		const float	modifier	= (numInvocations > 1 ? static_cast<float>(invocationNdx) / static_cast<float>(numInvocations - 1) : 0.0f);
    523 		const Vec4	color		(deFloatAbs(x), deFloatAbs(y), 0.2f + 0.8f * modifier, 1.0f);
    524 		const float size		= 0.05f + 0.03f * modifier;
    525 		const float dx			= (deFloatSign(-x) - x) / static_cast<float>(numInvocations);
    526 		const float xOffset		= static_cast<float>(invocationNdx) * dx;
    527 		const float yOffset		= 0.3f * deFloatSin(12.0f * modifier);
    528 
    529 		tcu::PixelBufferAccess rect = getSubregion(image, x + xOffset - size, y + yOffset - size, size + size);
    530 		tcu::clear(rect, color);
    531 	}
    532 }
    533 
    534 void initPrograms (SourceCollections& programCollection, const TestParams params)
    535 {
    536 	// Vertex shader
    537 	{
    538 		std::ostringstream src;
    539 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
    540 			<< "\n"
    541 			<< "layout(location = 0) in vec4 in_position;\n"
    542 			<< "\n"
    543 			<< "out gl_PerVertex {\n"
    544 			<< "    vec4 gl_Position;\n"
    545 			<< "};\n"
    546 			<< "\n"
    547 			<< "void main(void)\n"
    548 			<< "{\n"
    549 			<< "    gl_Position = in_position;\n"
    550 			<< "}\n";
    551 
    552 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
    553 	}
    554 
    555 	// Geometry shader
    556 	{
    557 		// The shader must be in sync with reference image rendering routine.
    558 
    559 		std::ostringstream src;
    560 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
    561 			<< "\n"
    562 			<< "layout(points, invocations = " << params.numInvocations << ") in;\n"
    563 			<< "layout(triangle_strip, max_vertices = 4) out;\n"
    564 			<< "\n"
    565 			<< "layout(location = 0) out vec4 out_color;\n"
    566 			<< "\n"
    567 			<< "in gl_PerVertex {\n"
    568 			<< "    vec4 gl_Position;\n"
    569 			<< "} gl_in[];\n"
    570 			<< "\n"
    571 			<< "out gl_PerVertex {\n"
    572 			<< "    vec4 gl_Position;\n"
    573 			<< "};\n"
    574 			<< "\n"
    575 			<< "void main(void)\n"
    576 			<< "{\n"
    577 			<< "    const vec4  pos       = gl_in[0].gl_Position;\n"
    578 			<< "    const float modifier  = " << (params.numInvocations > 1 ? "float(gl_InvocationID) / float(" + de::toString(params.numInvocations - 1) + ")" : "0.0") << ";\n"
    579 			<< "    const vec4  color     = vec4(abs(pos.x), abs(pos.y), 0.2 + 0.8 * modifier, 1.0);\n"
    580 			<< "    const float size      = 0.05 + 0.03 * modifier;\n"
    581 			<< "    const float dx        = (sign(-pos.x) - pos.x) / float(" << params.numInvocations << ");\n"
    582 			<< "    const vec4  offsetPos = pos + vec4(float(gl_InvocationID) * dx,\n"
    583 			<< "                                       0.3 * sin(12.0 * modifier),\n"
    584 			<< "                                       0.0,\n"
    585 			<< "                                       0.0);\n"
    586 			<< "\n"
    587 			<< "    gl_Position = offsetPos + vec4(-size, -size, 0.0, 0.0);\n"
    588 			<< "    out_color   = color;\n"
    589 			<< "    EmitVertex();\n"
    590 			<< "\n"
    591 			<< "    gl_Position = offsetPos + vec4(-size,  size, 0.0, 0.0);\n"
    592 			<< "    out_color   = color;\n"
    593 			<< "    EmitVertex();\n"
    594 			<< "\n"
    595 			<< "    gl_Position = offsetPos + vec4( size, -size, 0.0, 0.0);\n"
    596 			<< "    out_color   = color;\n"
    597 			<< "    EmitVertex();\n"
    598 			<< "\n"
    599 			<< "    gl_Position = offsetPos + vec4( size,  size, 0.0, 0.0);\n"
    600 			<< "    out_color   = color;\n"
    601 			<< "    EmitVertex();\n"
    602 			<<	"}\n";
    603 
    604 		programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
    605 	}
    606 
    607 	// Fragment shader
    608 	{
    609 		std::ostringstream src;
    610 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
    611 			<< "\n"
    612 			<< "layout(location = 0) in  vec4 in_color;\n"
    613 			<< "layout(location = 0) out vec4 o_color;\n"
    614 			<< "\n"
    615 			<< "void main(void)\n"
    616 			<< "{\n"
    617 			<< "    o_color = in_color;\n"
    618 			<< "}\n";
    619 
    620 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
    621 	}
    622 }
    623 
    624 tcu::TestStatus test (Context& context, const TestParams params)
    625 {
    626 	const DeviceInterface&			vk					= context.getDeviceInterface();
    627 	const InstanceInterface&		vki					= context.getInstanceInterface();
    628 	const VkDevice					device				= context.getDevice();
    629 	const VkPhysicalDevice			physDevice			= context.getPhysicalDevice();
    630 	Allocator&						allocator			= context.getDefaultAllocator();
    631 
    632 	checkGeometryShaderSupport(vki, physDevice, params.numInvocations);
    633 
    634 	const UVec2						renderSize			(128u, 128u);
    635 	const VkFormat					colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
    636 	const Vec4						clearColor			= Vec4(0.0f, 0.0f, 0.0f, 1.0f);
    637 
    638 	const VkDeviceSize				colorBufferSize		= renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
    639 	const Unique<VkBuffer>			colorBuffer			(makeBuffer(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
    640 	const UniquePtr<Allocation>		colorBufferAlloc	(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
    641 
    642 	const std::vector<Vec4>			perInstancePosition	= generatePerInstancePosition(params.numDrawInstances);
    643 
    644 	{
    645 		context.getTestContext().getLog()
    646 			<< tcu::TestLog::Message << "Rendering " << params.numDrawInstances << " instance(s) of colorful quads." << tcu::TestLog::EndMessage
    647 			<< tcu::TestLog::Message << "Drawing " << params.numInvocations << " quad(s), each drawn by a geometry shader invocation." << tcu::TestLog::EndMessage;
    648 	}
    649 
    650 	zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
    651 	draw(context, renderSize, colorFormat, clearColor, *colorBuffer, params.numDrawInstances, perInstancePosition);
    652 
    653 	// Compare result
    654 	{
    655 		invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSize);
    656 		const tcu::ConstPixelBufferAccess result(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, colorBufferAlloc->getHostPtr());
    657 
    658 		tcu::TextureLevel reference(mapVkFormat(colorFormat), renderSize.x(), renderSize.y());
    659 		generateReferenceImage(reference.getAccess(), clearColor, perInstancePosition, params.numInvocations);
    660 
    661 		if (!tcu::fuzzyCompare(context.getTestContext().getLog(), "Image Compare", "Image Compare", reference.getAccess(), result, 0.01f, tcu::COMPARE_LOG_RESULT))
    662 			return tcu::TestStatus::fail("Rendered image is incorrect");
    663 		else
    664 			return tcu::TestStatus::pass("OK");
    665 	}
    666 }
    667 
    668 } // anonymous
    669 
    670 //! \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
    671 //!       a shader based on that. This applies to number of GS invocations which can't be injected into the shader.
    672 tcu::TestCaseGroup* createInstancedRenderingTests (tcu::TestContext& testCtx)
    673 {
    674 	MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "instanced", "Instanced rendering tests."));
    675 
    676 	const int drawInstanceCases[]	=
    677 	{
    678 		1, 2, 4, 8,
    679 	};
    680 	const int invocationCases[]		=
    681 	{
    682 		1, 2, 8, 32,	// required by the Vulkan spec
    683 		64, 127,		// larger than the minimum, but perhaps some implementations support it, so we'll try
    684 	};
    685 
    686 	for (const int* pNumDrawInstances = drawInstanceCases; pNumDrawInstances != drawInstanceCases + DE_LENGTH_OF_ARRAY(drawInstanceCases); ++pNumDrawInstances)
    687 	for (const int* pNumInvocations   = invocationCases;   pNumInvocations   != invocationCases   + DE_LENGTH_OF_ARRAY(invocationCases);   ++pNumInvocations)
    688 	{
    689 		std::ostringstream caseName;
    690 		caseName << "draw_" << *pNumDrawInstances << "_instances_" << *pNumInvocations << "_geometry_invocations";
    691 
    692 		const TestParams params =
    693 		{
    694 			*pNumDrawInstances,
    695 			*pNumInvocations,
    696 		};
    697 
    698 		addFunctionCaseWithPrograms(group.get(), caseName.str(), "", initPrograms, test, params);
    699 	}
    700 
    701 	return group.release();
    702 }
    703 
    704 } // geometry
    705 } // vkt
    706