• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2014 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 Geometry shader layered rendering tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktGeometryLayeredRenderingTests.hpp"
26 #include "vktTestCase.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktGeometryTestsUtil.hpp"
29 
30 #include "vkPrograms.hpp"
31 #include "vkStrUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkImageUtil.hpp"
37 
38 #include "deStringUtil.hpp"
39 #include "deUniquePtr.hpp"
40 
41 #include "tcuTextureUtil.hpp"
42 #include "tcuVectorUtil.hpp"
43 
44 namespace vkt
45 {
46 namespace geometry
47 {
48 namespace
49 {
50 using namespace vk;
51 using de::MovePtr;
52 using de::UniquePtr;
53 using tcu::Vec4;
54 using tcu::IVec3;
55 
56 enum TestType
57 {
58 	TEST_TYPE_DEFAULT_LAYER,					// !< draw to default layer
59 	TEST_TYPE_SINGLE_LAYER,						// !< draw to single layer
60 	TEST_TYPE_ALL_LAYERS,						// !< draw all layers
61 	TEST_TYPE_DIFFERENT_CONTENT,				// !< draw different content to different layers
62 	TEST_TYPE_LAYER_ID,							// !< draw to all layers, verify gl_Layer fragment input
63 	TEST_TYPE_INVOCATION_PER_LAYER,				// !< draw to all layers, one invocation per layer
64 	TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION,	// !< draw to all layers, multiple invocations write to multiple layers
65 };
66 
67 struct ImageParams
68 {
69 	VkImageViewType		viewType;
70 	VkExtent3D			size;
71 	deUint32			numLayers;
72 };
73 
74 struct TestParams
75 {
76 	TestType			testType;
77 	ImageParams			image;
78 };
79 
80 static const float s_colors[][4] =
81 {
82 	{ 1.0f, 1.0f, 1.0f, 1.0f },		// white
83 	{ 1.0f, 0.0f, 0.0f, 1.0f },		// red
84 	{ 0.0f, 1.0f, 0.0f, 1.0f },		// green
85 	{ 0.0f, 0.0f, 1.0f, 1.0f },		// blue
86 	{ 1.0f, 1.0f, 0.0f, 1.0f },		// yellow
87 	{ 1.0f, 0.0f, 1.0f, 1.0f },		// magenta
88 };
89 
getTargetLayer(const ImageParams & imageParams)90 deUint32 getTargetLayer (const ImageParams& imageParams)
91 {
92 	if (imageParams.viewType == VK_IMAGE_VIEW_TYPE_3D)
93 		return imageParams.size.depth / 2;
94 	else
95 		return imageParams.numLayers / 2;
96 }
97 
getShortImageViewTypeName(const VkImageViewType imageViewType)98 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
99 {
100 	std::string s(getImageViewTypeName(imageViewType));
101 	return de::toLower(s.substr(19));
102 }
103 
getImageType(const VkImageViewType viewType)104 VkImageType getImageType (const VkImageViewType viewType)
105 {
106 	switch (viewType)
107 	{
108 		case VK_IMAGE_VIEW_TYPE_1D:
109 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
110 			return VK_IMAGE_TYPE_1D;
111 
112 		case VK_IMAGE_VIEW_TYPE_2D:
113 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
114 		case VK_IMAGE_VIEW_TYPE_CUBE:
115 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
116 			return VK_IMAGE_TYPE_2D;
117 
118 		case VK_IMAGE_VIEW_TYPE_3D:
119 			return VK_IMAGE_TYPE_3D;
120 
121 		default:
122 			DE_ASSERT(0);
123 			return VK_IMAGE_TYPE_LAST;
124 	}
125 }
126 
isCubeImageViewType(const VkImageViewType viewType)127 inline bool isCubeImageViewType (const VkImageViewType viewType)
128 {
129 	return viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
130 }
131 
makeImageCreateInfo(const VkImageCreateFlags flags,const VkImageType type,const VkFormat format,const VkExtent3D size,const deUint32 numLayers,const VkImageUsageFlags usage)132 VkImageCreateInfo makeImageCreateInfo (const VkImageCreateFlags flags, const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const VkImageUsageFlags usage)
133 {
134 	const VkImageCreateInfo imageParams =
135 	{
136 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
137 		DE_NULL,										// const void*				pNext;
138 		flags,											// VkImageCreateFlags		flags;
139 		type,											// VkImageType				imageType;
140 		format,											// VkFormat					format;
141 		size,											// VkExtent3D				extent;
142 		1u,												// deUint32					mipLevels;
143 		numLayers,										// deUint32					arrayLayers;
144 		VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples;
145 		VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
146 		usage,											// VkImageUsageFlags		usage;
147 		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
148 		0u,												// deUint32					queueFamilyIndexCount;
149 		DE_NULL,										// const deUint32*			pQueueFamilyIndices;
150 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout;
151 	};
152 	return imageParams;
153 }
154 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat)155 Move<VkRenderPass> makeRenderPass (const DeviceInterface&	vk,
156 								   const VkDevice			device,
157 								   const VkFormat			colorFormat)
158 {
159 	const VkAttachmentDescription colorAttachmentDescription =
160 	{
161 		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
162 		colorFormat,										// VkFormat							format;
163 		VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
164 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
165 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
166 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
167 		VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
168 		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					initialLayout;
169 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
170 	};
171 
172 	const VkAttachmentReference colorAttachmentRef =
173 	{
174 		0u,													// deUint32			attachment;
175 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
176 	};
177 
178 	const VkSubpassDescription subpassDescription =
179 	{
180 		(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags		flags;
181 		VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
182 		0u,													// deUint32							inputAttachmentCount;
183 		DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
184 		1u,													// deUint32							colorAttachmentCount;
185 		&colorAttachmentRef,								// const VkAttachmentReference*		pColorAttachments;
186 		DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
187 		DE_NULL,											// const VkAttachmentReference*		pDepthStencilAttachment;
188 		0u,													// deUint32							preserveAttachmentCount;
189 		DE_NULL												// const deUint32*					pPreserveAttachments;
190 	};
191 
192 	const VkRenderPassCreateInfo renderPassInfo =
193 	{
194 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
195 		DE_NULL,											// const void*						pNext;
196 		(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
197 		1u,													// deUint32							attachmentCount;
198 		&colorAttachmentDescription,						// const VkAttachmentDescription*	pAttachments;
199 		1u,													// deUint32							subpassCount;
200 		&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
201 		0u,													// deUint32							dependencyCount;
202 		DE_NULL												// const VkSubpassDependency*		pDependencies;
203 	};
204 
205 	return createRenderPass(vk, device, &renderPassInfo);
206 }
207 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule geometryModule,const VkShaderModule fragmentModule,const VkExtent2D renderSize)208 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&		vk,
209 									   const VkDevice				device,
210 									   const VkPipelineLayout		pipelineLayout,
211 									   const VkRenderPass			renderPass,
212 									   const VkShaderModule			vertexModule,
213 									   const VkShaderModule			geometryModule,
214 									   const VkShaderModule			fragmentModule,
215 									   const VkExtent2D				renderSize)
216 {
217 	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
218 	{
219 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType                             sType;
220 		DE_NULL,														// const void*                                 pNext;
221 		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags       flags;
222 		0u,																// uint32_t                                    vertexBindingDescriptionCount;
223 		DE_NULL,														// const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
224 		0u,																// uint32_t                                    vertexAttributeDescriptionCount;
225 		DE_NULL,														// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
226 	};
227 
228 	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
229 	{
230 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType                             sType;
231 		DE_NULL,														// const void*                                 pNext;
232 		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags     flags;
233 		VK_PRIMITIVE_TOPOLOGY_POINT_LIST,								// VkPrimitiveTopology                         topology;
234 		VK_FALSE,														// VkBool32                                    primitiveRestartEnable;
235 	};
236 
237 	const VkViewport viewport = makeViewport(
238 		0.0f, 0.0f,
239 		static_cast<float>(renderSize.width), static_cast<float>(renderSize.height),
240 		0.0f, 1.0f);
241 	const VkRect2D scissor =
242 	{
243 		makeOffset2D(0, 0),
244 		makeExtent2D(renderSize.width, renderSize.height),
245 	};
246 
247 	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
248 	{
249 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType                             sType;
250 		DE_NULL,														// const void*                                 pNext;
251 		(VkPipelineViewportStateCreateFlags)0,							// VkPipelineViewportStateCreateFlags          flags;
252 		1u,																// uint32_t                                    viewportCount;
253 		&viewport,														// const VkViewport*                           pViewports;
254 		1u,																// uint32_t                                    scissorCount;
255 		&scissor,														// const VkRect2D*                             pScissors;
256 	};
257 
258 	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
259 	{
260 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType                          sType;
261 		DE_NULL,														// const void*                              pNext;
262 		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags  flags;
263 		VK_FALSE,														// VkBool32                                 depthClampEnable;
264 		VK_FALSE,														// VkBool32                                 rasterizerDiscardEnable;
265 		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
266 		VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
267 		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
268 		VK_FALSE,														// VkBool32									depthBiasEnable;
269 		0.0f,															// float									depthBiasConstantFactor;
270 		0.0f,															// float									depthBiasClamp;
271 		0.0f,															// float									depthBiasSlopeFactor;
272 		1.0f,															// float									lineWidth;
273 	};
274 
275 	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
276 	{
277 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
278 		DE_NULL,														// const void*								pNext;
279 		(VkPipelineMultisampleStateCreateFlags)0,						// VkPipelineMultisampleStateCreateFlags	flags;
280 		VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits					rasterizationSamples;
281 		VK_FALSE,														// VkBool32									sampleShadingEnable;
282 		0.0f,															// float									minSampleShading;
283 		DE_NULL,														// const VkSampleMask*						pSampleMask;
284 		VK_FALSE,														// VkBool32									alphaToCoverageEnable;
285 		VK_FALSE														// VkBool32									alphaToOneEnable;
286 	};
287 
288 	const VkStencilOpState stencilOpState = makeStencilOpState(
289 		VK_STENCIL_OP_KEEP,				// stencil fail
290 		VK_STENCIL_OP_KEEP,				// depth & stencil pass
291 		VK_STENCIL_OP_KEEP,				// depth only fail
292 		VK_COMPARE_OP_ALWAYS,			// compare op
293 		0u,								// compare mask
294 		0u,								// write mask
295 		0u);							// reference
296 
297 	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
298 	{
299 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,		// VkStructureType							sType;
300 		DE_NULL,														// const void*								pNext;
301 		(VkPipelineDepthStencilStateCreateFlags)0,						// VkPipelineDepthStencilStateCreateFlags	flags;
302 		VK_FALSE,														// VkBool32									depthTestEnable;
303 		VK_FALSE,														// VkBool32									depthWriteEnable;
304 		VK_COMPARE_OP_LESS,												// VkCompareOp								depthCompareOp;
305 		VK_FALSE,														// VkBool32									depthBoundsTestEnable;
306 		VK_FALSE,														// VkBool32									stencilTestEnable;
307 		stencilOpState,													// VkStencilOpState							front;
308 		stencilOpState,													// VkStencilOpState							back;
309 		0.0f,															// float									minDepthBounds;
310 		1.0f,															// float									maxDepthBounds;
311 	};
312 
313 	const VkColorComponentFlags					colorComponentsAll					= VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
314 	const VkPipelineColorBlendAttachmentState	pipelineColorBlendAttachmentState	=
315 	{
316 		VK_FALSE,						// VkBool32					blendEnable;
317 		VK_BLEND_FACTOR_ONE,			// VkBlendFactor			srcColorBlendFactor;
318 		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstColorBlendFactor;
319 		VK_BLEND_OP_ADD,				// VkBlendOp				colorBlendOp;
320 		VK_BLEND_FACTOR_ONE,			// VkBlendFactor			srcAlphaBlendFactor;
321 		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstAlphaBlendFactor;
322 		VK_BLEND_OP_ADD,				// VkBlendOp				alphaBlendOp;
323 		colorComponentsAll,				// VkColorComponentFlags	colorWriteMask;
324 	};
325 
326 	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
327 	{
328 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,		// VkStructureType								sType;
329 		DE_NULL,														// const void*									pNext;
330 		(VkPipelineColorBlendStateCreateFlags)0,						// VkPipelineColorBlendStateCreateFlags			flags;
331 		VK_FALSE,														// VkBool32										logicOpEnable;
332 		VK_LOGIC_OP_COPY,												// VkLogicOp									logicOp;
333 		1u,																// deUint32										attachmentCount;
334 		&pipelineColorBlendAttachmentState,								// const VkPipelineColorBlendAttachmentState*	pAttachments;
335 		{ 0.0f, 0.0f, 0.0f, 0.0f },										// float										blendConstants[4];
336 	};
337 
338 	const VkPipelineShaderStageCreateInfo pShaderStages[] =
339 	{
340 		{
341 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
342 			DE_NULL,													// const void*							pNext;
343 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
344 			VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStageFlagBits				stage;
345 			vertexModule,												// VkShaderModule						module;
346 			"main",														// const char*							pName;
347 			DE_NULL,													// const VkSpecializationInfo*			pSpecializationInfo;
348 		},
349 		{
350 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
351 			DE_NULL,													// const void*							pNext;
352 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
353 			VK_SHADER_STAGE_GEOMETRY_BIT,								// VkShaderStageFlagBits				stage;
354 			geometryModule,												// VkShaderModule						module;
355 			"main",														// const char*							pName;
356 			DE_NULL,													// const VkSpecializationInfo*			pSpecializationInfo;
357 		},
358 		{
359 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
360 			DE_NULL,													// const void*							pNext;
361 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
362 			VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlagBits				stage;
363 			fragmentModule,												// VkShaderModule						module;
364 			"main",														// const char*							pName;
365 			DE_NULL,													// const VkSpecializationInfo*			pSpecializationInfo;
366 		},
367 	};
368 
369 	const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
370 	{
371 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
372 		DE_NULL,											// const void*										pNext;
373 		(VkPipelineCreateFlags)0,							// VkPipelineCreateFlags							flags;
374 		DE_LENGTH_OF_ARRAY(pShaderStages),					// deUint32											stageCount;
375 		pShaderStages,										// const VkPipelineShaderStageCreateInfo*			pStages;
376 		&vertexInputStateInfo,								// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
377 		&pipelineInputAssemblyStateInfo,					// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
378 		DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
379 		&pipelineViewportStateInfo,							// const VkPipelineViewportStateCreateInfo*			pViewportState;
380 		&pipelineRasterizationStateInfo,					// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
381 		&pipelineMultisampleStateInfo,						// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
382 		&pipelineDepthStencilStateInfo,						// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
383 		&pipelineColorBlendStateInfo,						// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
384 		DE_NULL,											// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
385 		pipelineLayout,										// VkPipelineLayout									layout;
386 		renderPass,											// VkRenderPass										renderPass;
387 		0u,													// deUint32											subpass;
388 		DE_NULL,											// VkPipeline										basePipelineHandle;
389 		0,													// deInt32											basePipelineIndex;
390 	};
391 
392 	return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
393 }
394 
395 //! Convenience wrapper to access 1D, 2D, and 3D image layers/slices in a uniform way.
396 class LayeredImageAccess
397 {
398 public:
create(const VkImageType type,const VkFormat format,const VkExtent3D size,const deUint32 numLayers,const void * pData)399 	static LayeredImageAccess create (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
400 	{
401 		if (type == VK_IMAGE_TYPE_1D)
402 			return LayeredImageAccess(format, size.width, numLayers, pData);
403 		else
404 			return LayeredImageAccess(type, format, size, numLayers, pData);
405 	}
406 
getLayer(const int layer) const407 	inline tcu::ConstPixelBufferAccess getLayer (const int layer) const
408 	{
409 		return tcu::getSubregion(m_wholeImage, 0, (m_1dModifier * layer), ((~m_1dModifier & 1) * layer), m_width, m_height, 1);
410 	}
411 
getNumLayersOrSlices(void) const412 	inline int getNumLayersOrSlices (void) const
413 	{
414 		return m_layers;
415 	}
416 
417 private:
418 	// Specialized for 1D images.
LayeredImageAccess(const VkFormat format,const deUint32 width,const deUint32 numLayers,const void * pData)419 	LayeredImageAccess (const VkFormat format, const deUint32 width, const deUint32 numLayers, const void* pData)
420 		: m_width		(static_cast<int>(width))
421 		, m_height		(1)
422 		, m_1dModifier	(1)
423 		, m_layers		(numLayers)
424 		, m_wholeImage	(tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_layers, 1, pData))
425 	{
426 	}
427 
LayeredImageAccess(const VkImageType type,const VkFormat format,const VkExtent3D size,const deUint32 numLayers,const void * pData)428 	LayeredImageAccess (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
429 		: m_width		(static_cast<int>(size.width))
430 		, m_height		(static_cast<int>(size.height))
431 		, m_1dModifier	(0)
432 		, m_layers		(static_cast<int>(type == VK_IMAGE_TYPE_3D ? size.depth : numLayers))
433 		, m_wholeImage	(tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_height, m_layers, pData))
434 	{
435 	}
436 
437 	const int							m_width;
438 	const int							m_height;
439 	const int							m_1dModifier;
440 	const int							m_layers;
441 	const tcu::ConstPixelBufferAccess	m_wholeImage;
442 };
443 
compareColors(const Vec4 & colorA,const Vec4 & colorB,const Vec4 & threshold)444 inline bool compareColors (const Vec4& colorA, const Vec4& colorB, const Vec4& threshold)
445 {
446 	return tcu::allEqual(
447 				tcu::lessThan(tcu::abs(colorA - colorB), threshold),
448 				tcu::BVec4(true, true, true, true));
449 }
450 
verifyImageSingleColoredRow(tcu::TestLog & log,const tcu::ConstPixelBufferAccess image,const float rowWidthRatio,const tcu::Vec4 & barColor)451 bool verifyImageSingleColoredRow (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image, const float rowWidthRatio, const tcu::Vec4& barColor)
452 {
453 	DE_ASSERT(rowWidthRatio > 0.0f);
454 
455 	const Vec4				black				(0.0f, 0.0f, 0.0f, 1.0f);
456 	const Vec4				green				(0.0f, 1.0f, 0.0f, 1.0f);
457 	const Vec4				red					(1.0f, 0.0f, 0.0f, 1.0f);
458 	const Vec4				threshold			(0.02f);
459 	const int				barLength			= static_cast<int>(rowWidthRatio * static_cast<float>(image.getWidth()));
460 	const int				barLengthThreshold	= 1;
461 	tcu::TextureLevel		errorMask			(image.getFormat(), image.getWidth(), image.getHeight());
462 	tcu::PixelBufferAccess	errorMaskAccess		= errorMask.getAccess();
463 
464 	tcu::clear(errorMask.getAccess(), green);
465 
466 	log << tcu::TestLog::Message
467 		<< "Expecting all pixels with distance less or equal to (about) " << barLength
468 		<< " pixels from left border to be of color " << barColor.swizzle(0, 1, 2) << "."
469 		<< tcu::TestLog::EndMessage;
470 
471 	bool allPixelsOk = true;
472 
473 	for (int y = 0; y < image.getHeight(); ++y)
474 	for (int x = 0; x < image.getWidth();  ++x)
475 	{
476 		const Vec4	color		= image.getPixel(x, y);
477 		const bool	isBlack		= compareColors(color, black, threshold);
478 		const bool	isColor		= compareColors(color, barColor, threshold);
479 
480 		bool isOk;
481 
482 		if (x <= barLength - barLengthThreshold)
483 			isOk = isColor;
484 		else if (x >= barLength + barLengthThreshold)
485 			isOk = isBlack;
486 		else
487 			isOk = isColor || isBlack;
488 
489 		allPixelsOk &= isOk;
490 
491 		if (!isOk)
492 			errorMaskAccess.setPixel(red, x, y);
493 	}
494 
495 	if (allPixelsOk)
496 	{
497 		log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
498 			<< tcu::TestLog::ImageSet("LayerContent", "Layer content")
499 			<< tcu::TestLog::Image("Layer", "Layer", image)
500 			<< tcu::TestLog::EndImageSet;
501 		return true;
502 	}
503 	else
504 	{
505 		log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
506 			<< tcu::TestLog::ImageSet("LayerContent", "Layer content")
507 			<< tcu::TestLog::Image("Layer",		"Layer",	image)
508 			<< tcu::TestLog::Image("ErrorMask",	"Errors",	errorMask)
509 			<< tcu::TestLog::EndImageSet;
510 		return false;
511 	}
512 
513 	log << tcu::TestLog::Image("LayerContent", "Layer content", image);
514 
515 	return allPixelsOk;
516 }
517 
verifyEmptyImage(tcu::TestLog & log,const tcu::ConstPixelBufferAccess image)518 bool verifyEmptyImage (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image)
519 {
520 	log << tcu::TestLog::Message << "Expecting empty image" << tcu::TestLog::EndMessage;
521 
522 	const Vec4	black		(0.0f, 0.0f, 0.0f, 1.0f);
523 	const Vec4	threshold	(0.02f);
524 
525 	for (int y = 0; y < image.getHeight(); ++y)
526 	for (int x = 0; x < image.getWidth();  ++x)
527 	{
528 		const Vec4 color = image.getPixel(x, y);
529 
530 		if (!compareColors(color, black, threshold))
531 		{
532 			log	<< tcu::TestLog::Message
533 				<< "Found (at least) one bad pixel at " << x << "," << y << ". Pixel color is not background color."
534 				<< tcu::TestLog::EndMessage
535 				<< tcu::TestLog::ImageSet("LayerContent", "Layer content")
536 				<< tcu::TestLog::Image("Layer", "Layer", image)
537 				<< tcu::TestLog::EndImageSet;
538 			return false;
539 		}
540 	}
541 
542 	log << tcu::TestLog::Message << "Image is valid" << tcu::TestLog::EndMessage;
543 
544 	return true;
545 }
546 
verifyLayerContent(tcu::TestLog & log,const TestType testType,const tcu::ConstPixelBufferAccess image,const int layerNdx,const int numLayers)547 bool verifyLayerContent (tcu::TestLog& log, const TestType testType, const tcu::ConstPixelBufferAccess image, const int layerNdx, const int numLayers)
548 {
549 	const Vec4	white				(1.0f, 1.0f, 1.0f, 1.0f);
550 	const int	targetLayer			= numLayers / 2;
551 	const float	variableBarRatio	= static_cast<float>(layerNdx) / static_cast<float>(numLayers);
552 
553 	switch (testType)
554 	{
555 		case TEST_TYPE_DEFAULT_LAYER:
556 			if (layerNdx == 0)
557 				return verifyImageSingleColoredRow(log, image, 0.5f, white);
558 			else
559 				return verifyEmptyImage(log, image);
560 
561 		case TEST_TYPE_SINGLE_LAYER:
562 			if (layerNdx == targetLayer)
563 				return verifyImageSingleColoredRow(log, image, 0.5f, white);
564 			else
565 				return verifyEmptyImage(log, image);
566 
567 		case TEST_TYPE_ALL_LAYERS:
568 		case TEST_TYPE_INVOCATION_PER_LAYER:
569 			return verifyImageSingleColoredRow(log, image, 0.5f, s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
570 
571 		case TEST_TYPE_DIFFERENT_CONTENT:
572 		case TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION:
573 			if (layerNdx == 0)
574 				return verifyEmptyImage(log, image);
575 			else
576 				return verifyImageSingleColoredRow(log, image, variableBarRatio, white);
577 
578 		case TEST_TYPE_LAYER_ID:
579 		{
580 			// This code must be in sync with the fragment shader.
581 			const tcu::Vec4 layerColor( (layerNdx    % 2) == 1 ? 1.0f : 0.5f,
582 									   ((layerNdx/2) % 2) == 1 ? 1.0f : 0.5f,
583 									     layerNdx         == 0 ? 1.0f : 0.0f,
584 																 1.0f);
585 			return verifyImageSingleColoredRow(log, image, 0.5f, layerColor);
586 		}
587 
588 		default:
589 			DE_ASSERT(0);
590 			return false;
591 	};
592 }
593 
getLayerDescription(const VkImageViewType viewType,const int layer)594 std::string getLayerDescription (const VkImageViewType viewType, const int layer)
595 {
596 	std::ostringstream str;
597 	const int numCubeFaces = 6;
598 
599 	if (isCubeImageViewType(viewType))
600 		str << "cube " << (layer / numCubeFaces) << ", face " << (layer % numCubeFaces);
601 	else if (viewType == VK_IMAGE_VIEW_TYPE_3D)
602 		str << "slice z = " << layer;
603 	else
604 		str << "layer " << layer;
605 
606 	return str.str();
607 }
608 
verifyResults(tcu::TestLog & log,const TestParams & params,const VkFormat colorFormat,const void * resultData)609 bool verifyResults (tcu::TestLog& log, const TestParams& params, const VkFormat colorFormat, const void* resultData)
610 {
611 	const LayeredImageAccess image = LayeredImageAccess::create(getImageType(params.image.viewType), colorFormat, params.image.size, params.image.numLayers, resultData);
612 
613 	int numGoodLayers = 0;
614 
615 	for (int layerNdx = 0; layerNdx < image.getNumLayersOrSlices(); ++layerNdx)
616 	{
617 		const tcu::ConstPixelBufferAccess layerImage = image.getLayer(layerNdx);
618 
619 		log << tcu::TestLog::Message << "Verifying " << getLayerDescription(params.image.viewType, layerNdx) << tcu::TestLog::EndMessage;
620 
621 		if (verifyLayerContent(log, params.testType, layerImage, layerNdx, image.getNumLayersOrSlices()))
622 			++numGoodLayers;
623 	}
624 
625 	return numGoodLayers == image.getNumLayersOrSlices();
626 }
627 
toGlsl(const Vec4 & v)628 std::string toGlsl (const Vec4& v)
629 {
630 	std::ostringstream str;
631 	str << "vec4(";
632 	for (int i = 0; i < 4; ++i)
633 		str << (i != 0 ? ", " : "") << de::floatToString(v[i], 1);
634 	str << ")";
635 	return str.str();
636 }
637 
initPrograms(SourceCollections & programCollection,const TestParams params)638 void initPrograms (SourceCollections& programCollection, const TestParams params)
639 {
640 	const bool geomOutputColor = (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_INVOCATION_PER_LAYER);
641 
642 	// Vertex shader
643 	{
644 		std::ostringstream src;
645 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
646 			<< "\n"
647 			<< "void main(void)\n"
648 			<< "{\n"
649 			<< "}\n";
650 
651 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
652 	}
653 
654 	// Geometry shader
655 	{
656 		const int numLayers		= static_cast<int>(params.image.viewType == VK_IMAGE_VIEW_TYPE_3D ? params.image.size.depth : params.image.numLayers);
657 
658 		const int maxVertices	= (params.testType == TEST_TYPE_DIFFERENT_CONTENT)										? (numLayers + 1) * numLayers :
659 								  (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_LAYER_ID)	? numLayers * 4 :
660 								  (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)							? 6 : 4;
661 
662 		std::ostringstream src;
663 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
664 			<< "\n";
665 
666 		if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
667 			src << "layout(points, invocations = " << numLayers << ") in;\n";
668 		else
669 			src << "layout(points) in;\n";
670 
671 		src << "layout(triangle_strip, max_vertices = " << maxVertices << ") out;\n"
672 			<< "\n"
673 			<< (geomOutputColor ? "layout(location = 0) out vec4 vert_color;\n\n" : "")
674 			<< "out gl_PerVertex {\n"
675 			<< "    vec4 gl_Position;\n"
676 			<< "};\n"
677 			<< "\n"
678 			<< "void main(void)\n"
679 			<< "{\n";
680 
681 		std::ostringstream colorTable;
682 		{
683 			const int numColors = DE_LENGTH_OF_ARRAY(s_colors);
684 
685 			colorTable << "    const vec4 colors[" << numColors << "] = vec4[" << numColors << "](";
686 
687 			const std::string padding(colorTable.str().length(), ' ');
688 
689 			for (int i = 0; i < numColors; ++i)
690 				colorTable << (i != 0 ? ",\n" + padding : "") << toGlsl(s_colors[i]);
691 
692 			colorTable << ");\n";
693 		}
694 
695 		if (params.testType == TEST_TYPE_DEFAULT_LAYER)
696 		{
697 			src << "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
698 				<< "    EmitVertex();\n"
699 				<< "\n"
700 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
701 				<< "    EmitVertex();\n"
702 				<< "\n"
703 				<< "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
704 				<< "    EmitVertex();\n"
705 				<< "\n"
706 				<< "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
707 				<< "    EmitVertex();\n";
708 		}
709 		else if (params.testType == TEST_TYPE_SINGLE_LAYER)
710 		{
711 			const deUint32 targetLayer = getTargetLayer(params.image);
712 
713 			src << "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
714 				<< "    gl_Layer    = " << targetLayer << ";\n"
715 				<< "    EmitVertex();\n"
716 				<< "\n"
717 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
718 				<< "    gl_Layer    = " << targetLayer << ";\n"
719 				<< "    EmitVertex();\n"
720 				<< "\n"
721 				<< "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
722 				<< "    gl_Layer    = " << targetLayer << ";\n"
723 				<< "    EmitVertex();\n"
724 				<< "\n"
725 				<< "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
726 				<< "    gl_Layer    = " << targetLayer << ";\n"
727 				<< "    EmitVertex();\n";
728 		}
729 		else if (params.testType == TEST_TYPE_ALL_LAYERS)
730 		{
731 			src << colorTable.str()
732 				<< "\n"
733 				<< "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
734 				<< "        const int colorNdx = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
735 				<< "\n"
736 				<< "        gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
737 				<< "        gl_Layer    = layerNdx;\n"
738 				<< "        vert_color  = colors[colorNdx];\n"
739 				<< "        EmitVertex();\n"
740 				<< "\n"
741 				<< "        gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
742 				<< "        gl_Layer    = layerNdx;\n"
743 				<< "        vert_color  = colors[colorNdx];\n"
744 				<< "        EmitVertex();\n"
745 				<< "\n"
746 				<< "        gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
747 				<< "        gl_Layer    = layerNdx;\n"
748 				<< "        vert_color  = colors[colorNdx];\n"
749 				<< "        EmitVertex();\n"
750 				<< "\n"
751 				<< "        gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
752 				<< "        gl_Layer    = layerNdx;\n"
753 				<< "        vert_color  = colors[colorNdx];\n"
754 				<< "        EmitVertex();\n"
755 				<< "        EndPrimitive();\n"
756 				<< "    };\n";
757 		}
758 		else if (params.testType == TEST_TYPE_LAYER_ID)
759 		{
760 			src << "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
761 				<< "        gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
762 				<< "        gl_Layer    = layerNdx;\n"
763 				<< "        EmitVertex();\n"
764 				<< "\n"
765 				<< "        gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
766 				<< "        gl_Layer    = layerNdx;\n"
767 				<< "        EmitVertex();\n"
768 				<< "\n"
769 				<< "        gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
770 				<< "        gl_Layer    = layerNdx;\n"
771 				<< "        EmitVertex();\n"
772 				<< "\n"
773 				<< "        gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
774 				<< "        gl_Layer    = layerNdx;\n"
775 				<< "        EmitVertex();\n"
776 				<< "        EndPrimitive();\n"
777 				<< "    };\n";
778 		}
779 		else if (params.testType == TEST_TYPE_DIFFERENT_CONTENT)
780 		{
781 			src << "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
782 				<< "        for (int colNdx = 0; colNdx <= layerNdx; ++colNdx) {\n"
783 				<< "            const float posX = float(colNdx) / float(" << numLayers << ") * 2.0 - 1.0;\n"
784 				<< "\n"
785 				<< "            gl_Position = vec4(posX,  1.0, 0.0, 1.0);\n"
786 				<< "            gl_Layer    = layerNdx;\n"
787 				<< "            EmitVertex();\n"
788 				<< "\n"
789 				<< "            gl_Position = vec4(posX, -1.0, 0.0, 1.0);\n"
790 				<< "            gl_Layer    = layerNdx;\n"
791 				<< "            EmitVertex();\n"
792 				<< "        }\n"
793 				<< "        EndPrimitive();\n"
794 				<< "    }\n";
795 		}
796 		else if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER)
797 		{
798 			src << colorTable.str()
799 				<< "    const int colorNdx = gl_InvocationID % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
800 				<< "\n"
801 				<< "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
802 				<< "    gl_Layer    = gl_InvocationID;\n"
803 				<< "    vert_color  = colors[colorNdx];\n"
804 				<< "    EmitVertex();\n"
805 				<< "\n"
806 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
807 				<< "    gl_Layer    = gl_InvocationID;\n"
808 				<< "    vert_color  = colors[colorNdx];\n"
809 				<< "    EmitVertex();\n"
810 				<< "\n"
811 				<< "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
812 				<< "    gl_Layer    = gl_InvocationID;\n"
813 				<< "    vert_color  = colors[colorNdx];\n"
814 				<< "    EmitVertex();\n"
815 				<< "\n"
816 				<< "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
817 				<< "    gl_Layer    = gl_InvocationID;\n"
818 				<< "    vert_color  = colors[colorNdx];\n"
819 				<< "    EmitVertex();\n"
820 				<< "    EndPrimitive();\n";
821 		}
822 		else if (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
823 		{
824 			src << "    const int   layerA = gl_InvocationID;\n"
825 				<< "    const int   layerB = (gl_InvocationID + 1) % " << numLayers << ";\n"
826 				<< "    const float aEnd   = float(layerA) / float(" << numLayers << ") * 2.0 - 1.0;\n"
827 				<< "    const float bEnd   = float(layerB) / float(" << numLayers << ") * 2.0 - 1.0;\n"
828 				<< "\n"
829 				<< "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
830 				<< "    gl_Layer    = layerA;\n"
831 				<< "    EmitVertex();\n"
832 				<< "\n"
833 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
834 				<< "    gl_Layer    = layerA;\n"
835 				<< "    EmitVertex();\n"
836 				<< "\n"
837 				<< "    gl_Position = vec4(aEnd, -1.0, 0.0, 1.0);\n"
838 				<< "    gl_Layer    = layerA;\n"
839 				<< "    EmitVertex();\n"
840 				<< "    EndPrimitive();\n"
841 				<< "\n"
842 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
843 				<< "    gl_Layer    = layerB;\n"
844 				<< "    EmitVertex();\n"
845 				<< "\n"
846 				<< "    gl_Position = vec4(bEnd,  1.0, 0.0, 1.0);\n"
847 				<< "    gl_Layer    = layerB;\n"
848 				<< "    EmitVertex();\n"
849 				<< "\n"
850 				<< "    gl_Position = vec4(bEnd, -1.0, 0.0, 1.0);\n"
851 				<< "    gl_Layer    = layerB;\n"
852 				<< "    EmitVertex();\n"
853 				<< "    EndPrimitive();\n";
854 		}
855 		else
856 			DE_ASSERT(0);
857 
858 		src <<	"}\n";	// end main
859 
860 		programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
861 	}
862 
863 	// Fragment shader
864 	{
865 		std::ostringstream src;
866 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
867 			<< "\n"
868 			<< "layout(location = 0) out vec4 o_color;\n"
869 			<< (geomOutputColor ? "layout(location = 0) in  vec4 vert_color;\n" : "")
870 			<< "\n"
871 			<< "void main(void)\n"
872 			<< "{\n";
873 
874 		if (params.testType == TEST_TYPE_LAYER_ID)
875 		{
876 			// This code must be in sync with verifyLayerContent()
877 			src << "    o_color = vec4( (gl_Layer    % 2) == 1 ? 1.0 : 0.5,\n"
878 				<< "                   ((gl_Layer/2) % 2) == 1 ? 1.0 : 0.5,\n"
879 				<< "                     gl_Layer         == 0 ? 1.0 : 0.0,\n"
880 				<< "                                             1.0);\n";
881 		}
882 		else if (geomOutputColor)
883 			src << "    o_color = vert_color;\n";
884 		else
885 			src << "    o_color = vec4(1.0);\n";
886 
887 		src << "}\n";
888 
889 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
890 	}
891 }
892 
test(Context & context,const TestParams params)893 tcu::TestStatus test (Context& context, const TestParams params)
894 {
895 	if (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType &&
896 		(!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_maintenance1")))
897 		TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
898 
899 	const DeviceInterface&			vk						= context.getDeviceInterface();
900 	const InstanceInterface&		vki						= context.getInstanceInterface();
901 	const VkDevice					device					= context.getDevice();
902 	const VkPhysicalDevice			physDevice				= context.getPhysicalDevice();
903 	const deUint32					queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
904 	const VkQueue					queue					= context.getUniversalQueue();
905 	Allocator&						allocator				= context.getDefaultAllocator();
906 
907 	checkGeometryShaderSupport(vki, physDevice);
908 
909 	const VkFormat					colorFormat				= VK_FORMAT_R8G8B8A8_UNORM;
910 	const deUint32					numLayers				= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
911 	const Vec4						clearColor				= Vec4(0.0f, 0.0f, 0.0f, 1.0f);
912 	const VkDeviceSize				colorBufferSize			= params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * tcu::getPixelSize(mapVkFormat(colorFormat));
913 	const VkImageCreateFlags		imageCreateFlags		= (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
914 															  (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
915 	const VkImageViewType			viewType				= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
916 
917 	const Unique<VkImage>			colorImage				(makeImage				(vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
918 																					 params.image.numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
919 	const UniquePtr<Allocation>		colorImageAlloc			(bindImage				(vk, device, allocator, *colorImage, MemoryRequirement::Any));
920 	const Unique<VkImageView>		colorAttachment			(makeImageView			(vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
921 
922 	const Unique<VkBuffer>			colorBuffer				(makeBuffer				(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
923 	const UniquePtr<Allocation>		colorBufferAlloc		(bindBuffer				(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
924 
925 	const Unique<VkShaderModule>	vertexModule			(createShaderModule		(vk, device, context.getBinaryCollection().get("vert"), 0u));
926 	const Unique<VkShaderModule>	geometryModule			(createShaderModule		(vk, device, context.getBinaryCollection().get("geom"), 0u));
927 	const Unique<VkShaderModule>	fragmentModule			(createShaderModule		(vk, device, context.getBinaryCollection().get("frag"), 0u));
928 
929 	const Unique<VkRenderPass>		renderPass				(makeRenderPass			(vk, device, colorFormat));
930 	const Unique<VkFramebuffer>		framebuffer				(makeFramebuffer		(vk, device, *renderPass, *colorAttachment, params.image.size.width,  params.image.size.height, numLayers));
931 	const Unique<VkPipelineLayout>	pipelineLayout			(makePipelineLayout		(vk, device));
932 	const Unique<VkPipeline>		pipeline				(makeGraphicsPipeline	(vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule,
933 																					 makeExtent2D(params.image.size.width, params.image.size.height)));
934 	const Unique<VkCommandPool>		cmdPool					(makeCommandPool		(vk, device, queueFamilyIndex));
935 	const Unique<VkCommandBuffer>	cmdBuffer				(makeCommandBuffer		(vk, device, *cmdPool));
936 
937 	zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
938 
939 	beginCommandBuffer(vk, *cmdBuffer);
940 
941 	const VkClearValue			clearValue	= makeClearValueColor(clearColor);
942 	const VkRect2D				renderArea	=
943 	{
944 		makeOffset2D(0, 0),
945 		makeExtent2D(params.image.size.width, params.image.size.height),
946 	};
947 	const VkRenderPassBeginInfo renderPassBeginInfo =
948 	{
949 		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,		// VkStructureType         sType;
950 		DE_NULL,										// const void*             pNext;
951 		*renderPass,									// VkRenderPass            renderPass;
952 		*framebuffer,									// VkFramebuffer           framebuffer;
953 		renderArea,										// VkRect2D                renderArea;
954 		1u,												// uint32_t                clearValueCount;
955 		&clearValue,									// const VkClearValue*     pClearValues;
956 	};
957 	vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
958 
959 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
960 	vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
961 	vk.cmdEndRenderPass(*cmdBuffer);
962 
963 	// Prepare color image for copy
964 	{
965 		const VkImageSubresourceRange	colorSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers);
966 		const VkImageMemoryBarrier		barriers[] =
967 		{
968 			{
969 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
970 				DE_NULL,										// const void*				pNext;
971 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			outputMask;
972 				VK_ACCESS_TRANSFER_READ_BIT,					// VkAccessFlags			inputMask;
973 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			oldLayout;
974 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,			// VkImageLayout			newLayout;
975 				VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
976 				VK_QUEUE_FAMILY_IGNORED,						// deUint32					destQueueFamilyIndex;
977 				*colorImage,									// VkImage					image;
978 				colorSubresourceRange,							// VkImageSubresourceRange	subresourceRange;
979 			},
980 		};
981 
982 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
983 			0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
984 	}
985 	// Color image -> host buffer
986 	{
987 		const VkBufferImageCopy region =
988 		{
989 			0ull,																						// VkDeviceSize                bufferOffset;
990 			0u,																							// uint32_t                    bufferRowLength;
991 			0u,																							// uint32_t                    bufferImageHeight;
992 			makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, params.image.numLayers),		// VkImageSubresourceLayers    imageSubresource;
993 			makeOffset3D(0, 0, 0),																		// VkOffset3D                  imageOffset;
994 			params.image.size,																			// VkExtent3D                  imageExtent;
995 		};
996 
997 		vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
998 	}
999 	// Buffer write barrier
1000 	{
1001 		const VkBufferMemoryBarrier barriers[] =
1002 		{
1003 			{
1004 				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// VkStructureType    sType;
1005 				DE_NULL,										// const void*        pNext;
1006 				VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags      srcAccessMask;
1007 				VK_ACCESS_HOST_READ_BIT,						// VkAccessFlags      dstAccessMask;
1008 				VK_QUEUE_FAMILY_IGNORED,						// uint32_t           srcQueueFamilyIndex;
1009 				VK_QUEUE_FAMILY_IGNORED,						// uint32_t           dstQueueFamilyIndex;
1010 				*colorBuffer,									// VkBuffer           buffer;
1011 				0ull,											// VkDeviceSize       offset;
1012 				VK_WHOLE_SIZE,									// VkDeviceSize       size;
1013 			},
1014 		};
1015 
1016 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1017 			0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u);
1018 	}
1019 
1020 	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1021 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1022 
1023 	invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSize);
1024 
1025 	if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1026 		return tcu::TestStatus::fail("Rendered images are incorrect");
1027 	else
1028 		return tcu::TestStatus::pass("OK");
1029 }
1030 
1031 } // anonymous
1032 
createLayeredRenderingTests(tcu::TestContext & testCtx)1033 tcu::TestCaseGroup* createLayeredRenderingTests (tcu::TestContext& testCtx)
1034 {
1035 	MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "layered", "Layered rendering tests."));
1036 
1037 	const struct
1038 	{
1039 		TestType		test;
1040 		const char*		name;
1041 		const char*		description;
1042 	} testTypes[] =
1043 	{
1044 		{ TEST_TYPE_DEFAULT_LAYER,					"render_to_default_layer",			"Render to the default layer"															},
1045 		{ TEST_TYPE_SINGLE_LAYER,					"render_to_one",					"Render to one layer"																	},
1046 		{ TEST_TYPE_ALL_LAYERS,						"render_to_all",					"Render to all layers"																	},
1047 		{ TEST_TYPE_DIFFERENT_CONTENT,				"render_different_content",			"Render different data to different layers"												},
1048 		{ TEST_TYPE_LAYER_ID,						"fragment_layer",					"Read gl_Layer in fragment shader"														},
1049 		{ TEST_TYPE_INVOCATION_PER_LAYER,			"invocation_per_layer",				"Render to multiple layers with multiple invocations, one invocation per layer"			},
1050 		{ TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION,	"multiple_layers_per_invocation",	"Render to multiple layers with multiple invocations, multiple layers per invocation",	},
1051 	};
1052 
1053 	const ImageParams imageParams[] =
1054 	{
1055 		{ VK_IMAGE_VIEW_TYPE_1D_ARRAY,		{ 64,  1, 1 },	4	},
1056 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		{ 64, 64, 1 },	4	},
1057 		{ VK_IMAGE_VIEW_TYPE_CUBE,			{ 64, 64, 1 },	6	},
1058 		{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	{ 64, 64, 1 },	2*6	},
1059 		{ VK_IMAGE_VIEW_TYPE_3D,			{ 64, 64, 8 },	1	}
1060 	};
1061 
1062 	for (int imageParamNdx = 0; imageParamNdx < DE_LENGTH_OF_ARRAY(imageParams); ++imageParamNdx)
1063 	{
1064 		MovePtr<tcu::TestCaseGroup> viewTypeGroup(new tcu::TestCaseGroup(testCtx, getShortImageViewTypeName(imageParams[imageParamNdx].viewType).c_str(), ""));
1065 
1066 		for (int testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx)
1067 		{
1068 			const TestParams params =
1069 			{
1070 				testTypes[testTypeNdx].test,
1071 				imageParams[imageParamNdx],
1072 			};
1073 			addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, initPrograms, test, params);
1074 		}
1075 
1076 		group->addChild(viewTypeGroup.release());
1077 	}
1078 
1079 	return group.release();
1080 }
1081 
1082 } // geometry
1083 } // vkt
1084