Home | History | Annotate | Download | only in tessellation
      1 /*------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2014 The Android Open Source Project
      6  * Copyright (c) 2016 The Khronos Group Inc.
      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 Tessellation Utilities
     23  *//*--------------------------------------------------------------------*/
     24 
     25 #include "vktTessellationUtil.hpp"
     26 #include "vkTypeUtil.hpp"
     27 #include "deMath.h"
     28 
     29 namespace vkt
     30 {
     31 namespace tessellation
     32 {
     33 
     34 using namespace vk;
     35 
     36 VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize			bufferSize,
     37 										 const VkBufferUsageFlags	usage)
     38 {
     39 	const VkBufferCreateInfo bufferCreateInfo =
     40 	{
     41 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
     42 		DE_NULL,								// const void*			pNext;
     43 		(VkBufferCreateFlags)0,					// VkBufferCreateFlags	flags;
     44 		bufferSize,								// VkDeviceSize			size;
     45 		usage,									// VkBufferUsageFlags	usage;
     46 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
     47 		0u,										// deUint32				queueFamilyIndexCount;
     48 		DE_NULL,								// const deUint32*		pQueueFamilyIndices;
     49 	};
     50 	return bufferCreateInfo;
     51 }
     52 
     53 VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags	srcAccessMask,
     54 											   const VkAccessFlags	dstAccessMask,
     55 											   const VkBuffer		buffer,
     56 											   const VkDeviceSize	offset,
     57 											   const VkDeviceSize	bufferSizeBytes)
     58 {
     59 	const VkBufferMemoryBarrier barrier =
     60 	{
     61 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
     62 		DE_NULL,									// const void*		pNext;
     63 		srcAccessMask,								// VkAccessFlags	srcAccessMask;
     64 		dstAccessMask,								// VkAccessFlags	dstAccessMask;
     65 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
     66 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			destQueueFamilyIndex;
     67 		buffer,										// VkBuffer			buffer;
     68 		offset,										// VkDeviceSize		offset;
     69 		bufferSizeBytes,							// VkDeviceSize		size;
     70 	};
     71 	return barrier;
     72 }
     73 
     74 VkImageMemoryBarrier makeImageMemoryBarrier	(const VkAccessFlags			srcAccessMask,
     75 											 const VkAccessFlags			dstAccessMask,
     76 											 const VkImageLayout			oldLayout,
     77 											 const VkImageLayout			newLayout,
     78 											 const VkImage					image,
     79 											 const VkImageSubresourceRange	subresourceRange)
     80 {
     81 	const VkImageMemoryBarrier barrier =
     82 	{
     83 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
     84 		DE_NULL,										// const void*				pNext;
     85 		srcAccessMask,									// VkAccessFlags			outputMask;
     86 		dstAccessMask,									// VkAccessFlags			inputMask;
     87 		oldLayout,										// VkImageLayout			oldLayout;
     88 		newLayout,										// VkImageLayout			newLayout;
     89 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
     90 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					destQueueFamilyIndex;
     91 		image,											// VkImage					image;
     92 		subresourceRange,								// VkImageSubresourceRange	subresourceRange;
     93 	};
     94 	return barrier;
     95 }
     96 
     97 Move<VkCommandPool> makeCommandPool (const DeviceInterface& vk, const VkDevice device, const deUint32 queueFamilyIndex)
     98 {
     99 	const VkCommandPoolCreateInfo info =
    100 	{
    101 		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,			// VkStructureType			sType;
    102 		DE_NULL,											// const void*				pNext;
    103 		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,	// VkCommandPoolCreateFlags	flags;
    104 		queueFamilyIndex,									// deUint32					queueFamilyIndex;
    105 	};
    106 	return createCommandPool(vk, device, &info);
    107 }
    108 
    109 Move<VkCommandBuffer> makeCommandBuffer (const DeviceInterface& vk, const VkDevice device, const VkCommandPool commandPool)
    110 {
    111 	const VkCommandBufferAllocateInfo info =
    112 	{
    113 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,		// VkStructureType		sType;
    114 		DE_NULL,											// const void*			pNext;
    115 		commandPool,										// VkCommandPool		commandPool;
    116 		VK_COMMAND_BUFFER_LEVEL_PRIMARY,					// VkCommandBufferLevel	level;
    117 		1u,													// deUint32				commandBufferCount;
    118 	};
    119 	return allocateCommandBuffer(vk, device, &info);
    120 }
    121 
    122 Move<VkDescriptorSet> makeDescriptorSet (const DeviceInterface&			vk,
    123 										 const VkDevice					device,
    124 										 const VkDescriptorPool			descriptorPool,
    125 										 const VkDescriptorSetLayout	setLayout)
    126 {
    127 	const VkDescriptorSetAllocateInfo info =
    128 	{
    129 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType				sType;
    130 		DE_NULL,											// const void*					pNext;
    131 		descriptorPool,										// VkDescriptorPool				descriptorPool;
    132 		1u,													// deUint32						descriptorSetCount;
    133 		&setLayout,											// const VkDescriptorSetLayout*	pSetLayouts;
    134 	};
    135 	return allocateDescriptorSet(vk, device, &info);
    136 }
    137 
    138 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface&		vk,
    139 										   const VkDevice				device,
    140 										   const VkDescriptorSetLayout	descriptorSetLayout)
    141 {
    142 	const VkPipelineLayoutCreateInfo info =
    143 	{
    144 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
    145 		DE_NULL,											// const void*					pNext;
    146 		(VkPipelineLayoutCreateFlags)0,						// VkPipelineLayoutCreateFlags	flags;
    147 		1u,													// deUint32						setLayoutCount;
    148 		&descriptorSetLayout,								// const VkDescriptorSetLayout*	pSetLayouts;
    149 		0u,													// deUint32						pushConstantRangeCount;
    150 		DE_NULL,											// const VkPushConstantRange*	pPushConstantRanges;
    151 	};
    152 	return createPipelineLayout(vk, device, &info);
    153 }
    154 
    155 Move<VkPipelineLayout> makePipelineLayoutWithoutDescriptors (const DeviceInterface&		vk,
    156 															 const VkDevice				device)
    157 {
    158 	const VkPipelineLayoutCreateInfo info =
    159 	{
    160 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
    161 		DE_NULL,											// const void*					pNext;
    162 		(VkPipelineLayoutCreateFlags)0,						// VkPipelineLayoutCreateFlags	flags;
    163 		0u,													// deUint32						setLayoutCount;
    164 		DE_NULL,											// const VkDescriptorSetLayout*	pSetLayouts;
    165 		0u,													// deUint32						pushConstantRangeCount;
    166 		DE_NULL,											// const VkPushConstantRange*	pPushConstantRanges;
    167 	};
    168 	return createPipelineLayout(vk, device, &info);
    169 }
    170 
    171 Move<VkPipeline> makeComputePipeline (const DeviceInterface&		vk,
    172 									  const VkDevice				device,
    173 									  const VkPipelineLayout		pipelineLayout,
    174 									  const VkShaderModule			shaderModule,
    175 									  const VkSpecializationInfo*	specInfo)
    176 {
    177 	const VkPipelineShaderStageCreateInfo shaderStageInfo =
    178 	{
    179 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType					sType;
    180 		DE_NULL,												// const void*						pNext;
    181 		(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags	flags;
    182 		VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits			stage;
    183 		shaderModule,											// VkShaderModule					module;
    184 		"main",													// const char*						pName;
    185 		specInfo,												// const VkSpecializationInfo*		pSpecializationInfo;
    186 	};
    187 	const VkComputePipelineCreateInfo pipelineInfo =
    188 	{
    189 		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,		// VkStructureType					sType;
    190 		DE_NULL,											// const void*						pNext;
    191 		(VkPipelineCreateFlags)0,							// VkPipelineCreateFlags			flags;
    192 		shaderStageInfo,									// VkPipelineShaderStageCreateInfo	stage;
    193 		pipelineLayout,										// VkPipelineLayout					layout;
    194 		DE_NULL,											// VkPipeline						basePipelineHandle;
    195 		0,													// deInt32							basePipelineIndex;
    196 	};
    197 	return createComputePipeline(vk, device, DE_NULL , &pipelineInfo);
    198 }
    199 
    200 VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage, const deUint32 numArrayLayers)
    201 {
    202 	const VkImageCreateInfo imageInfo =
    203 	{
    204 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType          sType;
    205 		DE_NULL,									// const void*              pNext;
    206 		(VkImageCreateFlags)0,						// VkImageCreateFlags       flags;
    207 		VK_IMAGE_TYPE_2D,							// VkImageType              imageType;
    208 		format,										// VkFormat                 format;
    209 		makeExtent3D(size.x(), size.y(), 1),		// VkExtent3D               extent;
    210 		1u,											// uint32_t                 mipLevels;
    211 		numArrayLayers,								// uint32_t                 arrayLayers;
    212 		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits    samples;
    213 		VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling            tiling;
    214 		usage,										// VkImageUsageFlags        usage;
    215 		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode            sharingMode;
    216 		0u,											// uint32_t                 queueFamilyIndexCount;
    217 		DE_NULL,									// const uint32_t*          pQueueFamilyIndices;
    218 		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout            initialLayout;
    219 	};
    220 	return imageInfo;
    221 }
    222 
    223 Move<VkImageView> makeImageView (const DeviceInterface&			vk,
    224 								 const VkDevice					vkDevice,
    225 								 const VkImage					image,
    226 								 const VkImageViewType			viewType,
    227 								 const VkFormat					format,
    228 								 const VkImageSubresourceRange	subresourceRange)
    229 {
    230 	const VkImageViewCreateInfo imageViewParams =
    231 	{
    232 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
    233 		DE_NULL,										// const void*				pNext;
    234 		(VkImageViewCreateFlags)0,						// VkImageViewCreateFlags	flags;
    235 		image,											// VkImage					image;
    236 		viewType,										// VkImageViewType			viewType;
    237 		format,											// VkFormat					format;
    238 		makeComponentMappingRGBA(),						// VkComponentMapping		components;
    239 		subresourceRange,								// VkImageSubresourceRange	subresourceRange;
    240 	};
    241 	return createImageView(vk, vkDevice, &imageViewParams);
    242 }
    243 
    244 VkBufferImageCopy makeBufferImageCopy (const VkExtent3D					extent,
    245 									   const VkImageSubresourceLayers	subresourceLayers)
    246 {
    247 	const VkBufferImageCopy copyParams =
    248 	{
    249 		0ull,										//	VkDeviceSize				bufferOffset;
    250 		0u,											//	deUint32					bufferRowLength;
    251 		0u,											//	deUint32					bufferImageHeight;
    252 		subresourceLayers,							//	VkImageSubresourceLayers	imageSubresource;
    253 		makeOffset3D(0, 0, 0),						//	VkOffset3D					imageOffset;
    254 		extent,										//	VkExtent3D					imageExtent;
    255 	};
    256 	return copyParams;
    257 }
    258 
    259 void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
    260 {
    261 	const VkCommandBufferBeginInfo info =
    262 	{
    263 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType                          sType;
    264 		DE_NULL,										// const void*                              pNext;
    265 		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// VkCommandBufferUsageFlags                flags;
    266 		DE_NULL,										// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
    267 	};
    268 	VK_CHECK(vk.beginCommandBuffer(commandBuffer, &info));
    269 }
    270 
    271 void endCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
    272 {
    273 	VK_CHECK(vk.endCommandBuffer(commandBuffer));
    274 }
    275 
    276 void submitCommandsAndWait (const DeviceInterface&	vk,
    277 							const VkDevice			device,
    278 							const VkQueue			queue,
    279 							const VkCommandBuffer	commandBuffer)
    280 {
    281 	const VkFenceCreateInfo fenceInfo =
    282 	{
    283 		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
    284 		DE_NULL,								// const void*			pNext;
    285 		(VkFenceCreateFlags)0,					// VkFenceCreateFlags	flags;
    286 	};
    287 	const Unique<VkFence> fence(createFence(vk, device, &fenceInfo));
    288 
    289 	const VkSubmitInfo submitInfo =
    290 	{
    291 		VK_STRUCTURE_TYPE_SUBMIT_INFO,		// VkStructureType                sType;
    292 		DE_NULL,							// const void*                    pNext;
    293 		0u,									// uint32_t                       waitSemaphoreCount;
    294 		DE_NULL,							// const VkSemaphore*             pWaitSemaphores;
    295 		DE_NULL,							// const VkPipelineStageFlags*    pWaitDstStageMask;
    296 		1u,									// uint32_t                       commandBufferCount;
    297 		&commandBuffer,						// const VkCommandBuffer*         pCommandBuffers;
    298 		0u,									// uint32_t                       signalSemaphoreCount;
    299 		DE_NULL,							// const VkSemaphore*             pSignalSemaphores;
    300 	};
    301 	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
    302 	VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
    303 }
    304 
    305 void beginRenderPass (const DeviceInterface&	vk,
    306 					  const VkCommandBuffer		commandBuffer,
    307 					  const VkRenderPass		renderPass,
    308 					  const VkFramebuffer		framebuffer,
    309 					  const VkRect2D&			renderArea,
    310 					  const tcu::Vec4&			clearColor)
    311 {
    312 	const VkClearValue clearValue = makeClearValueColor(clearColor);
    313 
    314 	const VkRenderPassBeginInfo renderPassBeginInfo = {
    315 		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,		// VkStructureType         sType;
    316 		DE_NULL,										// const void*             pNext;
    317 		renderPass,										// VkRenderPass            renderPass;
    318 		framebuffer,									// VkFramebuffer           framebuffer;
    319 		renderArea,										// VkRect2D                renderArea;
    320 		1u,												// uint32_t                clearValueCount;
    321 		&clearValue,									// const VkClearValue*     pClearValues;
    322 	};
    323 
    324 	vk.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
    325 }
    326 
    327 void beginRenderPassWithRasterizationDisabled (const DeviceInterface&	vk,
    328 											   const VkCommandBuffer	commandBuffer,
    329 											   const VkRenderPass		renderPass,
    330 											   const VkFramebuffer		framebuffer)
    331 {
    332 	const VkRect2D renderArea = {{ 0, 0 }, { 0, 0 }};
    333 
    334 	const VkRenderPassBeginInfo renderPassBeginInfo = {
    335 		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,		// VkStructureType         sType;
    336 		DE_NULL,										// const void*             pNext;
    337 		renderPass,										// VkRenderPass            renderPass;
    338 		framebuffer,									// VkFramebuffer           framebuffer;
    339 		renderArea,										// VkRect2D                renderArea;
    340 		0u,												// uint32_t                clearValueCount;
    341 		DE_NULL,										// const VkClearValue*     pClearValues;
    342 	};
    343 
    344 	vk.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
    345 }
    346 
    347 void endRenderPass (const DeviceInterface&	vk,
    348 					const VkCommandBuffer	commandBuffer)
    349 {
    350 	vk.cmdEndRenderPass(commandBuffer);
    351 }
    352 
    353 Move<VkRenderPass> makeRenderPass (const DeviceInterface&	vk,
    354 								   const VkDevice			device,
    355 								   const VkFormat			colorFormat)
    356 {
    357 	const VkAttachmentDescription colorAttachmentDescription =
    358 	{
    359 		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
    360 		colorFormat,										// VkFormat							format;
    361 		VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
    362 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
    363 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
    364 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
    365 		VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
    366 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
    367 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout;
    368 	};
    369 
    370 	const VkAttachmentReference colorAttachmentReference =
    371 	{
    372 		0u,													// deUint32			attachment;
    373 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
    374 	};
    375 
    376 	const VkAttachmentReference depthAttachmentReference =
    377 	{
    378 		VK_ATTACHMENT_UNUSED,								// deUint32			attachment;
    379 		VK_IMAGE_LAYOUT_UNDEFINED							// VkImageLayout	layout;
    380 	};
    381 
    382 	const VkSubpassDescription subpassDescription =
    383 	{
    384 		(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags		flags;
    385 		VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
    386 		0u,													// deUint32							inputAttachmentCount;
    387 		DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
    388 		1u,													// deUint32							colorAttachmentCount;
    389 		&colorAttachmentReference,							// const VkAttachmentReference*		pColorAttachments;
    390 		DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
    391 		&depthAttachmentReference,							// const VkAttachmentReference*		pDepthStencilAttachment;
    392 		0u,													// deUint32							preserveAttachmentCount;
    393 		DE_NULL												// const deUint32*					pPreserveAttachments;
    394 	};
    395 
    396 	const VkRenderPassCreateInfo renderPassInfo =
    397 	{
    398 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
    399 		DE_NULL,											// const void*						pNext;
    400 		(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
    401 		1u,													// deUint32							attachmentCount;
    402 		&colorAttachmentDescription,						// const VkAttachmentDescription*	pAttachments;
    403 		1u,													// deUint32							subpassCount;
    404 		&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
    405 		0u,													// deUint32							dependencyCount;
    406 		DE_NULL												// const VkSubpassDependency*		pDependencies;
    407 	};
    408 
    409 	return createRenderPass(vk, device, &renderPassInfo);
    410 }
    411 
    412 Move<VkRenderPass> makeRenderPassWithoutAttachments (const DeviceInterface&	vk,
    413 													 const VkDevice			device)
    414 {
    415 	const VkAttachmentReference unusedAttachment =
    416 	{
    417 		VK_ATTACHMENT_UNUSED,								// deUint32			attachment;
    418 		VK_IMAGE_LAYOUT_UNDEFINED							// VkImageLayout	layout;
    419 	};
    420 
    421 	const VkSubpassDescription subpassDescription =
    422 	{
    423 		(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags		flags;
    424 		VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
    425 		0u,													// deUint32							inputAttachmentCount;
    426 		DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
    427 		0u,													// deUint32							colorAttachmentCount;
    428 		DE_NULL,											// const VkAttachmentReference*		pColorAttachments;
    429 		DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
    430 		&unusedAttachment,									// const VkAttachmentReference*		pDepthStencilAttachment;
    431 		0u,													// deUint32							preserveAttachmentCount;
    432 		DE_NULL												// const deUint32*					pPreserveAttachments;
    433 	};
    434 
    435 	const VkRenderPassCreateInfo renderPassInfo =
    436 	{
    437 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
    438 		DE_NULL,											// const void*						pNext;
    439 		(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
    440 		0u,													// deUint32							attachmentCount;
    441 		DE_NULL,											// const VkAttachmentDescription*	pAttachments;
    442 		1u,													// deUint32							subpassCount;
    443 		&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
    444 		0u,													// deUint32							dependencyCount;
    445 		DE_NULL												// const VkSubpassDependency*		pDependencies;
    446 	};
    447 
    448 	return createRenderPass(vk, device, &renderPassInfo);
    449 }
    450 
    451 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&		vk,
    452 									 const VkDevice				device,
    453 									 const VkRenderPass			renderPass,
    454 									 const VkImageView			colorAttachment,
    455 									 const deUint32				width,
    456 									 const deUint32				height,
    457 									 const deUint32				layers)
    458 {
    459 	const VkFramebufferCreateInfo framebufferInfo = {
    460 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,		// VkStructureType                             sType;
    461 		DE_NULL,										// const void*                                 pNext;
    462 		(VkFramebufferCreateFlags)0,					// VkFramebufferCreateFlags                    flags;
    463 		renderPass,										// VkRenderPass                                renderPass;
    464 		1u,												// uint32_t                                    attachmentCount;
    465 		&colorAttachment,								// const VkImageView*                          pAttachments;
    466 		width,											// uint32_t                                    width;
    467 		height,											// uint32_t                                    height;
    468 		layers,											// uint32_t                                    layers;
    469 	};
    470 
    471 	return createFramebuffer(vk, device, &framebufferInfo);
    472 }
    473 
    474 Move<VkFramebuffer> makeFramebufferWithoutAttachments (const DeviceInterface&		vk,
    475 													   const VkDevice				device,
    476 													   const VkRenderPass			renderPass)
    477 {
    478 	const VkFramebufferCreateInfo framebufferInfo = {
    479 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,		// VkStructureType                             sType;
    480 		DE_NULL,										// const void*                                 pNext;
    481 		(VkFramebufferCreateFlags)0,					// VkFramebufferCreateFlags                    flags;
    482 		renderPass,										// VkRenderPass                                renderPass;
    483 		0u,												// uint32_t                                    attachmentCount;
    484 		DE_NULL,										// const VkImageView*                          pAttachments;
    485 		1u,												// uint32_t                                    width;
    486 		1u,												// uint32_t                                    height;
    487 		1u,												// uint32_t                                    layers;
    488 	};
    489 
    490 	return createFramebuffer(vk, device, &framebufferInfo);
    491 }
    492 
    493 GraphicsPipelineBuilder& GraphicsPipelineBuilder::setShader (const DeviceInterface&			vk,
    494 															 const VkDevice					device,
    495 															 const VkShaderStageFlagBits	stage,
    496 															 const ProgramBinary&			binary,
    497 															 const VkSpecializationInfo*	specInfo)
    498 {
    499 	VkShaderModule module;
    500 	switch (stage)
    501 	{
    502 		case (VK_SHADER_STAGE_VERTEX_BIT):
    503 			DE_ASSERT(m_vertexShaderModule.get() == DE_NULL);
    504 			m_vertexShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
    505 			module = *m_vertexShaderModule;
    506 			break;
    507 
    508 		case (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT):
    509 			DE_ASSERT(m_tessControlShaderModule.get() == DE_NULL);
    510 			m_tessControlShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
    511 			module = *m_tessControlShaderModule;
    512 			break;
    513 
    514 		case (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT):
    515 			DE_ASSERT(m_tessEvaluationShaderModule.get() == DE_NULL);
    516 			m_tessEvaluationShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
    517 			module = *m_tessEvaluationShaderModule;
    518 			break;
    519 
    520 		case (VK_SHADER_STAGE_GEOMETRY_BIT):
    521 			DE_ASSERT(m_geometryShaderModule.get() == DE_NULL);
    522 			m_geometryShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
    523 			module = *m_geometryShaderModule;
    524 			break;
    525 
    526 		case (VK_SHADER_STAGE_FRAGMENT_BIT):
    527 			DE_ASSERT(m_fragmentShaderModule.get() == DE_NULL);
    528 			m_fragmentShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
    529 			module = *m_fragmentShaderModule;
    530 			break;
    531 
    532 		default:
    533 			DE_FATAL("Invalid shader stage");
    534 			return *this;
    535 	}
    536 
    537 	const VkPipelineShaderStageCreateInfo pipelineShaderStageInfo =
    538 	{
    539 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
    540 		DE_NULL,												// const void*							pNext;
    541 		(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
    542 		stage,													// VkShaderStageFlagBits				stage;
    543 		module,													// VkShaderModule						module;
    544 		"main",													// const char*							pName;
    545 		specInfo,												// const VkSpecializationInfo*			pSpecializationInfo;
    546 	};
    547 
    548 	m_shaderStageFlags |= stage;
    549 	m_shaderStages.push_back(pipelineShaderStageInfo);
    550 
    551 	return *this;
    552 }
    553 
    554 GraphicsPipelineBuilder& GraphicsPipelineBuilder::setVertexInputSingleAttribute (const VkFormat vertexFormat, const deUint32 stride)
    555 {
    556 	const VkVertexInputBindingDescription bindingDesc =
    557 	{
    558 		0u,									// uint32_t				binding;
    559 		stride,								// uint32_t				stride;
    560 		VK_VERTEX_INPUT_RATE_VERTEX,		// VkVertexInputRate	inputRate;
    561 	};
    562 	const VkVertexInputAttributeDescription attributeDesc =
    563 	{
    564 		0u,									// uint32_t			location;
    565 		0u,									// uint32_t			binding;
    566 		vertexFormat,						// VkFormat			format;
    567 		0u,									// uint32_t			offset;
    568 	};
    569 
    570 	m_vertexInputBindings.clear();
    571 	m_vertexInputBindings.push_back(bindingDesc);
    572 
    573 	m_vertexInputAttributes.clear();
    574 	m_vertexInputAttributes.push_back(attributeDesc);
    575 
    576 	return *this;
    577 }
    578 
    579 template<typename T>
    580 inline const T* dataPointer (const std::vector<T>& vec)
    581 {
    582 	return (vec.size() != 0 ? &vec[0] : DE_NULL);
    583 }
    584 
    585 Move<VkPipeline> GraphicsPipelineBuilder::build (const DeviceInterface&	vk,
    586 												 const VkDevice			device,
    587 												 const VkPipelineLayout	pipelineLayout,
    588 												 const VkRenderPass		renderPass)
    589 {
    590 	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
    591 	{
    592 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType                             sType;
    593 		DE_NULL,														// const void*                                 pNext;
    594 		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags       flags;
    595 		static_cast<deUint32>(m_vertexInputBindings.size()),			// uint32_t                                    vertexBindingDescriptionCount;
    596 		dataPointer(m_vertexInputBindings),								// const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
    597 		static_cast<deUint32>(m_vertexInputAttributes.size()),			// uint32_t                                    vertexAttributeDescriptionCount;
    598 		dataPointer(m_vertexInputAttributes),							// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
    599 	};
    600 
    601 	const VkPrimitiveTopology topology = (m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
    602 																										 : m_primitiveTopology;
    603 	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
    604 	{
    605 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType                             sType;
    606 		DE_NULL,														// const void*                                 pNext;
    607 		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags     flags;
    608 		topology,														// VkPrimitiveTopology                         topology;
    609 		VK_FALSE,														// VkBool32                                    primitiveRestartEnable;
    610 	};
    611 
    612 	const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
    613 	{
    614 		VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,		// VkStructureType                             sType;
    615 		DE_NULL,														// const void*                                 pNext;
    616 		(VkPipelineTessellationStateCreateFlags)0,						// VkPipelineTessellationStateCreateFlags      flags;
    617 		m_patchControlPoints,											// uint32_t                                    patchControlPoints;
    618 	};
    619 
    620 	const VkViewport viewport = makeViewport(
    621 		0.0f, 0.0f,
    622 		static_cast<float>(m_renderSize.x()), static_cast<float>(m_renderSize.y()),
    623 		0.0f, 1.0f);
    624 
    625 	const VkRect2D scissor = {
    626 		makeOffset2D(0, 0),
    627 		makeExtent2D(m_renderSize.x(), m_renderSize.y()),
    628 	};
    629 
    630 	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
    631 	{
    632 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType                             sType;
    633 		DE_NULL,												// const void*                                 pNext;
    634 		(VkPipelineViewportStateCreateFlags)0,					// VkPipelineViewportStateCreateFlags          flags;
    635 		1u,														// uint32_t                                    viewportCount;
    636 		&viewport,												// const VkViewport*                           pViewports;
    637 		1u,														// uint32_t                                    scissorCount;
    638 		&scissor,												// const VkRect2D*                             pScissors;
    639 	};
    640 
    641 	const bool isRasterizationDisabled = ((m_shaderStageFlags & VK_SHADER_STAGE_FRAGMENT_BIT) == 0);
    642 	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
    643 	{
    644 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType                          sType;
    645 		DE_NULL,														// const void*                              pNext;
    646 		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags  flags;
    647 		VK_FALSE,														// VkBool32                                 depthClampEnable;
    648 		isRasterizationDisabled,										// VkBool32                                 rasterizerDiscardEnable;
    649 		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
    650 		m_cullModeFlags,												// VkCullModeFlags							cullMode;
    651 		m_frontFace,													// VkFrontFace								frontFace;
    652 		VK_FALSE,														// VkBool32									depthBiasEnable;
    653 		0.0f,															// float									depthBiasConstantFactor;
    654 		0.0f,															// float									depthBiasClamp;
    655 		0.0f,															// float									depthBiasSlopeFactor;
    656 		1.0f,															// float									lineWidth;
    657 	};
    658 
    659 	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
    660 	{
    661 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
    662 		DE_NULL,													// const void*								pNext;
    663 		(VkPipelineMultisampleStateCreateFlags)0,					// VkPipelineMultisampleStateCreateFlags	flags;
    664 		VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples;
    665 		VK_FALSE,													// VkBool32									sampleShadingEnable;
    666 		0.0f,														// float									minSampleShading;
    667 		DE_NULL,													// const VkSampleMask*						pSampleMask;
    668 		VK_FALSE,													// VkBool32									alphaToCoverageEnable;
    669 		VK_FALSE													// VkBool32									alphaToOneEnable;
    670 	};
    671 
    672 	const VkStencilOpState stencilOpState = makeStencilOpState(
    673 		VK_STENCIL_OP_KEEP,		// stencil fail
    674 		VK_STENCIL_OP_KEEP,		// depth & stencil pass
    675 		VK_STENCIL_OP_KEEP,		// depth only fail
    676 		VK_COMPARE_OP_NEVER,	// compare op
    677 		0u,						// compare mask
    678 		0u,						// write mask
    679 		0u);					// reference
    680 
    681 	const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
    682 	{
    683 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
    684 		DE_NULL,													// const void*								pNext;
    685 		(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags	flags;
    686 		VK_FALSE,													// VkBool32									depthTestEnable;
    687 		VK_FALSE,													// VkBool32									depthWriteEnable;
    688 		VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
    689 		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
    690 		VK_FALSE,													// VkBool32									stencilTestEnable;
    691 		stencilOpState,												// VkStencilOpState							front;
    692 		stencilOpState,												// VkStencilOpState							back;
    693 		0.0f,														// float									minDepthBounds;
    694 		1.0f,														// float									maxDepthBounds;
    695 	};
    696 
    697 	const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
    698 	const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
    699 	{
    700 		m_blendEnable,						// VkBool32					blendEnable;
    701 		VK_BLEND_FACTOR_SRC_ALPHA,			// VkBlendFactor			srcColorBlendFactor;
    702 		VK_BLEND_FACTOR_ONE,				// VkBlendFactor			dstColorBlendFactor;
    703 		VK_BLEND_OP_ADD,					// VkBlendOp				colorBlendOp;
    704 		VK_BLEND_FACTOR_SRC_ALPHA,			// VkBlendFactor			srcAlphaBlendFactor;
    705 		VK_BLEND_FACTOR_ONE,				// VkBlendFactor			dstAlphaBlendFactor;
    706 		VK_BLEND_OP_ADD,					// VkBlendOp				alphaBlendOp;
    707 		colorComponentsAll,					// VkColorComponentFlags	colorWriteMask;
    708 	};
    709 
    710 	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
    711 	{
    712 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
    713 		DE_NULL,													// const void*									pNext;
    714 		(VkPipelineColorBlendStateCreateFlags)0,					// VkPipelineColorBlendStateCreateFlags			flags;
    715 		VK_FALSE,													// VkBool32										logicOpEnable;
    716 		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
    717 		1u,															// deUint32										attachmentCount;
    718 		&pipelineColorBlendAttachmentState,							// const VkPipelineColorBlendAttachmentState*	pAttachments;
    719 		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConstants[4];
    720 	};
    721 
    722 	const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
    723 	{
    724 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,						// VkStructureType									sType;
    725 		DE_NULL,																// const void*										pNext;
    726 		(VkPipelineCreateFlags)0,												// VkPipelineCreateFlags							flags;
    727 		static_cast<deUint32>(m_shaderStages.size()),							// deUint32											stageCount;
    728 		&m_shaderStages[0],														// const VkPipelineShaderStageCreateInfo*			pStages;
    729 		&vertexInputStateInfo,													// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
    730 		&pipelineInputAssemblyStateInfo,										// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
    731 		(m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? &pipelineTessellationStateInfo : DE_NULL), // const VkPipelineTessellationStateCreateInfo*		pTessellationState;
    732 		(isRasterizationDisabled ? DE_NULL : &pipelineViewportStateInfo),		// const VkPipelineViewportStateCreateInfo*			pViewportState;
    733 		&pipelineRasterizationStateInfo,										// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
    734 		(isRasterizationDisabled ? DE_NULL : &pipelineMultisampleStateInfo),	// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
    735 		(isRasterizationDisabled ? DE_NULL : &pipelineDepthStencilStateInfo),	// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
    736 		(isRasterizationDisabled ? DE_NULL : &pipelineColorBlendStateInfo),		// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
    737 		DE_NULL,																// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
    738 		pipelineLayout,															// VkPipelineLayout									layout;
    739 		renderPass,																// VkRenderPass										renderPass;
    740 		0u,																		// deUint32											subpass;
    741 		DE_NULL,																// VkPipeline										basePipelineHandle;
    742 		0,																		// deInt32											basePipelineIndex;
    743 	};
    744 
    745 	return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
    746 }
    747 
    748 float getClampedTessLevel (const SpacingMode mode, const float tessLevel)
    749 {
    750 	switch (mode)
    751 	{
    752 		case SPACINGMODE_EQUAL:				return de::max(1.0f, tessLevel);
    753 		case SPACINGMODE_FRACTIONAL_ODD:	return de::max(1.0f, tessLevel);
    754 		case SPACINGMODE_FRACTIONAL_EVEN:	return de::max(2.0f, tessLevel);
    755 		default:
    756 			DE_ASSERT(false);
    757 			return 0.0f;
    758 	}
    759 }
    760 
    761 int getRoundedTessLevel (const SpacingMode mode, const float clampedTessLevel)
    762 {
    763 	static const int minimumMaxTessGenLevel = 64;	//!< Minimum maxTessellationGenerationLevel defined by the spec.
    764 
    765 	int result = (int)deFloatCeil(clampedTessLevel);
    766 
    767 	switch (mode)
    768 	{
    769 		case SPACINGMODE_EQUAL:											break;
    770 		case SPACINGMODE_FRACTIONAL_ODD:	result += 1 - result % 2;	break;
    771 		case SPACINGMODE_FRACTIONAL_EVEN:	result += result % 2;		break;
    772 		default:
    773 			DE_ASSERT(false);
    774 	}
    775 	DE_ASSERT(de::inRange<int>(result, 1, minimumMaxTessGenLevel));
    776 	DE_UNREF(minimumMaxTessGenLevel);
    777 
    778 	return result;
    779 }
    780 
    781 int getClampedRoundedTessLevel (const SpacingMode mode, const float tessLevel)
    782 {
    783 	return getRoundedTessLevel(mode, getClampedTessLevel(mode, tessLevel));
    784 }
    785 
    786 void getClampedRoundedTriangleTessLevels (const SpacingMode	spacingMode,
    787 										  const float*		innerSrc,
    788 										  const float*		outerSrc,
    789 										  int*				innerDst,
    790 										  int*				outerDst)
    791 {
    792 	innerDst[0] = getClampedRoundedTessLevel(spacingMode, innerSrc[0]);
    793 	for (int i = 0; i < 3; i++)
    794 		outerDst[i] = getClampedRoundedTessLevel(spacingMode, outerSrc[i]);
    795 }
    796 
    797 void getClampedRoundedQuadTessLevels (const SpacingMode spacingMode,
    798 									  const float*		innerSrc,
    799 									  const float*		outerSrc,
    800 									  int*				innerDst,
    801 									  int*				outerDst)
    802 {
    803 	for (int i = 0; i < 2; i++)
    804 		innerDst[i] = getClampedRoundedTessLevel(spacingMode, innerSrc[i]);
    805 	for (int i = 0; i < 4; i++)
    806 		outerDst[i] = getClampedRoundedTessLevel(spacingMode, outerSrc[i]);
    807 }
    808 
    809 void getClampedRoundedIsolineTessLevels (const SpacingMode	spacingMode,
    810 										 const float*		outerSrc,
    811 										 int*				outerDst)
    812 {
    813 	outerDst[0] = getClampedRoundedTessLevel(SPACINGMODE_EQUAL,	outerSrc[0]);
    814 	outerDst[1] = getClampedRoundedTessLevel(spacingMode,		outerSrc[1]);
    815 }
    816 
    817 int numOuterTessellationLevels (const TessPrimitiveType primType)
    818 {
    819 	switch (primType)
    820 	{
    821 		case TESSPRIMITIVETYPE_TRIANGLES:	return 3;
    822 		case TESSPRIMITIVETYPE_QUADS:		return 4;
    823 		case TESSPRIMITIVETYPE_ISOLINES:	return 2;
    824 		default:
    825 			DE_ASSERT(false);
    826 			return 0;
    827 	}
    828 }
    829 
    830 bool isPatchDiscarded (const TessPrimitiveType primitiveType, const float* outerLevels)
    831 {
    832 	const int numOuterLevels = numOuterTessellationLevels(primitiveType);
    833 	for (int i = 0; i < numOuterLevels; i++)
    834 		if (outerLevels[i] <= 0.0f)
    835 			return true;
    836 	return false;
    837 }
    838 
    839 std::string getTessellationLevelsString (const TessLevels& tessLevels, const TessPrimitiveType primitiveType)
    840 {
    841 	std::ostringstream str;
    842 	switch (primitiveType)
    843 	{
    844 		case TESSPRIMITIVETYPE_ISOLINES:
    845 			str << "inner: { }, "
    846 				<< "outer: { " << tessLevels.outer[0] << ", " << tessLevels.outer[1] << " }";
    847 			break;
    848 
    849 		case TESSPRIMITIVETYPE_TRIANGLES:
    850 			str << "inner: { " << tessLevels.inner[0] << " }, "
    851 				<< "outer: { " << tessLevels.outer[0] << ", " << tessLevels.outer[1] << ", " << tessLevels.outer[2] << " }";
    852 			break;
    853 
    854 		case TESSPRIMITIVETYPE_QUADS:
    855 			str << "inner: { " << tessLevels.inner[0] << ", " << tessLevels.inner[1] << " }, "
    856 				<< "outer: { " << tessLevels.outer[0] << ", " << tessLevels.outer[1] << ", " << tessLevels.outer[2] << ", " << tessLevels.outer[3] << " }";
    857 			break;
    858 
    859 		default:
    860 			DE_ASSERT(false);
    861 	}
    862 
    863 	return str.str();
    864 }
    865 
    866 //! Assumes array sizes inner[2] and outer[4].
    867 std::string getTessellationLevelsString (const float* inner, const float* outer)
    868 {
    869 	const TessLevels tessLevels =
    870 	{
    871 		{ inner[0], inner[1] },
    872 		{ outer[0], outer[1], outer[2], outer[3] }
    873 	};
    874 	return getTessellationLevelsString(tessLevels, TESSPRIMITIVETYPE_QUADS);
    875 }
    876 
    877 // \note The tessellation coordinates generated by this function could break some of the rules given in the spec
    878 // (e.g. it may not exactly hold that u+v+w == 1.0f, or [uvw] + (1.0f-[uvw]) == 1.0f).
    879 std::vector<tcu::Vec3> generateReferenceTriangleTessCoords (const SpacingMode	spacingMode,
    880 															const int			inner,
    881 															const int			outer0,
    882 															const int			outer1,
    883 															const int			outer2)
    884 {
    885 	std::vector<tcu::Vec3> tessCoords;
    886 
    887 	if (inner == 1)
    888 	{
    889 		if (outer0 == 1 && outer1 == 1 && outer2 == 1)
    890 		{
    891 			tessCoords.push_back(tcu::Vec3(1.0f, 0.0f, 0.0f));
    892 			tessCoords.push_back(tcu::Vec3(0.0f, 1.0f, 0.0f));
    893 			tessCoords.push_back(tcu::Vec3(0.0f, 0.0f, 1.0f));
    894 			return tessCoords;
    895 		}
    896 		else
    897 			return generateReferenceTriangleTessCoords(spacingMode, spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
    898 													   outer0, outer1, outer2);
    899 	}
    900 	else
    901 	{
    902 		for (int i = 0; i < outer0; i++) { const float v = (float)i / (float)outer0; tessCoords.push_back(tcu::Vec3(    0.0f,        v, 1.0f - v)); }
    903 		for (int i = 0; i < outer1; i++) { const float v = (float)i / (float)outer1; tessCoords.push_back(tcu::Vec3(1.0f - v,     0.0f,        v)); }
    904 		for (int i = 0; i < outer2; i++) { const float v = (float)i / (float)outer2; tessCoords.push_back(tcu::Vec3(       v, 1.0f - v,     0.0f)); }
    905 
    906 		const int numInnerTriangles = inner/2;
    907 		for (int innerTriangleNdx = 0; innerTriangleNdx < numInnerTriangles; innerTriangleNdx++)
    908 		{
    909 			const int curInnerTriangleLevel = inner - 2*(innerTriangleNdx+1);
    910 
    911 			if (curInnerTriangleLevel == 0)
    912 				tessCoords.push_back(tcu::Vec3(1.0f/3.0f));
    913 			else
    914 			{
    915 				const float		minUVW		= (float)(2 * (innerTriangleNdx + 1)) / (float)(3 * inner);
    916 				const float		maxUVW		= 1.0f - 2.0f*minUVW;
    917 				const tcu::Vec3	corners[3]	=
    918 				{
    919 					tcu::Vec3(maxUVW, minUVW, minUVW),
    920 					tcu::Vec3(minUVW, maxUVW, minUVW),
    921 					tcu::Vec3(minUVW, minUVW, maxUVW)
    922 				};
    923 
    924 				for (int i = 0; i < curInnerTriangleLevel; i++)
    925 				{
    926 					const float f = (float)i / (float)curInnerTriangleLevel;
    927 					for (int j = 0; j < 3; j++)
    928 						tessCoords.push_back((1.0f - f)*corners[j] + f*corners[(j+1)%3]);
    929 				}
    930 			}
    931 		}
    932 
    933 		return tessCoords;
    934 	}
    935 }
    936 
    937 // \note The tessellation coordinates generated by this function could break some of the rules given in the spec
    938 // (e.g. it may not exactly hold that [uv] + (1.0f-[uv]) == 1.0f).
    939 std::vector<tcu::Vec3> generateReferenceQuadTessCoords (const SpacingMode	spacingMode,
    940 														const int			inner0,
    941 														const int			inner1,
    942 														const int			outer0,
    943 														const int			outer1,
    944 														const int			outer2,
    945 														const int			outer3)
    946 {
    947 	std::vector<tcu::Vec3> tessCoords;
    948 
    949 	if (inner0 == 1 || inner1 == 1)
    950 	{
    951 		if (inner0 == 1 && inner1 == 1 && outer0 == 1 && outer1 == 1 && outer2 == 1 && outer3 == 1)
    952 		{
    953 			tessCoords.push_back(tcu::Vec3(0.0f, 0.0f, 0.0f));
    954 			tessCoords.push_back(tcu::Vec3(1.0f, 0.0f, 0.0f));
    955 			tessCoords.push_back(tcu::Vec3(0.0f, 1.0f, 0.0f));
    956 			tessCoords.push_back(tcu::Vec3(1.0f, 1.0f, 0.0f));
    957 			return tessCoords;
    958 		}
    959 		else
    960 			return generateReferenceQuadTessCoords(spacingMode, inner0 > 1 ? inner0 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
    961 																inner1 > 1 ? inner1 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
    962 																outer0, outer1, outer2, outer3);
    963 	}
    964 	else
    965 	{
    966 		for (int i = 0; i < outer0; i++) { const float v = (float)i / (float)outer0; tessCoords.push_back(tcu::Vec3(    0.0f,        v, 0.0f)); }
    967 		for (int i = 0; i < outer1; i++) { const float v = (float)i / (float)outer1; tessCoords.push_back(tcu::Vec3(1.0f - v,     0.0f, 0.0f)); }
    968 		for (int i = 0; i < outer2; i++) { const float v = (float)i / (float)outer2; tessCoords.push_back(tcu::Vec3(    1.0f, 1.0f - v, 0.0f)); }
    969 		for (int i = 0; i < outer3; i++) { const float v = (float)i / (float)outer3; tessCoords.push_back(tcu::Vec3(       v,     1.0f, 0.0f)); }
    970 
    971 		for (int innerVtxY = 0; innerVtxY < inner1-1; innerVtxY++)
    972 		for (int innerVtxX = 0; innerVtxX < inner0-1; innerVtxX++)
    973 			tessCoords.push_back(tcu::Vec3((float)(innerVtxX + 1) / (float)inner0,
    974 										   (float)(innerVtxY + 1) / (float)inner1,
    975 										   0.0f));
    976 
    977 		return tessCoords;
    978 	}
    979 }
    980 
    981 // \note The tessellation coordinates generated by this function could break some of the rules given in the spec
    982 // (e.g. it may not exactly hold that [uv] + (1.0f-[uv]) == 1.0f).
    983 std::vector<tcu::Vec3> generateReferenceIsolineTessCoords (const int outer0, const int outer1)
    984 {
    985 	std::vector<tcu::Vec3> tessCoords;
    986 
    987 	for (int y = 0; y < outer0;   y++)
    988 	for (int x = 0; x < outer1+1; x++)
    989 		tessCoords.push_back(tcu::Vec3((float)x / (float)outer1,
    990 									   (float)y / (float)outer0,
    991 									   0.0f));
    992 
    993 	return tessCoords;
    994 }
    995 
    996 static int referencePointModePrimitiveCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const float* innerLevels, const float* outerLevels)
    997 {
    998 	if (isPatchDiscarded(primitiveType, outerLevels))
    999 		return 0;
   1000 
   1001 	switch (primitiveType)
   1002 	{
   1003 		case TESSPRIMITIVETYPE_TRIANGLES:
   1004 		{
   1005 			int inner;
   1006 			int outer[3];
   1007 			getClampedRoundedTriangleTessLevels(spacingMode, innerLevels, outerLevels, &inner, &outer[0]);
   1008 			return static_cast<int>(generateReferenceTriangleTessCoords(spacingMode, inner, outer[0], outer[1], outer[2]).size());
   1009 		}
   1010 
   1011 		case TESSPRIMITIVETYPE_QUADS:
   1012 		{
   1013 			int inner[2];
   1014 			int outer[4];
   1015 			getClampedRoundedQuadTessLevels(spacingMode, innerLevels, outerLevels, &inner[0], &outer[0]);
   1016 			return static_cast<int>(generateReferenceQuadTessCoords(spacingMode, inner[0], inner[1], outer[0], outer[1], outer[2], outer[3]).size());
   1017 		}
   1018 
   1019 		case TESSPRIMITIVETYPE_ISOLINES:
   1020 		{
   1021 			int outer[2];
   1022 			getClampedRoundedIsolineTessLevels(spacingMode, &outerLevels[0], &outer[0]);
   1023 			return static_cast<int>(generateReferenceIsolineTessCoords(outer[0], outer[1]).size());
   1024 		}
   1025 
   1026 		default:
   1027 			DE_ASSERT(false);
   1028 			return 0;
   1029 	}
   1030 }
   1031 
   1032 static int referenceTriangleNonPointModePrimitiveCount (const SpacingMode spacingMode, const int inner, const int outer0, const int outer1, const int outer2)
   1033 {
   1034 	if (inner == 1)
   1035 	{
   1036 		if (outer0 == 1 && outer1 == 1 && outer2 == 1)
   1037 			return 1;
   1038 		else
   1039 			return referenceTriangleNonPointModePrimitiveCount(spacingMode, spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
   1040 																			outer0, outer1, outer2);
   1041 	}
   1042 	else
   1043 	{
   1044 		int result = outer0 + outer1 + outer2;
   1045 
   1046 		const int numInnerTriangles = inner/2;
   1047 		for (int innerTriangleNdx = 0; innerTriangleNdx < numInnerTriangles; innerTriangleNdx++)
   1048 		{
   1049 			const int curInnerTriangleLevel = inner - 2*(innerTriangleNdx+1);
   1050 
   1051 			if (curInnerTriangleLevel == 1)
   1052 				result += 4;
   1053 			else
   1054 				result += 2*3*curInnerTriangleLevel;
   1055 		}
   1056 
   1057 		return result;
   1058 	}
   1059 }
   1060 
   1061 static int referenceQuadNonPointModePrimitiveCount (const SpacingMode spacingMode, const int inner0, const int inner1, const int outer0, const int outer1, const int outer2, const int outer3)
   1062 {
   1063 	if (inner0 == 1 || inner1 == 1)
   1064 	{
   1065 		if (inner0 == 1 && inner1 == 1 && outer0 == 1 && outer1 == 1 && outer2 == 1 && outer3 == 1)
   1066 			return 2;
   1067 		else
   1068 			return referenceQuadNonPointModePrimitiveCount(spacingMode, inner0 > 1 ? inner0 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
   1069 																		inner1 > 1 ? inner1 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
   1070 																		outer0, outer1, outer2, outer3);
   1071 	}
   1072 	else
   1073 		return 2*(inner0-2)*(inner1-2) + 2*(inner0-2) + 2*(inner1-2) + outer0+outer1+outer2+outer3;
   1074 }
   1075 
   1076 static inline int referenceIsolineNonPointModePrimitiveCount (const int outer0, const int outer1)
   1077 {
   1078 	return outer0*outer1;
   1079 }
   1080 
   1081 static int referenceNonPointModePrimitiveCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const float* innerLevels, const float* outerLevels)
   1082 {
   1083 	if (isPatchDiscarded(primitiveType, outerLevels))
   1084 		return 0;
   1085 
   1086 	switch (primitiveType)
   1087 	{
   1088 		case TESSPRIMITIVETYPE_TRIANGLES:
   1089 		{
   1090 			int inner;
   1091 			int outer[3];
   1092 			getClampedRoundedTriangleTessLevels(spacingMode, innerLevels, outerLevels, &inner, &outer[0]);
   1093 			return referenceTriangleNonPointModePrimitiveCount(spacingMode, inner, outer[0], outer[1], outer[2]);
   1094 		}
   1095 
   1096 		case TESSPRIMITIVETYPE_QUADS:
   1097 		{
   1098 			int inner[2];
   1099 			int outer[4];
   1100 			getClampedRoundedQuadTessLevels(spacingMode, innerLevels, outerLevels, &inner[0], &outer[0]);
   1101 			return referenceQuadNonPointModePrimitiveCount(spacingMode, inner[0], inner[1], outer[0], outer[1], outer[2], outer[3]);
   1102 		}
   1103 
   1104 		case TESSPRIMITIVETYPE_ISOLINES:
   1105 		{
   1106 			int outer[2];
   1107 			getClampedRoundedIsolineTessLevels(spacingMode, &outerLevels[0], &outer[0]);
   1108 			return referenceIsolineNonPointModePrimitiveCount(outer[0], outer[1]);
   1109 		}
   1110 
   1111 		default:
   1112 			DE_ASSERT(false);
   1113 			return 0;
   1114 	}
   1115 }
   1116 
   1117 int numVerticesPerPrimitive (const TessPrimitiveType primitiveType, const bool usePointMode)
   1118 {
   1119 	if (usePointMode)
   1120 		return 1;
   1121 
   1122 	switch (primitiveType)
   1123 	{
   1124 		case TESSPRIMITIVETYPE_TRIANGLES:	return 3;
   1125 		case TESSPRIMITIVETYPE_QUADS:		return 3;  // quads are composed of two triangles
   1126 		case TESSPRIMITIVETYPE_ISOLINES:	return 2;
   1127 		default:
   1128 			DE_ASSERT(false);
   1129 			return 0;
   1130 	}
   1131 }
   1132 
   1133 int referencePrimitiveCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const bool usePointMode, const float* innerLevels, const float* outerLevels)
   1134 {
   1135 	return usePointMode ? referencePointModePrimitiveCount		(primitiveType, spacingMode, innerLevels, outerLevels)
   1136 						: referenceNonPointModePrimitiveCount	(primitiveType, spacingMode, innerLevels, outerLevels);
   1137 }
   1138 
   1139 //! In point mode this should return the number of unique vertices, while in non-point mode the maximum theoretical number of verticies.
   1140 //! Actual implementation will likely return a much smaller number because the shader isn't required to be run for duplicate coordinates.
   1141 int referenceVertexCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const bool usePointMode, const float* innerLevels, const float* outerLevels)
   1142 {
   1143 	return referencePrimitiveCount(primitiveType, spacingMode, usePointMode, innerLevels, outerLevels)
   1144 		   * numVerticesPerPrimitive(primitiveType, usePointMode);
   1145 }
   1146 
   1147 void requireFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const FeatureFlags flags)
   1148 {
   1149 	const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
   1150 
   1151 	if (((flags & FEATURE_TESSELLATION_SHADER) != 0) && !features.tessellationShader)
   1152 		throw tcu::NotSupportedError("Tessellation shader not supported");
   1153 
   1154 	if (((flags & FEATURE_GEOMETRY_SHADER) != 0) && !features.geometryShader)
   1155 		throw tcu::NotSupportedError("Geometry shader not supported");
   1156 
   1157 	if (((flags & FEATURE_SHADER_FLOAT_64) != 0) && !features.shaderFloat64)
   1158 		throw tcu::NotSupportedError("Double-precision floats not supported");
   1159 
   1160 	if (((flags & FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS) != 0) && !features.vertexPipelineStoresAndAtomics)
   1161 		throw tcu::NotSupportedError("SSBO and image writes not supported in vertex pipeline");
   1162 
   1163 	if (((flags & FEATURE_FRAGMENT_STORES_AND_ATOMICS) != 0) && !features.fragmentStoresAndAtomics)
   1164 		throw tcu::NotSupportedError("SSBO and image writes not supported in fragment shader");
   1165 
   1166 	if (((flags & FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE) != 0) && !features.shaderTessellationAndGeometryPointSize)
   1167 		throw tcu::NotSupportedError("Tessellation and geometry shaders don't support PointSize built-in");
   1168 }
   1169 
   1170 } // tessellation
   1171 } // vkt
   1172