• 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 		programCollection.glslSources.add("vert_1_2") << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true);
390 
391 	}
392 
393 	// Fragment shader
394 	{
395 		std::ostringstream src;
396 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
397 			<< "\n"
398 			<< "layout(location = 0) in  vec4 in_color;\n"
399 			<< "layout(location = 0) out vec4 out_color;\n"
400 			<< "\n"
401 			<< "void main(void)\n"
402 			<< "{\n"
403 			<< "    out_color = in_color;\n"
404 			<< "}\n";
405 
406 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
407 	}
408 }
409 
initTessellationTestPrograms(SourceCollections & programCollection,const TestParams params)410 void initTessellationTestPrograms (SourceCollections& programCollection, const TestParams params)
411 {
412 	DE_UNREF(params.numLayers);
413 
414 	// Vertex shader
415 	{
416 		std::ostringstream src;
417 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
418 			<< "\n"
419 			<< "layout(location = 0) in  vec4 in_position;\n"
420 			<< "layout(location = 1) in  vec4 in_color;\n"
421 			<< "layout(location = 0) out vec4 out_color;\n"
422 			<< "\n"
423 			<< "void main(void)\n"
424 			<< "{\n"
425 			<< "    gl_Position = in_position;\n"
426 			<< "    out_color = in_color;\n"
427 			<< "}\n";
428 
429 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
430 		programCollection.glslSources.add("vert_1_2") << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true);
431 	}
432 
433 	// Tessellation control shader
434 	{
435 		std::ostringstream src;
436 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
437 			<< "\n"
438 			<< "layout(vertices = 3) out;\n"
439 			<< "\n"
440 			<< "layout(location = 0) in  vec4 in_color[];\n"
441 			<< "layout(location = 0) out vec4 out_color[];\n"
442 			<< "\n"
443 			<< "void main(void)\n"
444 			<< "{\n"
445 			<< "    if (gl_InvocationID == 0) {\n"
446 			<< "        gl_TessLevelInner[0] = 1.0;\n"
447 			<< "        gl_TessLevelInner[1] = 1.0;\n"
448 			<< "        gl_TessLevelOuter[0] = 1.0;\n"
449 			<< "        gl_TessLevelOuter[1] = 1.0;\n"
450 			<< "        gl_TessLevelOuter[2] = 1.0;\n"
451 			<< "        gl_TessLevelOuter[3] = 1.0;\n"
452 			<< "    }\n"
453 			<< "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
454 			<< "    out_color[gl_InvocationID] = in_color[gl_InvocationID];\n"
455 			<< "}\n";
456 
457 		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
458 	}
459 
460 	// Tessellation evaluation shader
461 	{
462 		std::ostringstream src;
463 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
464 			<< "#extension GL_ARB_shader_viewport_layer_array : require\n"
465 			<< "\n"
466 			<< "layout(triangles, equal_spacing, cw) in;\n"
467 			<< "\n"
468 			<< "layout(location = 0) in  vec4 in_color[];\n"
469 			<< "layout(location = 0) out vec4 out_color;\n"
470 			<< "\n"
471 			<< "void main(void)\n"
472 			<< "{\n"
473 			<< "    gl_Layer = gl_PrimitiveID / 2;\n"
474 			<< "    gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n"
475 			<< "                  gl_in[1].gl_Position * gl_TessCoord.y +\n"
476 			<< "                  gl_in[2].gl_Position * gl_TessCoord.z;\n"
477 			<< "\n"
478 			<< "    out_color = in_color[0] * gl_TessCoord.x +\n"
479 			<< "                in_color[1] * gl_TessCoord.y +\n"
480 			<< "                in_color[2] * gl_TessCoord.z;\n"
481 			<< "}\n";
482 
483 		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
484 		programCollection.glslSources.add("tese_1_2") << glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true);
485 	}
486 
487 	// Fragment shader
488 	{
489 		std::ostringstream src;
490 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
491 			<< "\n"
492 			<< "layout(location = 0) in  vec4 in_color;\n"
493 			<< "layout(location = 0) out vec4 out_color;\n"
494 			<< "\n"
495 			<< "void main(void)\n"
496 			<< "{\n"
497 			<< "    out_color = in_color;\n"
498 			<< "}\n";
499 
500 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
501 	}
502 }
503 
generateGrid(const int numCells,const UVec2 & renderSize)504 std::vector<UVec4> generateGrid (const int numCells, const UVec2& renderSize)
505 {
506 	const int numCols		= deCeilFloatToInt32(deFloatSqrt(static_cast<float>(numCells)));
507 	const int numRows		= deCeilFloatToInt32(static_cast<float>(numCells) / static_cast<float>(numCols));
508 	const int rectWidth		= renderSize.x() / numCols;
509 	const int rectHeight	= renderSize.y() / numRows;
510 
511 	std::vector<UVec4> cells;
512 	cells.reserve(numCells);
513 
514 	int x = 0;
515 	int y = 0;
516 
517 	for (int cellNdx = 0; cellNdx < numCells; ++cellNdx)
518 	{
519 		const bool nextRow = (cellNdx != 0) && (cellNdx % numCols == 0);
520 		if (nextRow)
521 		{
522 			x  = 0;
523 			y += rectHeight;
524 		}
525 
526 		cells.push_back(UVec4(x, y, rectWidth, rectHeight));
527 
528 		x += rectWidth;
529 	}
530 
531 	return cells;
532 }
533 
generateColors(int numColors)534 std::vector<Vec4> generateColors (int numColors)
535 {
536 	const Vec4 colors[] =
537 	{
538 		Vec4(0.18f, 0.42f, 0.17f, 1.0f),
539 		Vec4(0.29f, 0.62f, 0.28f, 1.0f),
540 		Vec4(0.59f, 0.84f, 0.44f, 1.0f),
541 		Vec4(0.96f, 0.95f, 0.72f, 1.0f),
542 		Vec4(0.94f, 0.55f, 0.39f, 1.0f),
543 		Vec4(0.82f, 0.19f, 0.12f, 1.0f),
544 		Vec4(0.46f, 0.15f, 0.26f, 1.0f),
545 		Vec4(0.24f, 0.14f, 0.24f, 1.0f),
546 		Vec4(0.49f, 0.31f, 0.26f, 1.0f),
547 		Vec4(0.78f, 0.52f, 0.33f, 1.0f),
548 		Vec4(0.94f, 0.82f, 0.31f, 1.0f),
549 		Vec4(0.98f, 0.65f, 0.30f, 1.0f),
550 		Vec4(0.22f, 0.65f, 0.53f, 1.0f),
551 		Vec4(0.67f, 0.81f, 0.91f, 1.0f),
552 		Vec4(0.43f, 0.44f, 0.75f, 1.0f),
553 		Vec4(0.26f, 0.24f, 0.48f, 1.0f),
554 	};
555 
556 	std::vector<Vec4> result;
557 	result.reserve(numColors);
558 
559 	for (int i = 0; i < numColors; ++i)
560 	{
561 		result.push_back(colors[i % DE_LENGTH_OF_ARRAY(colors)]);
562 	}
563 
564 	return result;
565 }
566 
generateVertices(const std::vector<UVec4> & grid,const std::vector<Vec4> & colors,const UVec2 & renderSize)567 std::vector<PositionColorVertex> generateVertices (const std::vector<UVec4>& grid, const std::vector<Vec4>& colors, const UVec2& renderSize)
568 {
569 	DE_ASSERT(colors.size() == grid.size());
570 
571 	// Two triangles for each cell. Each cell correspond to a layer.
572 	std::size_t total = grid.size() * 6;
573 
574 	std::vector<PositionColorVertex> result;
575 	result.reserve(total);
576 
577 	for (std::size_t i = 0; i < total; ++i)
578 	{
579 		Vec4 pos;
580 		pos.z() = 0.0;
581 		pos.w() = 1.0;
582 
583 		Vec4 cell = grid[i/6].asFloat() * 2.0f;
584 		float x			= cell.x() / float(renderSize.x()) - 1.0f;
585 		float y			= cell.y() / float(renderSize.y()) - 1.0f;
586 		float width		= cell.z() / float(renderSize.x());
587 		float height	= cell.w() / float(renderSize.y());
588 
589 		switch (i % 6)
590 		{
591 		case 0: pos.xy() = Vec2(x,			y + height);	break;
592 		case 1: pos.xy() = Vec2(x + width,	y + height);	break;
593 		case 2: pos.xy() = Vec2(x,			y);				break;
594 		case 3: pos.xy() = Vec2(x + width,	y);				break;
595 		case 4: pos.xy() = Vec2(x + width,	y + height);	break;
596 		case 5: pos.xy() = Vec2(x,			y);				break;
597 		}
598 
599 		result.push_back(PositionColorVertex(pos, colors[i/6]));
600 	}
601 
602 	return result;
603 }
604 
605 // Renderer generates two triangles per layer, each pair using a different
606 // color and a different position.
607 class Renderer
608 {
609 public:
610 	enum Shader
611 	{
612 		VERTEX,
613 		TESSELLATION,
614 	};
615 
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)616 	Renderer (Context&									context,
617 			  const SharedGroupParams					groupParams,
618 			  const UVec2&								renderSize,
619 			  const int									numLayers,
620 			  const VkFormat							colorFormat,
621 			  const Vec4&								clearColor,
622 			  const std::vector<PositionColorVertex>&	vertices,
623 			  const Shader								shader)
624 		: m_groupParams				(groupParams)
625 		, m_renderSize				(renderSize)
626 		, m_colorFormat				(colorFormat)
627 		, m_colorSubresourceRange	(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers))
628 		, m_clearColor				(clearColor)
629 		, m_numLayers				(numLayers)
630 		, m_vertices				(vertices)
631 	{
632 		const DeviceInterface&		vk					= context.getDeviceInterface();
633 		const VkDevice				device				= context.getDevice();
634 		const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
635 		Allocator&					allocator			= context.getDefaultAllocator();
636 		const VkDeviceSize			vertexBufferSize	= sizeInBytes(m_vertices);
637 
638 		m_colorImage		= makeImage					(vk, device, makeImageCreateInfo(m_colorFormat, m_renderSize, m_numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
639 		m_colorImageAlloc	= bindImage					(vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
640 		m_colorAttachment	= makeImageView				(vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D_ARRAY, m_colorFormat, m_colorSubresourceRange);
641 
642 		m_vertexBuffer		= Buffer::createAndAlloc	(vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), allocator, MemoryRequirement::HostVisible);
643 
644 		deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &m_vertices[0], static_cast<std::size_t>(vertexBufferSize));
645 		flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
646 
647 		if (shader == TESSELLATION)
648 		{
649 			m_tessellationControlModule		= createShaderModule	(vk, device, context.getBinaryCollection().get("tesc"), 0u);
650 			if (context.contextSupports(VK_API_VERSION_1_2))
651 				m_tessellationEvaluationModule	= createShaderModule	(vk, device, context.getBinaryCollection().get("tese_1_2"), 0u);
652 			else
653 				m_tessellationEvaluationModule = createShaderModule(vk, device, context.getBinaryCollection().get("tese"), 0u);
654 		}
655 
656 		if (context.contextSupports(VK_API_VERSION_1_2))
657 			m_vertexModule = createShaderModule(vk, device, context.getBinaryCollection().get("vert_1_2"), 0u);
658 		else
659 			m_vertexModule = createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u);
660 
661 		m_fragmentModule	= createShaderModule	(vk, device, context.getBinaryCollection().get("frag"), 0u);
662 
663 		if (!m_groupParams->useDynamicRendering)
664 		{
665 			m_renderPass	= makeRenderPass		(vk, device, m_colorFormat);
666 
667 			m_framebuffer	= makeFramebuffer		(vk, device, *m_renderPass, m_colorAttachment.get(),
668 													 static_cast<deUint32>(m_renderSize.x()),
669 													 static_cast<deUint32>(m_renderSize.y()),
670 													 numLayers);
671 		}
672 
673 		m_pipelineLayout	= makePipelineLayout	(vk, device);
674 		m_pipeline			= makeGraphicsPipeline	(vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_tessellationControlModule,
675 													 *m_tessellationEvaluationModule, *m_fragmentModule, m_renderSize);
676 		m_cmdPool			= createCommandPool		(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
677 		m_cmdBuffer			= allocateCommandBuffer	(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
678 		m_secCmdBuffer		= allocateCommandBuffer	(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
679 	}
680 
draw(Context & context,const VkBuffer colorBuffer) const681 	void draw (Context& context, const VkBuffer colorBuffer) const
682 	{
683 		const DeviceInterface&	vk			= context.getDeviceInterface();
684 		const VkDevice			device		= context.getDevice();
685 		const VkQueue			queue		= context.getUniversalQueue();
686 		const VkClearValue		clearValue	= makeClearValueColor(m_clearColor);
687 		const VkRect2D			renderArea
688 		{
689 			makeOffset2D(0, 0),
690 			makeExtent2D(m_renderSize.x(), m_renderSize.y()),
691 		};
692 
693 #ifndef CTS_USES_VULKANSC
694 		if (m_groupParams->useSecondaryCmdBuffer)
695 		{
696 			// record secondary command buffer
697 			if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
698 			{
699 				beginSecondaryCmdBuffer(context, *m_secCmdBuffer, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
700 				beginRendering(vk, *m_secCmdBuffer, *m_colorAttachment, renderArea, clearValue,
701 							   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR, 0u, m_numLayers);
702 			}
703 			else
704 				beginSecondaryCmdBuffer(context, *m_secCmdBuffer);
705 
706 			drawCommands(context, *m_secCmdBuffer);
707 
708 			if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
709 				endRendering(vk, *m_secCmdBuffer);
710 
711 			endCommandBuffer(vk, *m_secCmdBuffer);
712 
713 			// record primary command buffer
714 			beginCommandBuffer(vk, *m_cmdBuffer, 0u);
715 
716 			preRenderCommands(context, *m_cmdBuffer);
717 
718 			if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
719 				beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, clearValue, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
720 							   VK_ATTACHMENT_LOAD_OP_CLEAR, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT, m_numLayers);
721 
722 			vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
723 
724 			if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
725 				endRendering(vk, *m_cmdBuffer);
726 
727 			postRenderCommands(context, colorBuffer);
728 			endCommandBuffer(vk, *m_cmdBuffer);
729 		}
730 		else if (m_groupParams->useDynamicRendering)
731 		{
732 			beginCommandBuffer(vk, *m_cmdBuffer);
733 
734 			preRenderCommands(context, *m_cmdBuffer);
735 			beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, clearValue,
736 						   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR, 0u, m_numLayers);
737 			drawCommands(context, *m_cmdBuffer);
738 			endRendering(vk, *m_cmdBuffer);
739 			postRenderCommands(context, colorBuffer);
740 
741 			endCommandBuffer(vk, *m_cmdBuffer);
742 		}
743 #endif // CTS_USES_VULKANSC
744 
745 		if (!m_groupParams->useDynamicRendering)
746 		{
747 			beginCommandBuffer(vk, *m_cmdBuffer);
748 
749 			preRenderCommands(context, *m_cmdBuffer);
750 			beginRenderPass(context, *m_cmdBuffer, renderArea, clearValue);
751 			drawCommands(context, *m_cmdBuffer);
752 			vk.cmdEndRenderPass(*m_cmdBuffer);
753 			postRenderCommands(context, colorBuffer);
754 
755 			endCommandBuffer(vk, *m_cmdBuffer);
756 		}
757 
758 		submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
759 	}
760 
761 protected:
762 
preRenderCommands(Context & context,VkCommandBuffer cmdBuffer) const763 	void preRenderCommands(Context& context, VkCommandBuffer cmdBuffer) const
764 	{
765 		if (m_groupParams->useDynamicRendering)
766 		{
767 			const DeviceInterface& vk = context.getDeviceInterface();
768 			initialTransitionColor2DImage(vk, cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
769 										  VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, m_colorSubresourceRange.layerCount);
770 		}
771 	}
772 
postRenderCommands(Context & context,VkBuffer colorBuffer) const773 	void postRenderCommands(Context& context, VkBuffer colorBuffer) const
774 	{
775 		const DeviceInterface& vk = context.getDeviceInterface();
776 		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);
777 	}
778 
beginRenderPass(Context & context,VkCommandBuffer cmdBuffer,const VkRect2D & renderArea,const VkClearValue & clearValue) const779 	void beginRenderPass(Context& context, VkCommandBuffer cmdBuffer, const VkRect2D& renderArea, const VkClearValue& clearValue) const
780 	{
781 		const DeviceInterface& vk = context.getDeviceInterface();
782 		const VkRenderPassBeginInfo renderPassBeginInfo
783 		{
784 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,		// VkStructureType			sType;
785 			DE_NULL,										// const void*				pNext;
786 			*m_renderPass,									// VkRenderPass				renderPass;
787 			*m_framebuffer,									// VkFramebuffer			framebuffer;
788 			renderArea,										// VkRect2D					renderArea;
789 			1u,												// uint32_t					clearValueCount;
790 			&clearValue,									// const VkClearValue*		pClearValues;
791 		};
792 		vk.cmdBeginRenderPass(cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
793 	}
794 
drawCommands(Context & context,VkCommandBuffer cmdBuffer) const795 	void drawCommands (Context& context, VkCommandBuffer cmdBuffer) const
796 	{
797 		const DeviceInterface&	vk					= context.getDeviceInterface();
798 		const VkBuffer			vertexBuffer		= m_vertexBuffer->object();
799 		const VkDeviceSize		vertexBufferOffset	= 0ull;
800 
801 		vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
802 		vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
803 		vk.cmdDraw(cmdBuffer, static_cast<deUint32>(m_numLayers * 6), 1u, 0u, 0u);	// two triangles per layer
804 	}
805 
806 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(Context & context,VkCommandBuffer cmdBuffer,VkRenderingFlagsKHR renderingFlags=0u) const807 	void beginSecondaryCmdBuffer(Context& context, VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags = 0u) const
808 	{
809 		VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
810 		{
811 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,		// VkStructureType					sType;
812 			DE_NULL,																// const void*						pNext;
813 			renderingFlags,															// VkRenderingFlagsKHR				flags;
814 			0u,																		// uint32_t							viewMask;
815 			1u,																		// uint32_t							colorAttachmentCount;
816 			&m_colorFormat,															// const VkFormat*					pColorAttachmentFormats;
817 			VK_FORMAT_UNDEFINED,													// VkFormat							depthAttachmentFormat;
818 			VK_FORMAT_UNDEFINED,													// VkFormat							stencilAttachmentFormat;
819 			VK_SAMPLE_COUNT_1_BIT,													// VkSampleCountFlagBits			rasterizationSamples;
820 		};
821 		const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
822 
823 		VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
824 		if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
825 			usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
826 
827 		const VkCommandBufferBeginInfo commandBufBeginParams
828 		{
829 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,							// VkStructureType					sType;
830 			DE_NULL,																// const void*						pNext;
831 			usageFlags,																// VkCommandBufferUsageFlags		flags;
832 			&bufferInheritanceInfo
833 		};
834 
835 		const DeviceInterface& vk = context.getDeviceInterface();
836 		VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
837 	}
838 #endif // CTS_USES_VULKANSC
839 
840 private:
841 	const SharedGroupParams					m_groupParams;
842 	const UVec2								m_renderSize;
843 	const VkFormat							m_colorFormat;
844 	const VkImageSubresourceRange			m_colorSubresourceRange;
845 	const Vec4								m_clearColor;
846 	const int								m_numLayers;
847 	const std::vector<PositionColorVertex>	m_vertices;
848 
849 	Move<VkImage>							m_colorImage;
850 	MovePtr<Allocation>						m_colorImageAlloc;
851 	Move<VkImageView>						m_colorAttachment;
852 	SharedPtr<Buffer>						m_vertexBuffer;
853 	Move<VkShaderModule>					m_vertexModule;
854 	Move<VkShaderModule>					m_tessellationControlModule;
855 	Move<VkShaderModule>					m_tessellationEvaluationModule;
856 	Move<VkShaderModule>					m_fragmentModule;
857 	Move<VkRenderPass>						m_renderPass;
858 	Move<VkFramebuffer>						m_framebuffer;
859 	Move<VkPipelineLayout>					m_pipelineLayout;
860 	Move<VkPipeline>						m_pipeline;
861 	Move<VkCommandPool>						m_cmdPool;
862 	Move<VkCommandBuffer>					m_cmdBuffer;
863 	Move<VkCommandBuffer>					m_secCmdBuffer;
864 
865 	// "deleted"
866 				Renderer	(const Renderer&);
867 	Renderer&	operator=	(const Renderer&);
868 };
869 
checkRequirements(Context & context,const TestParams params)870 void checkRequirements (Context& context, const TestParams params)
871 {
872 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
873 	context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
874 
875 	if (params.groupParams->useDynamicRendering)
876 		context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
877 
878 	const VkPhysicalDeviceLimits	limits	= context.getDeviceProperties().limits;
879 
880 	if (limits.maxFramebufferLayers < MIN_MAX_FRAMEBUFFER_LAYERS)
881 		TCU_FAIL("maxFramebuffersLayers is less than the minimum required");
882 
883 	if (limits.maxViewports < MIN_MAX_VIEWPORTS)
884 		TCU_FAIL("multiViewport supported but maxViewports is less than the minimum required");
885 }
886 
testVertexShader(Context & context,const TestParams params)887 tcu::TestStatus testVertexShader (Context& context, const TestParams params)
888 {
889 	const DeviceInterface&					vk					= context.getDeviceInterface();
890 	const VkDevice							device				= context.getDevice();
891 	Allocator&								allocator			= context.getDefaultAllocator();
892 
893 	const UVec2								renderSize			(256, 256);
894 	const VkFormat							colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
895 	const Vec4								clearColor			(0.5f, 0.5f, 0.5f, 1.0f);
896 	const std::vector<UVec4>				grid				= generateGrid(params.numLayers, renderSize);
897 	const std::vector<Vec4>					colors				= generateColors(params.numLayers);
898 	const std::vector<PositionColorVertex>	vertices			= generateVertices(grid, colors, renderSize);
899 
900 	const VkDeviceSize						colorBufferSize		= renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)) * params.numLayers;
901 
902 	const SharedPtr<Buffer>					colorBuffer			= Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
903 
904 	// Zero buffer.
905 	{
906 		const Allocation alloc = colorBuffer->getBoundMemory();
907 		deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
908 		flushAlloc(vk, device, alloc);
909 	}
910 
911 	{
912 		context.getTestContext().getLog()
913 			<< tcu::TestLog::Message << "Rendering a rectangle in each of the " << params.numLayers << " layer(s)." << tcu::TestLog::EndMessage
914 			<< tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
915 	}
916 
917 	// Draw.
918 	{
919 		const Renderer renderer (context, params.groupParams, renderSize, params.numLayers, colorFormat, clearColor, vertices, Renderer::VERTEX);
920 		renderer.draw(context, colorBuffer->object());
921 	}
922 
923 	// Verify layers.
924 	{
925 		const Allocation alloc = colorBuffer->getBoundMemory();
926 		invalidateAlloc(vk, device, alloc);
927 
928 		deUint8* resultMem = reinterpret_cast<deUint8*>(alloc.getHostPtr());
929 		for (int i = 0; i < params.numLayers; i++)
930 		{
931 			const tcu::ConstPixelBufferAccess	resultImage		(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, resultMem + ((colorBufferSize / params.numLayers) * i));
932 			const tcu::TextureLevel				referenceImage	= generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, grid[i], colors[i]);
933 			std::string imageSetName = "layer_" + de::toString(i);
934 			std::string imageSetDesc = "Image compare for layer " + de::toString(i);
935 			if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), imageSetName.c_str(), imageSetDesc.c_str(), referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
936 				TCU_FAIL("Rendered image is not correct");
937 		}
938 	}
939 
940 	return tcu::TestStatus::pass("OK");
941 }
942 
testTessellationShader(Context & context,const TestParams params)943 tcu::TestStatus testTessellationShader (Context& context, const TestParams params)
944 {
945 	const VkPhysicalDeviceFeatures&			features			= context.getDeviceFeatures();
946 	if (!features.tessellationShader)
947 		TCU_THROW(NotSupportedError, "Required feature is not supported: tessellationShader");
948 
949 	const DeviceInterface&					vk					= context.getDeviceInterface();
950 	const VkDevice							device				= context.getDevice();
951 	Allocator&								allocator			= context.getDefaultAllocator();
952 
953 	const UVec2								renderSize			(256, 256);
954 	const VkFormat							colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
955 	const Vec4								clearColor			(0.5f, 0.5f, 0.5f, 1.0f);
956 	const std::vector<UVec4>				grid				= generateGrid(params.numLayers, renderSize);
957 	const std::vector<Vec4>					colors				= generateColors(params.numLayers);
958 	const std::vector<PositionColorVertex>	vertices			= generateVertices(grid, colors, renderSize);
959 
960 	const VkDeviceSize						colorBufferSize		= renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)) * params.numLayers;
961 
962 	const SharedPtr<Buffer>					colorBuffer			= Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
963 
964 	// Zero buffer.
965 	{
966 		const Allocation alloc = colorBuffer->getBoundMemory();
967 		deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
968 		flushAlloc(vk, device, alloc);
969 	}
970 
971 	{
972 		context.getTestContext().getLog()
973 			<< tcu::TestLog::Message << "Rendering a rectangle in each of the " << params.numLayers << " layer(s)." << tcu::TestLog::EndMessage
974 			<< tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
975 	}
976 
977 	// Draw.
978 	{
979 		const Renderer renderer (context, params.groupParams, renderSize, params.numLayers, colorFormat, clearColor, vertices, Renderer::TESSELLATION);
980 		renderer.draw(context, colorBuffer->object());
981 	}
982 
983 	// Verify layers.
984 	{
985 		const Allocation alloc = colorBuffer->getBoundMemory();
986 		invalidateAlloc(vk, device, alloc);
987 
988 		deUint8* resultMem = reinterpret_cast<deUint8*>(alloc.getHostPtr());
989 		for (int i = 0; i < params.numLayers; i++) {
990 			const tcu::ConstPixelBufferAccess	resultImage		(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, resultMem + ((colorBufferSize / params.numLayers) * i));
991 			const tcu::TextureLevel				referenceImage	= generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, grid[i], colors[i]);
992 			std::string imageSetName = "layer_" + de::toString(i);
993 			std::string imageSetDesc = "Image compare for layer " + de::toString(i);
994 			if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), imageSetName.c_str(), imageSetDesc.c_str(), referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
995 				TCU_FAIL("Rendered image is not correct");
996 		}
997 	}
998 
999 	return tcu::TestStatus::pass("OK");
1000 }
1001 
1002 } // anonymous
1003 
createShaderLayerTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)1004 tcu::TestCaseGroup* createShaderLayerTests	(tcu::TestContext& testCtx, const SharedGroupParams groupParams)
1005 {
1006 	MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_layer", ""));
1007 
1008 	int numLayersToTest[] =
1009 	{
1010 		1,
1011 		2,
1012 		3,
1013 		4,
1014 		5,
1015 		6,
1016 		7,
1017 		8,
1018 		MIN_MAX_FRAMEBUFFER_LAYERS,
1019 	};
1020 
1021 	TestParams parmas
1022 	{
1023 		1,
1024 		groupParams
1025 	};
1026 
1027 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(numLayersToTest); ++i)
1028 	{
1029 		// reduce number of tests for dynamic rendering cases where secondary command buffer is used
1030 		if (groupParams->useSecondaryCmdBuffer && (i % 2))
1031 			continue;
1032 
1033 		parmas.numLayers = numLayersToTest[i];
1034 		addFunctionCaseWithPrograms<TestParams>(group.get(), "vertex_shader_" + de::toString(parmas.numLayers), "", checkRequirements, initVertexTestPrograms, testVertexShader, parmas);
1035 	}
1036 
1037 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(numLayersToTest); ++i)
1038 	{
1039 		// reduce number of tests for dynamic rendering cases where secondary command buffer is used
1040 		if (groupParams->useSecondaryCmdBuffer && (i % 2))
1041 			continue;
1042 
1043 		parmas.numLayers = numLayersToTest[i];
1044 		addFunctionCaseWithPrograms<TestParams>(group.get(), "tessellation_shader_" + de::toString(parmas.numLayers), "", checkRequirements, initTessellationTestPrograms, testTessellationShader, parmas);
1045 	}
1046 
1047 	return group.release();
1048 }
1049 
1050 } // Draw
1051 } // vkt
1052