Home | History | Annotate | Download | only in draw
      1 /*------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2018 The Khronos Group Inc.
      6  * Copyright (c) 2018 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 Use of gl_Layer in Vertex and Tessellation Shaders
     23  *        (part of VK_EXT_ShaderViewportIndexLayer)
     24  *//*--------------------------------------------------------------------*/
     25 
     26 #include "vktDrawShaderLayerTests.hpp"
     27 
     28 #include "vktDrawBaseClass.hpp"
     29 #include "vktTestCaseUtil.hpp"
     30 
     31 #include "vkDefs.hpp"
     32 #include "vkRef.hpp"
     33 #include "vkRefUtil.hpp"
     34 #include "vkTypeUtil.hpp"
     35 #include "vkMemUtil.hpp"
     36 #include "vkPrograms.hpp"
     37 #include "vkImageUtil.hpp"
     38 #include "vkQueryUtil.hpp"
     39 
     40 #include "tcuTestLog.hpp"
     41 #include "tcuVector.hpp"
     42 #include "tcuImageCompare.hpp"
     43 #include "tcuTextureUtil.hpp"
     44 
     45 #include "deUniquePtr.hpp"
     46 #include "deMath.h"
     47 
     48 #include <vector>
     49 
     50 namespace vkt
     51 {
     52 namespace Draw
     53 {
     54 using namespace vk;
     55 using de::UniquePtr;
     56 using de::MovePtr;
     57 using de::SharedPtr;
     58 using tcu::Vec4;
     59 using tcu::Vec2;
     60 using tcu::UVec2;
     61 using tcu::UVec4;
     62 
     63 namespace
     64 {
     65 
     66 enum Constants
     67 {
     68 	MIN_MAX_FRAMEBUFFER_LAYERS = 256,	//!< Minimum number of framebuffer layers.
     69 	MIN_MAX_VIEWPORTS = 16,				//!< Minimum number of viewports for an implementation supporting multiViewport.
     70 };
     71 
     72 template<typename T>
     73 inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
     74 {
     75 	return vec.size() * sizeof(vec[0]);
     76 }
     77 
     78 VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize			bufferSize,
     79 										 const VkBufferUsageFlags	usage)
     80 {
     81 	const VkBufferCreateInfo bufferCreateInfo =
     82 	{
     83 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
     84 		DE_NULL,								// const void*			pNext;
     85 		(VkBufferCreateFlags)0,					// VkBufferCreateFlags	flags;
     86 		bufferSize,								// VkDeviceSize			size;
     87 		usage,									// VkBufferUsageFlags	usage;
     88 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
     89 		0u,										// deUint32				queueFamilyIndexCount;
     90 		DE_NULL,								// const deUint32*		pQueueFamilyIndices;
     91 	};
     92 	return bufferCreateInfo;
     93 }
     94 
     95 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface&		vk,
     96 										   const VkDevice				device)
     97 {
     98 	const VkPipelineLayoutCreateInfo info =
     99 	{
    100 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
    101 		DE_NULL,											// const void*					pNext;
    102 		(VkPipelineLayoutCreateFlags)0,						// VkPipelineLayoutCreateFlags	flags;
    103 		0u,													// deUint32						setLayoutCount;
    104 		DE_NULL,											// const VkDescriptorSetLayout*	pSetLayouts;
    105 		0u,													// deUint32						pushConstantRangeCount;
    106 		DE_NULL,											// const VkPushConstantRange*	pPushConstantRanges;
    107 	};
    108 	return createPipelineLayout(vk, device, &info);
    109 }
    110 
    111 Move<VkImageView> makeImageView (const DeviceInterface&			vk,
    112 								 const VkDevice					vkDevice,
    113 								 const VkImage					image,
    114 								 const VkImageViewType			viewType,
    115 								 const VkFormat					format,
    116 								 const VkImageSubresourceRange	subresourceRange)
    117 {
    118 	const VkImageViewCreateInfo imageViewParams =
    119 	{
    120 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
    121 		DE_NULL,										// const void*				pNext;
    122 		(VkImageViewCreateFlags)0,						// VkImageViewCreateFlags	flags;
    123 		image,											// VkImage					image;
    124 		viewType,										// VkImageViewType			viewType;
    125 		format,											// VkFormat					format;
    126 		makeComponentMappingRGBA(),						// VkComponentMapping		components;
    127 		subresourceRange,								// VkImageSubresourceRange	subresourceRange;
    128 	};
    129 	return createImageView(vk, vkDevice, &imageViewParams);
    130 }
    131 
    132 void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
    133 {
    134 	const VkCommandBufferBeginInfo info =
    135 	{
    136 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType                          sType;
    137 		DE_NULL,										// const void*                              pNext;
    138 		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// VkCommandBufferUsageFlags                flags;
    139 		DE_NULL,										// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
    140 	};
    141 	VK_CHECK(vk.beginCommandBuffer(commandBuffer, &info));
    142 }
    143 
    144 void submitCommandsAndWait (const DeviceInterface&	vk,
    145 							const VkDevice			device,
    146 							const VkQueue			queue,
    147 							const VkCommandBuffer	commandBuffer)
    148 {
    149 	const Unique<VkFence> fence(createFence(vk, device));
    150 
    151 	const VkSubmitInfo submitInfo =
    152 	{
    153 		VK_STRUCTURE_TYPE_SUBMIT_INFO,		// VkStructureType                sType;
    154 		DE_NULL,							// const void*                    pNext;
    155 		0u,									// uint32_t                       waitSemaphoreCount;
    156 		DE_NULL,							// const VkSemaphore*             pWaitSemaphores;
    157 		DE_NULL,							// const VkPipelineStageFlags*    pWaitDstStageMask;
    158 		1u,									// uint32_t                       commandBufferCount;
    159 		&commandBuffer,						// const VkCommandBuffer*         pCommandBuffers;
    160 		0u,									// uint32_t                       signalSemaphoreCount;
    161 		DE_NULL,							// const VkSemaphore*             pSignalSemaphores;
    162 	};
    163 	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
    164 	VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
    165 }
    166 
    167 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&		vk,
    168 									 const VkDevice				device,
    169 									 const VkRenderPass			renderPass,
    170 									 const deUint32				attachmentCount,
    171 									 const VkImageView*			pAttachments,
    172 									 const deUint32				width,
    173 									 const deUint32				height,
    174 									 const deUint32				layers = 1u)
    175 {
    176 	const VkFramebufferCreateInfo framebufferInfo = {
    177 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,		// VkStructureType                             sType;
    178 		DE_NULL,										// const void*                                 pNext;
    179 		(VkFramebufferCreateFlags)0,					// VkFramebufferCreateFlags                    flags;
    180 		renderPass,										// VkRenderPass                                renderPass;
    181 		attachmentCount,								// uint32_t                                    attachmentCount;
    182 		pAttachments,									// const VkImageView*                          pAttachments;
    183 		width,											// uint32_t                                    width;
    184 		height,											// uint32_t                                    height;
    185 		layers,											// uint32_t                                    layers;
    186 	};
    187 
    188 	return createFramebuffer(vk, device, &framebufferInfo);
    189 }
    190 
    191 MovePtr<Allocation> bindImage (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkImage image, const MemoryRequirement requirement)
    192 {
    193 	MovePtr<Allocation> alloc = allocator.allocate(getImageMemoryRequirements(vk, device, image), requirement);
    194 	VK_CHECK(vk.bindImageMemory(device, image, alloc->getMemory(), alloc->getOffset()));
    195 	return alloc;
    196 }
    197 
    198 inline vk::Move<vk::VkImage> makeImage (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkImageCreateInfo& createInfo)
    199 {
    200 	return createImage(vk, device, &createInfo);
    201 }
    202 
    203 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const UVec2& size, const deUint32 numLayers, VkImageUsageFlags usage)
    204 {
    205 	const VkImageCreateInfo imageParams =
    206 	{
    207 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
    208 		DE_NULL,										// const void*				pNext;
    209 		(VkImageCreateFlags)0,							// VkImageCreateFlags		flags;
    210 		VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
    211 		format,											// VkFormat					format;
    212 		makeExtent3D(size.x(), size.y(), 1),			// VkExtent3D				extent;
    213 		1u,												// deUint32					mipLevels;
    214 		numLayers,										// deUint32					arrayLayers;
    215 		VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples;
    216 		VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
    217 		usage,											// VkImageUsageFlags		usage;
    218 		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
    219 		0u,												// deUint32					queueFamilyIndexCount;
    220 		DE_NULL,										// const deUint32*			pQueueFamilyIndices;
    221 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout;
    222 	};
    223 	return imageParams;
    224 }
    225 
    226 //! A single-attachment, single-subpass render pass.
    227 Move<VkRenderPass> makeRenderPass (const DeviceInterface&	vk,
    228 								   const VkDevice			device,
    229 								   const VkFormat			colorFormat)
    230 {
    231 	const VkAttachmentDescription colorAttachmentDescription =
    232 	{
    233 		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
    234 		colorFormat,										// VkFormat							format;
    235 		VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
    236 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
    237 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
    238 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
    239 		VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
    240 		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					initialLayout;
    241 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
    242 	};
    243 
    244 	const VkAttachmentReference colorAttachmentRef =
    245 	{
    246 		0u,													// deUint32			attachment;
    247 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
    248 	};
    249 
    250 	const VkSubpassDescription subpassDescription =
    251 	{
    252 		(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags		flags;
    253 		VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
    254 		0u,													// deUint32							inputAttachmentCount;
    255 		DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
    256 		1u,													// deUint32							colorAttachmentCount;
    257 		&colorAttachmentRef,								// const VkAttachmentReference*		pColorAttachments;
    258 		DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
    259 		DE_NULL,											// const VkAttachmentReference*		pDepthStencilAttachment;
    260 		0u,													// deUint32							preserveAttachmentCount;
    261 		DE_NULL												// const deUint32*					pPreserveAttachments;
    262 	};
    263 
    264 	const VkRenderPassCreateInfo renderPassInfo =
    265 	{
    266 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
    267 		DE_NULL,											// const void*						pNext;
    268 		(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
    269 		1u,													// deUint32							attachmentCount;
    270 		&colorAttachmentDescription,						// const VkAttachmentDescription*	pAttachments;
    271 		1u,													// deUint32							subpassCount;
    272 		&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
    273 		0u,													// deUint32							dependencyCount;
    274 		DE_NULL												// const VkSubpassDependency*		pDependencies;
    275 	};
    276 
    277 	return createRenderPass(vk, device, &renderPassInfo);
    278 }
    279 
    280 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&		vk,
    281 									   const VkDevice				device,
    282 									   const VkPipelineLayout		pipelineLayout,
    283 									   const VkRenderPass			renderPass,
    284 									   const VkShaderModule			vertexModule,
    285 									   const VkShaderModule			tessellationControlModule,
    286 									   const VkShaderModule			tessellationEvaluationModule,
    287 									   const VkShaderModule			fragmentModule,
    288 									   const UVec2					renderSize)
    289 {
    290 	const VkVertexInputBindingDescription vertexInputBindingDescription =
    291 	{
    292 		0u,								// uint32_t				binding;
    293 		sizeof(PositionColorVertex),	// uint32_t				stride;
    294 		VK_VERTEX_INPUT_RATE_VERTEX,	// VkVertexInputRate	inputRate;
    295 	};
    296 
    297 	const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
    298 	{
    299 		{
    300 			0u,									// uint32_t			location;
    301 			0u,									// uint32_t			binding;
    302 			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat			format;
    303 			0u,									// uint32_t			offset;
    304 		},
    305 		{
    306 			1u,									// uint32_t			location;
    307 			0u,									// uint32_t			binding;
    308 			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat			format;
    309 			sizeof(Vec4),						// uint32_t			offset;
    310 		},
    311 	};
    312 
    313 	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
    314 	{
    315 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType                             sType;
    316 		DE_NULL,														// const void*                                 pNext;
    317 		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags       flags;
    318 		1u,																// uint32_t                                    vertexBindingDescriptionCount;
    319 		&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
    320 		DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),			// uint32_t                                    vertexAttributeDescriptionCount;
    321 		vertexInputAttributeDescriptions,								// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
    322 	};
    323 
    324 	const bool useTessellationShaders = (tessellationControlModule != DE_NULL) && (tessellationEvaluationModule != DE_NULL);
    325 
    326 	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
    327 	{
    328 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,										// VkStructureType                             sType;
    329 		DE_NULL,																							// const void*                                 pNext;
    330 		(VkPipelineInputAssemblyStateCreateFlags)0,															// VkPipelineInputAssemblyStateCreateFlags     flags;
    331 		useTessellationShaders ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// VkPrimitiveTopology                         topology;
    332 		VK_FALSE,																							// VkBool32                                    primitiveRestartEnable;
    333 	};
    334 
    335 
    336 	VkViewport viewport = makeViewport(0.0f, 0.0f, static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()), 0.0f, 1.0f);
    337 	VkRect2D rectScissor = { { 0, 0 }, { renderSize.x(), renderSize.y() } };
    338 
    339 	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
    340 	{
    341 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType                             sType;
    342 		DE_NULL,														// const void*                                 pNext;
    343 		(VkPipelineViewportStateCreateFlags)0,							// VkPipelineViewportStateCreateFlags          flags;
    344 		1u,																// uint32_t                                    viewportCount;
    345 		&viewport,														// const VkViewport*                           pViewports;
    346 		1u,																// uint32_t                                    scissorCount;
    347 		&rectScissor,													// const VkRect2D*                             pScissors;
    348 	};
    349 
    350 	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
    351 	{
    352 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType                          sType;
    353 		DE_NULL,														// const void*                              pNext;
    354 		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags  flags;
    355 		VK_FALSE,														// VkBool32                                 depthClampEnable;
    356 		VK_FALSE,														// VkBool32                                 rasterizerDiscardEnable;
    357 		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
    358 		VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
    359 		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
    360 		VK_FALSE,														// VkBool32									depthBiasEnable;
    361 		0.0f,															// float									depthBiasConstantFactor;
    362 		0.0f,															// float									depthBiasClamp;
    363 		0.0f,															// float									depthBiasSlopeFactor;
    364 		1.0f,															// float									lineWidth;
    365 	};
    366 
    367 	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
    368 	{
    369 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
    370 		DE_NULL,														// const void*								pNext;
    371 		(VkPipelineMultisampleStateCreateFlags)0,						// VkPipelineMultisampleStateCreateFlags	flags;
    372 		VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits					rasterizationSamples;
    373 		VK_FALSE,														// VkBool32									sampleShadingEnable;
    374 		0.0f,															// float									minSampleShading;
    375 		DE_NULL,														// const VkSampleMask*						pSampleMask;
    376 		VK_FALSE,														// VkBool32									alphaToCoverageEnable;
    377 		VK_FALSE														// VkBool32									alphaToOneEnable;
    378 	};
    379 
    380 	const VkStencilOpState stencilOpState = makeStencilOpState(
    381 		VK_STENCIL_OP_KEEP,				// stencil fail
    382 		VK_STENCIL_OP_KEEP,				// depth & stencil pass
    383 		VK_STENCIL_OP_KEEP,				// depth only fail
    384 		VK_COMPARE_OP_ALWAYS,			// compare op
    385 		0u,								// compare mask
    386 		0u,								// write mask
    387 		0u);							// reference
    388 
    389 	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
    390 	{
    391 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,		// VkStructureType							sType;
    392 		DE_NULL,														// const void*								pNext;
    393 		(VkPipelineDepthStencilStateCreateFlags)0,						// VkPipelineDepthStencilStateCreateFlags	flags;
    394 		VK_FALSE,														// VkBool32									depthTestEnable;
    395 		VK_FALSE,														// VkBool32									depthWriteEnable;
    396 		VK_COMPARE_OP_LESS,												// VkCompareOp								depthCompareOp;
    397 		VK_FALSE,														// VkBool32									depthBoundsTestEnable;
    398 		VK_FALSE,														// VkBool32									stencilTestEnable;
    399 		stencilOpState,													// VkStencilOpState							front;
    400 		stencilOpState,													// VkStencilOpState							back;
    401 		0.0f,															// float									minDepthBounds;
    402 		1.0f,															// float									maxDepthBounds;
    403 	};
    404 
    405 	const VkColorComponentFlags					colorComponentsAll					= VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
    406 	const VkPipelineColorBlendAttachmentState	pipelineColorBlendAttachmentState	=
    407 	{
    408 		VK_FALSE,						// VkBool32					blendEnable;
    409 		VK_BLEND_FACTOR_ONE,			// VkBlendFactor			srcColorBlendFactor;
    410 		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstColorBlendFactor;
    411 		VK_BLEND_OP_ADD,				// VkBlendOp				colorBlendOp;
    412 		VK_BLEND_FACTOR_ONE,			// VkBlendFactor			srcAlphaBlendFactor;
    413 		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstAlphaBlendFactor;
    414 		VK_BLEND_OP_ADD,				// VkBlendOp				alphaBlendOp;
    415 		colorComponentsAll,				// VkColorComponentFlags	colorWriteMask;
    416 	};
    417 
    418 	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
    419 	{
    420 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,		// VkStructureType								sType;
    421 		DE_NULL,														// const void*									pNext;
    422 		(VkPipelineColorBlendStateCreateFlags)0,						// VkPipelineColorBlendStateCreateFlags			flags;
    423 		VK_FALSE,														// VkBool32										logicOpEnable;
    424 		VK_LOGIC_OP_COPY,												// VkLogicOp									logicOp;
    425 		1u,																// deUint32										attachmentCount;
    426 		&pipelineColorBlendAttachmentState,								// const VkPipelineColorBlendAttachmentState*	pAttachments;
    427 		{ 0.0f, 0.0f, 0.0f, 0.0f },										// float										blendConstants[4];
    428 	};
    429 
    430 	const VkPipelineShaderStageCreateInfo pShaderStages[] =
    431 	{
    432 		{
    433 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
    434 			DE_NULL,													// const void*							pNext;
    435 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
    436 			VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStageFlagBits				stage;
    437 			vertexModule,												// VkShaderModule						module;
    438 			"main",														// const char*							pName;
    439 			DE_NULL,													// const VkSpecializationInfo*			pSpecializationInfo;
    440 		},
    441 		{
    442 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
    443 			DE_NULL,													// const void*							pNext;
    444 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
    445 			VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlagBits				stage;
    446 			fragmentModule,												// VkShaderModule						module;
    447 			"main",														// const char*							pName;
    448 			DE_NULL,													// const VkSpecializationInfo*			pSpecializationInfo;
    449 		},
    450 		{
    451 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
    452 			DE_NULL,													// const void*							pNext;
    453 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
    454 			VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,					// VkShaderStageFlagBits				stage;
    455 			tessellationControlModule,									// VkShaderModule						module;
    456 			"main",														// const char*							pName;
    457 			DE_NULL,													// const VkSpecializationInfo*			pSpecializationInfo;
    458 		},
    459 		{
    460 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
    461 			DE_NULL,													// const void*							pNext;
    462 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
    463 			VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,				// VkShaderStageFlagBits				stage;
    464 			tessellationEvaluationModule,								// VkShaderModule						module;
    465 			"main",														// const char*							pName;
    466 			DE_NULL,													// const VkSpecializationInfo*			pSpecializationInfo;
    467 		},
    468 	};
    469 
    470 	const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
    471 	{
    472 		VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,		// VkStructureType							sType;
    473 		DE_NULL,														// const void*								pNext;
    474 		(VkPipelineTessellationStateCreateFlags)0,						// VkPipelineTessellationStateCreateFlags	flags;
    475 		3,																// uint32_t									patchControlPoints;
    476 	};
    477 
    478 	const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
    479 	{
    480 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,					// VkStructureType									sType;
    481 		DE_NULL,															// const void*										pNext;
    482 		(VkPipelineCreateFlags)0,											// VkPipelineCreateFlags							flags;
    483 		useTessellationShaders ? deUint32(4) : deUint32(2),					// deUint32											stageCount;
    484 		pShaderStages,														// const VkPipelineShaderStageCreateInfo*			pStages;
    485 		&vertexInputStateInfo,												// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
    486 		&pipelineInputAssemblyStateInfo,									// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
    487 		useTessellationShaders ? &pipelineTessellationStateInfo : DE_NULL,	// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
    488 		&pipelineViewportStateInfo,											// const VkPipelineViewportStateCreateInfo*			pViewportState;
    489 		&pipelineRasterizationStateInfo,									// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
    490 		&pipelineMultisampleStateInfo,										// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
    491 		&pipelineDepthStencilStateInfo,										// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
    492 		&pipelineColorBlendStateInfo,										// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
    493 		DE_NULL,															// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
    494 		pipelineLayout,														// VkPipelineLayout									layout;
    495 		renderPass,															// VkRenderPass										renderPass;
    496 		0u,																	// deUint32											subpass;
    497 		DE_NULL,															// VkPipeline										basePipelineHandle;
    498 		0,																	// deInt32											basePipelineIndex;
    499 	};
    500 
    501 	return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
    502 }
    503 
    504 //! Renders a colorful grid of rectangles.
    505 tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat	format,
    506 										  const UVec2&				renderSize,
    507 										  const Vec4&				clearColor,
    508 										  const UVec4&				cell,
    509 										  const Vec4&				cellColor)
    510 {
    511 	tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
    512 	tcu::clear(image.getAccess(), clearColor);
    513 
    514 	tcu::clear(tcu::getSubregion(image.getAccess(), cell.x(), cell.y(), cell.z(), cell.w()),
    515 			   cellColor);
    516 
    517 	return image;
    518 }
    519 
    520 void initVertexTestPrograms (SourceCollections& programCollection, const int numViewports)
    521 {
    522 	DE_UNREF(numViewports);
    523 
    524 	// Vertex shader
    525 	{
    526 		std::ostringstream src;
    527 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
    528 			<< "#extension GL_ARB_shader_viewport_layer_array : require\n"
    529 			<< "\n"
    530 			<< "layout(location = 0) in  vec4 in_position;\n"
    531 			<< "layout(location = 1) in  vec4 in_color;\n"
    532 			<< "layout(location = 0) out vec4 out_color;\n"
    533 			<< "\n"
    534 			<< "void main(void)\n"
    535 			<< "{\n"
    536 			<< "    gl_Layer = gl_VertexIndex / 6;\n"
    537 			<< "    gl_Position = in_position;\n"
    538 			<< "    out_color = in_color;\n"
    539 			<< "}\n";
    540 
    541 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
    542 	}
    543 
    544 	// Fragment shader
    545 	{
    546 		std::ostringstream src;
    547 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
    548 			<< "\n"
    549 			<< "layout(location = 0) in  vec4 in_color;\n"
    550 			<< "layout(location = 0) out vec4 out_color;\n"
    551 			<< "\n"
    552 			<< "void main(void)\n"
    553 			<< "{\n"
    554 			<< "    out_color = in_color;\n"
    555 			<< "}\n";
    556 
    557 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
    558 	}
    559 }
    560 
    561 void initTessellationTestPrograms (SourceCollections& programCollection, const int numViewports)
    562 {
    563 	DE_UNREF(numViewports);
    564 
    565 	// Vertex shader
    566 	{
    567 		std::ostringstream src;
    568 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
    569 			<< "\n"
    570 			<< "layout(location = 0) in  vec4 in_position;\n"
    571 			<< "layout(location = 1) in  vec4 in_color;\n"
    572 			<< "layout(location = 0) out vec4 out_color;\n"
    573 			<< "\n"
    574 			<< "void main(void)\n"
    575 			<< "{\n"
    576 			<< "    gl_Position = in_position;\n"
    577 			<< "    out_color = in_color;\n"
    578 			<< "}\n";
    579 
    580 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
    581 	}
    582 
    583 	// Tessellation control shader
    584 	{
    585 		std::ostringstream src;
    586 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
    587 			<< "\n"
    588 			<< "layout(vertices = 3) out;\n"
    589 			<< "\n"
    590 			<< "layout(location = 0) in  vec4 in_color[];\n"
    591 			<< "layout(location = 0) out vec4 out_color[];\n"
    592 			<< "\n"
    593 			<< "void main(void)\n"
    594 			<< "{\n"
    595 			<< "    if (gl_InvocationID == 0) {\n"
    596 			<< "        gl_TessLevelInner[0] = 1.0;\n"
    597 			<< "        gl_TessLevelInner[1] = 1.0;\n"
    598 			<< "        gl_TessLevelOuter[0] = 1.0;\n"
    599 			<< "        gl_TessLevelOuter[1] = 1.0;\n"
    600 			<< "        gl_TessLevelOuter[2] = 1.0;\n"
    601 			<< "        gl_TessLevelOuter[3] = 1.0;\n"
    602 			<< "    }\n"
    603 			<< "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
    604 			<< "    out_color[gl_InvocationID] = in_color[gl_InvocationID];\n"
    605 			<< "}\n";
    606 
    607 		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
    608 	}
    609 
    610 	// Tessellation evaluation shader
    611 	{
    612 		std::ostringstream src;
    613 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
    614 			<< "#extension GL_ARB_shader_viewport_layer_array : require\n"
    615 			<< "\n"
    616 			<< "layout(triangles, equal_spacing, cw) in;\n"
    617 			<< "\n"
    618 			<< "layout(location = 0) in  vec4 in_color[];\n"
    619 			<< "layout(location = 0) out vec4 out_color;\n"
    620 			<< "\n"
    621 			<< "void main(void)\n"
    622 			<< "{\n"
    623 			<< "    gl_Layer = gl_PrimitiveID / 2;\n"
    624 			<< "    gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n"
    625 			<< "                  gl_in[1].gl_Position * gl_TessCoord.y +\n"
    626 			<< "                  gl_in[2].gl_Position * gl_TessCoord.z;\n"
    627 			<< "\n"
    628 			<< "    out_color = in_color[0] * gl_TessCoord.x +\n"
    629 			<< "                in_color[1] * gl_TessCoord.y +\n"
    630 			<< "                in_color[2] * gl_TessCoord.z;\n"
    631 			<< "}\n";
    632 
    633 		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
    634 	}
    635 
    636 	// Fragment shader
    637 	{
    638 		std::ostringstream src;
    639 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
    640 			<< "\n"
    641 			<< "layout(location = 0) in  vec4 in_color;\n"
    642 			<< "layout(location = 0) out vec4 out_color;\n"
    643 			<< "\n"
    644 			<< "void main(void)\n"
    645 			<< "{\n"
    646 			<< "    out_color = in_color;\n"
    647 			<< "}\n";
    648 
    649 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
    650 	}
    651 }
    652 
    653 std::vector<UVec4> generateGrid (const int numCells, const UVec2& renderSize)
    654 {
    655 	const int numCols		= deCeilFloatToInt32(deFloatSqrt(static_cast<float>(numCells)));
    656 	const int numRows		= deCeilFloatToInt32(static_cast<float>(numCells) / static_cast<float>(numCols));
    657 	const int rectWidth		= renderSize.x() / numCols;
    658 	const int rectHeight	= renderSize.y() / numRows;
    659 
    660 	std::vector<UVec4> cells;
    661 	cells.reserve(numCells);
    662 
    663 	int x = 0;
    664 	int y = 0;
    665 
    666 	for (int cellNdx = 0; cellNdx < numCells; ++cellNdx)
    667 	{
    668 		const bool nextRow = (cellNdx != 0) && (cellNdx % numCols == 0);
    669 		if (nextRow)
    670 		{
    671 			x  = 0;
    672 			y += rectHeight;
    673 		}
    674 
    675 		cells.push_back(UVec4(x, y, rectWidth, rectHeight));
    676 
    677 		x += rectWidth;
    678 	}
    679 
    680 	return cells;
    681 }
    682 
    683 std::vector<Vec4> generateColors (int numColors)
    684 {
    685 	const Vec4 colors[] =
    686 	{
    687 		Vec4(0.18f, 0.42f, 0.17f, 1.0f),
    688 		Vec4(0.29f, 0.62f, 0.28f, 1.0f),
    689 		Vec4(0.59f, 0.84f, 0.44f, 1.0f),
    690 		Vec4(0.96f, 0.95f, 0.72f, 1.0f),
    691 		Vec4(0.94f, 0.55f, 0.39f, 1.0f),
    692 		Vec4(0.82f, 0.19f, 0.12f, 1.0f),
    693 		Vec4(0.46f, 0.15f, 0.26f, 1.0f),
    694 		Vec4(0.24f, 0.14f, 0.24f, 1.0f),
    695 		Vec4(0.49f, 0.31f, 0.26f, 1.0f),
    696 		Vec4(0.78f, 0.52f, 0.33f, 1.0f),
    697 		Vec4(0.94f, 0.82f, 0.31f, 1.0f),
    698 		Vec4(0.98f, 0.65f, 0.30f, 1.0f),
    699 		Vec4(0.22f, 0.65f, 0.53f, 1.0f),
    700 		Vec4(0.67f, 0.81f, 0.91f, 1.0f),
    701 		Vec4(0.43f, 0.44f, 0.75f, 1.0f),
    702 		Vec4(0.26f, 0.24f, 0.48f, 1.0f),
    703 	};
    704 
    705 	std::vector<Vec4> result;
    706 	result.reserve(numColors);
    707 
    708 	for (int i = 0; i < numColors; ++i)
    709 	{
    710 		result.push_back(colors[i % DE_LENGTH_OF_ARRAY(colors)]);
    711 	}
    712 
    713 	return result;
    714 }
    715 
    716 std::vector<PositionColorVertex> generateVertices (const std::vector<UVec4>& grid, const std::vector<Vec4>& colors, const UVec2& renderSize)
    717 {
    718 	DE_ASSERT(colors.size() == grid.size());
    719 
    720 	// Two triangles for each cell. Each cell correspond to a layer.
    721 	std::size_t total = grid.size() * 6;
    722 
    723 	std::vector<PositionColorVertex> result;
    724 	result.reserve(total);
    725 
    726 	for (std::size_t i = 0; i < total; ++i)
    727 	{
    728 		Vec4 pos;
    729 		pos.z() = 0.0;
    730 		pos.w() = 1.0;
    731 
    732 		Vec4 cell = grid[i/6].asFloat() * 2.0f;
    733 		float x			= cell.x() / float(renderSize.x()) - 1.0f;
    734 		float y			= cell.y() / float(renderSize.y()) - 1.0f;
    735 		float width		= cell.z() / float(renderSize.x());
    736 		float height	= cell.w() / float(renderSize.y());
    737 
    738 		switch (i % 6)
    739 		{
    740 		case 0: pos.xy() = Vec2(x,			y + height);	break;
    741 		case 1: pos.xy() = Vec2(x + width,	y + height);	break;
    742 		case 2: pos.xy() = Vec2(x,			y);				break;
    743 		case 3: pos.xy() = Vec2(x + width,	y);				break;
    744 		case 4: pos.xy() = Vec2(x + width,	y + height);	break;
    745 		case 5: pos.xy() = Vec2(x,			y);				break;
    746 		}
    747 
    748 		result.push_back(PositionColorVertex(pos, colors[i/6]));
    749 	}
    750 
    751 	return result;
    752 }
    753 
    754 // Renderer generates two triangles per layer, each pair using a different
    755 // color and a different position.
    756 class Renderer
    757 {
    758 public:
    759 	enum Shader
    760 	{
    761 		VERTEX,
    762 		TESSELLATION,
    763 	};
    764 
    765 	Renderer (Context&									context,
    766 			  const UVec2&								renderSize,
    767 			  const int									numLayers,
    768 			  const VkFormat							colorFormat,
    769 			  const Vec4&								clearColor,
    770 			  const std::vector<PositionColorVertex>&	vertices,
    771 			  const Shader								shader)
    772 		: m_renderSize				(renderSize)
    773 		, m_colorFormat				(colorFormat)
    774 		, m_colorSubresourceRange	(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers))
    775 		, m_clearColor				(clearColor)
    776 		, m_numLayers				(numLayers)
    777 		, m_vertices				(vertices)
    778 	{
    779 		const DeviceInterface&		vk					= context.getDeviceInterface();
    780 		const VkDevice				device				= context.getDevice();
    781 		const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
    782 		Allocator&					allocator			= context.getDefaultAllocator();
    783 		const VkDeviceSize			vertexBufferSize    = sizeInBytes(m_vertices);
    784 
    785 		m_colorImage		= makeImage					(vk, device, makeImageCreateInfo(m_colorFormat, m_renderSize, m_numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
    786 		m_colorImageAlloc	= bindImage					(vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
    787 		m_colorAttachment	= makeImageView				(vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D_ARRAY, m_colorFormat, m_colorSubresourceRange);
    788 
    789 		m_vertexBuffer		= Buffer::createAndAlloc	(vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), allocator, MemoryRequirement::HostVisible);
    790 
    791 		deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &m_vertices[0], static_cast<std::size_t>(vertexBufferSize));
    792 		flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
    793 
    794 		if (shader == TESSELLATION)
    795 		{
    796 			m_tessellationControlModule		= createShaderModule	(vk, device, context.getBinaryCollection().get("tesc"), 0u);
    797 			m_tessellationEvaluationModule	= createShaderModule	(vk, device, context.getBinaryCollection().get("tese"), 0u);
    798 		}
    799 
    800 		m_vertexModule		= createShaderModule	(vk, device, context.getBinaryCollection().get("vert"), 0u);
    801 		m_fragmentModule	= createShaderModule	(vk, device, context.getBinaryCollection().get("frag"), 0u);
    802 		m_renderPass		= makeRenderPass		(vk, device, m_colorFormat);
    803 		m_framebuffer		= makeFramebuffer		(vk, device, *m_renderPass, 1u, &m_colorAttachment.get(),
    804 													 static_cast<deUint32>(m_renderSize.x()),
    805 													 static_cast<deUint32>(m_renderSize.y()),
    806 													 numLayers);
    807 		m_pipelineLayout	= makePipelineLayout	(vk, device);
    808 		m_pipeline			= makeGraphicsPipeline	(vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_tessellationControlModule,
    809 													 *m_tessellationEvaluationModule, *m_fragmentModule, m_renderSize);
    810 		m_cmdPool			= createCommandPool		(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
    811 		m_cmdBuffer			= allocateCommandBuffer	(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
    812 	}
    813 
    814 	void draw (Context& context, const VkBuffer colorBuffer) const
    815 	{
    816 		const DeviceInterface&		vk			= context.getDeviceInterface();
    817 		const VkDevice				device		= context.getDevice();
    818 		const VkQueue				queue		= context.getUniversalQueue();
    819 
    820 		beginCommandBuffer(vk, *m_cmdBuffer);
    821 
    822 		const VkClearValue			clearValue	= makeClearValueColor(m_clearColor);
    823 		const VkRect2D				renderArea	=
    824 		{
    825 			makeOffset2D(0, 0),
    826 			makeExtent2D(m_renderSize.x(), m_renderSize.y()),
    827 		};
    828 		const VkRenderPassBeginInfo renderPassBeginInfo =
    829 		{
    830 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,		// VkStructureType         sType;
    831 			DE_NULL,										// const void*             pNext;
    832 			*m_renderPass,									// VkRenderPass            renderPass;
    833 			*m_framebuffer,									// VkFramebuffer           framebuffer;
    834 			renderArea,										// VkRect2D                renderArea;
    835 			1u,												// uint32_t                clearValueCount;
    836 			&clearValue,									// const VkClearValue*     pClearValues;
    837 		};
    838 		vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
    839 
    840 		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
    841 		{
    842 			const VkBuffer vertexBuffer = m_vertexBuffer->object();
    843 			const VkDeviceSize vertexBufferOffset = 0ull;
    844 			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
    845 		}
    846 		vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_numLayers * 6), 1u, 0u, 0u);	// two triangles per layer
    847 		vk.cmdEndRenderPass(*m_cmdBuffer);
    848 
    849 		copyImageToBuffer(vk, *m_cmdBuffer, *m_colorImage, colorBuffer, tcu::IVec2(m_renderSize.x(), m_renderSize.y()), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, m_colorSubresourceRange.layerCount);
    850 
    851 		VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
    852 		submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
    853 	}
    854 
    855 private:
    856 	const UVec2								m_renderSize;
    857 	const VkFormat							m_colorFormat;
    858 	const VkImageSubresourceRange			m_colorSubresourceRange;
    859 	const Vec4								m_clearColor;
    860 	const int								m_numLayers;
    861 	const std::vector<PositionColorVertex>	m_vertices;
    862 
    863 	Move<VkImage>							m_colorImage;
    864 	MovePtr<Allocation>						m_colorImageAlloc;
    865 	Move<VkImageView>						m_colorAttachment;
    866 	SharedPtr<Buffer>						m_vertexBuffer;
    867 	Move<VkShaderModule>					m_vertexModule;
    868 	Move<VkShaderModule>					m_tessellationControlModule;
    869 	Move<VkShaderModule>					m_tessellationEvaluationModule;
    870 	Move<VkShaderModule>					m_fragmentModule;
    871 	Move<VkRenderPass>						m_renderPass;
    872 	Move<VkFramebuffer>						m_framebuffer;
    873 	Move<VkPipelineLayout>					m_pipelineLayout;
    874 	Move<VkPipeline>						m_pipeline;
    875 	Move<VkCommandPool>						m_cmdPool;
    876 	Move<VkCommandBuffer>					m_cmdBuffer;
    877 
    878 	// "deleted"
    879 				Renderer	(const Renderer&);
    880 	Renderer&	operator=	(const Renderer&);
    881 };
    882 
    883 void checkRequirements (const Context& context)
    884 {
    885 	const VkPhysicalDeviceFeatures	features		= getPhysicalDeviceFeatures(context.getInstanceInterface(), context.getPhysicalDevice());
    886 	const VkPhysicalDeviceLimits	limits			= getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice()).limits;
    887 
    888 	if (!features.multiViewport)
    889 		TCU_THROW(NotSupportedError, "Required feature is not supported: multiViewport");
    890 
    891 	if (limits.maxFramebufferLayers < MIN_MAX_FRAMEBUFFER_LAYERS)
    892 		TCU_FAIL("maxFramebuffersLayers is less than the minimum required");
    893 
    894 	if (limits.maxViewports < MIN_MAX_VIEWPORTS)
    895 		TCU_FAIL("multiViewport supported but maxViewports is less than the minimum required");
    896 
    897 	const std::vector<std::string>&	extensions		= context.getDeviceExtensions();
    898 	if (!isDeviceExtensionSupported(context.getUsedApiVersion(), extensions, "VK_EXT_shader_viewport_index_layer"))
    899 		TCU_THROW(NotSupportedError, "Extension VK_EXT_shader_viewport_index_layer not supported");
    900 }
    901 
    902 tcu::TestStatus testVertexShader (Context& context, const int numLayers)
    903 {
    904 	checkRequirements(context);
    905 
    906 	const DeviceInterface&					vk					= context.getDeviceInterface();
    907 	const VkDevice							device				= context.getDevice();
    908 	Allocator&								allocator			= context.getDefaultAllocator();
    909 
    910 	const UVec2								renderSize			(256, 256);
    911 	const VkFormat							colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
    912 	const Vec4								clearColor			(0.5f, 0.5f, 0.5f, 1.0f);
    913 	const std::vector<UVec4>				grid				= generateGrid(numLayers, renderSize);
    914 	const std::vector<Vec4>					colors				= generateColors(numLayers);
    915 	const std::vector<PositionColorVertex>	vertices			= generateVertices(grid, colors, renderSize);
    916 
    917 	const VkDeviceSize						colorBufferSize		= renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)) * numLayers;
    918 
    919 	const SharedPtr<Buffer>					colorBuffer			= Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
    920 
    921 	// Zero buffer.
    922 	{
    923 		const Allocation alloc = colorBuffer->getBoundMemory();
    924 		deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
    925 		flushAlloc(vk, device, alloc);
    926 	}
    927 
    928 	{
    929 		context.getTestContext().getLog()
    930 			<< tcu::TestLog::Message << "Rendering a rectangle in each of the " << numLayers << " layer(s)." << tcu::TestLog::EndMessage
    931 			<< tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
    932 	}
    933 
    934 	// Draw.
    935 	{
    936 		const Renderer renderer (context, renderSize, numLayers, colorFormat, clearColor, vertices, Renderer::VERTEX);
    937 		renderer.draw(context, colorBuffer->object());
    938 	}
    939 
    940 	// Verify layers.
    941 	{
    942 		const Allocation alloc = colorBuffer->getBoundMemory();
    943 		invalidateMappedMemoryRange(vk, device, alloc.getMemory(), 0ull, colorBufferSize);
    944 
    945 		deUint8* resultMem = reinterpret_cast<deUint8*>(alloc.getHostPtr());
    946 		for (int i = 0; i < numLayers; i++)
    947 		{
    948 			const tcu::ConstPixelBufferAccess	resultImage		(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, resultMem + ((colorBufferSize / numLayers) * i));
    949 			const tcu::TextureLevel				referenceImage	= generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, grid[i], colors[i]);
    950 			std::string imageSetName = "layer_" + de::toString(i);
    951 			std::string imageSetDesc = "Image compare for layer " + de::toString(i);
    952 			if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), imageSetName.c_str(), imageSetDesc.c_str(), referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
    953 				TCU_FAIL("Rendered image is not correct");
    954 		}
    955 	}
    956 
    957 	return tcu::TestStatus::pass("OK");
    958 }
    959 
    960 tcu::TestStatus testTessellationShader (Context& context, const int numLayers)
    961 {
    962 	checkRequirements(context);
    963 
    964 	const VkPhysicalDeviceFeatures&			features			= context.getDeviceFeatures();
    965 	if (!features.tessellationShader)
    966 		TCU_THROW(NotSupportedError, "Required feature is not supported: tessellationShader");
    967 
    968 	const DeviceInterface&					vk					= context.getDeviceInterface();
    969 	const VkDevice							device				= context.getDevice();
    970 	Allocator&								allocator			= context.getDefaultAllocator();
    971 
    972 	const UVec2								renderSize			(256, 256);
    973 	const VkFormat							colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
    974 	const Vec4								clearColor			(0.5f, 0.5f, 0.5f, 1.0f);
    975 	const std::vector<UVec4>				grid				= generateGrid(numLayers, renderSize);
    976 	const std::vector<Vec4>					colors				= generateColors(numLayers);
    977 	const std::vector<PositionColorVertex>	vertices			= generateVertices(grid, colors, renderSize);
    978 
    979 	const VkDeviceSize						colorBufferSize		= renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)) * numLayers;
    980 
    981 	const SharedPtr<Buffer>					colorBuffer			= Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
    982 
    983 	// Zero buffer.
    984 	{
    985 		const Allocation alloc = colorBuffer->getBoundMemory();
    986 		deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
    987 		flushAlloc(vk, device, alloc);
    988 	}
    989 
    990 	{
    991 		context.getTestContext().getLog()
    992 			<< tcu::TestLog::Message << "Rendering a rectangle in each of the " << numLayers << " layer(s)." << tcu::TestLog::EndMessage
    993 			<< tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
    994 	}
    995 
    996 	// Draw.
    997 	{
    998 		const Renderer renderer (context, renderSize, numLayers, colorFormat, clearColor, vertices, Renderer::TESSELLATION);
    999 		renderer.draw(context, colorBuffer->object());
   1000 	}
   1001 
   1002 	// Verify layers.
   1003 	{
   1004 		const Allocation alloc = colorBuffer->getBoundMemory();
   1005 		invalidateMappedMemoryRange(vk, device, alloc.getMemory(), 0ull, colorBufferSize);
   1006 
   1007 		deUint8* resultMem = reinterpret_cast<deUint8*>(alloc.getHostPtr());
   1008 		for (int i = 0; i < numLayers; i++) {
   1009 			const tcu::ConstPixelBufferAccess	resultImage		(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, resultMem + ((colorBufferSize / numLayers) * i));
   1010 			const tcu::TextureLevel				referenceImage	= generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, grid[i], colors[i]);
   1011 			std::string imageSetName = "layer_" + de::toString(i);
   1012 			std::string imageSetDesc = "Image compare for layer " + de::toString(i);
   1013 			if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), imageSetName.c_str(), imageSetDesc.c_str(), referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
   1014 				TCU_FAIL("Rendered image is not correct");
   1015 		}
   1016 	}
   1017 
   1018 	return tcu::TestStatus::pass("OK");
   1019 }
   1020 
   1021 } // anonymous
   1022 
   1023 tcu::TestCaseGroup* createShaderLayerTests	(tcu::TestContext& testCtx)
   1024 {
   1025 	MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_layer", ""));
   1026 
   1027 	int numLayersToTest[] =
   1028 	{
   1029 		1,
   1030 		2,
   1031 		3,
   1032 		4,
   1033 		5,
   1034 		6,
   1035 		7,
   1036 		8,
   1037 		MIN_MAX_FRAMEBUFFER_LAYERS,
   1038 	};
   1039 
   1040 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(numLayersToTest); ++i)
   1041 	{
   1042 		int numLayers = numLayersToTest[i];
   1043 		addFunctionCaseWithPrograms(group.get(), "vertex_shader_" + de::toString(numLayers), "", initVertexTestPrograms, testVertexShader, numLayers);
   1044 	}
   1045 
   1046 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(numLayersToTest); ++i)
   1047 	{
   1048 		int numLayers = numLayersToTest[i];
   1049 		addFunctionCaseWithPrograms(group.get(), "tessellation_shader_" + de::toString(numLayers), "", initTessellationTestPrograms, testTessellationShader, numLayers);
   1050 	}
   1051 
   1052 	return group.release();
   1053 }
   1054 
   1055 } // Draw
   1056 } // vkt
   1057