• 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 	const SharedGroupParams	groupParams;
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 #ifndef CTS_USES_VULKANSC
348 	VkFormat colorAttachmentFormat = VK_FORMAT_R8G8B8A8_UNORM;
349 	VkPipelineRenderingCreateInfoKHR renderingCreateInfo
350 	{
351 		VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
352 		DE_NULL,
353 		0u,
354 		1u,
355 		&colorAttachmentFormat,
356 		VK_FORMAT_UNDEFINED,
357 		VK_FORMAT_UNDEFINED
358 	};
359 
360 	// when pipeline is created without render pass we are using dynamic rendering
361 	if (renderPass == DE_NULL)
362 		graphicsPipelineInfo.pNext = &renderingCreateInfo;
363 #endif // CTS_USES_VULKANSC
364 
365 	return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
366 }
367 
generateGrid(const int numCells,const UVec2 & renderSize)368 std::vector<UVec4> generateGrid (const int numCells, const UVec2& renderSize)
369 {
370 	const int numCols		= deCeilFloatToInt32(deFloatSqrt(static_cast<float>(numCells)));
371 	const int numRows		= deCeilFloatToInt32(static_cast<float>(numCells) / static_cast<float>(numCols));
372 	const int rectWidth		= renderSize.x() / numCols;
373 	const int rectHeight	= renderSize.y() / numRows;
374 
375 	std::vector<UVec4> cells;
376 	cells.reserve(numCells);
377 
378 	int x = 0;
379 	int y = 0;
380 
381 	for (int cellNdx = 0; cellNdx < numCells; ++cellNdx)
382 	{
383 		const bool nextRow = (cellNdx != 0) && (cellNdx % numCols == 0);
384 		if (nextRow)
385 		{
386 			x  = 0;
387 			y += rectHeight;
388 		}
389 
390 		cells.push_back(UVec4(x, y, rectWidth, rectHeight));
391 
392 		x += rectWidth;
393 	}
394 
395 	return cells;
396 }
397 
generateColors(const int numColors)398 std::vector<Vec4> generateColors (const int numColors)
399 {
400 	const Vec4 colors[] =
401 	{
402 		Vec4(0.18f, 0.42f, 0.17f, 1.0f),
403 		Vec4(0.29f, 0.62f, 0.28f, 1.0f),
404 		Vec4(0.59f, 0.84f, 0.44f, 1.0f),
405 		Vec4(0.96f, 0.95f, 0.72f, 1.0f),
406 		Vec4(0.94f, 0.55f, 0.39f, 1.0f),
407 		Vec4(0.82f, 0.19f, 0.12f, 1.0f),
408 		Vec4(0.46f, 0.15f, 0.26f, 1.0f),
409 		Vec4(0.24f, 0.14f, 0.24f, 1.0f),
410 		Vec4(0.49f, 0.31f, 0.26f, 1.0f),
411 		Vec4(0.78f, 0.52f, 0.33f, 1.0f),
412 		Vec4(0.94f, 0.82f, 0.31f, 1.0f),
413 		Vec4(0.98f, 0.65f, 0.30f, 1.0f),
414 		Vec4(0.22f, 0.65f, 0.53f, 1.0f),
415 		Vec4(0.67f, 0.81f, 0.91f, 1.0f),
416 		Vec4(0.43f, 0.44f, 0.75f, 1.0f),
417 		Vec4(0.26f, 0.24f, 0.48f, 1.0f),
418 	};
419 
420 	DE_ASSERT(numColors <= DE_LENGTH_OF_ARRAY(colors));
421 
422 	return std::vector<Vec4>(colors, colors + numColors);
423 }
424 
425 //! 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)426 tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat	format,
427 										  const UVec2&				renderSize,
428 										  const Vec4&				clearColor,
429 										  const std::vector<UVec4>&	cells,
430 										  const std::vector<Vec4>&	cellColors)
431 {
432 	DE_ASSERT(cells.size() == cellColors.size());
433 
434 	tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
435 	tcu::clear(image.getAccess(), clearColor);
436 
437 	for (std::size_t i = 0; i < cells.size(); ++i)
438 	{
439 		const UVec4& cell = cells[i];
440 		tcu::clear(
441 			tcu::getSubregion(image.getAccess(), cell.x(), cell.y(), cell.z(), cell.w()),
442 			cellColors[i]);
443 	}
444 
445 	return image;
446 }
447 
initVertexTestPrograms(SourceCollections & programCollection,const TestParams)448 void initVertexTestPrograms (SourceCollections& programCollection, const TestParams)
449 {
450 	// Vertex shader
451 	{
452 		std::ostringstream src;
453 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
454 			<< "#extension GL_ARB_shader_viewport_layer_array : require\n"
455 			<< "\n"
456 			<< "layout(location = 0) in  vec4 in_position;\n"
457 			<< "layout(location = 1) in  vec4 in_color;\n"
458 			<< "layout(location = 0) out vec4 out_color;\n"
459 			<< "\n"
460 			<< "void main(void)\n"
461 			<< "{\n"
462 			<< "    gl_ViewportIndex = gl_VertexIndex / 6;\n"
463 			<< "    gl_Position = in_position;\n"
464 			<< "    out_color = in_color;\n"
465 			<< "}\n";
466 
467 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
468 	}
469 
470 	// Fragment shader
471 	{
472 		std::ostringstream src;
473 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
474 			<< "\n"
475 			<< "layout(location = 0) in  vec4 in_color;\n"
476 			<< "layout(location = 0) out vec4 out_color;\n"
477 			<< "\n"
478 			<< "void main(void)\n"
479 			<< "{\n"
480 			<< "    out_color = in_color;\n"
481 			<< "}\n";
482 
483 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
484 	}
485 }
486 
initFragmentTestPrograms(SourceCollections & programCollection,const TestParams testParams)487 void initFragmentTestPrograms (SourceCollections& programCollection, const TestParams testParams)
488 {
489 	// Vertex shader.
490 	{
491 		std::ostringstream src;
492 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
493 			<< "#extension GL_ARB_shader_viewport_layer_array : require\n"
494 			<< "\n"
495 			<< "layout(location = 0) in  vec4 in_position;\n"
496 			<< "layout(location = 1) in  vec4 in_color;\n"
497 			<< "layout(location = 0) out vec4 out_color;\n"
498 			<< "\n"
499 			<< "void main(void)\n"
500 			<< "{\n"
501 			<< (testParams.writeFromVertex ? "    gl_ViewportIndex = gl_VertexIndex / 6;\n" : "")
502 			<< "    gl_Position = in_position;\n"
503 			<< "    out_color = in_color;\n"
504 			<< "}\n";
505 
506 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
507 	}
508 
509 	// Fragment shader
510 	{
511 		// Ignore input color and choose one using the viewport index.
512 		std::ostringstream src;
513 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
514 			<< "\n"
515 			<< "layout(location = 0) in  vec4 in_color;\n"
516 			<< "layout(location = 0) out vec4 out_color;\n"
517 			<< "layout(set=0, binding=0) uniform Colors {\n"
518 			<< "    vec4 color[" << testParams.numViewports << "];\n"
519 			<< "};\n"
520 			<< "\n"
521 			<< "void main(void)\n"
522 			<< "{\n"
523 			<< "    out_color = color[gl_ViewportIndex];\n"
524 			<< "}\n";
525 
526 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
527 	}
528 }
529 
initTessellationTestPrograms(SourceCollections & programCollection,const TestParams)530 void initTessellationTestPrograms (SourceCollections& programCollection, const TestParams)
531 {
532 	// Vertex shader
533 	{
534 		std::ostringstream src;
535 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
536 			<< "\n"
537 			<< "layout(location = 0) in  vec4 in_position;\n"
538 			<< "layout(location = 1) in  vec4 in_color;\n"
539 			<< "layout(location = 0) out vec4 out_color;\n"
540 			<< "\n"
541 			<< "void main(void)\n"
542 			<< "{\n"
543 			<< "    gl_Position = in_position;\n"
544 			<< "    out_color = in_color;\n"
545 			<< "}\n";
546 
547 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
548 	}
549 
550 	// Tessellation control shader
551 	{
552 		std::ostringstream src;
553 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
554 			<< "\n"
555 			<< "layout(vertices = 3) out;\n"
556 			<< "\n"
557 			<< "layout(location = 0) in  vec4 in_color[];\n"
558 			<< "layout(location = 0) out vec4 out_color[];\n"
559 			<< "\n"
560 			<< "void main(void)\n"
561 			<< "{\n"
562 			<< "    if (gl_InvocationID == 0) {\n"
563 			<< "        gl_TessLevelInner[0] = 1.0;\n"
564 			<< "        gl_TessLevelInner[1] = 1.0;\n"
565 			<< "        gl_TessLevelOuter[0] = 1.0;\n"
566 			<< "        gl_TessLevelOuter[1] = 1.0;\n"
567 			<< "        gl_TessLevelOuter[2] = 1.0;\n"
568 			<< "        gl_TessLevelOuter[3] = 1.0;\n"
569 			<< "    }\n"
570 			<< "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
571 			<< "    out_color[gl_InvocationID] = in_color[gl_InvocationID];\n"
572 			<< "}\n";
573 
574 		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
575 	}
576 
577 	// Tessellation evaluation shader
578 	{
579 		std::ostringstream src;
580 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
581 			<< "#extension GL_ARB_shader_viewport_layer_array : require\n"
582 			<< "\n"
583 			<< "layout(triangles, equal_spacing, cw) in;\n"
584 			<< "\n"
585 			<< "layout(location = 0) in  vec4 in_color[];\n"
586 			<< "layout(location = 0) out vec4 out_color;\n"
587 			<< "\n"
588 			<< "void main(void)\n"
589 			<< "{\n"
590 			<< "    gl_ViewportIndex = gl_PrimitiveID / 2;\n"
591 			<< "    gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n"
592 			<< "                  gl_in[1].gl_Position * gl_TessCoord.y +\n"
593 			<< "                  gl_in[2].gl_Position * gl_TessCoord.z;\n"
594 			<< "\n"
595 			<< "    out_color = in_color[0] * gl_TessCoord.x +\n"
596 			<< "                in_color[1] * gl_TessCoord.y +\n"
597 			<< "                in_color[2] * gl_TessCoord.z;\n"
598 			<< "}\n";
599 
600 		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
601 	}
602 
603 	// Fragment shader
604 	{
605 		std::ostringstream src;
606 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
607 			<< "\n"
608 			<< "layout(location = 0) in  vec4 in_color;\n"
609 			<< "layout(location = 0) out vec4 out_color;\n"
610 			<< "\n"
611 			<< "void main(void)\n"
612 			<< "{\n"
613 			<< "    out_color = in_color;\n"
614 			<< "}\n";
615 
616 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
617 	}
618 }
619 
generateVertices(const std::vector<Vec4> & colors)620 std::vector<PositionColorVertex> generateVertices (const std::vector<Vec4>& colors)
621 {
622 	// Two triangles for each color (viewport).
623 	std::size_t total = colors.size() * 6;
624 
625 	std::vector<PositionColorVertex> result;
626 	result.reserve(total);
627 
628 	for (std::size_t i = 0; i < total; ++i)
629 	{
630 		Vec4 pos;
631 		pos.z() = 0.0;
632 		pos.w() = 1.0;
633 
634 		switch (i % 6) {
635 		case 0: pos.xy() = Vec2(-1.0,  1.0); break;
636 		case 1: pos.xy() = Vec2( 1.0,  1.0); break;
637 		case 2: pos.xy() = Vec2(-1.0, -1.0); break;
638 		case 3: pos.xy() = Vec2( 1.0, -1.0); break;
639 		case 4: pos.xy() = Vec2( 1.0,  1.0); break;
640 		case 5: pos.xy() = Vec2(-1.0, -1.0); break;
641 		}
642 
643 		result.push_back(PositionColorVertex(pos, colors[i/6]));
644 	}
645 
646 	return result;
647 }
648 
649 // Renderer generates two triangles per viewport, each pair using a different color. The
650 // numViewports are positioned to form a grid.
651 class Renderer
652 {
653 public:
654 	enum Shader {
655 		VERTEX,
656 		TESSELLATION,
657 		FRAGMENT,
658 	};
659 
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)660 	Renderer (Context&						context,
661 			  const UVec2&					renderSize,
662 			  const TestParams&				testParams,
663 			  const std::vector<UVec4>&		cells,
664 			  const VkFormat				colorFormat,
665 			  const Vec4&					clearColor,
666 			  const std::vector<Vec4>&		colors,
667 			  const Shader					shader)
668 		: m_groupParams				(testParams.groupParams)
669 		, m_renderSize				(renderSize)
670 		, m_colorFormat				(colorFormat)
671 		, m_colorSubresourceRange	(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
672 		, m_clearValue				(makeClearValueColor(clearColor))
673 		, m_numViewports			(testParams.numViewports)
674 		, m_colors					(colors)
675 		, m_vertices				(generateVertices(colors))
676 		, m_shader					(shader)
677 	{
678 		const DeviceInterface&		vk					= context.getDeviceInterface();
679 		const VkDevice				device				= context.getDevice();
680 		const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
681 		Allocator&					allocator			= context.getDefaultAllocator();
682 		const VkDeviceSize			vertexBufferSize    = sizeInBytes(m_vertices);
683 
684 		m_colorImage		= makeImage					(vk, device, makeImageCreateInfo(m_colorFormat, m_renderSize, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
685 		m_colorImageAlloc	= bindImage					(vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
686 		m_colorAttachment	= makeImageView				(vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorSubresourceRange);
687 
688 		m_vertexBuffer		= Buffer::createAndAlloc	(vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), allocator, MemoryRequirement::HostVisible);
689 
690 		{
691 			deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &m_vertices[0], static_cast<std::size_t>(vertexBufferSize));
692 			flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
693 		}
694 
695 		if (shader == TESSELLATION)
696 		{
697 			m_tessellationControlModule		= createShaderModule	(vk, device, context.getBinaryCollection().get("tesc"), 0u);
698 			m_tessellationEvaluationModule	= createShaderModule	(vk, device, context.getBinaryCollection().get("tese"), 0u);
699 		}
700 
701 		m_vertexModule		= createShaderModule	(vk, device, context.getBinaryCollection().get("vert"), 0u);
702 		m_fragmentModule	= createShaderModule	(vk, device, context.getBinaryCollection().get("frag"), 0u);
703 
704 		if (!m_groupParams->useDynamicRendering)
705 		{
706 			m_renderPass	= makeRenderPass		(vk, device, m_colorFormat);
707 
708 			m_framebuffer	= makeFramebuffer		(vk, device, *m_renderPass, m_colorAttachment.get(),
709 													 static_cast<deUint32>(m_renderSize.x()),  static_cast<deUint32>(m_renderSize.y()));
710 		}
711 
712 		if (shader == FRAGMENT)
713 		{
714 			vk::DescriptorSetLayoutBuilder builder;
715 			builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
716 			m_descriptorSetLayout = builder.build(vk, device);
717 		}
718 
719 		m_pipelineLayout	= makePipelineLayout	(vk, device, (shader == FRAGMENT ? m_descriptorSetLayout.get() : DE_NULL));
720 		m_pipeline			= makeGraphicsPipeline	(vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_tessellationControlModule,
721 													 *m_tessellationEvaluationModule, *m_fragmentModule, m_renderSize, m_numViewports, cells);
722 		m_cmdPool			= createCommandPool		(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
723 		m_cmdBuffer			= allocateCommandBuffer	(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
724 		m_secCmdBuffer		= allocateCommandBuffer	(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
725 	}
726 
draw(Context & context,const VkBuffer colorBuffer)727 	void draw (Context& context, const VkBuffer colorBuffer)
728 	{
729 		const DeviceInterface&	vk			= context.getDeviceInterface();
730 		const VkDevice			device		= context.getDevice();
731 		const VkQueue			queue		= context.getUniversalQueue();
732 		const VkRect2D			renderArea
733 		{
734 			makeOffset2D(0, 0),
735 			makeExtent2D(m_renderSize.x(), m_renderSize.y()),
736 		};
737 
738 #ifndef CTS_USES_VULKANSC
739 		if (m_groupParams->useSecondaryCmdBuffer)
740 		{
741 			// record secondary command buffer
742 			if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
743 			{
744 				beginSecondaryCmdBuffer(context, *m_secCmdBuffer, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
745 				beginRendering(vk, *m_secCmdBuffer, *m_colorAttachment, renderArea, m_clearValue,
746 							   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR);
747 			}
748 			else
749 				beginSecondaryCmdBuffer(context, *m_secCmdBuffer);
750 
751 			drawCommands(context, *m_secCmdBuffer);
752 
753 			if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
754 				endRendering(vk, *m_secCmdBuffer);
755 
756 			endCommandBuffer(vk, *m_secCmdBuffer);
757 
758 			// record primary command buffer
759 			beginCommandBuffer(vk, *m_cmdBuffer, 0u);
760 
761 			preRenderCommands(context, *m_cmdBuffer);
762 
763 			if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
764 				beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, m_clearValue,
765 							   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR);
766 
767 			vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
768 
769 			if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
770 				endRendering(vk, *m_cmdBuffer);
771 
772 			postRenderCommands(context, colorBuffer);
773 			endCommandBuffer(vk, *m_cmdBuffer);
774 		}
775 		else if (m_groupParams->useDynamicRendering)
776 		{
777 			beginCommandBuffer(vk, *m_cmdBuffer);
778 
779 			preRenderCommands(context, *m_cmdBuffer);
780 			beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, m_clearValue,
781 						   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR);
782 			drawCommands(context, *m_cmdBuffer);
783 			endRendering(vk, *m_cmdBuffer);
784 			postRenderCommands(context, colorBuffer);
785 
786 			endCommandBuffer(vk, *m_cmdBuffer);
787 		}
788 #endif // CTS_USES_VULKANSC
789 
790 		if (!m_groupParams->useDynamicRendering)
791 		{
792 			beginCommandBuffer(vk, *m_cmdBuffer);
793 
794 			preRenderCommands(context, *m_cmdBuffer);
795 			beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, m_clearValue);
796 			drawCommands(context, *m_cmdBuffer);
797 			endRenderPass(vk, *m_cmdBuffer);
798 			postRenderCommands(context, colorBuffer);
799 
800 			endCommandBuffer(vk, *m_cmdBuffer);
801 		}
802 
803 		submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
804 	}
805 
806 protected:
807 
808 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(Context & context,VkCommandBuffer cmdBuffer,VkRenderingFlagsKHR renderingFlags=0u) const809 	void beginSecondaryCmdBuffer(Context& context, VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags = 0u) const
810 	{
811 		VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
812 		{
813 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,		// VkStructureType					sType;
814 			DE_NULL,																// const void*						pNext;
815 			renderingFlags,															// VkRenderingFlagsKHR				flags;
816 			0u,																		// uint32_t							viewMask;
817 			1u,																		// uint32_t							colorAttachmentCount;
818 			&m_colorFormat,															// const VkFormat*					pColorAttachmentFormats;
819 			VK_FORMAT_UNDEFINED,													// VkFormat							depthAttachmentFormat;
820 			VK_FORMAT_UNDEFINED,													// VkFormat							stencilAttachmentFormat;
821 			VK_SAMPLE_COUNT_1_BIT,													// VkSampleCountFlagBits			rasterizationSamples;
822 		};
823 		const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
824 
825 		VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
826 		if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
827 			usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
828 
829 		const VkCommandBufferBeginInfo commandBufBeginParams
830 		{
831 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,							// VkStructureType					sType;
832 			DE_NULL,																// const void*						pNext;
833 			usageFlags,																// VkCommandBufferUsageFlags		flags;
834 			&bufferInheritanceInfo
835 		};
836 
837 		const DeviceInterface& vk = context.getDeviceInterface();
838 		VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
839 	}
840 #endif // CTS_USES_VULKANSC
841 
preRenderCommands(Context & context,VkCommandBuffer cmdBuffer) const842 	void preRenderCommands(Context& context, VkCommandBuffer cmdBuffer) const
843 	{
844 		if (m_groupParams->useDynamicRendering)
845 		{
846 			const DeviceInterface& vk = context.getDeviceInterface();
847 			initialTransitionColor2DImage(vk, cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
848 				VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
849 		}
850 	}
851 
postRenderCommands(Context & context,VkBuffer colorBuffer) const852 	void postRenderCommands(Context& context, VkBuffer colorBuffer) const
853 	{
854 		const DeviceInterface& vk = context.getDeviceInterface();
855 		copyImageToBuffer(vk, *m_cmdBuffer, *m_colorImage, colorBuffer, tcu::IVec2(m_renderSize.x(), m_renderSize.y()));
856 	}
857 
drawCommands(Context & context,VkCommandBuffer cmdBuffer)858 	void drawCommands(Context& context, VkCommandBuffer cmdBuffer)
859 	{
860 		const DeviceInterface&	vk					= context.getDeviceInterface();
861 		const VkDevice			device				= context.getDevice();
862 		Allocator&				allocator			= context.getDefaultAllocator();
863 		const VkBuffer			vertexBuffer		= m_vertexBuffer->object();
864 		const VkDeviceSize		vertexBufferOffset	= 0ull;
865 
866 		vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
867 		vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
868 
869 		// Prepare colors buffer if needed.
870 		if (m_shader == FRAGMENT)
871 		{
872 			// Create buffer.
873 			const auto	colorsBufferSize = m_colors.size() * sizeof(decltype(m_colors)::value_type);
874 			const auto	colorsBufferCreateInfo = vk::makeBufferCreateInfo(static_cast<VkDeviceSize>(colorsBufferSize), vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
875 			m_colorsBuffer = SharedPtr<BufferWithMemory>(new vk::BufferWithMemory{ vk, device, allocator, colorsBufferCreateInfo, MemoryRequirement::HostVisible });
876 
877 			// Copy colors and flush allocation.
878 			auto& colorsBufferAlloc = m_colorsBuffer->getAllocation();
879 			deMemcpy(colorsBufferAlloc.getHostPtr(), m_colors.data(), colorsBufferSize);
880 			vk::flushAlloc(vk, device, colorsBufferAlloc);
881 
882 			// Descriptor pool.
883 			DescriptorPoolBuilder poolBuilder;
884 			poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u);
885 			m_descriptorPool = poolBuilder.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
886 
887 			// Descriptor set.
888 			m_descriptorSet = vk::makeDescriptorSet(vk, device, m_descriptorPool.get(), m_descriptorSetLayout.get());
889 
890 			// Update and bind descriptor set.
891 			const auto						colorsBufferDescriptorInfo = vk::makeDescriptorBufferInfo(m_colorsBuffer->get(), 0ull, VK_WHOLE_SIZE);
892 			vk::DescriptorSetUpdateBuilder	updateBuilder;
893 			updateBuilder.writeSingle(m_descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &colorsBufferDescriptorInfo);
894 			updateBuilder.update(vk, device);
895 
896 			vk.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout.get(), 0u, 1u, &m_descriptorSet.get(), 0u, nullptr);
897 		}
898 
899 		vk.cmdDraw(cmdBuffer, static_cast<deUint32>(m_numViewports * 6), 1u, 0u, 0u);	// two triangles per viewport
900 	}
901 
902 private:
903 	const SharedGroupParams					m_groupParams;
904 	const UVec2								m_renderSize;
905 	const VkFormat							m_colorFormat;
906 	const VkImageSubresourceRange			m_colorSubresourceRange;
907 	const VkClearValue						m_clearValue;
908 	const int								m_numViewports;
909 	const std::vector<Vec4>					m_colors;
910 	const std::vector<PositionColorVertex>	m_vertices;
911 	const Shader							m_shader;
912 
913 	Move<VkImage>							m_colorImage;
914 	MovePtr<Allocation>						m_colorImageAlloc;
915 	Move<VkImageView>						m_colorAttachment;
916 	SharedPtr<BufferWithMemory>				m_colorsBuffer;
917 	SharedPtr<Buffer>						m_vertexBuffer;
918 	Move<VkShaderModule>					m_vertexModule;
919 	Move<VkShaderModule>					m_tessellationControlModule;
920 	Move<VkShaderModule>					m_tessellationEvaluationModule;
921 	Move<VkShaderModule>					m_fragmentModule;
922 	Move<VkRenderPass>						m_renderPass;
923 	Move<VkFramebuffer>						m_framebuffer;
924 	Move<VkDescriptorPool>					m_descriptorPool;
925 	Move<VkDescriptorSet>					m_descriptorSet;
926 	Move<VkDescriptorSetLayout>				m_descriptorSetLayout;
927 	Move<VkPipelineLayout>					m_pipelineLayout;
928 	Move<VkPipeline>						m_pipeline;
929 	Move<VkCommandPool>						m_cmdPool;
930 	Move<VkCommandBuffer>					m_cmdBuffer;
931 	Move<VkCommandBuffer>					m_secCmdBuffer;
932 
933 	// "deleted"
934 				Renderer	(const Renderer&);
935 	Renderer&	operator=	(const Renderer&);
936 };
937 
testVertexFragmentShader(Context & context,const TestParams & testParams,Renderer::Shader shader)938 tcu::TestStatus testVertexFragmentShader (Context& context, const TestParams& testParams, Renderer::Shader shader)
939 {
940 	const DeviceInterface&			vk					= context.getDeviceInterface();
941 	const VkDevice					device				= context.getDevice();
942 	Allocator&						allocator			= context.getDefaultAllocator();
943 
944 	const UVec2						renderSize			(128, 128);
945 	const VkFormat					colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
946 	const Vec4						clearColor			(0.5f, 0.5f, 0.5f, 1.0f);
947 	const std::vector<Vec4>			colors				= generateColors(testParams.numViewports);
948 	const std::vector<UVec4>		cells				= generateGrid(testParams.numViewports, renderSize);
949 
950 	const VkDeviceSize				colorBufferSize		= renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
951 
952 	const SharedPtr<Buffer>			colorBuffer			= Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
953 
954 	// Zero buffer.
955 	{
956 		const Allocation alloc = colorBuffer->getBoundMemory();
957 		deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
958 		flushAlloc(vk, device, alloc);
959 	}
960 
961 	{
962 		context.getTestContext().getLog()
963 			<< tcu::TestLog::Message << "Rendering a colorful grid of " << testParams.numViewports << " rectangle(s)." << tcu::TestLog::EndMessage
964 			<< tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
965 	}
966 
967 	// Draw
968 	{
969 		Renderer renderer (context, renderSize, testParams, cells, colorFormat, clearColor, colors, shader);
970 		renderer.draw(context, colorBuffer->object());
971 	}
972 
973 	// Log image
974 	{
975 		const Allocation alloc = colorBuffer->getBoundMemory();
976 		invalidateAlloc(vk, device, alloc);
977 
978 		const tcu::ConstPixelBufferAccess	resultImage		(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, alloc.getHostPtr());
979 		const tcu::TextureLevel				referenceImage	= generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, cells, colors);
980 
981 		// Images should now match.
982 		if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), "color", "Image compare", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
983 			TCU_FAIL("Rendered image is not correct");
984 	}
985 
986 	return tcu::TestStatus::pass("OK");
987 }
988 
testVertexShader(Context & context,const TestParams testParams)989 tcu::TestStatus testVertexShader (Context& context, const TestParams testParams)
990 {
991 	return testVertexFragmentShader(context, testParams, Renderer::VERTEX);
992 }
993 
testFragmentShader(Context & context,const TestParams testParams)994 tcu::TestStatus testFragmentShader (Context& context, const TestParams testParams)
995 {
996 	return testVertexFragmentShader(context, testParams, Renderer::FRAGMENT);
997 }
998 
testTessellationShader(Context & context,const TestParams testParams)999 tcu::TestStatus testTessellationShader (Context& context, const TestParams testParams)
1000 {
1001 	const DeviceInterface&			vk					= context.getDeviceInterface();
1002 	const VkDevice					device				= context.getDevice();
1003 	Allocator&						allocator			= context.getDefaultAllocator();
1004 
1005 	const UVec2						renderSize			(128, 128);
1006 	const VkFormat					colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
1007 	const Vec4						clearColor			(0.5f, 0.5f, 0.5f, 1.0f);
1008 	const std::vector<Vec4>			colors				= generateColors(testParams.numViewports);
1009 	const std::vector<UVec4>		cells				= generateGrid(testParams.numViewports, renderSize);
1010 
1011 	const VkDeviceSize				colorBufferSize		= renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
1012 
1013 	const SharedPtr<Buffer>			colorBuffer			= Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
1014 
1015 	// Zero buffer.
1016 	{
1017 		const Allocation alloc = colorBuffer->getBoundMemory();
1018 		deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
1019 		flushAlloc(vk, device, alloc);
1020 	}
1021 
1022 	{
1023 		context.getTestContext().getLog()
1024 			<< tcu::TestLog::Message << "Rendering a colorful grid of " << testParams.numViewports << " rectangle(s)." << tcu::TestLog::EndMessage
1025 			<< tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
1026 	}
1027 
1028 	// Draw
1029 	{
1030 		Renderer renderer (context, renderSize, testParams, cells, colorFormat, clearColor, colors, Renderer::TESSELLATION);
1031 		renderer.draw(context, colorBuffer->object());
1032 	}
1033 
1034 	// Log image
1035 	{
1036 		const Allocation alloc = colorBuffer->getBoundMemory();
1037 		invalidateAlloc(vk, device, alloc);
1038 
1039 		const tcu::ConstPixelBufferAccess	resultImage		(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, alloc.getHostPtr());
1040 		const tcu::TextureLevel				referenceImage	= generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, cells, colors);
1041 
1042 		// Images should now match.
1043 		if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), "color", "Image compare", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
1044 			TCU_FAIL("Rendered image is not correct");
1045 	}
1046 
1047 	return tcu::TestStatus::pass("OK");
1048 }
1049 
checkSupport(Context & context,TestParams params)1050 void checkSupport (Context& context, TestParams params)
1051 {
1052 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
1053 	context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
1054 
1055 	if (context.getDeviceProperties().limits.maxViewports < MIN_MAX_VIEWPORTS)
1056 		TCU_FAIL("multiViewport supported but maxViewports is less than the minimum required");
1057 
1058 	if (params.useTessellationShader)
1059 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
1060 
1061 	if (params.groupParams->useDynamicRendering)
1062 		context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
1063 }
1064 
1065 } // anonymous
1066 
createShaderViewportIndexTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)1067 tcu::TestCaseGroup* createShaderViewportIndexTests	(tcu::TestContext& testCtx, const SharedGroupParams groupParams)
1068 {
1069 	MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_viewport_index", ""));
1070 
1071 	TestParams testParams
1072 	{
1073 		1,						// int					numViewports;
1074 		false,					// bool					writeFromVertex;
1075 		groupParams,			// SharedGroupParams	groupParams;
1076 		false					// bool					useTessellationShader;
1077 	};
1078 
1079 	for (testParams.numViewports = 1; testParams.numViewports <= MIN_MAX_VIEWPORTS; ++testParams.numViewports)
1080 		addFunctionCaseWithPrograms(group.get(), "vertex_shader_" + de::toString(testParams.numViewports), "", checkSupport, initVertexTestPrograms, testVertexShader, testParams);
1081 
1082 	testParams.numViewports = 1;
1083 	addFunctionCaseWithPrograms(group.get(), "fragment_shader_implicit", "", checkSupport, initFragmentTestPrograms, testFragmentShader, testParams);
1084 	testParams.writeFromVertex = true;
1085 	for (testParams.numViewports = 1; testParams.numViewports <= MIN_MAX_VIEWPORTS; ++testParams.numViewports)
1086 		addFunctionCaseWithPrograms(group.get(), "fragment_shader_" + de::toString(testParams.numViewports), "", checkSupport, initFragmentTestPrograms, testFragmentShader, testParams);
1087 	testParams.writeFromVertex = false;
1088 
1089 	testParams.useTessellationShader = true;
1090 	for (testParams.numViewports = 1; testParams.numViewports <= MIN_MAX_VIEWPORTS; ++testParams.numViewports)
1091 		addFunctionCaseWithPrograms(group.get(), "tessellation_shader_" + de::toString(testParams.numViewports), "", checkSupport, initTessellationTestPrograms, testTessellationShader, testParams);
1092 
1093 	return group.release();
1094 }
1095 
1096 } // Draw
1097 } // vkt
1098