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