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