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