• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 	// Note: this is never reached
539 	log << tcu::TestLog::Image("LayerContent", "Layer content", image);
540 
541 	return allPixelsOk;
542 }
543 
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)544 static bool verifyImageMultipleBars (tcu::TestLog&						log,
545 									 const tcu::ConstPixelBufferAccess	image,
546 									 const float*						barWidthRatios,
547 									 const tcu::Vec4*					barValues,
548 									 const int							barsCount,
549 									 const int							numUsedChannels,
550 									 const std::string&					imageTypeName)
551 {
552 	const Vec4					green				(0.0f, 1.0f, 0.0f, 1.0f);
553 	const Vec4					red					(1.0f, 0.0f, 0.0f, 1.0f);
554 	const Vec4					threshold			(0.02f);
555 	const tcu::TextureFormat	errorMaskFormat		(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8));
556 	tcu::TextureLevel			errorMask			(errorMaskFormat, image.getWidth(), image.getHeight());
557 	tcu::PixelBufferAccess		errorMaskAccess		= errorMask.getAccess();
558 	bool						allPixelsOk			= true;
559 
560 	DE_ASSERT(barsCount > 0);
561 
562 	tcu::clear(errorMask.getAccess(), green);
563 
564 	// Format information message
565 	{
566 		int					leftBorder	= 0;
567 		int					rightBorder	= 0;
568 		std::ostringstream	str;
569 
570 		for (int barNdx = 0; barNdx < barsCount; ++barNdx)
571 		{
572 			leftBorder	= rightBorder;
573 			rightBorder	= static_cast<int>(barWidthRatios[barNdx] * static_cast<float>(image.getWidth()));
574 
575 			DE_ASSERT(leftBorder < rightBorder);
576 
577 			str << std::endl << " [" << leftBorder << "," <<rightBorder << "): ";
578 
579 			switch (numUsedChannels)
580 			{
581 				case 1:	str << barValues[barNdx][0];	break;
582 				case 4:	str << barValues[barNdx];		break;
583 				default: DE_ASSERT(false);				break;
584 			}
585 		}
586 
587 		log << tcu::TestLog::Message
588 			<< "Expecting " + imageTypeName + " values depending x-axis position to be of following values: "
589 			<< str.str()
590 			<< tcu::TestLog::EndMessage;
591 	}
592 
593 	for (int x = 0; x < image.getWidth();  ++x)
594 	{
595 		tcu::Vec4	expectedValue	= barValues[0];
596 
597 		for (int barNdx = 0; barNdx < barsCount; ++barNdx)
598 		{
599 			const int rightBorder	= static_cast<int>(barWidthRatios[barNdx] * static_cast<float>(image.getWidth()));
600 
601 			if (x < rightBorder)
602 			{
603 				expectedValue = barValues[barNdx];
604 
605 				break;
606 			}
607 		}
608 
609 		for (int y = 0; y < image.getHeight(); ++y)
610 		{
611 			const tcu::Vec4	realValue	= image.getPixel(x, y);
612 			bool			isOk		= false;
613 
614 			switch (numUsedChannels)
615 			{
616 				case 1:	isOk = fabs(realValue[0] - expectedValue[0]) < threshold[0];	break;
617 				case 4:	isOk = compareColors(realValue, expectedValue, threshold);		break;
618 				default: DE_ASSERT(false);												break;
619 			}
620 
621 			if (!isOk)
622 				errorMaskAccess.setPixel(red, x, y);
623 
624 			allPixelsOk = allPixelsOk && isOk;
625 		}
626 	}
627 
628 	if (allPixelsOk)
629 	{
630 		log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
631 			<< tcu::TestLog::ImageSet(imageTypeName + "LayerContent", imageTypeName + " Layer Content")
632 			<< tcu::TestLog::Image("Layer", "Layer", image)
633 			<< tcu::TestLog::EndImageSet;
634 	}
635 	else
636 	{
637 		log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
638 			<< tcu::TestLog::ImageSet(imageTypeName + "LayerContent", imageTypeName + " Layer Content")
639 			<< tcu::TestLog::Image("Layer",		"Layer",	image)
640 			<< tcu::TestLog::Image("ErrorMask",	"Errors",	errorMask)
641 			<< tcu::TestLog::EndImageSet;
642 	}
643 
644 	return allPixelsOk;
645 }
646 
convertDepthToColorBufferAccess(const tcu::ConstPixelBufferAccess & inputImage,tcu::PixelBufferAccess & outputImage)647 static void convertDepthToColorBufferAccess (const tcu::ConstPixelBufferAccess& inputImage, tcu::PixelBufferAccess& outputImage)
648 {
649 	for (int y = 0; y < inputImage.getHeight(); y++)
650 	for (int x = 0; x < inputImage.getWidth(); x++)
651 	{
652 		const float		depth	= inputImage.getPixDepth(x, y);
653 		const tcu::Vec4	color	= tcu::Vec4(depth, depth, depth, 1.0f);
654 
655 		outputImage.setPixel(color, x, y);
656 	}
657 }
658 
convertStencilToColorBufferAccess(const tcu::ConstPixelBufferAccess & inputImage,tcu::PixelBufferAccess & outputImage,int maxValue)659 static void convertStencilToColorBufferAccess (const tcu::ConstPixelBufferAccess& inputImage, tcu::PixelBufferAccess& outputImage, int maxValue)
660 {
661 	for (int y = 0; y < inputImage.getHeight(); y++)
662 	for (int x = 0; x < inputImage.getWidth(); x++)
663 	{
664 		const int		stencilInt	= inputImage.getPixStencil(x, y);
665 		const float		stencil		= (stencilInt < maxValue) ? float(stencilInt) / float(maxValue) : 1.0f;
666 		const tcu::Vec4	color		= tcu::Vec4(stencil, stencil, stencil, 1.0f);
667 
668 		outputImage.setPixel(color, x, y);
669 	}
670 }
671 
verifyEmptyImage(tcu::TestLog & log,const tcu::ConstPixelBufferAccess image)672 bool verifyEmptyImage (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image)
673 {
674 	log << tcu::TestLog::Message << "Expecting empty image" << tcu::TestLog::EndMessage;
675 
676 	const Vec4	black		(0.0f, 0.0f, 0.0f, 1.0f);
677 	const Vec4	threshold	(0.02f);
678 
679 	for (int y = 0; y < image.getHeight(); ++y)
680 	for (int x = 0; x < image.getWidth();  ++x)
681 	{
682 		const Vec4 color = image.getPixel(x, y);
683 
684 		if (!compareColors(color, black, threshold))
685 		{
686 			log	<< tcu::TestLog::Message
687 				<< "Found (at least) one bad pixel at " << x << "," << y << ". Pixel color is not background color."
688 				<< tcu::TestLog::EndMessage
689 				<< tcu::TestLog::ImageSet("LayerContent", "Layer content")
690 				<< tcu::TestLog::Image("Layer", "Layer", image)
691 				<< tcu::TestLog::EndImageSet;
692 			return false;
693 		}
694 	}
695 
696 	log << tcu::TestLog::Message << "Image is valid" << tcu::TestLog::EndMessage;
697 
698 	return true;
699 }
700 
verifyLayerContent(tcu::TestLog & log,const TestType testType,const tcu::ConstPixelBufferAccess image,const int layerNdx,const int numLayers,const bool depthCheck,const bool stencilCheck)701 bool verifyLayerContent (tcu::TestLog& log, const TestType testType, const tcu::ConstPixelBufferAccess image, const int layerNdx, const int numLayers, const bool depthCheck, const bool stencilCheck)
702 {
703 	const Vec4	white				(1.0f, 1.0f, 1.0f, 1.0f);
704 	const int	targetLayer			= numLayers / 2;
705 	const float	variableBarRatio	= static_cast<float>(layerNdx) / static_cast<float>(numLayers);
706 
707 	switch (testType)
708 	{
709 		case TEST_TYPE_DEFAULT_LAYER:
710 			if (layerNdx == 0)
711 				return verifyImageSingleColoredRow(log, image, 0.5f, white);
712 			else
713 				return verifyEmptyImage(log, image);
714 
715 		case TEST_TYPE_SINGLE_LAYER:
716 			if (layerNdx == targetLayer)
717 				return verifyImageSingleColoredRow(log, image, 0.5f, white);
718 			else
719 				return verifyEmptyImage(log, image);
720 
721 		case TEST_TYPE_ALL_LAYERS:
722 		case TEST_TYPE_INVOCATION_PER_LAYER:
723 			return verifyImageSingleColoredRow(log, image, 0.5f, s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
724 
725 		case TEST_TYPE_DIFFERENT_CONTENT:
726 		case TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION:
727 			if (layerNdx == 0)
728 				return verifyEmptyImage(log, image);
729 			else
730 				return verifyImageSingleColoredRow(log, image, variableBarRatio, white);
731 
732 		case TEST_TYPE_LAYER_ID:
733 		{
734 			// This code must be in sync with the fragment shader.
735 			const tcu::Vec4 layerColor( (layerNdx    % 2) == 1 ? 1.0f : 0.5f,
736 									   ((layerNdx/2) % 2) == 1 ? 1.0f : 0.5f,
737 									     layerNdx         == 0 ? 1.0f : 0.0f,
738 																 1.0f);
739 			return verifyImageSingleColoredRow(log, image, 0.5f, layerColor);
740 		}
741 
742 		case TEST_TYPE_LAYERED_READBACK:
743 		{
744 			const float	barWidthRatios[]	= { 0.25f, 0.5f, 1.0f };
745 			const int	barsCount			= DE_LENGTH_OF_ARRAY(barWidthRatios);
746 			bool		result				= false;
747 
748 			if (depthCheck)
749 			{
750 				const std::string		checkType				= "Depth";
751 				const float				pass0depth				= static_cast<float>(layerNdx + 1) / static_cast<float>(2 * numLayers);
752 				const float				pass1depth				= static_cast<float>(layerNdx + 0) / static_cast<float>(2 * numLayers);
753 				const tcu::Vec4			barDepths[barsCount]	= { tcu::Vec4(pass1depth), tcu::Vec4(pass0depth), tcu::Vec4(1.0f) };
754 				tcu::TextureLevel		depthAsColorBuffer		(tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), image.getWidth(), image.getHeight());
755 				tcu::PixelBufferAccess	depthAsColor			(depthAsColorBuffer);
756 				const int				numUsedChannels			(tcu::getNumUsedChannels(depthAsColor.getFormat().order));
757 
758 				convertDepthToColorBufferAccess(image, depthAsColor);
759 
760 				result = verifyImageMultipleBars(log, depthAsColor, barWidthRatios, barDepths, barsCount, numUsedChannels, checkType);
761 			}
762 			else if (stencilCheck)
763 			{
764 				const std::string		checkType				= "Stencil";
765 				const int				maxStencilValue			= 4;
766 				const float				pass0stencil			= static_cast<float>(1.0f / maxStencilValue);
767 				const float				pass1stencil			= static_cast<float>(2.0f / maxStencilValue);
768 				const tcu::Vec4			barStencils[barsCount]	= { tcu::Vec4(pass1stencil), tcu::Vec4(pass0stencil), tcu::Vec4(0.0f) };
769 				tcu::TextureLevel		stencilAsColorBuffer	(tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), image.getWidth(), image.getHeight());
770 				tcu::PixelBufferAccess	stencilAsColor			(stencilAsColorBuffer);
771 				const int				numUsedChannels			(tcu::getNumUsedChannels(stencilAsColor.getFormat().order));
772 
773 				convertStencilToColorBufferAccess(image, stencilAsColor, maxStencilValue);
774 
775 				result = verifyImageMultipleBars(log, stencilAsColor, barWidthRatios, barStencils, barsCount, numUsedChannels, checkType);
776 			}
777 			else
778 			{
779 				const std::string		checkType				= "Color";
780 				const tcu::Vec4			baseColor				(s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
781 				const tcu::Vec4			barColors[barsCount]	= { scaleColor(baseColor, 1.00f), scaleColor(baseColor, 0.50f), scaleColor(baseColor, 0.25f) };
782 				const int				numUsedChannels			(tcu::getNumUsedChannels(image.getFormat().order));
783 
784 				result = verifyImageMultipleBars(log, image, barWidthRatios, barColors, barsCount, numUsedChannels, checkType);
785 			}
786 
787 			return result;
788 		}
789 
790 		case TEST_TYPE_SECONDARY_CMD_BUFFER:
791 		{
792 			const tcu::Vec4	clearColor	= secondaryCmdBufClearColors[layerNdx % DE_LENGTH_OF_ARRAY(secondaryCmdBufClearColors)];
793 			const tcu::Vec4	quadColor	= s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)];
794 			// The first draw: blend clearColor and quadColor
795 			const tcu::Vec4	firstDraw	= (clearColor + quadColor) * 0.5f;
796 			// The second draw: blend previous result and quadColor
797 			const tcu::Vec4	secondDraw	= (firstDraw + quadColor) * 0.5f;
798 
799 			return verifyImageSingleColoredRow(log, image, 0.5f, secondDraw, layerNdx < numLayers / 2, layerNdx >= numLayers / 2);
800 		}
801 
802 		default:
803 			DE_ASSERT(0);
804 			return false;
805 	}
806 }
807 
getLayerDescription(const VkImageViewType viewType,const int layer)808 std::string getLayerDescription (const VkImageViewType viewType, const int layer)
809 {
810 	std::ostringstream str;
811 	const int numCubeFaces = 6;
812 
813 	if (isCubeImageViewType(viewType))
814 		str << "cube " << (layer / numCubeFaces) << ", face " << (layer % numCubeFaces);
815 	else if (viewType == VK_IMAGE_VIEW_TYPE_3D)
816 		str << "slice z = " << layer;
817 	else
818 		str << "layer " << layer;
819 
820 	return str.str();
821 }
822 
verifyResults(tcu::TestLog & log,const TestParams & params,const VkFormat imageFormat,const void * resultData,const bool depthCheck=false,const bool stencilCheck=false)823 bool verifyResults (tcu::TestLog& log, const TestParams& params, const VkFormat imageFormat, const void* resultData, const bool depthCheck = false, const bool stencilCheck = false)
824 {
825 	const LayeredImageAccess image = LayeredImageAccess::create(getImageType(params.image.viewType), imageFormat, params.image.size, params.image.numLayers, resultData);
826 
827 	int numGoodLayers = 0;
828 
829 	for (int layerNdx = 0; layerNdx < image.getNumLayersOrSlices(); ++layerNdx)
830 	{
831 		const tcu::ConstPixelBufferAccess layerImage = image.getLayer(layerNdx);
832 
833 		log << tcu::TestLog::Message << "Verifying " << getLayerDescription(params.image.viewType, layerNdx) << tcu::TestLog::EndMessage;
834 
835 		if (verifyLayerContent(log, params.testType, layerImage, layerNdx, image.getNumLayersOrSlices(), depthCheck, stencilCheck))
836 			++numGoodLayers;
837 	}
838 
839 	return numGoodLayers == image.getNumLayersOrSlices();
840 }
841 
toGlsl(const Vec4 & v)842 std::string toGlsl (const Vec4& v)
843 {
844 	std::ostringstream str;
845 	str << "vec4(";
846 	for (int i = 0; i < 4; ++i)
847 		str << (i != 0 ? ", " : "") << de::floatToString(v[i], 1);
848 	str << ")";
849 	return str.str();
850 }
851 
initPrograms(SourceCollections & programCollection,const TestParams params)852 void initPrograms (SourceCollections& programCollection, const TestParams params)
853 {
854 	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);
855 
856 	// Vertex shader
857 	{
858 		std::ostringstream src;
859 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
860 			<< "\n"
861 			<< "void main(void)\n"
862 			<< "{\n"
863 			<< "}\n";
864 
865 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
866 	}
867 
868 	// Geometry shader
869 	{
870 		const int numLayers		= static_cast<int>(params.image.viewType == VK_IMAGE_VIEW_TYPE_3D ? params.image.size.depth : params.image.numLayers);
871 
872 		const int maxVertices	= (params.testType == TEST_TYPE_DIFFERENT_CONTENT)				? (numLayers + 1) * numLayers :
873 								  (params.testType == TEST_TYPE_ALL_LAYERS
874 								   || params.testType == TEST_TYPE_LAYER_ID
875 								   || params.testType == TEST_TYPE_LAYERED_READBACK
876 								   || params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER)		? numLayers * 4 :
877 								  (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)	? 6 : 4;
878 
879 		std::ostringstream src;
880 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
881 			<< "\n";
882 
883 		if (params.testType == TEST_TYPE_LAYERED_READBACK)
884 			src << "layout(binding = 0) readonly uniform Input {\n"
885 				<< "    int pass;\n"
886 				<< "} uInput;\n\n";
887 
888 		if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
889 			src << "layout(points, invocations = " << numLayers << ") in;\n";
890 		else
891 			src << "layout(points) in;\n";
892 
893 		src << "layout(triangle_strip, max_vertices = " << maxVertices << ") out;\n"
894 			<< "\n"
895 			<< (geomOutputColor ? "layout(location = 0) out vec4 vert_color;\n\n" : "")
896 			<< "out gl_PerVertex {\n"
897 			<< "    vec4 gl_Position;\n"
898 			<< "    float gl_PointSize;\n"
899 			<< "};\n"
900 			<< "\n"
901 			<< "void main(void)\n"
902 			<< "{\n";
903 
904 		std::ostringstream colorTable;
905 		{
906 			const int numColors = DE_LENGTH_OF_ARRAY(s_colors);
907 
908 			colorTable << "    const vec4 colors[" << numColors << "] = vec4[" << numColors << "](";
909 
910 			const std::string padding(colorTable.str().length(), ' ');
911 
912 			for (int i = 0; i < numColors; ++i)
913 				colorTable << (i != 0 ? ",\n" + padding : "") << toGlsl(s_colors[i]);
914 
915 			colorTable << ");\n";
916 		}
917 
918 		if (params.testType == TEST_TYPE_DEFAULT_LAYER)
919 		{
920 			src << "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
921 				<< "    gl_PointSize = 1.0;\n"
922 				<< "    EmitVertex();\n"
923 				<< "\n"
924 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
925 				<< "    gl_PointSize = 1.0;\n"
926 				<< "    EmitVertex();\n"
927 				<< "\n"
928 				<< "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
929 				<< "    gl_PointSize = 1.0;\n"
930 				<< "    EmitVertex();\n"
931 				<< "\n"
932 				<< "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
933 				<< "    gl_PointSize = 1.0;\n"
934 				<< "    EmitVertex();\n";
935 		}
936 		else if (params.testType == TEST_TYPE_SINGLE_LAYER)
937 		{
938 			const deUint32 targetLayer = getTargetLayer(params.image);
939 
940 			src << "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
941 				<< "    gl_Layer    = " << targetLayer << ";\n"
942 				<< "    gl_PointSize = 1.0;\n"
943 				<< "    EmitVertex();\n"
944 				<< "\n"
945 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
946 				<< "    gl_Layer    = " << targetLayer << ";\n"
947 				<< "    gl_PointSize = 1.0;\n"
948 				<< "    EmitVertex();\n"
949 				<< "\n"
950 				<< "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
951 				<< "    gl_Layer    = " << targetLayer << ";\n"
952 				<< "    gl_PointSize = 1.0;\n"
953 				<< "    EmitVertex();\n"
954 				<< "\n"
955 				<< "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
956 				<< "    gl_Layer    = " << targetLayer << ";\n"
957 				<< "    gl_PointSize = 1.0;\n"
958 				<< "    EmitVertex();\n";
959 		}
960 		else if (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER)
961 		{
962 			src << colorTable.str()
963 				<< "\n"
964 				<< "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
965 				<< "        const int colorNdx = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
966 				<< "\n"
967 				<< "        gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
968 				<< "        gl_Layer    = layerNdx;\n"
969 				<< "        vert_color  = colors[colorNdx];\n"
970 				<< "        gl_PointSize = 1.0;\n"
971 				<< "        EmitVertex();\n"
972 				<< "\n"
973 				<< "        gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
974 				<< "        gl_Layer    = layerNdx;\n"
975 				<< "        vert_color  = colors[colorNdx];\n"
976 				<< "        gl_PointSize = 1.0;\n"
977 				<< "        EmitVertex();\n"
978 				<< "\n"
979 				<< "        gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
980 				<< "        gl_Layer    = layerNdx;\n"
981 				<< "        vert_color  = colors[colorNdx];\n"
982 				<< "        gl_PointSize = 1.0;\n"
983 				<< "        EmitVertex();\n"
984 				<< "\n"
985 				<< "        gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
986 				<< "        gl_Layer    = layerNdx;\n"
987 				<< "        vert_color  = colors[colorNdx];\n"
988 				<< "        gl_PointSize = 1.0;\n"
989 				<< "        EmitVertex();\n"
990 				<< "        EndPrimitive();\n"
991 				<< "    };\n";
992 		}
993 		else if (params.testType == TEST_TYPE_LAYER_ID)
994 		{
995 			src << "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
996 				<< "        gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
997 				<< "        gl_Layer    = layerNdx;\n"
998 				<< "        gl_PointSize = 1.0;\n"
999 				<< "        EmitVertex();\n"
1000 				<< "\n"
1001 				<< "        gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
1002 				<< "        gl_Layer    = layerNdx;\n"
1003 				<< "        gl_PointSize = 1.0;\n"
1004 				<< "        EmitVertex();\n"
1005 				<< "\n"
1006 				<< "        gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
1007 				<< "        gl_Layer    = layerNdx;\n"
1008 				<< "        gl_PointSize = 1.0;\n"
1009 				<< "        EmitVertex();\n"
1010 				<< "\n"
1011 				<< "        gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
1012 				<< "        gl_Layer    = layerNdx;\n"
1013 				<< "        gl_PointSize = 1.0;\n"
1014 				<< "        EmitVertex();\n"
1015 				<< "        EndPrimitive();\n"
1016 				<< "    };\n";
1017 		}
1018 		else if (params.testType == TEST_TYPE_DIFFERENT_CONTENT)
1019 		{
1020 			src << "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
1021 				<< "        for (int colNdx = 0; colNdx <= layerNdx; ++colNdx) {\n"
1022 				<< "            const float posX = float(colNdx) / float(" << numLayers << ") * 2.0 - 1.0;\n"
1023 				<< "\n"
1024 				<< "            gl_Position = vec4(posX,  1.0, 0.0, 1.0);\n"
1025 				<< "            gl_Layer    = layerNdx;\n"
1026 				<< "            gl_PointSize = 1.0;\n"
1027 				<< "            EmitVertex();\n"
1028 				<< "\n"
1029 				<< "            gl_Position = vec4(posX, -1.0, 0.0, 1.0);\n"
1030 				<< "            gl_Layer    = layerNdx;\n"
1031 				<< "            gl_PointSize = 1.0;\n"
1032 				<< "            EmitVertex();\n"
1033 				<< "        }\n"
1034 				<< "        EndPrimitive();\n"
1035 				<< "    }\n";
1036 		}
1037 		else if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER)
1038 		{
1039 			src << colorTable.str()
1040 				<< "    const int colorNdx = gl_InvocationID % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
1041 				<< "\n"
1042 				<< "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
1043 				<< "    gl_Layer    = gl_InvocationID;\n"
1044 				<< "    gl_PointSize = 1.0;\n"
1045 				<< "    vert_color  = colors[colorNdx];\n"
1046 				<< "    EmitVertex();\n"
1047 				<< "\n"
1048 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
1049 				<< "    gl_Layer    = gl_InvocationID;\n"
1050 				<< "    gl_PointSize = 1.0;\n"
1051 				<< "    vert_color  = colors[colorNdx];\n"
1052 				<< "    EmitVertex();\n"
1053 				<< "\n"
1054 				<< "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
1055 				<< "    gl_Layer    = gl_InvocationID;\n"
1056 				<< "    gl_PointSize = 1.0;\n"
1057 				<< "    vert_color  = colors[colorNdx];\n"
1058 				<< "    EmitVertex();\n"
1059 				<< "\n"
1060 				<< "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
1061 				<< "    gl_Layer    = gl_InvocationID;\n"
1062 				<< "    gl_PointSize = 1.0;\n"
1063 				<< "    vert_color  = colors[colorNdx];\n"
1064 				<< "    EmitVertex();\n"
1065 				<< "    EndPrimitive();\n";
1066 		}
1067 		else if (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
1068 		{
1069 			src << "    const int   layerA = gl_InvocationID;\n"
1070 				<< "    const int   layerB = (gl_InvocationID + 1) % " << numLayers << ";\n"
1071 				<< "    const float aEnd   = float(layerA) / float(" << numLayers << ") * 2.0 - 1.0;\n"
1072 				<< "    const float bEnd   = float(layerB) / float(" << numLayers << ") * 2.0 - 1.0;\n"
1073 				<< "\n"
1074 				<< "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
1075 				<< "    gl_Layer    = layerA;\n"
1076 				<< "    gl_PointSize = 1.0;\n"
1077 				<< "    EmitVertex();\n"
1078 				<< "\n"
1079 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
1080 				<< "    gl_Layer    = layerA;\n"
1081 				<< "    gl_PointSize = 1.0;\n"
1082 				<< "    EmitVertex();\n"
1083 				<< "\n"
1084 				<< "    gl_Position = vec4(aEnd, -1.0, 0.0, 1.0);\n"
1085 				<< "    gl_Layer    = layerA;\n"
1086 				<< "    gl_PointSize = 1.0;\n"
1087 				<< "    EmitVertex();\n"
1088 				<< "    EndPrimitive();\n"
1089 				<< "\n"
1090 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
1091 				<< "    gl_Layer    = layerB;\n"
1092 				<< "    gl_PointSize = 1.0;\n"
1093 				<< "    EmitVertex();\n"
1094 				<< "\n"
1095 				<< "    gl_Position = vec4(bEnd,  1.0, 0.0, 1.0);\n"
1096 				<< "    gl_Layer    = layerB;\n"
1097 				<< "    gl_PointSize = 1.0;\n"
1098 				<< "    EmitVertex();\n"
1099 				<< "\n"
1100 				<< "    gl_Position = vec4(bEnd, -1.0, 0.0, 1.0);\n"
1101 				<< "    gl_Layer    = layerB;\n"
1102 				<< "    gl_PointSize = 1.0;\n"
1103 				<< "    EmitVertex();\n"
1104 				<< "    EndPrimitive();\n";
1105 		}
1106 		else if (params.testType == TEST_TYPE_LAYERED_READBACK)
1107 		{
1108 			src << colorTable.str()
1109 				<< "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
1110 				<< "        const int   colorNdx   = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
1111 				<< "        const vec3  passColor0 = (uInput.pass == 0 ? 0.5 :  1.0) * vec3(colors[colorNdx]);\n"
1112 				<< "        const vec4  passColor  = vec4(passColor0, 1.0);\n"
1113 				<< "        const float posX       = (uInput.pass == 0 ? 0.0 : -0.5);\n"
1114 				<< "        const float posZ       = float(layerNdx + 1 - uInput.pass) / float(" << 2*numLayers << ");\n"
1115 				<< "\n"
1116 				<< "        gl_Position = vec4(-1.0, -1.0, posZ, 1.0);\n"
1117 				<< "        gl_Layer    = layerNdx;\n"
1118 				<< "        gl_PointSize = 1.0;\n"
1119 				<< "        vert_color  = passColor;\n"
1120 				<< "        EmitVertex();\n"
1121 				<< "\n"
1122 				<< "        gl_Position = vec4(-1.0,  1.0, posZ, 1.0);\n"
1123 				<< "        gl_Layer    = layerNdx;\n"
1124 				<< "        gl_PointSize = 1.0;\n"
1125 				<< "        vert_color  = passColor;\n"
1126 				<< "        EmitVertex();\n"
1127 				<< "\n"
1128 				<< "        gl_Position = vec4(posX, -1.0, posZ, 1.0);\n"
1129 				<< "        gl_Layer    = layerNdx;\n"
1130 				<< "        gl_PointSize = 1.0;\n"
1131 				<< "        vert_color  = passColor;\n"
1132 				<< "        EmitVertex();\n"
1133 				<< "\n"
1134 				<< "        gl_Position = vec4(posX,  1.0, posZ, 1.0);\n"
1135 				<< "        gl_Layer    = layerNdx;\n"
1136 				<< "        gl_PointSize = 1.0;\n"
1137 				<< "        vert_color  = passColor;\n"
1138 				<< "        EmitVertex();\n"
1139 				<< "\n"
1140 				<< "        EndPrimitive();\n"
1141 				<< "    }\n";
1142 		}
1143 		else
1144 			DE_ASSERT(0);
1145 
1146 		src <<	"}\n";	// end main
1147 
1148 		programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
1149 	}
1150 
1151 	// Fragment shader
1152 	{
1153 		std::string imageViewString;
1154 
1155 		switch (params.image.viewType)
1156 		{
1157 			case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1158 				imageViewString = "image1DArray";
1159 				break;
1160 			case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
1161 				imageViewString = "image2DArray";
1162 				break;
1163 			case VK_IMAGE_VIEW_TYPE_CUBE:
1164 				imageViewString = "imageCube";
1165 				break;
1166 			case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
1167 				imageViewString = "imageCubeArray";
1168 				break;
1169 			default:
1170 				DE_ASSERT(params.image.viewType == VK_IMAGE_VIEW_TYPE_3D);
1171 				imageViewString = "image3D";
1172 				break;
1173 		}
1174 
1175 		std::ostringstream src;
1176 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1177 			<< "\n"
1178 			<< "layout(location = 0) out vec4 o_color;\n"
1179 			<< (geomOutputColor ? "layout(location = 0) in  vec4 vert_color;\n" : "")
1180 			<< (params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER ? std::string("layout(set = 0, binding = 0, rgba8) uniform " + imageViewString + " storageImage;\n") : std::string(""))
1181 			<< "\n"
1182 			<< "void main(void)\n"
1183 			<< "{\n";
1184 
1185 		if (params.testType == TEST_TYPE_LAYER_ID)
1186 		{
1187 			// This code must be in sync with verifyLayerContent()
1188 			src << "    o_color = vec4( (gl_Layer    % 2) == 1 ? 1.0 : 0.5,\n"
1189 				<< "                   ((gl_Layer/2) % 2) == 1 ? 1.0 : 0.5,\n"
1190 				<< "                     gl_Layer         == 0 ? 1.0 : 0.0,\n"
1191 				<< "                                             1.0);\n";
1192 		}
1193 		else if (params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER)
1194 		{
1195 			switch (params.image.viewType)
1196 			{
1197 				case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1198 					src << "    ivec2 coord = ivec2(int(gl_FragCoord.x), gl_Layer);\n";
1199 					break;
1200 				default:
1201 					src << "    ivec3 coord = ivec3(int(gl_FragCoord.x), int(gl_FragCoord.y), gl_Layer);\n";
1202 					break;
1203 			}
1204 
1205 			src << "    vec4 src_color = imageLoad(storageImage, coord);\n"
1206 				<< "    o_color = (vert_color + src_color) / 2.0;\n"
1207 				<< "    imageStore(storageImage, coord, o_color);\n";
1208 		}
1209 		else if (geomOutputColor)
1210 			src << "    o_color = vert_color;\n";
1211 		else
1212 			src << "    o_color = vec4(1.0);\n";
1213 
1214 		src << "}\n";
1215 
1216 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1217 	}
1218 }
1219 
test(Context & context,const TestParams params)1220 tcu::TestStatus test (Context& context, const TestParams params)
1221 {
1222 	const DeviceInterface&			vk						= context.getDeviceInterface();
1223 	const InstanceInterface&		vki						= context.getInstanceInterface();
1224 	const VkDevice					device					= context.getDevice();
1225 	const VkPhysicalDevice			physDevice				= context.getPhysicalDevice();
1226 	const deUint32					queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
1227 	const VkQueue					queue					= context.getUniversalQueue();
1228 	Allocator&						allocator				= context.getDefaultAllocator();
1229 	VkDeviceSize					nonCoherentAtomSize		= vk::getPhysicalDeviceProperties(vki, physDevice).limits.nonCoherentAtomSize;
1230 	VkDeviceSize					alignmentSize			= std::max<VkDeviceSize>(nonCoherentAtomSize, 4u);
1231 
1232 	const VkFormat					colorFormat				= VK_FORMAT_R8G8B8A8_UNORM;
1233 	const deUint32					numLayers				= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
1234 	const Vec4						clearColor				= Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1235 	const deUint32					colorImagePixelSize		= static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(colorFormat)));
1236 	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);
1237 	const VkImageCreateFlags		imageCreateFlags		= (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
1238 															  (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
1239 	const VkImageViewType			viewType				= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
1240 
1241 	const Unique<VkImage>			colorImage				(makeImage				(vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
1242 																					 params.image.numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1243 	const UniquePtr<Allocation>		colorImageAlloc			(bindImage				(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1244 	const Unique<VkImageView>		colorAttachment			(makeImageView			(vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
1245 
1246 	const Unique<VkBuffer>			colorBuffer				(makeBuffer				(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1247 	const UniquePtr<Allocation>		colorBufferAlloc		(bindBuffer				(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1248 
1249 	const Unique<VkShaderModule>	vertexModule			(createShaderModule		(vk, device, context.getBinaryCollection().get("vert"), 0u));
1250 	const Unique<VkShaderModule>	geometryModule			(createShaderModule		(vk, device, context.getBinaryCollection().get("geom"), 0u));
1251 	const Unique<VkShaderModule>	fragmentModule			(createShaderModule		(vk, device, context.getBinaryCollection().get("frag"), 0u));
1252 
1253 	const Unique<VkRenderPass>		renderPass				(makeRenderPass			(vk, device, colorFormat));
1254 	const Unique<VkFramebuffer>		framebuffer				(makeFramebuffer		(vk, device, *renderPass, *colorAttachment, params.image.size.width,  params.image.size.height, numLayers));
1255 	const Unique<VkPipelineLayout>	pipelineLayout			(makePipelineLayout		(vk, device));
1256 	const Unique<VkPipeline>		pipeline				(makeGraphicsPipeline	(vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule,
1257 																					 makeExtent2D(params.image.size.width, params.image.size.height)));
1258 	const Unique<VkCommandPool>		cmdPool					(createCommandPool		(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1259 	const Unique<VkCommandBuffer>	cmdBuffer				(allocateCommandBuffer	(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1260 
1261 	zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
1262 
1263 	beginCommandBuffer(vk, *cmdBuffer);
1264 
1265 	beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, params.image.size.width, params.image.size.height), clearColor);
1266 
1267 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1268 	vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1269 	endRenderPass(vk, *cmdBuffer);
1270 
1271 	// Copy color image to buffer
1272 	copyLayeredImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, params.image);
1273 
1274 	endCommandBuffer(vk, *cmdBuffer);
1275 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1276 
1277 	invalidateAlloc(vk, device, *colorBufferAlloc);
1278 
1279 	if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1280 		return tcu::TestStatus::fail("Rendered images are incorrect");
1281 	else
1282 		return tcu::TestStatus::pass("OK");
1283 }
1284 
testLayeredReadBack(Context & context,const TestParams params)1285 tcu::TestStatus testLayeredReadBack (Context& context, const TestParams params)
1286 {
1287 	const DeviceInterface&				vk					= context.getDeviceInterface();
1288 	const InstanceInterface&			vki					= context.getInstanceInterface();
1289 	const VkDevice						device				= context.getDevice();
1290 	const VkPhysicalDevice				physDevice			= context.getPhysicalDevice();
1291 	const deUint32						queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1292 	const VkQueue						queue				= context.getUniversalQueue();
1293 	Allocator&							allocator			= context.getDefaultAllocator();
1294 	VkDeviceSize						nonCoherentAtomSize = vk::getPhysicalDeviceProperties(vki, physDevice).limits.nonCoherentAtomSize;
1295 	VkDeviceSize						alignmentSize		= std::max<VkDeviceSize>(nonCoherentAtomSize, 4u);
1296 
1297 	const size_t						passCount			= 2;
1298 	const deUint32						numLayers			= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
1299 	const VkImageCreateFlags			imageCreateFlags	= (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
1300 															  (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
1301 	const VkImageViewType				viewType			= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
1302 	const VkImageType					imageType			= getImageType(params.image.viewType);
1303 	const VkExtent2D					imageExtent2D		= makeExtent2D(params.image.size.width, params.image.size.height);
1304 
1305 	const VkFormat						colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
1306 	const deUint32						colorImagePixelSize	= static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(colorFormat)));
1307 	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 );
1308 	const VkImageUsageFlags				colorImageUsage		= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1309 
1310 	const bool							dsUsed				= true;
1311 	const VkFormat						dsFormat			= VK_FORMAT_D24_UNORM_S8_UINT;
1312 	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.
1313 	const VkExtent3D					dsImageSize			= makeExtent3D(params.image.size.width, params.image.size.height, 1u);
1314 	const VkImageCreateFlags			dsImageCreateFlags	= (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0);
1315 	const deUint32						dsImagePixelSize	= static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(dsFormat)));
1316 	const VkImageUsageFlags				dsImageUsage		= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1317 	const VkImageAspectFlags			dsAspectFlags		= VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
1318 	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);
1319 
1320 	const VkFormat						stencilBufferFormat	= getStencilBufferFormat(dsFormat);
1321 	const deUint32						stencilPixelSize	= static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(stencilBufferFormat)));
1322 	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);
1323 
1324 	checkImageFormatProperties(vki, physDevice, imageType, VK_IMAGE_TILING_OPTIMAL, dsImageUsage, imageCreateFlags, dsFormat, params.image.size, params.image.numLayers);
1325 
1326 	const Unique<VkImage>				colorImage			(makeImage				(vk, device, makeImageCreateInfo(imageCreateFlags, imageType, colorFormat, params.image.size, params.image.numLayers, colorImageUsage)));
1327 	const UniquePtr<Allocation>			colorImageAlloc		(bindImage				(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1328 	const Unique<VkImageView>			colorAttachment		(makeImageView			(vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
1329 	const Unique<VkBuffer>				colorBuffer			(makeBuffer				(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1330 	const UniquePtr<Allocation>			colorBufferAlloc	(bindBuffer				(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1331 
1332 	const Unique<VkImage>				dsImage				(makeImage				(vk, device, makeImageCreateInfo(dsImageCreateFlags, dsImageType, dsFormat, dsImageSize, numLayers, dsImageUsage)));
1333 	const UniquePtr<Allocation>			dsImageAlloc		(bindImage				(vk, device, allocator, *dsImage, MemoryRequirement::Any));
1334 	const Unique<VkImageView>			dsAttachment		(makeImageView			(vk, device, *dsImage, viewType, dsFormat, makeImageSubresourceRange(dsAspectFlags, 0u, 1u, 0u, numLayers)));
1335 	const Unique<VkBuffer>				depthBuffer			(makeBuffer				(vk, device, depthBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1336 	const UniquePtr<Allocation>			depthBufferAlloc	(bindBuffer				(vk, device, allocator, *depthBuffer, MemoryRequirement::HostVisible));
1337 	const Unique<VkBuffer>				stencilBuffer		(makeBuffer				(vk, device, stencilBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1338 	const UniquePtr<Allocation>			stencilBufferAlloc	(bindBuffer				(vk, device, allocator, *stencilBuffer, MemoryRequirement::HostVisible));
1339 
1340 	const VkImageView					attachments[]		= {*colorAttachment, *dsAttachment};
1341 	const deUint32						attachmentsCount	= dsUsed ? DE_LENGTH_OF_ARRAY(attachments) : 1u;
1342 
1343 	const Unique<VkShaderModule>		vertexModule		(createShaderModule		(vk, device, context.getBinaryCollection().get("vert"), 0u));
1344 	const Unique<VkShaderModule>		geometryModule		(createShaderModule		(vk, device, context.getBinaryCollection().get("geom"), 0u));
1345 	const Unique<VkShaderModule>		fragmentModule		(createShaderModule		(vk, device, context.getBinaryCollection().get("frag"), 0u));
1346 
1347 	const Unique<VkRenderPass>			renderPass			(makeRenderPass			(vk, device, colorFormat, dsFormat, dsUsed));
1348 	const Unique<VkFramebuffer>			framebuffer			(makeFramebuffer		(vk, device, *renderPass, attachmentsCount, attachments, params.image.size.width, params.image.size.height, numLayers));
1349 
1350 	const Move<VkDescriptorPool>		descriptorPool		= DescriptorPoolBuilder()
1351 															  .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, passCount)
1352 															  .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, passCount);
1353 	const Move<VkDescriptorSetLayout>	descriptorSetLayout	= DescriptorSetLayoutBuilder()
1354 															  .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_GEOMETRY_BIT)
1355 															  .build(vk, device);
1356 	const Move<VkDescriptorSet>			descriptorSet[]		=
1357 	{
1358 		makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout),
1359 		makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout),
1360 	};
1361 
1362 	const size_t						uniformBufSize		= sizeof(deUint32);
1363 	const VkBufferCreateInfo			uniformBufCI		= makeBufferCreateInfo(uniformBufSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1364 	const Move<VkBuffer>				uniformBuf[]		= { createBuffer(vk, device, &uniformBufCI), createBuffer(vk, device, &uniformBufCI) };
1365 	const MovePtr<Allocation>			uniformBufAlloc[]	=
1366 	{
1367 		allocator.allocate(getBufferMemoryRequirements(vk, device, *uniformBuf[0]), MemoryRequirement::HostVisible),
1368 		allocator.allocate(getBufferMemoryRequirements(vk, device, *uniformBuf[1]), MemoryRequirement::HostVisible),
1369 	};
1370 	const VkDescriptorBufferInfo		uniformBufDesc[]	=
1371 	{
1372 		makeDescriptorBufferInfo(*uniformBuf[0], 0ull, uniformBufSize),
1373 		makeDescriptorBufferInfo(*uniformBuf[1], 0ull, uniformBufSize),
1374 	};
1375 
1376 	const Unique<VkPipelineLayout>		pipelineLayout		(makePipelineLayout		(vk, device, *descriptorSetLayout));
1377 	const Unique<VkPipeline>			pipeline			(makeGraphicsPipeline	(vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule, imageExtent2D, dsUsed));
1378 	const Unique<VkCommandPool>			cmdPool				(createCommandPool		(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1379 	const Unique<VkCommandBuffer>		cmdBuffer			(allocateCommandBuffer	(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1380 	const VkImageSubresourceRange		colorSubresRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers);
1381 	const VkImageSubresourceRange		dsSubresRange		= makeImageSubresourceRange(dsAspectFlags, 0u, 1u, 0u, numLayers);
1382 	std::string							result;
1383 
1384 	beginCommandBuffer(vk, *cmdBuffer);
1385 	{
1386 		// Transition the images to new layouts
1387 		const VkImageMemoryBarrier		colorBarrier	= makeImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1388 																				 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, *colorImage, colorSubresRange);
1389 		const VkImageMemoryBarrier		dsBarrier		= makeImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1390 																				 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, *dsImage, dsSubresRange);
1391 
1392 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorBarrier);
1393 
1394 		if (dsUsed)
1395 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsBarrier);
1396 
1397 		for (deUint32 layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1398 		{
1399 			const VkExtent3D	imageExtent = makeExtent3D(params.image.size.width, params.image.size.height, 1u);
1400 
1401 			// Clear color image with initial value
1402 			{
1403 				const deUint32					layer					= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? 0u : layerNdx;
1404 				const deUint32					imageDepth				= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? layerNdx : 0u;
1405 				const VkOffset3D				imageOffset				= makeOffset3D(0u, 0u, imageDepth);
1406 
1407 				const tcu::Vec4					clearColor				= scaleColor(s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)], 0.25f);
1408 				const deUint32					bufferSliceSize			= deAlign32( params.image.size.width * params.image.size.height * colorImagePixelSize, static_cast<deInt32>(alignmentSize));
1409 				const VkDeviceSize				bufferOffset			= layerNdx * bufferSliceSize;
1410 				const VkImageSubresourceLayers	imageSubresource		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, layer, 1u);
1411 				const VkBufferImageCopy			bufferImageCopyRegion	= makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
1412 
1413 				fillBuffer(vk, device, *colorBufferAlloc, bufferOffset, bufferSliceSize, colorFormat, clearColor);
1414 				vk.cmdCopyBufferToImage(*cmdBuffer, *colorBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1415 			}
1416 
1417 			// Clear depth image with initial value
1418 			if (dsUsed)
1419 			{
1420 				const float						depthValue				= 1.0f;
1421 				const deUint32					bufferSliceSize			= deAlign32( params.image.size.width * params.image.size.height * dsImagePixelSize, static_cast<deInt32>(alignmentSize));
1422 				const VkDeviceSize				bufferOffset			= layerNdx * bufferSliceSize;
1423 				const VkImageSubresourceLayers	imageSubresource		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, layerNdx, 1u);
1424 				const VkBufferImageCopy			bufferImageCopyRegion	= makeBufferImageCopy(bufferOffset, imageSubresource, makeOffset3D(0u, 0u, 0u), imageExtent);
1425 
1426 				fillBuffer(vk, device, *depthBufferAlloc, bufferOffset, bufferSliceSize, dsFormat, depthValue);
1427 				vk.cmdCopyBufferToImage(*cmdBuffer, *depthBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1428 			}
1429 
1430 			// Clear stencil image with initial value
1431 			if (dsUsed)
1432 			{
1433 				const deUint8					stencilValue			= 0;
1434 				const deUint32					bufferSliceSize			= deAlign32( params.image.size.width * params.image.size.height * stencilPixelSize, static_cast<deInt32>(alignmentSize));
1435 				const VkDeviceSize				bufferOffset			= layerNdx * bufferSliceSize;
1436 				const VkImageSubresourceLayers	imageSubresource		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, layerNdx, 1u);
1437 				const VkBufferImageCopy			bufferImageCopyRegion	= makeBufferImageCopy(bufferOffset, imageSubresource, makeOffset3D(0u, 0u, 0u), imageExtent);
1438 				deUint8*						bufferStart				= static_cast<deUint8*>((*stencilBufferAlloc).getHostPtr());
1439 				deUint8*						bufferLayerStart		= &bufferStart[bufferOffset];
1440 
1441 				deMemset(bufferLayerStart, stencilValue, bufferSliceSize);
1442 				flushMappedMemoryRange(vk, device, stencilBufferAlloc->getMemory(), stencilBufferAlloc->getOffset() + bufferOffset, bufferSliceSize);
1443 				vk.cmdCopyBufferToImage(*cmdBuffer, *stencilBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1444 			}
1445 		}
1446 	}
1447 	// Change images layouts
1448 	{
1449 		// VK_ATTACHMENT_LOAD_OP_LOAD is used for both color and D/S attachments. Thus,
1450 		// VK_ACCESS_COLOR_ATTACHMENT_READ_BIT and VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
1451 		// bits must be included in the destination access mask of the color and depth barriers
1452 		// respectively.
1453 		const VkImageMemoryBarrier		colorBarrier	= makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
1454 																				 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresRange);
1455 		const VkImageMemoryBarrier		dsBarrier		= makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1456 																				 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *dsImage, dsSubresRange);
1457 
1458 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorBarrier);
1459 
1460 		if (dsUsed)
1461 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsBarrier);
1462 	}
1463 
1464 	{
1465 		// These barriers are inserted between each pair of renderpasses in the following
1466 		// loop. Note that VK_ATTACHMENT_LOAD_OP_LOAD is used for color and D/S attachments
1467 		// hence VK_ACCESS_COLOR_ATTACHMENT_READ_BIT and VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
1468 		// bits are included in src and dst access mask of the color and depth barriers.
1469 		const VkImageMemoryBarrier			colorPassBarrier	= makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
1470 																						 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
1471 																						 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresRange);
1472 		const VkImageMemoryBarrier			dsPassBarrier		= makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1473 																						 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1474 																						 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *dsImage, dsSubresRange);
1475 		for (deUint32 pass = 0; pass < passCount; ++pass)
1476 		{
1477 			DE_ASSERT(sizeof(pass) == uniformBufSize);
1478 
1479 			VK_CHECK(vk.bindBufferMemory(device, *uniformBuf[pass], uniformBufAlloc[pass]->getMemory(), uniformBufAlloc[pass]->getOffset()));
1480 			deMemcpy(uniformBufAlloc[pass]->getHostPtr(), &pass, uniformBufSize);
1481 			flushMappedMemoryRange(vk, device, uniformBufAlloc[pass]->getMemory(), uniformBufAlloc[pass]->getOffset(), VK_WHOLE_SIZE);
1482 
1483 			DescriptorSetUpdateBuilder()
1484 				.writeSingle(*descriptorSet[pass], DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufDesc[pass])
1485 				.update(vk, device);
1486 
1487 			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet[pass], 0u, DE_NULL);
1488 			beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(imageExtent2D));
1489 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1490 			vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1491 			endRenderPass(vk, *cmdBuffer);
1492 
1493 			// Don't add the barrier after the last renderpass
1494 			if (pass < passCount - 1)
1495 			{
1496 				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);
1497 
1498 				if (dsUsed)
1499 					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);
1500 			}
1501 		}
1502 	}
1503 	endCommandBuffer(vk, *cmdBuffer);
1504 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1505 
1506 	zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
1507 	zeroBuffer(vk, device, *depthBufferAlloc, depthBufferSize);
1508 	zeroBuffer(vk, device, *stencilBufferAlloc, stencilBufferSize);
1509 
1510 	beginCommandBuffer(vk, *cmdBuffer);
1511 	{
1512 		// Copy color image
1513 		{
1514 			const VkImageMemoryBarrier	preCopyBarrier	= makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
1515 																				 VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorImage, colorSubresRange);
1516 			const VkBufferImageCopy		region			= makeBufferImageCopy(params.image.size, makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, params.image.numLayers));
1517 			const VkBufferMemoryBarrier	postCopyBarrier	= makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, VK_WHOLE_SIZE);
1518 
1519 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1520 			vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
1521 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &postCopyBarrier, DE_NULL, 0u);
1522 		}
1523 
1524 		// Depth/Stencil image copy
1525 		if (dsUsed)
1526 		{
1527 			const VkImageMemoryBarrier	preCopyBarrier		= makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1528 																					 VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dsImage, dsSubresRange);
1529 			const VkBufferImageCopy		depthCopyRegion		= makeBufferImageCopy(dsImageSize, makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, numLayers));
1530 			const VkBufferImageCopy		stencilCopyRegion	= makeBufferImageCopy(dsImageSize, makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, numLayers));
1531 			const VkBufferMemoryBarrier	postCopyBarriers[]	=
1532 			{
1533 				makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *depthBuffer, 0ull, VK_WHOLE_SIZE),
1534 				makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *stencilBuffer, 0ull, VK_WHOLE_SIZE),
1535 			};
1536 
1537 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1538 			vk.cmdCopyImageToBuffer(*cmdBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *depthBuffer, 1u, &depthCopyRegion);
1539 			vk.cmdCopyImageToBuffer(*cmdBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *stencilBuffer, 1u, &stencilCopyRegion);
1540 			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);
1541 		}
1542 	}
1543 	endCommandBuffer(vk, *cmdBuffer);
1544 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1545 
1546 	invalidateAlloc(vk, device, *colorBufferAlloc);
1547 	invalidateAlloc(vk, device, *depthBufferAlloc);
1548 	invalidateAlloc(vk, device, *stencilBufferAlloc);
1549 
1550 	if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1551 		result += " Color";
1552 
1553 	if (dsUsed)
1554 	{
1555 		if (!verifyResults(context.getTestContext().getLog(), params, dsFormat, depthBufferAlloc->getHostPtr(), true, false))
1556 			result += " Depth";
1557 
1558 		if (!verifyResults(context.getTestContext().getLog(), params, stencilBufferFormat, stencilBufferAlloc->getHostPtr(), false, true))
1559 			result += " Stencil";
1560 	}
1561 
1562 	if (result.empty())
1563 		return tcu::TestStatus::pass("OK");
1564 	else
1565 		return tcu::TestStatus::fail("Following parts of image are incorrect:" + result);
1566 }
1567 
testSecondaryCmdBuffer(Context & context,const TestParams params)1568 tcu::TestStatus testSecondaryCmdBuffer (Context& context, const TestParams params)
1569 {
1570 	const DeviceInterface&				vk					= context.getDeviceInterface();
1571 	const InstanceInterface&			vki					= context.getInstanceInterface();
1572 	const VkDevice						device				= context.getDevice();
1573 	const VkPhysicalDevice				physDevice			= context.getPhysicalDevice();
1574 	const deUint32						queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1575 	const VkQueue						queue				= context.getUniversalQueue();
1576 	Allocator&							allocator			= context.getDefaultAllocator();
1577 	VkDeviceSize						nonCoherentAtomSize	= vk::getPhysicalDeviceProperties(vki, physDevice).limits.nonCoherentAtomSize;
1578 	VkDeviceSize						alignmentSize		= std::max<VkDeviceSize>(nonCoherentAtomSize, 4u);
1579 
1580 	const VkFormat						colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
1581 	const deUint32						numLayers			= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
1582 	const Vec4							clearColor			= Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1583 	const deUint32						colorImagePixelSize	= static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(colorFormat)));
1584 	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);
1585 
1586 	const VkImageCreateFlags			imageCreateFlags	= (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
1587 															  (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
1588 	const VkImageViewType				viewType			= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
1589 
1590 	const Unique<VkImage>				colorImage			(makeImage(vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
1591 																	   params.image.numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1592 	const UniquePtr<Allocation>			colorImageAlloc		(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1593 	const Unique<VkImageView>			colorImageView		(makeImageView(vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
1594 
1595 	const Unique<VkImage>				offscreenImage		(makeImage(vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
1596 																	   params.image.numLayers, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)));
1597 	const UniquePtr<Allocation>			offscreenImageAlloc	(bindImage(vk, device, allocator, *offscreenImage, MemoryRequirement::Any));
1598 	const Unique<VkImageView>			offscreenImageView	(makeImageView(vk, device, *offscreenImage, params.image.viewType, colorFormat,
1599 																		   makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers)));
1600 
1601 	const Unique<VkBuffer>				colorBuffer			(makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1602 	const UniquePtr<Allocation>			colorBufferAlloc	(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1603 
1604 	const Move<VkDescriptorPool>		descriptorPool		= DescriptorPoolBuilder() .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u) .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1605 	const Move<VkDescriptorSetLayout>	descriptorSetLayout	= DescriptorSetLayoutBuilder() .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT) .build(vk, device);
1606 	const Move<VkDescriptorSet>			descriptorSet		= makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
1607 
1608 	const Unique<VkShaderModule>		vertexModule		(createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
1609 	const Unique<VkShaderModule>		geometryModule		(createShaderModule(vk, device, context.getBinaryCollection().get("geom"), 0u));
1610 	const Unique<VkShaderModule>		fragmentModule		(createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
1611 
1612 	const Unique<VkRenderPass>			renderPass			(makeRenderPassWithSelfDependency(vk, device, colorFormat));
1613 	const Unique<VkFramebuffer>			framebuffer			(makeFramebuffer(vk, device, *renderPass, *colorImageView, params.image.size.width, params.image.size.height, numLayers));
1614 	const Unique<VkPipelineLayout>		pipelineLayout		(makePipelineLayout(vk, device, *descriptorSetLayout));
1615 	const Unique<VkPipeline>			pipeline			(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule,
1616 																				  makeExtent2D(params.image.size.width, params.image.size.height)));
1617 
1618 	const Unique<VkCommandPool>			cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1619 	const Unique<VkCommandBuffer>		cmdBuffer			(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1620 	const Unique<VkCommandBuffer>		secondaryCmdBuffer	(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY));
1621 
1622 	zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
1623 
1624 	const VkDescriptorImageInfo imageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *offscreenImageView, VK_IMAGE_LAYOUT_GENERAL);
1625 
1626 	DescriptorSetUpdateBuilder()
1627 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageDescriptorInfo)
1628 		.update(vk, device);
1629 
1630 	// Clear each layer of storage image
1631 	{
1632 		vk::Unique<vk::VkCommandBuffer> clearCmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1633 		beginCommandBuffer(vk, *clearCmdBuffer);
1634 
1635 		const vk::VkImageSubresourceRange	subresourceRange	=
1636 		{
1637 			vk::VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask
1638 			0u,								// deUint32				baseMipLevel
1639 			1u,								// deUint32				levelCount
1640 			0u,								// deUint32				baseArrayLayer
1641 			params.image.numLayers			// deUint32				layerCount
1642 		};
1643 
1644 		const vk::VkImageMemoryBarrier		preImageBarrier		=
1645 		{
1646 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,	// VkStructureType			sType
1647 			DE_NULL,									// const void*				pNext
1648 			0u,											// VkAccessFlags			srcAccessMask
1649 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,			// VkAccessFlags			dstAccessMask
1650 			vk::VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			oldLayout
1651 			vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,	// VkImageLayout			newLayout
1652 			queueFamilyIndex,							// deUint32					srcQueueFamilyIndex
1653 			queueFamilyIndex,							// deUint32					dstQueueFamilyIndex
1654 			*offscreenImage,							// VkImage					image
1655 			subresourceRange							// VkImageSubresourceRange	subresourceRange
1656 		};
1657 
1658 		const vk::VkImageMemoryBarrier		postImageBarrier	=
1659 		{
1660 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,	// VkStructureType			sType
1661 			DE_NULL,									// const void*				pNext
1662 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,			// VkAccessFlags			srcAccessMask
1663 			vk::VK_ACCESS_SHADER_WRITE_BIT,				// VkAccessFlags			dstAccessMask
1664 			vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,	// VkImageLayout			oldLayout
1665 			vk::VK_IMAGE_LAYOUT_GENERAL,				// VkImageLayout			newLayout
1666 			queueFamilyIndex,							// deUint32					srcQueueFamilyIndex
1667 			queueFamilyIndex,							// deUint32					dstQueueFamilyIndex
1668 			*offscreenImage,							// VkImage					image
1669 			subresourceRange							// VkImageSubresourceRange	subresourceRange
1670 		};
1671 
1672 		vk.cmdPipelineBarrier(*clearCmdBuffer,
1673 				vk::VK_PIPELINE_STAGE_HOST_BIT,
1674 				vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
1675 				(vk::VkDependencyFlags)0,
1676 				0, (const vk::VkMemoryBarrier*)DE_NULL,
1677 				0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1678 				1, &preImageBarrier);
1679 
1680 		for (deUint32 layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1681 		{
1682 			const deUint32		imageDepth	= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? layerNdx :       0u;
1683 			const deUint32		layer		= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ?       0u : layerNdx;
1684 			const VkOffset3D	imageOffset = makeOffset3D(0u, 0u, imageDepth);
1685 			const VkExtent3D	imageExtent = makeExtent3D(params.image.size.width, params.image.size.height, 1u);
1686 
1687 			{
1688 				const tcu::Vec4					storageImageClearColor	= secondaryCmdBufClearColors[layerNdx % DE_LENGTH_OF_ARRAY(secondaryCmdBufClearColors)];
1689 				const deUint32					bufferSliceSize			= deAlign32(params.image.size.width * params.image.size.height * colorImagePixelSize, static_cast<deInt32>(alignmentSize));
1690 				const VkDeviceSize				bufferOffset			= layerNdx * bufferSliceSize;
1691 				const VkImageSubresourceLayers	imageSubresource		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, layer, 1u);
1692 				const VkBufferImageCopy			bufferImageCopyRegion	= makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
1693 
1694 				fillBuffer(vk, device, *colorBufferAlloc, bufferOffset, bufferSliceSize, colorFormat, storageImageClearColor);
1695 				vk.cmdCopyBufferToImage(*clearCmdBuffer, *colorBuffer, *offscreenImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1696 			}
1697 		}
1698 
1699 		vk.cmdPipelineBarrier(*clearCmdBuffer,
1700 				vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
1701 				vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
1702 				(vk::VkDependencyFlags)0,
1703 				0, (const vk::VkMemoryBarrier*)DE_NULL,
1704 				0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1705 				1, &postImageBarrier);
1706 
1707 		endCommandBuffer(vk, *clearCmdBuffer);
1708 
1709 		submitCommandsAndWait(vk, device, queue, *clearCmdBuffer);
1710 	}
1711 
1712 	// Begin secondary command buffer
1713 	{
1714 		const VkCommandBufferInheritanceInfo	commandBufferInheritanceInfo	=
1715 		{
1716 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,				// VkStructureType					sType
1717 			DE_NULL,														// const void*						pNext
1718 			*renderPass,													// VkRenderPass						renderPass
1719 			0u,																// deUint32							subpass
1720 			params.inheritFramebuffer ? *framebuffer : (VkFramebuffer)0,	// VkFramebuffer					framebuffer
1721 			VK_FALSE,														// VkBool32							occlusionQueryEnable
1722 			0u,																// VkQueryControlFlags				queryFlags
1723 			0u																// VkQueryPipelineStatisticFlags	pipelineStatistics
1724 		};
1725 
1726 		const VkCommandBufferBeginInfo			commandBufferBeginInfo			=
1727 		{
1728 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,		// VkStructureType							sType
1729 			DE_NULL,											// const void*								pNext
1730 			VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
1731 			| VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,	// VkCommandBufferUsageFlags				flags
1732 			&commandBufferInheritanceInfo						// const VkCommandBufferInheritanceInfo*	pInheritanceInfo
1733 		};
1734 
1735 		VK_CHECK(vk.beginCommandBuffer(*secondaryCmdBuffer, &commandBufferBeginInfo));
1736 	}
1737 
1738 	vk.cmdBindDescriptorSets(*secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
1739 
1740 	// Clear framebuffer: upper right corner for half of the layers and bottom right for the others.
1741 	{
1742 		const VkClearAttachment	clearAttachment	=
1743 		{
1744 			VK_IMAGE_ASPECT_COLOR_BIT,						// VkImageAspectFlags	aspectMask
1745 			0u,												// deUint32				colorAttachment
1746 			makeClearValueColorF32(0.5f, 0.25, 0.0f, 1.0f)	// VkClearValue			clearValue
1747 		};
1748 
1749 		const VkOffset2D		offsetTop		= { (deInt32)params.image.size.width / 2, 0 };
1750 		const VkOffset2D		offsetBottom	= { (deInt32)params.image.size.width / 2, (deInt32)params.image.size.height / 2 };
1751 		const VkExtent2D		extentTop		= { params.image.size.width / 2, params.image.size.height / 2 };
1752 		const VkExtent2D		extentBottom	= { params.image.size.width / 2, de::max(params.image.size.height / 2, 1u) };
1753 		const VkRect2D			rectRightTop	= { offsetTop, extentTop };
1754 		const VkRect2D			rectRightBottom	= { offsetBottom, extentBottom };
1755 
1756 		const VkClearRect		rects[]			=
1757 		{
1758 			{
1759 				rectRightBottom,	// VkRect2D	rect
1760 				numLayers / 2,		// deUint32	baseArrayLayer
1761 				numLayers / 2		// deUint32	layerCount
1762 			},
1763 			{
1764 				rectRightTop,		// VkRect2D	rect
1765 				0u,					// deUint32	baseArrayLayer
1766 				numLayers / 2		// deUint32	layerCount
1767 			}
1768 		};
1769 
1770 		vk.cmdClearAttachments(*secondaryCmdBuffer, 1u, &clearAttachment, extentTop.height > 0 ? 2u : 1u, rects);
1771 	}
1772 
1773 	vk.cmdBindPipeline(*secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1774 	vk.cmdDraw(*secondaryCmdBuffer, 1u, 1u, 0u, 0u);
1775 	// Barrier between draws
1776 	{
1777 		const VkMemoryBarrier barrier =
1778 		{
1779 			VK_STRUCTURE_TYPE_MEMORY_BARRIER,	// VkStructureType	sType
1780 			DE_NULL,							// const void*		pNext
1781 			VK_ACCESS_SHADER_WRITE_BIT,			// VkAccessFlags	srcAccessMask
1782 			VK_ACCESS_SHADER_READ_BIT			// VkAccessFlags	dstAccessMask
1783 		};
1784 
1785 		vk.cmdPipelineBarrier(*secondaryCmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 1u, &barrier, 0u, DE_NULL, 0u, DE_NULL);
1786 	}
1787 	vk.cmdDraw(*secondaryCmdBuffer, 1u, 1u, 0u, 0u);
1788 	endCommandBuffer(vk, *secondaryCmdBuffer);
1789 
1790 	beginCommandBuffer(vk, *cmdBuffer);
1791 	beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, params.image.size.width, params.image.size.height), clearColor, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
1792 	vk.cmdExecuteCommands(*cmdBuffer, 1u, &(*secondaryCmdBuffer));
1793 	endRenderPass(vk, *cmdBuffer);
1794 
1795 	copyLayeredImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, params.image);
1796 
1797 	endCommandBuffer(vk, *cmdBuffer);
1798 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1799 
1800 	invalidateAlloc(vk, device, *colorBufferAlloc);
1801 
1802 	if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1803 		return tcu::TestStatus::fail("Rendered images are incorrect");
1804 	else
1805 		return tcu::TestStatus::pass("OK");
1806 }
1807 
checkSupport(Context & context,const TestParams params)1808 void checkSupport (Context& context, const TestParams params)
1809 {
1810 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
1811 
1812 	if (params.image.viewType == VK_IMAGE_VIEW_TYPE_3D)
1813 	{
1814 		context.requireDeviceFunctionality("VK_KHR_maintenance1");
1815 
1816 		if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
1817 			!context.getPortabilitySubsetFeatures().imageView2DOn3DImage)
1818 		{
1819 			TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Implementation does not support 2D or 2D array image view to be created on a 3D VkImage");
1820 		}
1821 	}
1822 
1823 	if (params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER)
1824 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
1825 }
1826 
1827 } // anonymous
1828 
createLayeredRenderingTests(tcu::TestContext & testCtx)1829 tcu::TestCaseGroup* createLayeredRenderingTests (tcu::TestContext& testCtx)
1830 {
1831 	MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "layered", "Layered rendering tests."));
1832 
1833 	const struct
1834 	{
1835 		TestType		test;
1836 		const char*		name;
1837 		const char*		description;
1838 	} testTypes[] =
1839 	{
1840 		{ TEST_TYPE_DEFAULT_LAYER,					"render_to_default_layer",			"Render to the default layer"															},
1841 		{ TEST_TYPE_SINGLE_LAYER,					"render_to_one",					"Render to one layer"																	},
1842 		{ TEST_TYPE_ALL_LAYERS,						"render_to_all",					"Render to all layers"																	},
1843 		{ TEST_TYPE_DIFFERENT_CONTENT,				"render_different_content",			"Render different data to different layers"												},
1844 		{ TEST_TYPE_LAYER_ID,						"fragment_layer",					"Read gl_Layer in fragment shader"														},
1845 		{ TEST_TYPE_INVOCATION_PER_LAYER,			"invocation_per_layer",				"Render to multiple layers with multiple invocations, one invocation per layer"			},
1846 		{ TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION,	"multiple_layers_per_invocation",	"Render to multiple layers with multiple invocations, multiple layers per invocation",	},
1847 		{ TEST_TYPE_LAYERED_READBACK,				"readback",							"Render to multiple layers with two passes to check LOAD_OP_LOAD capability"			},
1848 		{ TEST_TYPE_SECONDARY_CMD_BUFFER,			"secondary_cmd_buffer",				"Layered rendering using secondary command buffer"										}
1849 	};
1850 
1851 	const struct
1852 	{
1853 		VkImageViewType	viewType;
1854 		ImageParams		imageParams[2];
1855 	} imageParamGroups[] =
1856 	{
1857 		{ 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	} } },
1858 		{ 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	} } },
1859 		{ VK_IMAGE_VIEW_TYPE_CUBE,			{ { VK_IMAGE_VIEW_TYPE_CUBE,		{ 64, 64, 1 },	6	},	{ VK_IMAGE_VIEW_TYPE_CUBE,			{ 36, 36, 1 },	6	} } },
1860 		{ 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	} } },
1861 		{ VK_IMAGE_VIEW_TYPE_3D,			{ { VK_IMAGE_VIEW_TYPE_3D,			{ 64, 64, 8 },	1	},	{ VK_IMAGE_VIEW_TYPE_3D,			{ 12, 36, 6 },	1	} } }
1862 	};
1863 
1864 	for (int imageParamGroupNdx = 0; imageParamGroupNdx < DE_LENGTH_OF_ARRAY(imageParamGroups); ++imageParamGroupNdx)
1865 	{
1866 		MovePtr<tcu::TestCaseGroup> viewTypeMainGroup(new tcu::TestCaseGroup(testCtx, getShortImageViewTypeName(imageParamGroups[imageParamGroupNdx].viewType).c_str(), ""));
1867 
1868 		for (int imageParamNdx = 0; imageParamNdx < 2; imageParamNdx++)
1869 		{
1870 			std::ostringstream viewTypeGroupName;
1871 			viewTypeGroupName << imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].size.width << "_" << imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].size.height << "_";
1872 			if (imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].viewType == VK_IMAGE_VIEW_TYPE_3D)
1873 				viewTypeGroupName << imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].size.depth;
1874 			else
1875 				viewTypeGroupName << imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].numLayers;
1876 			MovePtr<tcu::TestCaseGroup> viewTypeGroup(new tcu::TestCaseGroup(testCtx, viewTypeGroupName.str().c_str(), ""));
1877 
1878 			for (int testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx)
1879 			{
1880 				TestParams params =
1881 				{
1882 					testTypes[testTypeNdx].test,
1883 					imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx],
1884 					false
1885 				};
1886 
1887 				if (testTypes[testTypeNdx].test == TEST_TYPE_LAYERED_READBACK)
1888 					addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, checkSupport, initPrograms, testLayeredReadBack, params);
1889 				else if (testTypes[testTypeNdx].test == TEST_TYPE_SECONDARY_CMD_BUFFER)
1890 				{
1891 					addFunctionCaseWithPrograms(viewTypeGroup.get(), "secondary_cmd_buffer", testTypes[testTypeNdx].description, checkSupport, initPrograms, testSecondaryCmdBuffer, params);
1892 					params.inheritFramebuffer = true;
1893 					addFunctionCaseWithPrograms(viewTypeGroup.get(), "secondary_cmd_buffer_inherit_framebuffer", testTypes[testTypeNdx].description, checkSupport, initPrograms, testSecondaryCmdBuffer, params);
1894 				}
1895 				else
1896 					addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, checkSupport, initPrograms, test, params);
1897 			}
1898 			viewTypeMainGroup->addChild(viewTypeGroup.release());
1899 		}
1900 		group->addChild(viewTypeMainGroup.release());
1901 	}
1902 
1903 	return group.release();
1904 }
1905 
1906 } // geometry
1907 } // vkt
1908