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