1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 Google Inc.
6  * Copyright (c) 2019 The Khronos Group Inc.
7  * Copyright (c) 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Geometry shader layered rendering tests
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktGeometryLayeredRenderingTests.hpp"
27 #include "vktTestCase.hpp"
28 #include "vktTestCaseUtil.hpp"
29 #include "vktGeometryTestsUtil.hpp"
30 
31 #include "vkPrograms.hpp"
32 #include "vkStrUtil.hpp"
33 #include "vkQueryUtil.hpp"
34 #include "vkMemUtil.hpp"
35 #include "vkRefUtil.hpp"
36 #include "vkBarrierUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkImageUtil.hpp"
39 #include "vkBuilderUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkObjUtil.hpp"
42 
43 #include "deStringUtil.hpp"
44 #include "deUniquePtr.hpp"
45 
46 #include "tcuTextureUtil.hpp"
47 #include "tcuVectorUtil.hpp"
48 #include "tcuTestLog.hpp"
49 
50 namespace vkt
51 {
52 namespace geometry
53 {
54 namespace
55 {
56 using namespace vk;
57 using de::MovePtr;
58 using de::UniquePtr;
59 using tcu::Vec4;
60 using tcu::IVec3;
61 
62 enum TestType
63 {
64 	TEST_TYPE_DEFAULT_LAYER,					// !< draw to default layer
65 	TEST_TYPE_SINGLE_LAYER,						// !< draw to single layer
66 	TEST_TYPE_ALL_LAYERS,						// !< draw all layers
67 	TEST_TYPE_DIFFERENT_CONTENT,				// !< draw different content to different layers
68 	TEST_TYPE_LAYER_ID,							// !< draw to all layers, verify gl_Layer fragment input
69 	TEST_TYPE_INVOCATION_PER_LAYER,				// !< draw to all layers, one invocation per layer
70 	TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION,	// !< draw to all layers, multiple invocations write to multiple layers
71 	TEST_TYPE_LAYERED_READBACK,					// !< draw to two layers multiple times
72 	TEST_TYPE_SECONDARY_CMD_BUFFER				// !< layered rendering using secondary command buffer
73 };
74 
75 struct ImageParams
76 {
77 	VkImageViewType	viewType;
78 	VkExtent3D		size;
79 	deUint32		numLayers;
80 };
81 
82 struct TestParams
83 {
84 	TestType	testType;
85 	ImageParams	image;
86 	bool		inheritFramebuffer;
87 };
88 
89 const float		s_colors[][4]					=
90 {
91 	{ 1.0f, 1.0f, 1.0f, 1.0f },		// white
92 	{ 1.0f, 0.0f, 0.0f, 1.0f },		// red
93 	{ 0.0f, 1.0f, 0.0f, 1.0f },		// green
94 	{ 0.0f, 0.0f, 1.0f, 1.0f },		// blue
95 	{ 1.0f, 1.0f, 0.0f, 1.0f },		// yellow
96 	{ 1.0f, 0.0f, 1.0f, 1.0f },		// magenta
97 };
98 
99 const tcu::Vec4	secondaryCmdBufClearColors[]	=
100 {
101 	tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
102 	tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
103 	tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
104 	tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
105 	tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f),
106 	tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f)
107 };
108 
scaleColor(const tcu::Vec4 & color,float factor)109 tcu::Vec4 scaleColor(const tcu::Vec4& color, float factor)
110 {
111 	return tcu::Vec4(color[0] * factor,
112 					 color[1] * factor,
113 					 color[2] * factor,
114 					 color[3]);
115 }
116 
getTargetLayer(const ImageParams & imageParams)117 deUint32 getTargetLayer (const ImageParams& imageParams)
118 {
119 	if (imageParams.viewType == VK_IMAGE_VIEW_TYPE_3D)
120 		return imageParams.size.depth / 2;
121 	else
122 		return imageParams.numLayers / 2;
123 }
124 
getShortImageViewTypeName(const VkImageViewType imageViewType)125 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
126 {
127 	std::string s(getImageViewTypeName(imageViewType));
128 	return de::toLower(s.substr(19));
129 }
130 
getImageType(const VkImageViewType viewType)131 VkImageType getImageType (const VkImageViewType viewType)
132 {
133 	switch (viewType)
134 	{
135 		case VK_IMAGE_VIEW_TYPE_1D:
136 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
137 			return VK_IMAGE_TYPE_1D;
138 
139 		case VK_IMAGE_VIEW_TYPE_2D:
140 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
141 		case VK_IMAGE_VIEW_TYPE_CUBE:
142 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
143 			return VK_IMAGE_TYPE_2D;
144 
145 		case VK_IMAGE_VIEW_TYPE_3D:
146 			return VK_IMAGE_TYPE_3D;
147 
148 		default:
149 			DE_ASSERT(0);
150 			return VK_IMAGE_TYPE_LAST;
151 	}
152 }
153 
getStencilBufferFormat(VkFormat depthStencilImageFormat)154 VkFormat getStencilBufferFormat(VkFormat depthStencilImageFormat)
155 {
156 	const tcu::TextureFormat tcuFormat = mapVkFormat(depthStencilImageFormat);
157 	const VkFormat result = (tcuFormat.order == tcu::TextureFormat::S || tcuFormat.order == tcu::TextureFormat::DS) ? VK_FORMAT_S8_UINT : VK_FORMAT_UNDEFINED;
158 
159 	DE_ASSERT(result != VK_FORMAT_UNDEFINED);
160 
161 	return result;
162 }
163 
isCubeImageViewType(const VkImageViewType viewType)164 inline bool isCubeImageViewType (const VkImageViewType viewType)
165 {
166 	return viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
167 }
168 
checkImageFormatProperties(const InstanceInterface & vki,const VkPhysicalDevice & physDevice,const VkImageType & imageType,const VkImageTiling & imageTiling,const VkImageUsageFlags imageUsageFlags,const VkImageCreateFlags imageCreateFlags,const VkFormat format,const VkExtent3D & requiredSize,const deUint32 requiredLayers)169 void checkImageFormatProperties (const InstanceInterface&	vki,
170 								 const VkPhysicalDevice&	physDevice,
171 								 const VkImageType&			imageType,
172 								 const VkImageTiling&		imageTiling,
173 								 const VkImageUsageFlags	imageUsageFlags,
174 								 const VkImageCreateFlags	imageCreateFlags,
175 								 const VkFormat				format,
176 								 const VkExtent3D&			requiredSize,
177 								 const deUint32				requiredLayers)
178 {
179 	VkImageFormatProperties	imageFormatProperties;
180 	VkResult				result;
181 
182 	deMemset(&imageFormatProperties, 0, sizeof(imageFormatProperties));
183 
184 	result = vki.getPhysicalDeviceImageFormatProperties(physDevice, format, imageType, imageTiling, imageUsageFlags, imageCreateFlags, &imageFormatProperties);
185 
186 	if (result									!= VK_SUCCESS			||
187 		imageFormatProperties.maxArrayLayers	<  requiredLayers		||
188 		imageFormatProperties.maxExtent.height	<  requiredSize.height	||
189 		imageFormatProperties.maxExtent.width	<  requiredSize.width	||
190 		imageFormatProperties.maxExtent.depth	<  requiredSize.depth)
191 	{
192 		TCU_THROW(NotSupportedError, "Depth/stencil format is not supported");
193 	}
194 }
195 
makeImageCreateInfo(const VkImageCreateFlags flags,const VkImageType type,const VkFormat format,const VkExtent3D size,const deUint32 numLayers,const VkImageUsageFlags usage)196 VkImageCreateInfo makeImageCreateInfo (const VkImageCreateFlags flags, const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const VkImageUsageFlags usage)
197 {
198 	const VkImageCreateInfo imageParams =
199 	{
200 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
201 		DE_NULL,										// const void*				pNext;
202 		flags,											// VkImageCreateFlags		flags;
203 		type,											// VkImageType				imageType;
204 		format,											// VkFormat					format;
205 		size,											// VkExtent3D				extent;
206 		1u,												// deUint32					mipLevels;
207 		numLayers,										// deUint32					arrayLayers;
208 		VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples;
209 		VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
210 		usage,											// VkImageUsageFlags		usage;
211 		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
212 		0u,												// deUint32					queueFamilyIndexCount;
213 		DE_NULL,										// const deUint32*			pQueueFamilyIndices;
214 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout;
215 	};
216 	return imageParams;
217 }
218 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const VkFormat dsFormat,const bool useDepthStencil)219 Move<VkRenderPass> makeRenderPass (const DeviceInterface&	vk,
220 								   const VkDevice			device,
221 								   const VkFormat			colorFormat,
222 								   const VkFormat			dsFormat,
223 								   const bool				useDepthStencil)
224 {
225 	return vk::makeRenderPass(vk, device, colorFormat, useDepthStencil ? dsFormat : VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD);
226 }
227 
makeRenderPassWithSelfDependency(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat)228 Move<VkRenderPass> makeRenderPassWithSelfDependency (const DeviceInterface&	vk,
229 													 const VkDevice			device,
230 													 const VkFormat			colorFormat)
231 {
232 	const VkAttachmentDescription	attachmentDescription	=
233 	{
234 		(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags	flags
235 		colorFormat,								// VkFormat						format
236 		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits		samples
237 		VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp			loadOp
238 		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp			storeOp
239 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp			stencilLoadOp
240 		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp			stencilStoreOp
241 		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout				initialLayout
242 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout				finalLayout
243 	};
244 
245 	const VkAttachmentReference		colorAttachmentRef		=
246 	{
247 		0u,											// deUint32			attachment
248 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout
249 	};
250 
251 	const VkSubpassDescription		subpassDescription		=
252 	{
253 		(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags
254 		VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint
255 		0u,									// deUint32							inputAttachmentCount
256 		DE_NULL,							// const VkAttachmentReference*		pInputAttachments
257 		1u,									// deUint32							colorAttachmentCount
258 		&colorAttachmentRef,				// const VkAttachmentReference*		pColorAttachments
259 		DE_NULL,							// const VkAttachmentReference*		pResolveAttachments
260 		DE_NULL,							// const VkAttachmentReference*		pDepthStencilAttachment
261 		0u,									// deUint32							preserveAttachmentCount
262 		DE_NULL								// const deUint32*					pPreserveAttachments
263 	};
264 
265 	const VkSubpassDependency		subpassDependency		=
266 	{
267 		0u,										// deUint32				srcSubpass
268 		0u,										// deUint32				dstSubpass
269 		VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,	// VkPipelineStageFlags	srcStageMask
270 		VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,	// VkPipelineStageFlags	dstStageMask
271 		VK_ACCESS_SHADER_WRITE_BIT,				// VkAccessFlags		srcAccessMask
272 		VK_ACCESS_SHADER_READ_BIT,				// VkAccessFlags		dstAccessMask
273 		0u,										// VkDependencyFlags	dependencyFlags
274 	};
275 
276 	const VkRenderPassCreateInfo	renderPassInfo			=
277 	{
278 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType
279 		DE_NULL,									// const void*						pNext
280 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags
281 		1u,											// deUint32							attachmentCount
282 		&attachmentDescription,						// const VkAttachmentDescription*	pAttachments
283 		1u,											// deUint32							subpassCount
284 		&subpassDescription,						// const VkSubpassDescription*		pSubpasses
285 		1u,											// deUint32							dependencyCount
286 		&subpassDependency							// const VkSubpassDependency*		pDependencies
287 	};
288 
289 	return createRenderPass(vk, device, &renderPassInfo);
290 }
291 
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,const bool useDepthStencil=false)292 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&		vk,
293 									   const VkDevice				device,
294 									   const VkPipelineLayout		pipelineLayout,
295 									   const VkRenderPass			renderPass,
296 									   const VkShaderModule			vertexModule,
297 									   const VkShaderModule			geometryModule,
298 									   const VkShaderModule			fragmentModule,
299 									   const VkExtent2D				renderSize,
300 									   const bool					useDepthStencil = false)
301 {
302 	const std::vector<VkViewport>				viewports						(1, makeViewport(renderSize));
303 	const std::vector<VkRect2D>					scissors						(1, makeRect2D(renderSize));
304 
305 	const VkStencilOpState						stencilOpState					= makeStencilOpState(
306 		VK_STENCIL_OP_KEEP,					// stencil fail
307 		VK_STENCIL_OP_INCREMENT_AND_CLAMP,	// depth & stencil pass
308 		VK_STENCIL_OP_KEEP,					// depth only fail
309 		VK_COMPARE_OP_ALWAYS,				// compare op
310 		~0u,								// compare mask
311 		~0u,								// write mask
312 		0u);								// reference
313 
314 	const VkPipelineDepthStencilStateCreateInfo	pipelineDepthStencilStateInfo	=
315 	{
316 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType
317 		DE_NULL,													// const void*								pNext
318 		(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags	flags
319 		useDepthStencil ? VK_TRUE : VK_FALSE,						// VkBool32									depthTestEnable
320 		useDepthStencil ? VK_TRUE : VK_FALSE,						// VkBool32									depthWriteEnable
321 		VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp
322 		VK_FALSE,													// VkBool32									depthBoundsTestEnable
323 		useDepthStencil ? VK_TRUE : VK_FALSE,						// VkBool32									stencilTestEnable
324 		stencilOpState,												// VkStencilOpState							front
325 		stencilOpState,												// VkStencilOpState							back
326 		0.0f,														// float									minDepthBounds
327 		1.0f														// float									maxDepthBounds
328 	};
329 
330 	const VkPipelineVertexInputStateCreateInfo	vertexInputStateInfo			=
331 	{
332 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType
333 		DE_NULL,													// const void*								pNext
334 		0u,															// VkPipelineVertexInputStateCreateFlags	flags
335 		0u,															// deUint32									vertexBindingDescriptionCount
336 		DE_NULL,													// const VkVertexInputBindingDescription*	pVertexBindingDescriptions
337 		0u,															// deUint32									vertexAttributeDescriptionCount
338 		DE_NULL														// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions
339 	};
340 
341 	return vk::makeGraphicsPipeline(vk,									// const DeviceInterface&							vk
342 									device,								// const VkDevice									device
343 									pipelineLayout,						// const VkPipelineLayout							pipelineLayout
344 									vertexModule,						// const VkShaderModule								vertexShaderModule
345 									DE_NULL,							// const VkShaderModule								tessellationControlModule
346 									DE_NULL,							// const VkShaderModule								tessellationEvalModule
347 									geometryModule,						// const VkShaderModule								geometryShaderModule
348 									fragmentModule,						// const VkShaderModule								fragmentShaderModule
349 									renderPass,							// const VkRenderPass								renderPass
350 									viewports,							// const std::vector<VkViewport>&					viewports
351 									scissors,							// const std::vector<VkRect2D>&						scissors
352 									VK_PRIMITIVE_TOPOLOGY_POINT_LIST,	// const VkPrimitiveTopology						topology
353 									0u,									// const deUint32									subpass
354 									0u,									// const deUint32									patchControlPoints
355 									&vertexInputStateInfo,				// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
356 									DE_NULL,							// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
357 									DE_NULL,							// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
358 									&pipelineDepthStencilStateInfo);	// const VkPipelineDepthStencilStateCreateInfo*		depthStencilStateCreateInfo
359 }
360 
copyLayeredImageToBuffer(const DeviceInterface & vk,VkCommandBuffer cmdBuffer,VkImage image,VkBuffer buffer,const ImageParams & imageParams)361 void copyLayeredImageToBuffer(const DeviceInterface& vk, VkCommandBuffer cmdBuffer, VkImage image, VkBuffer buffer, const ImageParams& imageParams)
362 {
363 	// Image read barrier
364 	{
365 		const VkImageSubresourceRange	colorSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, imageParams.numLayers);
366 		const VkImageMemoryBarrier		barrier =
367 		{
368 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType
369 			DE_NULL,									// const void*				pNext
370 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			outputMask
371 			VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			inputMask
372 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			oldLayout
373 			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// VkImageLayout			newLayout
374 			VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex
375 			VK_QUEUE_FAMILY_IGNORED,					// deUint32					destQueueFamilyIndex
376 			image,										// VkImage					image
377 			colorSubresourceRange						// VkImageSubresourceRange	subresourceRange
378 		};
379 
380 		vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
381 	}
382 	// Color image -> host buffer
383 	{
384 		const VkBufferImageCopy region =
385 		{
386 			0ull,																					// VkDeviceSize				bufferOffset
387 			0u,																						// deUint32					bufferRowLength
388 			0u,																						// deUint32					bufferImageHeight
389 			makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageParams.numLayers),	// VkImageSubresourceLayers	imageSubresource
390 			makeOffset3D(0, 0, 0),																	// VkOffset3D				imageOffset
391 			imageParams.size																		// VkExtent3D				imageExtent
392 		};
393 
394 		vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, &region);
395 	}
396 	// Buffer write barrier
397 	{
398 		const VkBufferMemoryBarrier barrier =
399 		{
400 			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType
401 			DE_NULL,									// const void*		pNext
402 			VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask
403 			VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask
404 			VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex
405 			VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex
406 			buffer,										// VkBuffer			buffer
407 			0ull,										// VkDeviceSize		offset
408 			VK_WHOLE_SIZE								// VkDeviceSize		size
409 		};
410 
411 		vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &barrier, DE_NULL, 0u);
412 	}
413 }
414 
415 //! Convenience wrapper to access 1D, 2D, and 3D image layers/slices in a uniform way.
416 class LayeredImageAccess
417 {
418 public:
create(const VkImageType type,const VkFormat format,const VkExtent3D size,const deUint32 numLayers,const void * pData)419 	static LayeredImageAccess create (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
420 	{
421 		if (type == VK_IMAGE_TYPE_1D)
422 			return LayeredImageAccess(format, size.width, numLayers, pData);
423 		else
424 			return LayeredImageAccess(type, format, size, numLayers, pData);
425 	}
426 
getLayer(const int layer) const427 	inline tcu::ConstPixelBufferAccess getLayer (const int layer) const
428 	{
429 		return tcu::getSubregion(m_wholeImage, 0, (m_1dModifier * layer), ((~m_1dModifier & 1) * layer), m_width, m_height, 1);
430 	}
431 
getNumLayersOrSlices(void) const432 	inline int getNumLayersOrSlices (void) const
433 	{
434 		return m_layers;
435 	}
436 
437 private:
438 	// Specialized for 1D images.
LayeredImageAccess(const VkFormat format,const deUint32 width,const deUint32 numLayers,const void * pData)439 	LayeredImageAccess (const VkFormat format, const deUint32 width, const deUint32 numLayers, const void* pData)
440 		: m_width		(static_cast<int>(width))
441 		, m_height		(1)
442 		, m_1dModifier	(1)
443 		, m_layers		(numLayers)
444 		, m_wholeImage	(tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_layers, 1, pData))
445 	{
446 	}
447 
LayeredImageAccess(const VkImageType type,const VkFormat format,const VkExtent3D size,const deUint32 numLayers,const void * pData)448 	LayeredImageAccess (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
449 		: m_width		(static_cast<int>(size.width))
450 		, m_height		(static_cast<int>(size.height))
451 		, m_1dModifier	(0)
452 		, m_layers		(static_cast<int>(type == VK_IMAGE_TYPE_3D ? size.depth : numLayers))
453 		, m_wholeImage	(tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_height, m_layers, pData))
454 	{
455 	}
456 
457 	const int							m_width;
458 	const int							m_height;
459 	const int							m_1dModifier;
460 	const int							m_layers;
461 	const tcu::ConstPixelBufferAccess	m_wholeImage;
462 };
463 
compareColors(const Vec4 & colorA,const Vec4 & colorB,const Vec4 & threshold)464 inline bool compareColors (const Vec4& colorA, const Vec4& colorB, const Vec4& threshold)
465 {
466 	return tcu::allEqual(
467 				tcu::lessThan(tcu::abs(colorA - colorB), threshold),
468 				tcu::BVec4(true, true, true, true));
469 }
470 
verifyImageSingleColoredRow(tcu::TestLog & log,const tcu::ConstPixelBufferAccess image,const float rowWidthRatio,const tcu::Vec4 & barColor,bool topRightCleared=false,bool bottomRightCleared=false)471 bool verifyImageSingleColoredRow (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image, const float rowWidthRatio, const tcu::Vec4& barColor, bool topRightCleared = false, bool bottomRightCleared = false)
472 {
473 	DE_ASSERT(rowWidthRatio > 0.0f);
474 
475 	const Vec4				black				(0.0f, 0.0f, 0.0f, 1.0f);
476 	const Vec4				green				(0.0f, 1.0f, 0.0f, 1.0f);
477 	const Vec4				red					(1.0f, 0.0f, 0.0f, 1.0f);
478 	const Vec4				brown				(0.5f, 0.25f, 0.0f, 1.0f);
479 	const Vec4				threshold			(0.02f);
480 	const int				barLength			= static_cast<int>(rowWidthRatio * static_cast<float>(image.getWidth()));
481 	const int				barLengthThreshold	= 1;
482 	tcu::TextureLevel		errorMask			(image.getFormat(), image.getWidth(), image.getHeight());
483 	tcu::PixelBufferAccess	errorMaskAccess		= errorMask.getAccess();
484 
485 	tcu::clear(errorMask.getAccess(), green);
486 
487 	log << tcu::TestLog::Message
488 		<< "Expecting all pixels with distance less or equal to (about) " << barLength
489 		<< " pixels from left border to be of color " << barColor.swizzle(0, 1, 2) << "."
490 		<< tcu::TestLog::EndMessage;
491 
492 	bool allPixelsOk = true;
493 
494 	for (int y = 0; y < image.getHeight(); ++y)
495 	for (int x = 0; x < image.getWidth();  ++x)
496 	{
497 		const Vec4	color			= image.getPixel(x, y);
498 		const bool	isBlack			= compareColors(color, black, threshold);
499 		const bool	isBrown			= compareColors(color, brown, threshold);
500 		const bool	isColor			= compareColors(color, barColor, threshold);
501 		const bool	isOutsideColor	= ((topRightCleared && y < image.getHeight() / 2) || (bottomRightCleared && y >= image.getHeight() / 2)) ? isBrown : isBlack;
502 
503 		bool isOk;
504 
505 		if (x <= barLength - barLengthThreshold)
506 			isOk = isColor;
507 		else if (x >= barLength + barLengthThreshold)
508 		{
509 			isOk = isOutsideColor;
510 		}
511 		else
512 			isOk = isColor || isOutsideColor;
513 
514 		allPixelsOk &= isOk;
515 
516 		if (!isOk)
517 			errorMaskAccess.setPixel(red, x, y);
518 	}
519 
520 	if (allPixelsOk)
521 	{
522 		log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
523 			<< tcu::TestLog::ImageSet("LayerContent", "Layer content")
524 			<< tcu::TestLog::Image("Layer", "Layer", image)
525 			<< tcu::TestLog::EndImageSet;
526 		return true;
527 	}
528 	else
529 	{
530 		log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
531 			<< tcu::TestLog::ImageSet("LayerContent", "Layer content")
532 			<< tcu::TestLog::Image("Layer",		"Layer",	image)
533 			<< tcu::TestLog::Image("ErrorMask",	"Errors",	errorMask)
534 			<< tcu::TestLog::EndImageSet;
535 		return false;
536 	}
537 
538 	log << tcu::TestLog::Image("LayerContent", "Layer content", image);
539 
540 	return allPixelsOk;
541 }
542 
verifyImageMultipleBars(tcu::TestLog & log,const tcu::ConstPixelBufferAccess image,const float * barWidthRatios,const tcu::Vec4 * barValues,const int barsCount,const int numUsedChannels,const std::string & imageTypeName)543 static bool verifyImageMultipleBars (tcu::TestLog&						log,
544 									 const tcu::ConstPixelBufferAccess	image,
545 									 const float*						barWidthRatios,
546 									 const tcu::Vec4*					barValues,
547 									 const int							barsCount,
548 									 const int							numUsedChannels,
549 									 const std::string&					imageTypeName)
550 {
551 	const Vec4					green				(0.0f, 1.0f, 0.0f, 1.0f);
552 	const Vec4					red					(1.0f, 0.0f, 0.0f, 1.0f);
553 	const Vec4					threshold			(0.02f);
554 	const tcu::TextureFormat	errorMaskFormat		(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8));
555 	tcu::TextureLevel			errorMask			(errorMaskFormat, image.getWidth(), image.getHeight());
556 	tcu::PixelBufferAccess		errorMaskAccess		= errorMask.getAccess();
557 	bool						allPixelsOk			= true;
558 
559 	DE_ASSERT(barsCount > 0);
560 
561 	tcu::clear(errorMask.getAccess(), green);
562 
563 	// Format information message
564 	{
565 		int					leftBorder	= 0;
566 		int					rightBorder	= 0;
567 		std::ostringstream	str;
568 
569 		for (int barNdx = 0; barNdx < barsCount; ++barNdx)
570 		{
571 			leftBorder	= rightBorder;
572 			rightBorder	= static_cast<int>(barWidthRatios[barNdx] * static_cast<float>(image.getWidth()));
573 
574 			DE_ASSERT(leftBorder < rightBorder);
575 
576 			str << std::endl << " [" << leftBorder << "," <<rightBorder << "): ";
577 
578 			switch (numUsedChannels)
579 			{
580 				case 1:	str << barValues[barNdx][0];	break;
581 				case 4:	str << barValues[barNdx];		break;
582 				default: DE_ASSERT(false);				break;
583 			}
584 		}
585 
586 		log << tcu::TestLog::Message
587 			<< "Expecting " + imageTypeName + " values depending x-axis position to be of following values: "
588 			<< str.str()
589 			<< tcu::TestLog::EndMessage;
590 	}
591 
592 	for (int x = 0; x < image.getWidth();  ++x)
593 	{
594 		tcu::Vec4	expectedValue	= barValues[0];
595 
596 		for (int barNdx = 0; barNdx < barsCount; ++barNdx)
597 		{
598 			const int rightBorder	= static_cast<int>(barWidthRatios[barNdx] * static_cast<float>(image.getWidth()));
599 
600 			if (x < rightBorder)
601 			{
602 				expectedValue = barValues[barNdx];
603 
604 				break;
605 			}
606 		}
607 
608 		for (int y = 0; y < image.getHeight(); ++y)
609 		{
610 			const tcu::Vec4	realValue	= image.getPixel(x, y);
611 			bool			isOk		= false;
612 
613 			switch (numUsedChannels)
614 			{
615 				case 1:	isOk = fabs(realValue[0] - expectedValue[0]) < threshold[0];	break;
616 				case 4:	isOk = compareColors(realValue, expectedValue, threshold);		break;
617 				default: DE_ASSERT(false);												break;
618 			}
619 
620 			if (!isOk)
621 				errorMaskAccess.setPixel(red, x, y);
622 
623 			allPixelsOk = allPixelsOk && isOk;
624 		}
625 	}
626 
627 	if (allPixelsOk)
628 	{
629 		log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
630 			<< tcu::TestLog::ImageSet(imageTypeName + "LayerContent", imageTypeName + " Layer Content")
631 			<< tcu::TestLog::Image("Layer", "Layer", image)
632 			<< tcu::TestLog::EndImageSet;
633 	}
634 	else
635 	{
636 		log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
637 			<< tcu::TestLog::ImageSet(imageTypeName + "LayerContent", imageTypeName + " Layer Content")
638 			<< tcu::TestLog::Image("Layer",		"Layer",	image)
639 			<< tcu::TestLog::Image("ErrorMask",	"Errors",	errorMask)
640 			<< tcu::TestLog::EndImageSet;
641 	}
642 
643 	return allPixelsOk;
644 }
645 
convertDepthToColorBufferAccess(const tcu::ConstPixelBufferAccess & inputImage,tcu::PixelBufferAccess & outputImage)646 static void convertDepthToColorBufferAccess (const tcu::ConstPixelBufferAccess& inputImage, tcu::PixelBufferAccess& outputImage)
647 {
648 	for (int y = 0; y < inputImage.getHeight(); y++)
649 	for (int x = 0; x < inputImage.getWidth(); x++)
650 	{
651 		const float		depth	= inputImage.getPixDepth(x, y);
652 		const tcu::Vec4	color	= tcu::Vec4(depth, depth, depth, 1.0f);
653 
654 		outputImage.setPixel(color, x, y);
655 	}
656 }
657 
convertStencilToColorBufferAccess(const tcu::ConstPixelBufferAccess & inputImage,tcu::PixelBufferAccess & outputImage,int maxValue)658 static void convertStencilToColorBufferAccess (const tcu::ConstPixelBufferAccess& inputImage, tcu::PixelBufferAccess& outputImage, int maxValue)
659 {
660 	for (int y = 0; y < inputImage.getHeight(); y++)
661 	for (int x = 0; x < inputImage.getWidth(); x++)
662 	{
663 		const int		stencilInt	= inputImage.getPixStencil(x, y);
664 		const float		stencil		= (stencilInt < maxValue) ? float(stencilInt) / float(maxValue) : 1.0f;
665 		const tcu::Vec4	color		= tcu::Vec4(stencil, stencil, stencil, 1.0f);
666 
667 		outputImage.setPixel(color, x, y);
668 	}
669 }
670 
verifyEmptyImage(tcu::TestLog & log,const tcu::ConstPixelBufferAccess image)671 bool verifyEmptyImage (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image)
672 {
673 	log << tcu::TestLog::Message << "Expecting empty image" << tcu::TestLog::EndMessage;
674 
675 	const Vec4	black		(0.0f, 0.0f, 0.0f, 1.0f);
676 	const Vec4	threshold	(0.02f);
677 
678 	for (int y = 0; y < image.getHeight(); ++y)
679 	for (int x = 0; x < image.getWidth();  ++x)
680 	{
681 		const Vec4 color = image.getPixel(x, y);
682 
683 		if (!compareColors(color, black, threshold))
684 		{
685 			log	<< tcu::TestLog::Message
686 				<< "Found (at least) one bad pixel at " << x << "," << y << ". Pixel color is not background color."
687 				<< tcu::TestLog::EndMessage
688 				<< tcu::TestLog::ImageSet("LayerContent", "Layer content")
689 				<< tcu::TestLog::Image("Layer", "Layer", image)
690 				<< tcu::TestLog::EndImageSet;
691 			return false;
692 		}
693 	}
694 
695 	log << tcu::TestLog::Message << "Image is valid" << tcu::TestLog::EndMessage;
696 
697 	return true;
698 }
699 
verifyLayerContent(tcu::TestLog & log,const TestType testType,const tcu::ConstPixelBufferAccess image,const int layerNdx,const int numLayers,const bool depthCheck,const bool stencilCheck)700 bool verifyLayerContent (tcu::TestLog& log, const TestType testType, const tcu::ConstPixelBufferAccess image, const int layerNdx, const int numLayers, const bool depthCheck, const bool stencilCheck)
701 {
702 	const Vec4	white				(1.0f, 1.0f, 1.0f, 1.0f);
703 	const int	targetLayer			= numLayers / 2;
704 	const float	variableBarRatio	= static_cast<float>(layerNdx) / static_cast<float>(numLayers);
705 
706 	switch (testType)
707 	{
708 		case TEST_TYPE_DEFAULT_LAYER:
709 			if (layerNdx == 0)
710 				return verifyImageSingleColoredRow(log, image, 0.5f, white);
711 			else
712 				return verifyEmptyImage(log, image);
713 
714 		case TEST_TYPE_SINGLE_LAYER:
715 			if (layerNdx == targetLayer)
716 				return verifyImageSingleColoredRow(log, image, 0.5f, white);
717 			else
718 				return verifyEmptyImage(log, image);
719 
720 		case TEST_TYPE_ALL_LAYERS:
721 		case TEST_TYPE_INVOCATION_PER_LAYER:
722 			return verifyImageSingleColoredRow(log, image, 0.5f, s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
723 
724 		case TEST_TYPE_DIFFERENT_CONTENT:
725 		case TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION:
726 			if (layerNdx == 0)
727 				return verifyEmptyImage(log, image);
728 			else
729 				return verifyImageSingleColoredRow(log, image, variableBarRatio, white);
730 
731 		case TEST_TYPE_LAYER_ID:
732 		{
733 			// This code must be in sync with the fragment shader.
734 			const tcu::Vec4 layerColor( (layerNdx    % 2) == 1 ? 1.0f : 0.5f,
735 									   ((layerNdx/2) % 2) == 1 ? 1.0f : 0.5f,
736 									     layerNdx         == 0 ? 1.0f : 0.0f,
737 																 1.0f);
738 			return verifyImageSingleColoredRow(log, image, 0.5f, layerColor);
739 		}
740 
741 		case TEST_TYPE_LAYERED_READBACK:
742 		{
743 			const float	barWidthRatios[]	= { 0.25f, 0.5f, 1.0f };
744 			const int	barsCount			= DE_LENGTH_OF_ARRAY(barWidthRatios);
745 			bool		result				= false;
746 
747 			if (depthCheck)
748 			{
749 				const std::string		checkType				= "Depth";
750 				const float				pass0depth				= static_cast<float>(layerNdx + 1) / static_cast<float>(2 * numLayers);
751 				const float				pass1depth				= static_cast<float>(layerNdx + 0) / static_cast<float>(2 * numLayers);
752 				const tcu::Vec4			barDepths[barsCount]	= { tcu::Vec4(pass1depth), tcu::Vec4(pass0depth), tcu::Vec4(1.0f) };
753 				tcu::TextureLevel		depthAsColorBuffer		(tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), image.getWidth(), image.getHeight());
754 				tcu::PixelBufferAccess	depthAsColor			(depthAsColorBuffer);
755 				const int				numUsedChannels			(tcu::getNumUsedChannels(depthAsColor.getFormat().order));
756 
757 				convertDepthToColorBufferAccess(image, depthAsColor);
758 
759 				result = verifyImageMultipleBars(log, depthAsColor, barWidthRatios, barDepths, barsCount, numUsedChannels, checkType);
760 			}
761 			else if (stencilCheck)
762 			{
763 				const std::string		checkType				= "Stencil";
764 				const int				maxStencilValue			= 4;
765 				const float				pass0stencil			= static_cast<float>(1.0f / maxStencilValue);
766 				const float				pass1stencil			= static_cast<float>(2.0f / maxStencilValue);
767 				const tcu::Vec4			barStencils[barsCount]	= { tcu::Vec4(pass1stencil), tcu::Vec4(pass0stencil), tcu::Vec4(0.0f) };
768 				tcu::TextureLevel		stencilAsColorBuffer	(tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), image.getWidth(), image.getHeight());
769 				tcu::PixelBufferAccess	stencilAsColor			(stencilAsColorBuffer);
770 				const int				numUsedChannels			(tcu::getNumUsedChannels(stencilAsColor.getFormat().order));
771 
772 				convertStencilToColorBufferAccess(image, stencilAsColor, maxStencilValue);
773 
774 				result = verifyImageMultipleBars(log, stencilAsColor, barWidthRatios, barStencils, barsCount, numUsedChannels, checkType);
775 			}
776 			else
777 			{
778 				const std::string		checkType				= "Color";
779 				const tcu::Vec4			baseColor				(s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
780 				const tcu::Vec4			barColors[barsCount]	= { scaleColor(baseColor, 1.00f), scaleColor(baseColor, 0.50f), scaleColor(baseColor, 0.25f) };
781 				const int				numUsedChannels			(tcu::getNumUsedChannels(image.getFormat().order));
782 
783 				result = verifyImageMultipleBars(log, image, barWidthRatios, barColors, barsCount, numUsedChannels, checkType);
784 			}
785 
786 			return result;
787 		}
788 
789 		case TEST_TYPE_SECONDARY_CMD_BUFFER:
790 		{
791 			const tcu::Vec4	clearColor	= secondaryCmdBufClearColors[layerNdx % DE_LENGTH_OF_ARRAY(secondaryCmdBufClearColors)];
792 			const tcu::Vec4	quadColor	= s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)];
793 			// The first draw: blend clearColor and quadColor
794 			const tcu::Vec4	firstDraw	= (clearColor + quadColor) * 0.5f;
795 			// The second draw: blend previous result and quadColor
796 			const tcu::Vec4	secondDraw	= (firstDraw + quadColor) * 0.5f;
797 
798 			return verifyImageSingleColoredRow(log, image, 0.5f, secondDraw, layerNdx < numLayers / 2, layerNdx >= numLayers / 2);
799 		}
800 
801 		default:
802 			DE_ASSERT(0);
803 			return false;
804 	};
805 }
806 
getLayerDescription(const VkImageViewType viewType,const int layer)807 std::string getLayerDescription (const VkImageViewType viewType, const int layer)
808 {
809 	std::ostringstream str;
810 	const int numCubeFaces = 6;
811 
812 	if (isCubeImageViewType(viewType))
813 		str << "cube " << (layer / numCubeFaces) << ", face " << (layer % numCubeFaces);
814 	else if (viewType == VK_IMAGE_VIEW_TYPE_3D)
815 		str << "slice z = " << layer;
816 	else
817 		str << "layer " << layer;
818 
819 	return str.str();
820 }
821 
verifyResults(tcu::TestLog & log,const TestParams & params,const VkFormat imageFormat,const void * resultData,const bool depthCheck=false,const bool stencilCheck=false)822 bool verifyResults (tcu::TestLog& log, const TestParams& params, const VkFormat imageFormat, const void* resultData, const bool depthCheck = false, const bool stencilCheck = false)
823 {
824 	const LayeredImageAccess image = LayeredImageAccess::create(getImageType(params.image.viewType), imageFormat, params.image.size, params.image.numLayers, resultData);
825 
826 	int numGoodLayers = 0;
827 
828 	for (int layerNdx = 0; layerNdx < image.getNumLayersOrSlices(); ++layerNdx)
829 	{
830 		const tcu::ConstPixelBufferAccess layerImage = image.getLayer(layerNdx);
831 
832 		log << tcu::TestLog::Message << "Verifying " << getLayerDescription(params.image.viewType, layerNdx) << tcu::TestLog::EndMessage;
833 
834 		if (verifyLayerContent(log, params.testType, layerImage, layerNdx, image.getNumLayersOrSlices(), depthCheck, stencilCheck))
835 			++numGoodLayers;
836 	}
837 
838 	return numGoodLayers == image.getNumLayersOrSlices();
839 }
840 
toGlsl(const Vec4 & v)841 std::string toGlsl (const Vec4& v)
842 {
843 	std::ostringstream str;
844 	str << "vec4(";
845 	for (int i = 0; i < 4; ++i)
846 		str << (i != 0 ? ", " : "") << de::floatToString(v[i], 1);
847 	str << ")";
848 	return str.str();
849 }
850 
initPrograms(SourceCollections & programCollection,const TestParams params)851 void initPrograms (SourceCollections& programCollection, const TestParams params)
852 {
853 	const bool geomOutputColor = (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_LAYERED_READBACK || params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER);
854 
855 	// Vertex shader
856 	{
857 		std::ostringstream src;
858 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
859 			<< "\n"
860 			<< "void main(void)\n"
861 			<< "{\n"
862 			<< "}\n";
863 
864 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
865 	}
866 
867 	// Geometry shader
868 	{
869 		const int numLayers		= static_cast<int>(params.image.viewType == VK_IMAGE_VIEW_TYPE_3D ? params.image.size.depth : params.image.numLayers);
870 
871 		const int maxVertices	= (params.testType == TEST_TYPE_DIFFERENT_CONTENT)				? (numLayers + 1) * numLayers :
872 								  (params.testType == TEST_TYPE_ALL_LAYERS
873 								   || params.testType == TEST_TYPE_LAYER_ID
874 								   || params.testType == TEST_TYPE_LAYERED_READBACK
875 								   || params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER)		? numLayers * 4 :
876 								  (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)	? 6 : 4;
877 
878 		std::ostringstream src;
879 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
880 			<< "\n";
881 
882 		if (params.testType == TEST_TYPE_LAYERED_READBACK)
883 			src << "layout(binding = 0) readonly uniform Input {\n"
884 				<< "    int pass;\n"
885 				<< "} uInput;\n\n";
886 
887 		if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
888 			src << "layout(points, invocations = " << numLayers << ") in;\n";
889 		else
890 			src << "layout(points) in;\n";
891 
892 		src << "layout(triangle_strip, max_vertices = " << maxVertices << ") out;\n"
893 			<< "\n"
894 			<< (geomOutputColor ? "layout(location = 0) out vec4 vert_color;\n\n" : "")
895 			<< "out gl_PerVertex {\n"
896 			<< "    vec4 gl_Position;\n"
897 			<< "    float gl_PointSize;\n"
898 			<< "};\n"
899 			<< "\n"
900 			<< "void main(void)\n"
901 			<< "{\n";
902 
903 		std::ostringstream colorTable;
904 		{
905 			const int numColors = DE_LENGTH_OF_ARRAY(s_colors);
906 
907 			colorTable << "    const vec4 colors[" << numColors << "] = vec4[" << numColors << "](";
908 
909 			const std::string padding(colorTable.str().length(), ' ');
910 
911 			for (int i = 0; i < numColors; ++i)
912 				colorTable << (i != 0 ? ",\n" + padding : "") << toGlsl(s_colors[i]);
913 
914 			colorTable << ");\n";
915 		}
916 
917 		if (params.testType == TEST_TYPE_DEFAULT_LAYER)
918 		{
919 			src << "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
920 				<< "    gl_PointSize = 1.0;\n"
921 				<< "    EmitVertex();\n"
922 				<< "\n"
923 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
924 				<< "    gl_PointSize = 1.0;\n"
925 				<< "    EmitVertex();\n"
926 				<< "\n"
927 				<< "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
928 				<< "    gl_PointSize = 1.0;\n"
929 				<< "    EmitVertex();\n"
930 				<< "\n"
931 				<< "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
932 				<< "    gl_PointSize = 1.0;\n"
933 				<< "    EmitVertex();\n";
934 		}
935 		else if (params.testType == TEST_TYPE_SINGLE_LAYER)
936 		{
937 			const deUint32 targetLayer = getTargetLayer(params.image);
938 
939 			src << "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
940 				<< "    gl_Layer    = " << targetLayer << ";\n"
941 				<< "    gl_PointSize = 1.0;\n"
942 				<< "    EmitVertex();\n"
943 				<< "\n"
944 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
945 				<< "    gl_Layer    = " << targetLayer << ";\n"
946 				<< "    gl_PointSize = 1.0;\n"
947 				<< "    EmitVertex();\n"
948 				<< "\n"
949 				<< "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
950 				<< "    gl_Layer    = " << targetLayer << ";\n"
951 				<< "    gl_PointSize = 1.0;\n"
952 				<< "    EmitVertex();\n"
953 				<< "\n"
954 				<< "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
955 				<< "    gl_Layer    = " << targetLayer << ";\n"
956 				<< "    gl_PointSize = 1.0;\n"
957 				<< "    EmitVertex();\n";
958 		}
959 		else if (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER)
960 		{
961 			src << colorTable.str()
962 				<< "\n"
963 				<< "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
964 				<< "        const int colorNdx = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
965 				<< "\n"
966 				<< "        gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
967 				<< "        gl_Layer    = layerNdx;\n"
968 				<< "        vert_color  = colors[colorNdx];\n"
969 				<< "        gl_PointSize = 1.0;\n"
970 				<< "        EmitVertex();\n"
971 				<< "\n"
972 				<< "        gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
973 				<< "        gl_Layer    = layerNdx;\n"
974 				<< "        vert_color  = colors[colorNdx];\n"
975 				<< "        gl_PointSize = 1.0;\n"
976 				<< "        EmitVertex();\n"
977 				<< "\n"
978 				<< "        gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
979 				<< "        gl_Layer    = layerNdx;\n"
980 				<< "        vert_color  = colors[colorNdx];\n"
981 				<< "        gl_PointSize = 1.0;\n"
982 				<< "        EmitVertex();\n"
983 				<< "\n"
984 				<< "        gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
985 				<< "        gl_Layer    = layerNdx;\n"
986 				<< "        vert_color  = colors[colorNdx];\n"
987 				<< "        gl_PointSize = 1.0;\n"
988 				<< "        EmitVertex();\n"
989 				<< "        EndPrimitive();\n"
990 				<< "    };\n";
991 		}
992 		else if (params.testType == TEST_TYPE_LAYER_ID)
993 		{
994 			src << "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
995 				<< "        gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
996 				<< "        gl_Layer    = layerNdx;\n"
997 				<< "        gl_PointSize = 1.0;\n"
998 				<< "        EmitVertex();\n"
999 				<< "\n"
1000 				<< "        gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
1001 				<< "        gl_Layer    = layerNdx;\n"
1002 				<< "        gl_PointSize = 1.0;\n"
1003 				<< "        EmitVertex();\n"
1004 				<< "\n"
1005 				<< "        gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
1006 				<< "        gl_Layer    = layerNdx;\n"
1007 				<< "        gl_PointSize = 1.0;\n"
1008 				<< "        EmitVertex();\n"
1009 				<< "\n"
1010 				<< "        gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
1011 				<< "        gl_Layer    = layerNdx;\n"
1012 				<< "        gl_PointSize = 1.0;\n"
1013 				<< "        EmitVertex();\n"
1014 				<< "        EndPrimitive();\n"
1015 				<< "    };\n";
1016 		}
1017 		else if (params.testType == TEST_TYPE_DIFFERENT_CONTENT)
1018 		{
1019 			src << "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
1020 				<< "        for (int colNdx = 0; colNdx <= layerNdx; ++colNdx) {\n"
1021 				<< "            const float posX = float(colNdx) / float(" << numLayers << ") * 2.0 - 1.0;\n"
1022 				<< "\n"
1023 				<< "            gl_Position = vec4(posX,  1.0, 0.0, 1.0);\n"
1024 				<< "            gl_Layer    = layerNdx;\n"
1025 				<< "            gl_PointSize = 1.0;\n"
1026 				<< "            EmitVertex();\n"
1027 				<< "\n"
1028 				<< "            gl_Position = vec4(posX, -1.0, 0.0, 1.0);\n"
1029 				<< "            gl_Layer    = layerNdx;\n"
1030 				<< "            gl_PointSize = 1.0;\n"
1031 				<< "            EmitVertex();\n"
1032 				<< "        }\n"
1033 				<< "        EndPrimitive();\n"
1034 				<< "    }\n";
1035 		}
1036 		else if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER)
1037 		{
1038 			src << colorTable.str()
1039 				<< "    const int colorNdx = gl_InvocationID % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
1040 				<< "\n"
1041 				<< "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
1042 				<< "    gl_Layer    = gl_InvocationID;\n"
1043 				<< "    gl_PointSize = 1.0;\n"
1044 				<< "    vert_color  = colors[colorNdx];\n"
1045 				<< "    EmitVertex();\n"
1046 				<< "\n"
1047 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
1048 				<< "    gl_Layer    = gl_InvocationID;\n"
1049 				<< "    gl_PointSize = 1.0;\n"
1050 				<< "    vert_color  = colors[colorNdx];\n"
1051 				<< "    EmitVertex();\n"
1052 				<< "\n"
1053 				<< "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
1054 				<< "    gl_Layer    = gl_InvocationID;\n"
1055 				<< "    gl_PointSize = 1.0;\n"
1056 				<< "    vert_color  = colors[colorNdx];\n"
1057 				<< "    EmitVertex();\n"
1058 				<< "\n"
1059 				<< "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
1060 				<< "    gl_Layer    = gl_InvocationID;\n"
1061 				<< "    gl_PointSize = 1.0;\n"
1062 				<< "    vert_color  = colors[colorNdx];\n"
1063 				<< "    EmitVertex();\n"
1064 				<< "    EndPrimitive();\n";
1065 		}
1066 		else if (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
1067 		{
1068 			src << "    const int   layerA = gl_InvocationID;\n"
1069 				<< "    const int   layerB = (gl_InvocationID + 1) % " << numLayers << ";\n"
1070 				<< "    const float aEnd   = float(layerA) / float(" << numLayers << ") * 2.0 - 1.0;\n"
1071 				<< "    const float bEnd   = float(layerB) / float(" << numLayers << ") * 2.0 - 1.0;\n"
1072 				<< "\n"
1073 				<< "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
1074 				<< "    gl_Layer    = layerA;\n"
1075 				<< "    gl_PointSize = 1.0;\n"
1076 				<< "    EmitVertex();\n"
1077 				<< "\n"
1078 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
1079 				<< "    gl_Layer    = layerA;\n"
1080 				<< "    gl_PointSize = 1.0;\n"
1081 				<< "    EmitVertex();\n"
1082 				<< "\n"
1083 				<< "    gl_Position = vec4(aEnd, -1.0, 0.0, 1.0);\n"
1084 				<< "    gl_Layer    = layerA;\n"
1085 				<< "    gl_PointSize = 1.0;\n"
1086 				<< "    EmitVertex();\n"
1087 				<< "    EndPrimitive();\n"
1088 				<< "\n"
1089 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
1090 				<< "    gl_Layer    = layerB;\n"
1091 				<< "    gl_PointSize = 1.0;\n"
1092 				<< "    EmitVertex();\n"
1093 				<< "\n"
1094 				<< "    gl_Position = vec4(bEnd,  1.0, 0.0, 1.0);\n"
1095 				<< "    gl_Layer    = layerB;\n"
1096 				<< "    gl_PointSize = 1.0;\n"
1097 				<< "    EmitVertex();\n"
1098 				<< "\n"
1099 				<< "    gl_Position = vec4(bEnd, -1.0, 0.0, 1.0);\n"
1100 				<< "    gl_Layer    = layerB;\n"
1101 				<< "    gl_PointSize = 1.0;\n"
1102 				<< "    EmitVertex();\n"
1103 				<< "    EndPrimitive();\n";
1104 		}
1105 		else if (params.testType == TEST_TYPE_LAYERED_READBACK)
1106 		{
1107 			src << colorTable.str()
1108 				<< "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
1109 				<< "        const int   colorNdx   = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
1110 				<< "        const vec3  passColor0 = (uInput.pass == 0 ? 0.5 :  1.0) * vec3(colors[colorNdx]);\n"
1111 				<< "        const vec4  passColor  = vec4(passColor0, 1.0);\n"
1112 				<< "        const float posX       = (uInput.pass == 0 ? 0.0 : -0.5);\n"
1113 				<< "        const float posZ       = float(layerNdx + 1 - uInput.pass) / float(" << 2*numLayers << ");\n"
1114 				<< "\n"
1115 				<< "        gl_Position = vec4(-1.0, -1.0, posZ, 1.0);\n"
1116 				<< "        gl_Layer    = layerNdx;\n"
1117 				<< "        gl_PointSize = 1.0;\n"
1118 				<< "        vert_color  = passColor;\n"
1119 				<< "        EmitVertex();\n"
1120 				<< "\n"
1121 				<< "        gl_Position = vec4(-1.0,  1.0, posZ, 1.0);\n"
1122 				<< "        gl_Layer    = layerNdx;\n"
1123 				<< "        gl_PointSize = 1.0;\n"
1124 				<< "        vert_color  = passColor;\n"
1125 				<< "        EmitVertex();\n"
1126 				<< "\n"
1127 				<< "        gl_Position = vec4(posX, -1.0, posZ, 1.0);\n"
1128 				<< "        gl_Layer    = layerNdx;\n"
1129 				<< "        gl_PointSize = 1.0;\n"
1130 				<< "        vert_color  = passColor;\n"
1131 				<< "        EmitVertex();\n"
1132 				<< "\n"
1133 				<< "        gl_Position = vec4(posX,  1.0, posZ, 1.0);\n"
1134 				<< "        gl_Layer    = layerNdx;\n"
1135 				<< "        gl_PointSize = 1.0;\n"
1136 				<< "        vert_color  = passColor;\n"
1137 				<< "        EmitVertex();\n"
1138 				<< "\n"
1139 				<< "        EndPrimitive();\n"
1140 				<< "    }\n";
1141 		}
1142 		else
1143 			DE_ASSERT(0);
1144 
1145 		src <<	"}\n";	// end main
1146 
1147 		programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
1148 	}
1149 
1150 	// Fragment shader
1151 	{
1152 		std::string imageViewString;
1153 
1154 		switch (params.image.viewType)
1155 		{
1156 			case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1157 				imageViewString = "image1DArray";
1158 				break;
1159 			case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
1160 				imageViewString = "image2DArray";
1161 				break;
1162 			case VK_IMAGE_VIEW_TYPE_CUBE:
1163 				imageViewString = "imageCube";
1164 				break;
1165 			case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
1166 				imageViewString = "imageCubeArray";
1167 				break;
1168 			default:
1169 				DE_ASSERT(params.image.viewType == VK_IMAGE_VIEW_TYPE_3D);
1170 				imageViewString = "image3D";
1171 				break;
1172 		};
1173 
1174 		std::ostringstream src;
1175 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1176 			<< "\n"
1177 			<< "layout(location = 0) out vec4 o_color;\n"
1178 			<< (geomOutputColor ? "layout(location = 0) in  vec4 vert_color;\n" : "")
1179 			<< (params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER ? std::string("layout(set = 0, binding = 0, rgba8) uniform " + imageViewString + " storageImage;\n") : std::string(""))
1180 			<< "\n"
1181 			<< "void main(void)\n"
1182 			<< "{\n";
1183 
1184 		if (params.testType == TEST_TYPE_LAYER_ID)
1185 		{
1186 			// This code must be in sync with verifyLayerContent()
1187 			src << "    o_color = vec4( (gl_Layer    % 2) == 1 ? 1.0 : 0.5,\n"
1188 				<< "                   ((gl_Layer/2) % 2) == 1 ? 1.0 : 0.5,\n"
1189 				<< "                     gl_Layer         == 0 ? 1.0 : 0.0,\n"
1190 				<< "                                             1.0);\n";
1191 		}
1192 		else if (params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER)
1193 		{
1194 			switch (params.image.viewType)
1195 			{
1196 				case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1197 					src << "    ivec2 coord = ivec2(int(gl_FragCoord.x), gl_Layer);\n";
1198 					break;
1199 				default:
1200 					src << "    ivec3 coord = ivec3(int(gl_FragCoord.x), int(gl_FragCoord.y), gl_Layer);\n";
1201 					break;
1202 			};
1203 
1204 			src << "    vec4 src_color = imageLoad(storageImage, coord);\n"
1205 				<< "    o_color = (vert_color + src_color) / 2.0;\n"
1206 				<< "    imageStore(storageImage, coord, o_color);\n";
1207 		}
1208 		else if (geomOutputColor)
1209 			src << "    o_color = vert_color;\n";
1210 		else
1211 			src << "    o_color = vec4(1.0);\n";
1212 
1213 		src << "}\n";
1214 
1215 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1216 	}
1217 }
1218 
test(Context & context,const TestParams params)1219 tcu::TestStatus test (Context& context, const TestParams params)
1220 {
1221 	const DeviceInterface&			vk						= context.getDeviceInterface();
1222 	const InstanceInterface&		vki						= context.getInstanceInterface();
1223 	const VkDevice					device					= context.getDevice();
1224 	const VkPhysicalDevice			physDevice				= context.getPhysicalDevice();
1225 	const deUint32					queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
1226 	const VkQueue					queue					= context.getUniversalQueue();
1227 	Allocator&						allocator				= context.getDefaultAllocator();
1228 	VkDeviceSize					nonCoherentAtomSize		= vk::getPhysicalDeviceProperties(vki, physDevice).limits.nonCoherentAtomSize;
1229 	VkDeviceSize					alignmentSize			= std::max<VkDeviceSize>(nonCoherentAtomSize, 4u);
1230 
1231 	const VkFormat					colorFormat				= VK_FORMAT_R8G8B8A8_UNORM;
1232 	const deUint32					numLayers				= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
1233 	const Vec4						clearColor				= Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1234 	const deUint32					colorImagePixelSize		= static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(colorFormat)));
1235 	const VkDeviceSize				colorBufferSize			= static_cast<VkDeviceSize>(deAlignSize(params.image.size.width * params.image.size.height * colorImagePixelSize, static_cast<std::size_t>(alignmentSize)) * params.image.size.depth * params.image.numLayers);
1236 	const VkImageCreateFlags		imageCreateFlags		= (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
1237 															  (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
1238 	const VkImageViewType			viewType				= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
1239 
1240 	const Unique<VkImage>			colorImage				(makeImage				(vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
1241 																					 params.image.numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1242 	const UniquePtr<Allocation>		colorImageAlloc			(bindImage				(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1243 	const Unique<VkImageView>		colorAttachment			(makeImageView			(vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
1244 
1245 	const Unique<VkBuffer>			colorBuffer				(makeBuffer				(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1246 	const UniquePtr<Allocation>		colorBufferAlloc		(bindBuffer				(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1247 
1248 	const Unique<VkShaderModule>	vertexModule			(createShaderModule		(vk, device, context.getBinaryCollection().get("vert"), 0u));
1249 	const Unique<VkShaderModule>	geometryModule			(createShaderModule		(vk, device, context.getBinaryCollection().get("geom"), 0u));
1250 	const Unique<VkShaderModule>	fragmentModule			(createShaderModule		(vk, device, context.getBinaryCollection().get("frag"), 0u));
1251 
1252 	const Unique<VkRenderPass>		renderPass				(makeRenderPass			(vk, device, colorFormat));
1253 	const Unique<VkFramebuffer>		framebuffer				(makeFramebuffer		(vk, device, *renderPass, *colorAttachment, params.image.size.width,  params.image.size.height, numLayers));
1254 	const Unique<VkPipelineLayout>	pipelineLayout			(makePipelineLayout		(vk, device));
1255 	const Unique<VkPipeline>		pipeline				(makeGraphicsPipeline	(vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule,
1256 																					 makeExtent2D(params.image.size.width, params.image.size.height)));
1257 	const Unique<VkCommandPool>		cmdPool					(createCommandPool		(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1258 	const Unique<VkCommandBuffer>	cmdBuffer				(allocateCommandBuffer	(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1259 
1260 	zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
1261 
1262 	beginCommandBuffer(vk, *cmdBuffer);
1263 
1264 	beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, params.image.size.width, params.image.size.height), clearColor);
1265 
1266 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1267 	vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1268 	endRenderPass(vk, *cmdBuffer);
1269 
1270 	// Copy color image to buffer
1271 	copyLayeredImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, params.image);
1272 
1273 	endCommandBuffer(vk, *cmdBuffer);
1274 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1275 
1276 	invalidateAlloc(vk, device, *colorBufferAlloc);
1277 
1278 	if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1279 		return tcu::TestStatus::fail("Rendered images are incorrect");
1280 	else
1281 		return tcu::TestStatus::pass("OK");
1282 }
1283 
testLayeredReadBack(Context & context,const TestParams params)1284 tcu::TestStatus testLayeredReadBack (Context& context, const TestParams params)
1285 {
1286 	const DeviceInterface&				vk					= context.getDeviceInterface();
1287 	const InstanceInterface&			vki					= context.getInstanceInterface();
1288 	const VkDevice						device				= context.getDevice();
1289 	const VkPhysicalDevice				physDevice			= context.getPhysicalDevice();
1290 	const deUint32						queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1291 	const VkQueue						queue				= context.getUniversalQueue();
1292 	Allocator&							allocator			= context.getDefaultAllocator();
1293 	VkDeviceSize						nonCoherentAtomSize = vk::getPhysicalDeviceProperties(vki, physDevice).limits.nonCoherentAtomSize;
1294 	VkDeviceSize						alignmentSize		= std::max<VkDeviceSize>(nonCoherentAtomSize, 4u);
1295 
1296 	const size_t						passCount			= 2;
1297 	const deUint32						numLayers			= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
1298 	const VkImageCreateFlags			imageCreateFlags	= (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
1299 															  (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
1300 	const VkImageViewType				viewType			= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
1301 	const VkImageType					imageType			= getImageType(params.image.viewType);
1302 	const VkExtent2D					imageExtent2D		= makeExtent2D(params.image.size.width, params.image.size.height);
1303 
1304 	const VkFormat						colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
1305 	const deUint32						colorImagePixelSize	= static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(colorFormat)));
1306 	const VkDeviceSize					colorBufferSize		= static_cast<VkDeviceSize>( deAlignSize(params.image.size.width * params.image.size.height * colorImagePixelSize, static_cast<std::size_t>(alignmentSize)) * params.image.size.depth * params.image.numLayers );
1307 	const VkImageUsageFlags				colorImageUsage		= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1308 
1309 	const bool							dsUsed				= true;
1310 	const VkFormat						dsFormat			= VK_FORMAT_D24_UNORM_S8_UINT;
1311 	const VkImageType					dsImageType			= (imageType == VK_IMAGE_TYPE_3D ? VK_IMAGE_TYPE_2D : imageType); // depth/stencil 2D_ARRAY attachments cannot be taken from 3D image, use 2D_ARRAY image instead.
1312 	const VkExtent3D					dsImageSize			= makeExtent3D(params.image.size.width, params.image.size.height, 1u);
1313 	const VkImageCreateFlags			dsImageCreateFlags	= (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0);
1314 	const deUint32						dsImagePixelSize	= static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(dsFormat)));
1315 	const VkImageUsageFlags				dsImageUsage		= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1316 	const VkImageAspectFlags			dsAspectFlags		= VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
1317 	const VkDeviceSize					depthBufferSize		= static_cast<VkDeviceSize>(deAlignSize(params.image.size.width * params.image.size.height * dsImagePixelSize, static_cast<std::size_t>(alignmentSize)) * params.image.size.depth * params.image.numLayers);
1318 
1319 	const VkFormat						stencilBufferFormat	= getStencilBufferFormat(dsFormat);
1320 	const deUint32						stencilPixelSize	= static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(stencilBufferFormat)));
1321 	const VkDeviceSize					stencilBufferSize	= static_cast<VkDeviceSize>(deAlignSize( params.image.size.width * params.image.size.height * stencilPixelSize, static_cast<std::size_t>(alignmentSize)) * params.image.size.depth * params.image.numLayers);
1322 
1323 	checkImageFormatProperties(vki, physDevice, imageType, VK_IMAGE_TILING_OPTIMAL, dsImageUsage, imageCreateFlags, dsFormat, params.image.size, params.image.numLayers);
1324 
1325 	const Unique<VkImage>				colorImage			(makeImage				(vk, device, makeImageCreateInfo(imageCreateFlags, imageType, colorFormat, params.image.size, params.image.numLayers, colorImageUsage)));
1326 	const UniquePtr<Allocation>			colorImageAlloc		(bindImage				(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1327 	const Unique<VkImageView>			colorAttachment		(makeImageView			(vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
1328 	const Unique<VkBuffer>				colorBuffer			(makeBuffer				(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1329 	const UniquePtr<Allocation>			colorBufferAlloc	(bindBuffer				(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1330 
1331 	const Unique<VkImage>				dsImage				(makeImage				(vk, device, makeImageCreateInfo(dsImageCreateFlags, dsImageType, dsFormat, dsImageSize, numLayers, dsImageUsage)));
1332 	const UniquePtr<Allocation>			dsImageAlloc		(bindImage				(vk, device, allocator, *dsImage, MemoryRequirement::Any));
1333 	const Unique<VkImageView>			dsAttachment		(makeImageView			(vk, device, *dsImage, viewType, dsFormat, makeImageSubresourceRange(dsAspectFlags, 0u, 1u, 0u, numLayers)));
1334 	const Unique<VkBuffer>				depthBuffer			(makeBuffer				(vk, device, depthBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1335 	const UniquePtr<Allocation>			depthBufferAlloc	(bindBuffer				(vk, device, allocator, *depthBuffer, MemoryRequirement::HostVisible));
1336 	const Unique<VkBuffer>				stencilBuffer		(makeBuffer				(vk, device, stencilBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1337 	const UniquePtr<Allocation>			stencilBufferAlloc	(bindBuffer				(vk, device, allocator, *stencilBuffer, MemoryRequirement::HostVisible));
1338 
1339 	const VkImageView					attachments[]		= {*colorAttachment, *dsAttachment};
1340 	const deUint32						attachmentsCount	= dsUsed ? DE_LENGTH_OF_ARRAY(attachments) : 1u;
1341 
1342 	const Unique<VkShaderModule>		vertexModule		(createShaderModule		(vk, device, context.getBinaryCollection().get("vert"), 0u));
1343 	const Unique<VkShaderModule>		geometryModule		(createShaderModule		(vk, device, context.getBinaryCollection().get("geom"), 0u));
1344 	const Unique<VkShaderModule>		fragmentModule		(createShaderModule		(vk, device, context.getBinaryCollection().get("frag"), 0u));
1345 
1346 	const Unique<VkRenderPass>			renderPass			(makeRenderPass			(vk, device, colorFormat, dsFormat, dsUsed));
1347 	const Unique<VkFramebuffer>			framebuffer			(makeFramebuffer		(vk, device, *renderPass, attachmentsCount, attachments, params.image.size.width, params.image.size.height, numLayers));
1348 
1349 	const Move<VkDescriptorPool>		descriptorPool		= DescriptorPoolBuilder()
1350 															  .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, passCount)
1351 															  .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, passCount);
1352 	const Move<VkDescriptorSetLayout>	descriptorSetLayout	= DescriptorSetLayoutBuilder()
1353 															  .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_GEOMETRY_BIT)
1354 															  .build(vk, device);
1355 	const Move<VkDescriptorSet>			descriptorSet[]		=
1356 	{
1357 		makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout),
1358 		makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout),
1359 	};
1360 
1361 	const size_t						uniformBufSize		= sizeof(deUint32);
1362 	const VkBufferCreateInfo			uniformBufCI		= makeBufferCreateInfo(uniformBufSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1363 	const Move<VkBuffer>				uniformBuf[]		= { createBuffer(vk, device, &uniformBufCI), createBuffer(vk, device, &uniformBufCI) };
1364 	const MovePtr<Allocation>			uniformBufAlloc[]	=
1365 	{
1366 		allocator.allocate(getBufferMemoryRequirements(vk, device, *uniformBuf[0]), MemoryRequirement::HostVisible),
1367 		allocator.allocate(getBufferMemoryRequirements(vk, device, *uniformBuf[1]), MemoryRequirement::HostVisible),
1368 	};
1369 	const VkDescriptorBufferInfo		uniformBufDesc[]	=
1370 	{
1371 		makeDescriptorBufferInfo(*uniformBuf[0], 0ull, uniformBufSize),
1372 		makeDescriptorBufferInfo(*uniformBuf[1], 0ull, uniformBufSize),
1373 	};
1374 
1375 	const Unique<VkPipelineLayout>		pipelineLayout		(makePipelineLayout		(vk, device, *descriptorSetLayout));
1376 	const Unique<VkPipeline>			pipeline			(makeGraphicsPipeline	(vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule, imageExtent2D, dsUsed));
1377 	const Unique<VkCommandPool>			cmdPool				(createCommandPool		(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1378 	const Unique<VkCommandBuffer>		cmdBuffer			(allocateCommandBuffer	(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1379 	const VkImageSubresourceRange		colorSubresRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers);
1380 	const VkImageSubresourceRange		dsSubresRange		= makeImageSubresourceRange(dsAspectFlags, 0u, 1u, 0u, numLayers);
1381 	std::string							result;
1382 
1383 	beginCommandBuffer(vk, *cmdBuffer);
1384 	{
1385 		// Transition the images to new layouts
1386 		const VkImageMemoryBarrier		colorBarrier	= makeImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1387 																				 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, *colorImage, colorSubresRange);
1388 		const VkImageMemoryBarrier		dsBarrier		= makeImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1389 																				 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, *dsImage, dsSubresRange);
1390 
1391 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorBarrier);
1392 
1393 		if (dsUsed)
1394 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsBarrier);
1395 
1396 		for (deUint32 layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1397 		{
1398 			const VkExtent3D	imageExtent = makeExtent3D(params.image.size.width, params.image.size.height, 1u);
1399 
1400 			// Clear color image with initial value
1401 			{
1402 				const deUint32					layer					= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? 0u : layerNdx;
1403 				const deUint32					imageDepth				= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? layerNdx : 0u;
1404 				const VkOffset3D				imageOffset				= makeOffset3D(0u, 0u, imageDepth);
1405 
1406 				const tcu::Vec4					clearColor				= scaleColor(s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)], 0.25f);
1407 				const deUint32					bufferSliceSize			= deAlign32( params.image.size.width * params.image.size.height * colorImagePixelSize, static_cast<deInt32>(alignmentSize));
1408 				const VkDeviceSize				bufferOffset			= layerNdx * bufferSliceSize;
1409 				const VkImageSubresourceLayers	imageSubresource		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, layer, 1u);
1410 				const VkBufferImageCopy			bufferImageCopyRegion	= makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
1411 
1412 				fillBuffer(vk, device, *colorBufferAlloc, bufferOffset, bufferSliceSize, colorFormat, clearColor);
1413 				vk.cmdCopyBufferToImage(*cmdBuffer, *colorBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1414 			}
1415 
1416 			// Clear depth image with initial value
1417 			if (dsUsed)
1418 			{
1419 				const float						depthValue				= 1.0f;
1420 				const deUint32					bufferSliceSize			= deAlign32( params.image.size.width * params.image.size.height * dsImagePixelSize, static_cast<deInt32>(alignmentSize));
1421 				const VkDeviceSize				bufferOffset			= layerNdx * bufferSliceSize;
1422 				const VkImageSubresourceLayers	imageSubresource		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, layerNdx, 1u);
1423 				const VkBufferImageCopy			bufferImageCopyRegion	= makeBufferImageCopy(bufferOffset, imageSubresource, makeOffset3D(0u, 0u, 0u), imageExtent);
1424 
1425 				fillBuffer(vk, device, *depthBufferAlloc, bufferOffset, bufferSliceSize, dsFormat, depthValue);
1426 				vk.cmdCopyBufferToImage(*cmdBuffer, *depthBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1427 			}
1428 
1429 			// Clear stencil image with initial value
1430 			if (dsUsed)
1431 			{
1432 				const deUint8					stencilValue			= 0;
1433 				const deUint32					bufferSliceSize			= deAlign32( params.image.size.width * params.image.size.height * stencilPixelSize, static_cast<deInt32>(alignmentSize));
1434 				const VkDeviceSize				bufferOffset			= layerNdx * bufferSliceSize;
1435 				const VkImageSubresourceLayers	imageSubresource		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, layerNdx, 1u);
1436 				const VkBufferImageCopy			bufferImageCopyRegion	= makeBufferImageCopy(bufferOffset, imageSubresource, makeOffset3D(0u, 0u, 0u), imageExtent);
1437 				deUint8*						bufferStart				= static_cast<deUint8*>((*stencilBufferAlloc).getHostPtr());
1438 				deUint8*						bufferLayerStart		= &bufferStart[bufferOffset];
1439 
1440 				deMemset(bufferLayerStart, stencilValue, bufferSliceSize);
1441 				flushMappedMemoryRange(vk, device, stencilBufferAlloc->getMemory(), stencilBufferAlloc->getOffset() + bufferOffset, bufferSliceSize);
1442 				vk.cmdCopyBufferToImage(*cmdBuffer, *stencilBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1443 			}
1444 		}
1445 	}
1446 	// Change images layouts
1447 	{
1448 		// VK_ATTACHMENT_LOAD_OP_LOAD is used for both color and D/S attachments. Thus,
1449 		// VK_ACCESS_COLOR_ATTACHMENT_READ_BIT and VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
1450 		// bits must be included in the destination access mask of the color and depth barriers
1451 		// respectively.
1452 		const VkImageMemoryBarrier		colorBarrier	= makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
1453 																				 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresRange);
1454 		const VkImageMemoryBarrier		dsBarrier		= makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1455 																				 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *dsImage, dsSubresRange);
1456 
1457 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorBarrier);
1458 
1459 		if (dsUsed)
1460 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsBarrier);
1461 	}
1462 
1463 	{
1464 		// These barriers are inserted between each pair of renderpasses in the following
1465 		// loop. Note that VK_ATTACHMENT_LOAD_OP_LOAD is used for color and D/S attachments
1466 		// hence VK_ACCESS_COLOR_ATTACHMENT_READ_BIT and VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
1467 		// bits are included in src and dst access mask of the color and depth barriers.
1468 		const VkImageMemoryBarrier			colorPassBarrier	= makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
1469 																						 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
1470 																						 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresRange);
1471 		const VkImageMemoryBarrier			dsPassBarrier		= makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1472 																						 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1473 																						 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *dsImage, dsSubresRange);
1474 		for (deUint32 pass = 0; pass < passCount; ++pass)
1475 		{
1476 			DE_ASSERT(sizeof(pass) == uniformBufSize);
1477 
1478 			VK_CHECK(vk.bindBufferMemory(device, *uniformBuf[pass], uniformBufAlloc[pass]->getMemory(), uniformBufAlloc[pass]->getOffset()));
1479 			deMemcpy(uniformBufAlloc[pass]->getHostPtr(), &pass, uniformBufSize);
1480 			flushMappedMemoryRange(vk, device, uniformBufAlloc[pass]->getMemory(), uniformBufAlloc[pass]->getOffset(), VK_WHOLE_SIZE);
1481 
1482 			DescriptorSetUpdateBuilder()
1483 				.writeSingle(*descriptorSet[pass], DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufDesc[pass])
1484 				.update(vk, device);
1485 
1486 			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet[pass], 0u, DE_NULL);
1487 			beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(imageExtent2D));
1488 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1489 			vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1490 			endRenderPass(vk, *cmdBuffer);
1491 
1492 			// Don't add the barrier after the last renderpass
1493 			if (pass < passCount - 1)
1494 			{
1495 				vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorPassBarrier);
1496 
1497 				if (dsUsed)
1498 					vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsPassBarrier);
1499 			}
1500 		}
1501 	}
1502 	endCommandBuffer(vk, *cmdBuffer);
1503 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1504 
1505 	zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
1506 	zeroBuffer(vk, device, *depthBufferAlloc, depthBufferSize);
1507 	zeroBuffer(vk, device, *stencilBufferAlloc, stencilBufferSize);
1508 
1509 	beginCommandBuffer(vk, *cmdBuffer);
1510 	{
1511 		// Copy color image
1512 		{
1513 			const VkImageMemoryBarrier	preCopyBarrier	= makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
1514 																				 VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorImage, colorSubresRange);
1515 			const VkBufferImageCopy		region			= makeBufferImageCopy(params.image.size, makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, params.image.numLayers));
1516 			const VkBufferMemoryBarrier	postCopyBarrier	= makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, VK_WHOLE_SIZE);
1517 
1518 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1519 			vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
1520 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &postCopyBarrier, DE_NULL, 0u);
1521 		}
1522 
1523 		// Depth/Stencil image copy
1524 		if (dsUsed)
1525 		{
1526 			const VkImageMemoryBarrier	preCopyBarrier		= makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1527 																					 VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dsImage, dsSubresRange);
1528 			const VkBufferImageCopy		depthCopyRegion		= makeBufferImageCopy(dsImageSize, makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, numLayers));
1529 			const VkBufferImageCopy		stencilCopyRegion	= makeBufferImageCopy(dsImageSize, makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, numLayers));
1530 			const VkBufferMemoryBarrier	postCopyBarriers[]	=
1531 			{
1532 				makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *depthBuffer, 0ull, VK_WHOLE_SIZE),
1533 				makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *stencilBuffer, 0ull, VK_WHOLE_SIZE),
1534 			};
1535 
1536 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1537 			vk.cmdCopyImageToBuffer(*cmdBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *depthBuffer, 1u, &depthCopyRegion);
1538 			vk.cmdCopyImageToBuffer(*cmdBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *stencilBuffer, 1u, &stencilCopyRegion);
1539 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(postCopyBarriers), postCopyBarriers, DE_NULL, 0u);
1540 		}
1541 	}
1542 	endCommandBuffer(vk, *cmdBuffer);
1543 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1544 
1545 	invalidateAlloc(vk, device, *colorBufferAlloc);
1546 	invalidateAlloc(vk, device, *depthBufferAlloc);
1547 	invalidateAlloc(vk, device, *stencilBufferAlloc);
1548 
1549 	if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1550 		result += " Color";
1551 
1552 	if (dsUsed)
1553 	{
1554 		if (!verifyResults(context.getTestContext().getLog(), params, dsFormat, depthBufferAlloc->getHostPtr(), true, false))
1555 			result += " Depth";
1556 
1557 		if (!verifyResults(context.getTestContext().getLog(), params, stencilBufferFormat, stencilBufferAlloc->getHostPtr(), false, true))
1558 			result += " Stencil";
1559 	}
1560 
1561 	if (result.empty())
1562 		return tcu::TestStatus::pass("OK");
1563 	else
1564 		return tcu::TestStatus::fail("Following parts of image are incorrect:" + result);
1565 }
1566 
testSecondaryCmdBuffer(Context & context,const TestParams params)1567 tcu::TestStatus testSecondaryCmdBuffer (Context& context, const TestParams params)
1568 {
1569 	const DeviceInterface&				vk					= context.getDeviceInterface();
1570 	const InstanceInterface&			vki					= context.getInstanceInterface();
1571 	const VkDevice						device				= context.getDevice();
1572 	const VkPhysicalDevice				physDevice			= context.getPhysicalDevice();
1573 	const deUint32						queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1574 	const VkQueue						queue				= context.getUniversalQueue();
1575 	Allocator&							allocator			= context.getDefaultAllocator();
1576 	VkDeviceSize						nonCoherentAtomSize	= vk::getPhysicalDeviceProperties(vki, physDevice).limits.nonCoherentAtomSize;
1577 	VkDeviceSize						alignmentSize		= std::max<VkDeviceSize>(nonCoherentAtomSize, 4u);
1578 
1579 	const VkFormat						colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
1580 	const deUint32						numLayers			= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
1581 	const Vec4							clearColor			= Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1582 	const deUint32						colorImagePixelSize	= static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(colorFormat)));
1583 	const VkDeviceSize					colorBufferSize		= static_cast<VkDeviceSize>(deAlignSize(params.image.size.width * params.image.size.height * colorImagePixelSize, static_cast<std::size_t>(alignmentSize)) * params.image.size.depth * params.image.numLayers);
1584 
1585 	const VkImageCreateFlags			imageCreateFlags	= (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
1586 															  (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
1587 	const VkImageViewType				viewType			= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
1588 
1589 	const Unique<VkImage>				colorImage			(makeImage(vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
1590 																	   params.image.numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1591 	const UniquePtr<Allocation>			colorImageAlloc		(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1592 	const Unique<VkImageView>			colorImageView		(makeImageView(vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
1593 
1594 	const Unique<VkImage>				offscreenImage		(makeImage(vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
1595 																	   params.image.numLayers, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)));
1596 	const UniquePtr<Allocation>			offscreenImageAlloc	(bindImage(vk, device, allocator, *offscreenImage, MemoryRequirement::Any));
1597 	const Unique<VkImageView>			offscreenImageView	(makeImageView(vk, device, *offscreenImage, params.image.viewType, colorFormat,
1598 																		   makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers)));
1599 
1600 	const Unique<VkBuffer>				colorBuffer			(makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1601 	const UniquePtr<Allocation>			colorBufferAlloc	(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1602 
1603 	const Move<VkDescriptorPool>		descriptorPool		= DescriptorPoolBuilder() .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u) .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1604 	const Move<VkDescriptorSetLayout>	descriptorSetLayout	= DescriptorSetLayoutBuilder() .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT) .build(vk, device);
1605 	const Move<VkDescriptorSet>			descriptorSet		= makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
1606 
1607 	const Unique<VkShaderModule>		vertexModule		(createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
1608 	const Unique<VkShaderModule>		geometryModule		(createShaderModule(vk, device, context.getBinaryCollection().get("geom"), 0u));
1609 	const Unique<VkShaderModule>		fragmentModule		(createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
1610 
1611 	const Unique<VkRenderPass>			renderPass			(makeRenderPassWithSelfDependency(vk, device, colorFormat));
1612 	const Unique<VkFramebuffer>			framebuffer			(makeFramebuffer(vk, device, *renderPass, *colorImageView, params.image.size.width, params.image.size.height, numLayers));
1613 	const Unique<VkPipelineLayout>		pipelineLayout		(makePipelineLayout(vk, device, *descriptorSetLayout));
1614 	const Unique<VkPipeline>			pipeline			(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule,
1615 																				  makeExtent2D(params.image.size.width, params.image.size.height)));
1616 
1617 	const Unique<VkCommandPool>			cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1618 	const Unique<VkCommandBuffer>		cmdBuffer			(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1619 	const Unique<VkCommandBuffer>		secondaryCmdBuffer	(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY));
1620 
1621 	zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
1622 
1623 	const VkDescriptorImageInfo imageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *offscreenImageView, VK_IMAGE_LAYOUT_GENERAL);
1624 
1625 	DescriptorSetUpdateBuilder()
1626 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageDescriptorInfo)
1627 		.update(vk, device);
1628 
1629 	// Clear each layer of storage image
1630 	{
1631 		vk::Unique<vk::VkCommandBuffer> clearCmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1632 		beginCommandBuffer(vk, *clearCmdBuffer);
1633 
1634 		const vk::VkImageSubresourceRange	subresourceRange	=
1635 		{
1636 			vk::VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask
1637 			0u,								// deUint32				baseMipLevel
1638 			1u,								// deUint32				levelCount
1639 			0u,								// deUint32				baseArrayLayer
1640 			params.image.numLayers			// deUint32				layerCount
1641 		};
1642 
1643 		const vk::VkImageMemoryBarrier		preImageBarrier		=
1644 		{
1645 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,	// VkStructureType			sType
1646 			DE_NULL,									// const void*				pNext
1647 			0u,											// VkAccessFlags			srcAccessMask
1648 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,			// VkAccessFlags			dstAccessMask
1649 			vk::VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			oldLayout
1650 			vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,	// VkImageLayout			newLayout
1651 			queueFamilyIndex,							// deUint32					srcQueueFamilyIndex
1652 			queueFamilyIndex,							// deUint32					dstQueueFamilyIndex
1653 			*offscreenImage,							// VkImage					image
1654 			subresourceRange							// VkImageSubresourceRange	subresourceRange
1655 		};
1656 
1657 		const vk::VkImageMemoryBarrier		postImageBarrier	=
1658 		{
1659 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,	// VkStructureType			sType
1660 			DE_NULL,									// const void*				pNext
1661 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,			// VkAccessFlags			srcAccessMask
1662 			vk::VK_ACCESS_SHADER_WRITE_BIT,				// VkAccessFlags			dstAccessMask
1663 			vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,	// VkImageLayout			oldLayout
1664 			vk::VK_IMAGE_LAYOUT_GENERAL,				// VkImageLayout			newLayout
1665 			queueFamilyIndex,							// deUint32					srcQueueFamilyIndex
1666 			queueFamilyIndex,							// deUint32					dstQueueFamilyIndex
1667 			*offscreenImage,							// VkImage					image
1668 			subresourceRange							// VkImageSubresourceRange	subresourceRange
1669 		};
1670 
1671 		vk.cmdPipelineBarrier(*clearCmdBuffer,
1672 				vk::VK_PIPELINE_STAGE_HOST_BIT,
1673 				vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
1674 				(vk::VkDependencyFlags)0,
1675 				0, (const vk::VkMemoryBarrier*)DE_NULL,
1676 				0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1677 				1, &preImageBarrier);
1678 
1679 		for (deUint32 layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1680 		{
1681 			const deUint32		imageDepth	= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? layerNdx :       0u;
1682 			const deUint32		layer		= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ?       0u : layerNdx;
1683 			const VkOffset3D	imageOffset = makeOffset3D(0u, 0u, imageDepth);
1684 			const VkExtent3D	imageExtent = makeExtent3D(params.image.size.width, params.image.size.height, 1u);
1685 
1686 			{
1687 				const tcu::Vec4					storageImageClearColor	= secondaryCmdBufClearColors[layerNdx % DE_LENGTH_OF_ARRAY(secondaryCmdBufClearColors)];
1688 				const deUint32					bufferSliceSize			= deAlign32(params.image.size.width * params.image.size.height * colorImagePixelSize, static_cast<deInt32>(alignmentSize));
1689 				const VkDeviceSize				bufferOffset			= layerNdx * bufferSliceSize;
1690 				const VkImageSubresourceLayers	imageSubresource		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, layer, 1u);
1691 				const VkBufferImageCopy			bufferImageCopyRegion	= makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
1692 
1693 				fillBuffer(vk, device, *colorBufferAlloc, bufferOffset, bufferSliceSize, colorFormat, storageImageClearColor);
1694 				vk.cmdCopyBufferToImage(*clearCmdBuffer, *colorBuffer, *offscreenImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1695 			}
1696 		}
1697 
1698 		vk.cmdPipelineBarrier(*clearCmdBuffer,
1699 				vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
1700 				vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
1701 				(vk::VkDependencyFlags)0,
1702 				0, (const vk::VkMemoryBarrier*)DE_NULL,
1703 				0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1704 				1, &postImageBarrier);
1705 
1706 		endCommandBuffer(vk, *clearCmdBuffer);
1707 
1708 		submitCommandsAndWait(vk, device, queue, *clearCmdBuffer);
1709 	}
1710 
1711 	// Begin secondary command buffer
1712 	{
1713 		const VkCommandBufferInheritanceInfo	commandBufferInheritanceInfo	=
1714 		{
1715 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,				// VkStructureType					sType
1716 			DE_NULL,														// const void*						pNext
1717 			*renderPass,													// VkRenderPass						renderPass
1718 			0u,																// deUint32							subpass
1719 			params.inheritFramebuffer ? *framebuffer : (VkFramebuffer)0,	// VkFramebuffer					framebuffer
1720 			VK_FALSE,														// VkBool32							occlusionQueryEnable
1721 			0u,																// VkQueryControlFlags				queryFlags
1722 			0u																// VkQueryPipelineStatisticFlags	pipelineStatistics
1723 		};
1724 
1725 		const VkCommandBufferBeginInfo			commandBufferBeginInfo			=
1726 		{
1727 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,		// VkStructureType							sType
1728 			DE_NULL,											// const void*								pNext
1729 			VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
1730 			| VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,	// VkCommandBufferUsageFlags				flags
1731 			&commandBufferInheritanceInfo						// const VkCommandBufferInheritanceInfo*	pInheritanceInfo
1732 		};
1733 
1734 		VK_CHECK(vk.beginCommandBuffer(*secondaryCmdBuffer, &commandBufferBeginInfo));
1735 	}
1736 
1737 	vk.cmdBindDescriptorSets(*secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
1738 
1739 	// Clear framebuffer: upper right corner for half of the layers and bottom right for the others.
1740 	{
1741 		const VkClearAttachment	clearAttachment	=
1742 		{
1743 			VK_IMAGE_ASPECT_COLOR_BIT,						// VkImageAspectFlags	aspectMask
1744 			0u,												// deUint32				colorAttachment
1745 			makeClearValueColorF32(0.5f, 0.25, 0.0f, 1.0f)	// VkClearValue			clearValue
1746 		};
1747 
1748 		const VkOffset2D		offsetTop		= { (deInt32)params.image.size.width / 2, 0 };
1749 		const VkOffset2D		offsetBottom	= { (deInt32)params.image.size.width / 2, (deInt32)params.image.size.height / 2 };
1750 		const VkExtent2D		extentTop		= { params.image.size.width / 2, params.image.size.height / 2 };
1751 		const VkExtent2D		extentBottom	= { params.image.size.width / 2, de::max(params.image.size.height / 2, 1u) };
1752 		const VkRect2D			rectRightTop	= { offsetTop, extentTop };
1753 		const VkRect2D			rectRightBottom	= { offsetBottom, extentBottom };
1754 
1755 		const VkClearRect		rects[]			=
1756 		{
1757 			{
1758 				rectRightBottom,	// VkRect2D	rect
1759 				numLayers / 2,		// deUint32	baseArrayLayer
1760 				numLayers / 2		// deUint32	layerCount
1761 			},
1762 			{
1763 				rectRightTop,		// VkRect2D	rect
1764 				0u,					// deUint32	baseArrayLayer
1765 				numLayers / 2		// deUint32	layerCount
1766 			}
1767 		};
1768 
1769 		vk.cmdClearAttachments(*secondaryCmdBuffer, 1u, &clearAttachment, extentTop.height > 0 ? 2u : 1u, rects);
1770 	}
1771 
1772 	vk.cmdBindPipeline(*secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1773 	vk.cmdDraw(*secondaryCmdBuffer, 1u, 1u, 0u, 0u);
1774 	// Barrier between draws
1775 	{
1776 		const VkMemoryBarrier barrier =
1777 		{
1778 			VK_STRUCTURE_TYPE_MEMORY_BARRIER,	// VkStructureType	sType
1779 			DE_NULL,							// const void*		pNext
1780 			VK_ACCESS_SHADER_WRITE_BIT,			// VkAccessFlags	srcAccessMask
1781 			VK_ACCESS_SHADER_READ_BIT			// VkAccessFlags	dstAccessMask
1782 		};
1783 
1784 		vk.cmdPipelineBarrier(*secondaryCmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 1u, &barrier, 0u, DE_NULL, 0u, DE_NULL);
1785 	}
1786 	vk.cmdDraw(*secondaryCmdBuffer, 1u, 1u, 0u, 0u);
1787 	endCommandBuffer(vk, *secondaryCmdBuffer);
1788 
1789 	beginCommandBuffer(vk, *cmdBuffer);
1790 	beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, params.image.size.width, params.image.size.height), clearColor, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
1791 	vk.cmdExecuteCommands(*cmdBuffer, 1u, &(*secondaryCmdBuffer));
1792 	endRenderPass(vk, *cmdBuffer);
1793 
1794 	copyLayeredImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, params.image);
1795 
1796 	endCommandBuffer(vk, *cmdBuffer);
1797 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1798 
1799 	invalidateAlloc(vk, device, *colorBufferAlloc);
1800 
1801 	if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1802 		return tcu::TestStatus::fail("Rendered images are incorrect");
1803 	else
1804 		return tcu::TestStatus::pass("OK");
1805 }
1806 
checkSupport(Context & context,const TestParams params)1807 void checkSupport (Context& context, const TestParams params)
1808 {
1809 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
1810 
1811 	if (params.image.viewType == VK_IMAGE_VIEW_TYPE_3D)
1812 		context.requireDeviceFunctionality("VK_KHR_maintenance1");
1813 
1814 	if (params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER)
1815 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
1816 }
1817 
1818 } // anonymous
1819 
createLayeredRenderingTests(tcu::TestContext & testCtx)1820 tcu::TestCaseGroup* createLayeredRenderingTests (tcu::TestContext& testCtx)
1821 {
1822 	MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "layered", "Layered rendering tests."));
1823 
1824 	const struct
1825 	{
1826 		TestType		test;
1827 		const char*		name;
1828 		const char*		description;
1829 	} testTypes[] =
1830 	{
1831 		{ TEST_TYPE_DEFAULT_LAYER,					"render_to_default_layer",			"Render to the default layer"															},
1832 		{ TEST_TYPE_SINGLE_LAYER,					"render_to_one",					"Render to one layer"																	},
1833 		{ TEST_TYPE_ALL_LAYERS,						"render_to_all",					"Render to all layers"																	},
1834 		{ TEST_TYPE_DIFFERENT_CONTENT,				"render_different_content",			"Render different data to different layers"												},
1835 		{ TEST_TYPE_LAYER_ID,						"fragment_layer",					"Read gl_Layer in fragment shader"														},
1836 		{ TEST_TYPE_INVOCATION_PER_LAYER,			"invocation_per_layer",				"Render to multiple layers with multiple invocations, one invocation per layer"			},
1837 		{ TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION,	"multiple_layers_per_invocation",	"Render to multiple layers with multiple invocations, multiple layers per invocation",	},
1838 		{ TEST_TYPE_LAYERED_READBACK,				"readback",							"Render to multiple layers with two passes to check LOAD_OP_LOAD capability"			},
1839 		{ TEST_TYPE_SECONDARY_CMD_BUFFER,			"secondary_cmd_buffer",				"Layered rendering using secondary command buffer"										}
1840 	};
1841 
1842 	const struct
1843 	{
1844 		VkImageViewType	viewType;
1845 		ImageParams		imageParams[2];
1846 	} imageParamGroups[] =
1847 	{
1848 		{ VK_IMAGE_VIEW_TYPE_1D_ARRAY,		{ { VK_IMAGE_VIEW_TYPE_1D_ARRAY,	{ 64,  1, 1 },	4	},	{ VK_IMAGE_VIEW_TYPE_1D_ARRAY,		{ 12,  1, 1 },	6	} } },
1849 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		{ { VK_IMAGE_VIEW_TYPE_2D_ARRAY,	{ 64, 64, 1 },	4	},	{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		{ 12, 36, 1 },	6	} } },
1850 		{ VK_IMAGE_VIEW_TYPE_CUBE,			{ { VK_IMAGE_VIEW_TYPE_CUBE,		{ 64, 64, 1 },	6	},	{ VK_IMAGE_VIEW_TYPE_CUBE,			{ 36, 36, 1 },	6	} } },
1851 		{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	{ { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	{ 64, 64, 1 },	2*6	},	{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	{ 36, 36, 1 },	2*6	} } },
1852 		{ VK_IMAGE_VIEW_TYPE_3D,			{ { VK_IMAGE_VIEW_TYPE_3D,			{ 64, 64, 8 },	1	},	{ VK_IMAGE_VIEW_TYPE_3D,			{ 12, 36, 6 },	1	} } }
1853 	};
1854 
1855 	for (int imageParamGroupNdx = 0; imageParamGroupNdx < DE_LENGTH_OF_ARRAY(imageParamGroups); ++imageParamGroupNdx)
1856 	{
1857 		MovePtr<tcu::TestCaseGroup> viewTypeMainGroup(new tcu::TestCaseGroup(testCtx, getShortImageViewTypeName(imageParamGroups[imageParamGroupNdx].viewType).c_str(), ""));
1858 
1859 		for (int imageParamNdx = 0; imageParamNdx < 2; imageParamNdx++)
1860 		{
1861 			std::ostringstream viewTypeGroupName;
1862 			viewTypeGroupName << imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].size.width << "_" << imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].size.height << "_";
1863 			if (imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].viewType == VK_IMAGE_VIEW_TYPE_3D)
1864 				viewTypeGroupName << imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].size.depth;
1865 			else
1866 				viewTypeGroupName << imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].numLayers;
1867 			MovePtr<tcu::TestCaseGroup> viewTypeGroup(new tcu::TestCaseGroup(testCtx, viewTypeGroupName.str().c_str(), ""));
1868 
1869 			for (int testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx)
1870 			{
1871 				TestParams params =
1872 				{
1873 					testTypes[testTypeNdx].test,
1874 					imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx],
1875 					false
1876 				};
1877 
1878 				if (testTypes[testTypeNdx].test == TEST_TYPE_LAYERED_READBACK)
1879 					addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, checkSupport, initPrograms, testLayeredReadBack, params);
1880 				else if (testTypes[testTypeNdx].test == TEST_TYPE_SECONDARY_CMD_BUFFER)
1881 				{
1882 					addFunctionCaseWithPrograms(viewTypeGroup.get(), "secondary_cmd_buffer", testTypes[testTypeNdx].description, checkSupport, initPrograms, testSecondaryCmdBuffer, params);
1883 					params.inheritFramebuffer = true;
1884 					addFunctionCaseWithPrograms(viewTypeGroup.get(), "secondary_cmd_buffer_inherit_framebuffer", testTypes[testTypeNdx].description, checkSupport, initPrograms, testSecondaryCmdBuffer, params);
1885 				}
1886 				else
1887 					addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, checkSupport, initPrograms, test, params);
1888 			}
1889 			viewTypeMainGroup->addChild(viewTypeGroup.release());
1890 		}
1891 		group->addChild(viewTypeMainGroup.release());
1892 	}
1893 
1894 	return group.release();
1895 }
1896 
1897 } // geometry
1898 } // vkt
1899