1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2014 The Android Open Source Project
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Geometry shader layered rendering tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktGeometryLayeredRenderingTests.hpp"
26 #include "vktTestCase.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktGeometryTestsUtil.hpp"
29 
30 #include "vkPrograms.hpp"
31 #include "vkStrUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkBarrierUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkBuilderUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkObjUtil.hpp"
41 
42 #include "deStringUtil.hpp"
43 #include "deUniquePtr.hpp"
44 
45 #include "tcuTextureUtil.hpp"
46 #include "tcuVectorUtil.hpp"
47 #include "tcuTestLog.hpp"
48 
49 namespace vkt
50 {
51 namespace geometry
52 {
53 namespace
54 {
55 using namespace vk;
56 using de::MovePtr;
57 using de::UniquePtr;
58 using tcu::Vec4;
59 using tcu::IVec3;
60 
61 enum TestType
62 {
63 	TEST_TYPE_DEFAULT_LAYER,					// !< draw to default layer
64 	TEST_TYPE_SINGLE_LAYER,						// !< draw to single layer
65 	TEST_TYPE_ALL_LAYERS,						// !< draw all layers
66 	TEST_TYPE_DIFFERENT_CONTENT,				// !< draw different content to different layers
67 	TEST_TYPE_LAYER_ID,							// !< draw to all layers, verify gl_Layer fragment input
68 	TEST_TYPE_INVOCATION_PER_LAYER,				// !< draw to all layers, one invocation per layer
69 	TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION,	// !< draw to all layers, multiple invocations write to multiple layers
70 	TEST_TYPE_LAYERED_READBACK,					// !< draw to two layers multiple times
71 };
72 
73 struct ImageParams
74 {
75 	VkImageViewType		viewType;
76 	VkExtent3D			size;
77 	deUint32			numLayers;
78 };
79 
80 struct TestParams
81 {
82 	TestType			testType;
83 	ImageParams			image;
84 };
85 
86 static const float s_colors[][4] =
87 {
88 	{ 1.0f, 1.0f, 1.0f, 1.0f },		// white
89 	{ 1.0f, 0.0f, 0.0f, 1.0f },		// red
90 	{ 0.0f, 1.0f, 0.0f, 1.0f },		// green
91 	{ 0.0f, 0.0f, 1.0f, 1.0f },		// blue
92 	{ 1.0f, 1.0f, 0.0f, 1.0f },		// yellow
93 	{ 1.0f, 0.0f, 1.0f, 1.0f },		// magenta
94 };
95 
scaleColor(const tcu::Vec4 & color,float factor)96 tcu::Vec4 scaleColor(const tcu::Vec4& color, float factor)
97 {
98 	return tcu::Vec4(color[0] * factor,
99 					 color[1] * factor,
100 					 color[2] * factor,
101 					 color[3]);
102 }
103 
getTargetLayer(const ImageParams & imageParams)104 deUint32 getTargetLayer (const ImageParams& imageParams)
105 {
106 	if (imageParams.viewType == VK_IMAGE_VIEW_TYPE_3D)
107 		return imageParams.size.depth / 2;
108 	else
109 		return imageParams.numLayers / 2;
110 }
111 
getShortImageViewTypeName(const VkImageViewType imageViewType)112 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
113 {
114 	std::string s(getImageViewTypeName(imageViewType));
115 	return de::toLower(s.substr(19));
116 }
117 
getImageType(const VkImageViewType viewType)118 VkImageType getImageType (const VkImageViewType viewType)
119 {
120 	switch (viewType)
121 	{
122 		case VK_IMAGE_VIEW_TYPE_1D:
123 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
124 			return VK_IMAGE_TYPE_1D;
125 
126 		case VK_IMAGE_VIEW_TYPE_2D:
127 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
128 		case VK_IMAGE_VIEW_TYPE_CUBE:
129 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
130 			return VK_IMAGE_TYPE_2D;
131 
132 		case VK_IMAGE_VIEW_TYPE_3D:
133 			return VK_IMAGE_TYPE_3D;
134 
135 		default:
136 			DE_ASSERT(0);
137 			return VK_IMAGE_TYPE_LAST;
138 	}
139 }
140 
getStencilBufferFormat(VkFormat depthStencilImageFormat)141 VkFormat getStencilBufferFormat(VkFormat depthStencilImageFormat)
142 {
143 	const tcu::TextureFormat tcuFormat = mapVkFormat(depthStencilImageFormat);
144 	const VkFormat result = (tcuFormat.order == tcu::TextureFormat::S || tcuFormat.order == tcu::TextureFormat::DS) ? VK_FORMAT_S8_UINT : VK_FORMAT_UNDEFINED;
145 
146 	DE_ASSERT(result != VK_FORMAT_UNDEFINED);
147 
148 	return result;
149 }
150 
isCubeImageViewType(const VkImageViewType viewType)151 inline bool isCubeImageViewType (const VkImageViewType viewType)
152 {
153 	return viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
154 }
155 
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)156 void checkImageFormatProperties (const InstanceInterface&	vki,
157 								 const VkPhysicalDevice&	physDevice,
158 								 const VkImageType&			imageType,
159 								 const VkImageTiling&		imageTiling,
160 								 const VkImageUsageFlags	imageUsageFlags,
161 								 const VkImageCreateFlags	imageCreateFlags,
162 								 const VkFormat				format,
163 								 const VkExtent3D&			requiredSize,
164 								 const deUint32				requiredLayers)
165 {
166 	VkImageFormatProperties	imageFormatProperties;
167 	VkResult				result;
168 
169 	deMemset(&imageFormatProperties, 0, sizeof(imageFormatProperties));
170 
171 	result = vki.getPhysicalDeviceImageFormatProperties(physDevice, format, imageType, imageTiling, imageUsageFlags, imageCreateFlags, &imageFormatProperties);
172 
173 	if (result									!= VK_SUCCESS			||
174 		imageFormatProperties.maxArrayLayers	<  requiredLayers		||
175 		imageFormatProperties.maxExtent.height	<  requiredSize.height	||
176 		imageFormatProperties.maxExtent.width	<  requiredSize.width	||
177 		imageFormatProperties.maxExtent.depth	<  requiredSize.depth)
178 	{
179 		TCU_THROW(NotSupportedError, "Depth/stencil format is not supported");
180 	}
181 }
182 
makeImageCreateInfo(const VkImageCreateFlags flags,const VkImageType type,const VkFormat format,const VkExtent3D size,const deUint32 numLayers,const VkImageUsageFlags usage)183 VkImageCreateInfo makeImageCreateInfo (const VkImageCreateFlags flags, const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const VkImageUsageFlags usage)
184 {
185 	const VkImageCreateInfo imageParams =
186 	{
187 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
188 		DE_NULL,										// const void*				pNext;
189 		flags,											// VkImageCreateFlags		flags;
190 		type,											// VkImageType				imageType;
191 		format,											// VkFormat					format;
192 		size,											// VkExtent3D				extent;
193 		1u,												// deUint32					mipLevels;
194 		numLayers,										// deUint32					arrayLayers;
195 		VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples;
196 		VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
197 		usage,											// VkImageUsageFlags		usage;
198 		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
199 		0u,												// deUint32					queueFamilyIndexCount;
200 		DE_NULL,										// const deUint32*			pQueueFamilyIndices;
201 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout;
202 	};
203 	return imageParams;
204 }
205 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const VkFormat dsFormat,const bool useDepthStencil)206 Move<VkRenderPass> makeRenderPass (const DeviceInterface&	vk,
207 								   const VkDevice			device,
208 								   const VkFormat			colorFormat,
209 								   const VkFormat			dsFormat,
210 								   const bool				useDepthStencil)
211 {
212 	return vk::makeRenderPass(vk, device, colorFormat, useDepthStencil ? dsFormat : VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD);
213 }
214 
215 
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)216 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&		vk,
217 									   const VkDevice				device,
218 									   const VkPipelineLayout		pipelineLayout,
219 									   const VkRenderPass			renderPass,
220 									   const VkShaderModule			vertexModule,
221 									   const VkShaderModule			geometryModule,
222 									   const VkShaderModule			fragmentModule,
223 									   const VkExtent2D				renderSize,
224 									   const bool					useDepthStencil = false)
225 {
226 	const std::vector<VkViewport>			viewports						(1, makeViewport(renderSize));
227 	const std::vector<VkRect2D>				scissors						(1, makeRect2D(renderSize));
228 
229 	const VkStencilOpState					stencilOpState					= makeStencilOpState(
230 		VK_STENCIL_OP_KEEP,					// stencil fail
231 		VK_STENCIL_OP_INCREMENT_AND_CLAMP,	// depth & stencil pass
232 		VK_STENCIL_OP_KEEP,					// depth only fail
233 		VK_COMPARE_OP_ALWAYS,				// compare op
234 		~0u,								// compare mask
235 		~0u,								// write mask
236 		0u);								// reference
237 
238 	VkPipelineDepthStencilStateCreateInfo	pipelineDepthStencilStateInfo	=
239 	{
240 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType                           sType;
241 		DE_NULL,													// const void*                               pNext;
242 		(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags    flags;
243 		useDepthStencil ? VK_TRUE : VK_FALSE,						// VkBool32                                  depthTestEnable;
244 		useDepthStencil ? VK_TRUE : VK_FALSE,						// VkBool32                                  depthWriteEnable;
245 		VK_COMPARE_OP_LESS,											// VkCompareOp                               depthCompareOp;
246 		VK_FALSE,													// VkBool32                                  depthBoundsTestEnable;
247 		useDepthStencil ? VK_TRUE : VK_FALSE,						// VkBool32                                  stencilTestEnable;
248 		stencilOpState,												// VkStencilOpState                          front;
249 		stencilOpState,												// VkStencilOpState                          back;
250 		0.0f,														// float                                     minDepthBounds;
251 		1.0f														// float                                     maxDepthBounds;
252 	};
253 
254 	return vk::makeGraphicsPipeline(vk,									// const DeviceInterface&                        vk
255 									device,								// const VkDevice                                device
256 									pipelineLayout,						// const VkPipelineLayout                        pipelineLayout
257 									vertexModule,						// const VkShaderModule                          vertexShaderModule
258 									DE_NULL,							// const VkShaderModule                          tessellationControlModule
259 									DE_NULL,							// const VkShaderModule                          tessellationEvalModule
260 									geometryModule,						// const VkShaderModule                          geometryShaderModule
261 									fragmentModule,						// const VkShaderModule                          fragmentShaderModule
262 									renderPass,							// const VkRenderPass                            renderPass
263 									viewports,							// const std::vector<VkViewport>&                viewports
264 									scissors,							// const std::vector<VkRect2D>&                  scissors
265 									VK_PRIMITIVE_TOPOLOGY_POINT_LIST,	// const VkPrimitiveTopology                     topology
266 									0u,									// const deUint32                                subpass
267 									0u,									// const deUint32                                patchControlPoints
268 									DE_NULL,							// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
269 									DE_NULL,							// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
270 									DE_NULL,							// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
271 									&pipelineDepthStencilStateInfo);	// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
272 }
273 
makeFramebuffer(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass,const VkImageView * pAttachments,const deUint32 attachmentsCount,const deUint32 width,const deUint32 height,const deUint32 layers)274 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&	vk,
275 									 const VkDevice			device,
276 									 const VkRenderPass		renderPass,
277 									 const VkImageView*		pAttachments,
278 									 const deUint32			attachmentsCount,
279 									 const deUint32			width,
280 									 const deUint32			height,
281 									 const deUint32			layers)
282 {
283 	const VkFramebufferCreateInfo framebufferInfo = {
284 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,		// VkStructureType                             sType;
285 		DE_NULL,										// const void*                                 pNext;
286 		(VkFramebufferCreateFlags)0,					// VkFramebufferCreateFlags                    flags;
287 		renderPass,										// VkRenderPass                                renderPass;
288 		attachmentsCount,								// uint32_t                                    attachmentCount;
289 		pAttachments,									// const VkImageView*                          pAttachments;
290 		width,											// uint32_t                                    width;
291 		height,											// uint32_t                                    height;
292 		layers,											// uint32_t                                    layers;
293 	};
294 
295 	return createFramebuffer(vk, device, &framebufferInfo);
296 }
297 
298 //! Convenience wrapper to access 1D, 2D, and 3D image layers/slices in a uniform way.
299 class LayeredImageAccess
300 {
301 public:
create(const VkImageType type,const VkFormat format,const VkExtent3D size,const deUint32 numLayers,const void * pData)302 	static LayeredImageAccess create (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
303 	{
304 		if (type == VK_IMAGE_TYPE_1D)
305 			return LayeredImageAccess(format, size.width, numLayers, pData);
306 		else
307 			return LayeredImageAccess(type, format, size, numLayers, pData);
308 	}
309 
getLayer(const int layer) const310 	inline tcu::ConstPixelBufferAccess getLayer (const int layer) const
311 	{
312 		return tcu::getSubregion(m_wholeImage, 0, (m_1dModifier * layer), ((~m_1dModifier & 1) * layer), m_width, m_height, 1);
313 	}
314 
getNumLayersOrSlices(void) const315 	inline int getNumLayersOrSlices (void) const
316 	{
317 		return m_layers;
318 	}
319 
320 private:
321 	// Specialized for 1D images.
LayeredImageAccess(const VkFormat format,const deUint32 width,const deUint32 numLayers,const void * pData)322 	LayeredImageAccess (const VkFormat format, const deUint32 width, const deUint32 numLayers, const void* pData)
323 		: m_width		(static_cast<int>(width))
324 		, m_height		(1)
325 		, m_1dModifier	(1)
326 		, m_layers		(numLayers)
327 		, m_wholeImage	(tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_layers, 1, pData))
328 	{
329 	}
330 
LayeredImageAccess(const VkImageType type,const VkFormat format,const VkExtent3D size,const deUint32 numLayers,const void * pData)331 	LayeredImageAccess (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
332 		: m_width		(static_cast<int>(size.width))
333 		, m_height		(static_cast<int>(size.height))
334 		, m_1dModifier	(0)
335 		, m_layers		(static_cast<int>(type == VK_IMAGE_TYPE_3D ? size.depth : numLayers))
336 		, m_wholeImage	(tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_height, m_layers, pData))
337 	{
338 	}
339 
340 	const int							m_width;
341 	const int							m_height;
342 	const int							m_1dModifier;
343 	const int							m_layers;
344 	const tcu::ConstPixelBufferAccess	m_wholeImage;
345 };
346 
compareColors(const Vec4 & colorA,const Vec4 & colorB,const Vec4 & threshold)347 inline bool compareColors (const Vec4& colorA, const Vec4& colorB, const Vec4& threshold)
348 {
349 	return tcu::allEqual(
350 				tcu::lessThan(tcu::abs(colorA - colorB), threshold),
351 				tcu::BVec4(true, true, true, true));
352 }
353 
verifyImageSingleColoredRow(tcu::TestLog & log,const tcu::ConstPixelBufferAccess image,const float rowWidthRatio,const tcu::Vec4 & barColor)354 bool verifyImageSingleColoredRow (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image, const float rowWidthRatio, const tcu::Vec4& barColor)
355 {
356 	DE_ASSERT(rowWidthRatio > 0.0f);
357 
358 	const Vec4				black				(0.0f, 0.0f, 0.0f, 1.0f);
359 	const Vec4				green				(0.0f, 1.0f, 0.0f, 1.0f);
360 	const Vec4				red					(1.0f, 0.0f, 0.0f, 1.0f);
361 	const Vec4				threshold			(0.02f);
362 	const int				barLength			= static_cast<int>(rowWidthRatio * static_cast<float>(image.getWidth()));
363 	const int				barLengthThreshold	= 1;
364 	tcu::TextureLevel		errorMask			(image.getFormat(), image.getWidth(), image.getHeight());
365 	tcu::PixelBufferAccess	errorMaskAccess		= errorMask.getAccess();
366 
367 	tcu::clear(errorMask.getAccess(), green);
368 
369 	log << tcu::TestLog::Message
370 		<< "Expecting all pixels with distance less or equal to (about) " << barLength
371 		<< " pixels from left border to be of color " << barColor.swizzle(0, 1, 2) << "."
372 		<< tcu::TestLog::EndMessage;
373 
374 	bool allPixelsOk = true;
375 
376 	for (int y = 0; y < image.getHeight(); ++y)
377 	for (int x = 0; x < image.getWidth();  ++x)
378 	{
379 		const Vec4	color		= image.getPixel(x, y);
380 		const bool	isBlack		= compareColors(color, black, threshold);
381 		const bool	isColor		= compareColors(color, barColor, threshold);
382 
383 		bool isOk;
384 
385 		if (x <= barLength - barLengthThreshold)
386 			isOk = isColor;
387 		else if (x >= barLength + barLengthThreshold)
388 			isOk = isBlack;
389 		else
390 			isOk = isColor || isBlack;
391 
392 		allPixelsOk &= isOk;
393 
394 		if (!isOk)
395 			errorMaskAccess.setPixel(red, x, y);
396 	}
397 
398 	if (allPixelsOk)
399 	{
400 		log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
401 			<< tcu::TestLog::ImageSet("LayerContent", "Layer content")
402 			<< tcu::TestLog::Image("Layer", "Layer", image)
403 			<< tcu::TestLog::EndImageSet;
404 		return true;
405 	}
406 	else
407 	{
408 		log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
409 			<< tcu::TestLog::ImageSet("LayerContent", "Layer content")
410 			<< tcu::TestLog::Image("Layer",		"Layer",	image)
411 			<< tcu::TestLog::Image("ErrorMask",	"Errors",	errorMask)
412 			<< tcu::TestLog::EndImageSet;
413 		return false;
414 	}
415 
416 	log << tcu::TestLog::Image("LayerContent", "Layer content", image);
417 
418 	return allPixelsOk;
419 }
420 
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)421 static bool verifyImageMultipleBars (tcu::TestLog&						log,
422 									 const tcu::ConstPixelBufferAccess	image,
423 									 const float*						barWidthRatios,
424 									 const tcu::Vec4*					barValues,
425 									 const int							barsCount,
426 									 const int							numUsedChannels,
427 									 const std::string&					imageTypeName)
428 {
429 	const Vec4					green				(0.0f, 1.0f, 0.0f, 1.0f);
430 	const Vec4					red					(1.0f, 0.0f, 0.0f, 1.0f);
431 	const Vec4					threshold			(0.02f);
432 	const tcu::TextureFormat	errorMaskFormat		(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8));
433 	tcu::TextureLevel			errorMask			(errorMaskFormat, image.getWidth(), image.getHeight());
434 	tcu::PixelBufferAccess		errorMaskAccess		= errorMask.getAccess();
435 	bool						allPixelsOk			= true;
436 
437 	DE_ASSERT(barsCount > 0);
438 
439 	tcu::clear(errorMask.getAccess(), green);
440 
441 	// Format information message
442 	{
443 		int					leftBorder	= 0;
444 		int					rightBorder	= 0;
445 		std::ostringstream	str;
446 
447 		for (int barNdx = 0; barNdx < barsCount; ++barNdx)
448 		{
449 			leftBorder	= rightBorder;
450 			rightBorder	= static_cast<int>(barWidthRatios[barNdx] * static_cast<float>(image.getWidth()));
451 
452 			DE_ASSERT(leftBorder < rightBorder);
453 
454 			str << std::endl << " [" << leftBorder << "," <<rightBorder << "): ";
455 
456 			switch (numUsedChannels)
457 			{
458 				case 1:	str << barValues[barNdx][0];	break;
459 				case 4:	str << barValues[barNdx];		break;
460 				default: DE_ASSERT(false);				break;
461 			}
462 		}
463 
464 		log << tcu::TestLog::Message
465 			<< "Expecting " + imageTypeName + " values depending x-axis position to be of following values: "
466 			<< str.str()
467 			<< tcu::TestLog::EndMessage;
468 	}
469 
470 	for (int x = 0; x < image.getWidth();  ++x)
471 	{
472 		tcu::Vec4	expectedValue	= barValues[0];
473 
474 		for (int barNdx = 0; barNdx < barsCount; ++barNdx)
475 		{
476 			const int rightBorder	= static_cast<int>(barWidthRatios[barNdx] * static_cast<float>(image.getWidth()));
477 
478 			if (x < rightBorder)
479 			{
480 				expectedValue = barValues[barNdx];
481 
482 				break;
483 			}
484 		}
485 
486 		for (int y = 0; y < image.getHeight(); ++y)
487 		{
488 			const tcu::Vec4	realValue	= image.getPixel(x, y);
489 			bool			isOk		= false;
490 
491 			switch (numUsedChannels)
492 			{
493 				case 1:	isOk = fabs(realValue[0] - expectedValue[0]) < threshold[0];	break;
494 				case 4:	isOk = compareColors(realValue, expectedValue, threshold);		break;
495 				default: DE_ASSERT(false);												break;
496 			}
497 
498 			if (!isOk)
499 				errorMaskAccess.setPixel(red, x, y);
500 
501 			allPixelsOk = allPixelsOk && isOk;
502 		}
503 	}
504 
505 	if (allPixelsOk)
506 	{
507 		log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
508 			<< tcu::TestLog::ImageSet(imageTypeName + "LayerContent", imageTypeName + " Layer Content")
509 			<< tcu::TestLog::Image("Layer", "Layer", image)
510 			<< tcu::TestLog::EndImageSet;
511 	}
512 	else
513 	{
514 		log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
515 			<< tcu::TestLog::ImageSet(imageTypeName + "LayerContent", imageTypeName + " Layer Content")
516 			<< tcu::TestLog::Image("Layer",		"Layer",	image)
517 			<< tcu::TestLog::Image("ErrorMask",	"Errors",	errorMask)
518 			<< tcu::TestLog::EndImageSet;
519 	}
520 
521 	return allPixelsOk;
522 }
523 
convertDepthToColorBufferAccess(const tcu::ConstPixelBufferAccess & inputImage,tcu::PixelBufferAccess & outputImage)524 static void convertDepthToColorBufferAccess (const tcu::ConstPixelBufferAccess& inputImage, tcu::PixelBufferAccess& outputImage)
525 {
526 	for (int y = 0; y < inputImage.getHeight(); y++)
527 	for (int x = 0; x < inputImage.getWidth(); x++)
528 	{
529 		const float		depth	= inputImage.getPixDepth(x, y);
530 		const tcu::Vec4	color	= tcu::Vec4(depth, depth, depth, 1.0f);
531 
532 		outputImage.setPixel(color, x, y);
533 	}
534 }
535 
convertStencilToColorBufferAccess(const tcu::ConstPixelBufferAccess & inputImage,tcu::PixelBufferAccess & outputImage,int maxValue)536 static void convertStencilToColorBufferAccess (const tcu::ConstPixelBufferAccess& inputImage, tcu::PixelBufferAccess& outputImage, int maxValue)
537 {
538 	for (int y = 0; y < inputImage.getHeight(); y++)
539 	for (int x = 0; x < inputImage.getWidth(); x++)
540 	{
541 		const int		stencilInt	= inputImage.getPixStencil(x, y);
542 		const float		stencil		= (stencilInt < maxValue) ? float(stencilInt) / float(maxValue) : 1.0f;
543 		const tcu::Vec4	color		= tcu::Vec4(stencil, stencil, stencil, 1.0f);
544 
545 		outputImage.setPixel(color, x, y);
546 	}
547 }
548 
verifyEmptyImage(tcu::TestLog & log,const tcu::ConstPixelBufferAccess image)549 bool verifyEmptyImage (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image)
550 {
551 	log << tcu::TestLog::Message << "Expecting empty image" << tcu::TestLog::EndMessage;
552 
553 	const Vec4	black		(0.0f, 0.0f, 0.0f, 1.0f);
554 	const Vec4	threshold	(0.02f);
555 
556 	for (int y = 0; y < image.getHeight(); ++y)
557 	for (int x = 0; x < image.getWidth();  ++x)
558 	{
559 		const Vec4 color = image.getPixel(x, y);
560 
561 		if (!compareColors(color, black, threshold))
562 		{
563 			log	<< tcu::TestLog::Message
564 				<< "Found (at least) one bad pixel at " << x << "," << y << ". Pixel color is not background color."
565 				<< tcu::TestLog::EndMessage
566 				<< tcu::TestLog::ImageSet("LayerContent", "Layer content")
567 				<< tcu::TestLog::Image("Layer", "Layer", image)
568 				<< tcu::TestLog::EndImageSet;
569 			return false;
570 		}
571 	}
572 
573 	log << tcu::TestLog::Message << "Image is valid" << tcu::TestLog::EndMessage;
574 
575 	return true;
576 }
577 
verifyLayerContent(tcu::TestLog & log,const TestType testType,const tcu::ConstPixelBufferAccess image,const int layerNdx,const int numLayers,const bool depthCheck,const bool stencilCheck)578 bool verifyLayerContent (tcu::TestLog& log, const TestType testType, const tcu::ConstPixelBufferAccess image, const int layerNdx, const int numLayers, const bool depthCheck, const bool stencilCheck)
579 {
580 	const Vec4	white				(1.0f, 1.0f, 1.0f, 1.0f);
581 	const int	targetLayer			= numLayers / 2;
582 	const float	variableBarRatio	= static_cast<float>(layerNdx) / static_cast<float>(numLayers);
583 
584 	switch (testType)
585 	{
586 		case TEST_TYPE_DEFAULT_LAYER:
587 			if (layerNdx == 0)
588 				return verifyImageSingleColoredRow(log, image, 0.5f, white);
589 			else
590 				return verifyEmptyImage(log, image);
591 
592 		case TEST_TYPE_SINGLE_LAYER:
593 			if (layerNdx == targetLayer)
594 				return verifyImageSingleColoredRow(log, image, 0.5f, white);
595 			else
596 				return verifyEmptyImage(log, image);
597 
598 		case TEST_TYPE_ALL_LAYERS:
599 		case TEST_TYPE_INVOCATION_PER_LAYER:
600 			return verifyImageSingleColoredRow(log, image, 0.5f, s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
601 
602 		case TEST_TYPE_DIFFERENT_CONTENT:
603 		case TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION:
604 			if (layerNdx == 0)
605 				return verifyEmptyImage(log, image);
606 			else
607 				return verifyImageSingleColoredRow(log, image, variableBarRatio, white);
608 
609 		case TEST_TYPE_LAYER_ID:
610 		{
611 			// This code must be in sync with the fragment shader.
612 			const tcu::Vec4 layerColor( (layerNdx    % 2) == 1 ? 1.0f : 0.5f,
613 									   ((layerNdx/2) % 2) == 1 ? 1.0f : 0.5f,
614 									     layerNdx         == 0 ? 1.0f : 0.0f,
615 																 1.0f);
616 			return verifyImageSingleColoredRow(log, image, 0.5f, layerColor);
617 		}
618 
619 		case TEST_TYPE_LAYERED_READBACK:
620 		{
621 			const float	barWidthRatios[]	= { 0.25f, 0.5f, 1.0f };
622 			const int	barsCount			= DE_LENGTH_OF_ARRAY(barWidthRatios);
623 			bool		result				= false;
624 
625 			if (depthCheck)
626 			{
627 				const std::string		checkType				= "Depth";
628 				const float				pass0depth				= static_cast<float>(layerNdx + 1) / static_cast<float>(2 * numLayers);
629 				const float				pass1depth				= static_cast<float>(layerNdx + 0) / static_cast<float>(2 * numLayers);
630 				const tcu::Vec4			barDepths[barsCount]	= { tcu::Vec4(pass1depth), tcu::Vec4(pass0depth), tcu::Vec4(1.0f) };
631 				tcu::TextureLevel		depthAsColorBuffer		(tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), image.getWidth(), image.getHeight());
632 				tcu::PixelBufferAccess	depthAsColor			(depthAsColorBuffer);
633 				const int				numUsedChannels			(tcu::getNumUsedChannels(depthAsColor.getFormat().order));
634 
635 				convertDepthToColorBufferAccess(image, depthAsColor);
636 
637 				result = verifyImageMultipleBars(log, depthAsColor, barWidthRatios, barDepths, barsCount, numUsedChannels, checkType);
638 			}
639 			else if (stencilCheck)
640 			{
641 				const std::string		checkType				= "Stencil";
642 				const int				maxStencilValue			= 4;
643 				const float				pass0stencil			= static_cast<float>(1.0f / maxStencilValue);
644 				const float				pass1stencil			= static_cast<float>(2.0f / maxStencilValue);
645 				const tcu::Vec4			barStencils[barsCount]	= { tcu::Vec4(pass1stencil), tcu::Vec4(pass0stencil), tcu::Vec4(0.0f) };
646 				tcu::TextureLevel		stencilAsColorBuffer	(tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), image.getWidth(), image.getHeight());
647 				tcu::PixelBufferAccess	stencilAsColor			(stencilAsColorBuffer);
648 				const int				numUsedChannels			(tcu::getNumUsedChannels(stencilAsColor.getFormat().order));
649 
650 				convertStencilToColorBufferAccess(image, stencilAsColor, maxStencilValue);
651 
652 				result = verifyImageMultipleBars(log, stencilAsColor, barWidthRatios, barStencils, barsCount, numUsedChannels, checkType);
653 			}
654 			else
655 			{
656 				const std::string		checkType				= "Color";
657 				const tcu::Vec4			baseColor				(s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
658 				const tcu::Vec4			barColors[barsCount]	= { scaleColor(baseColor, 1.00f), scaleColor(baseColor, 0.50f), scaleColor(baseColor, 0.25f) };
659 				const int				numUsedChannels			(tcu::getNumUsedChannels(image.getFormat().order));
660 
661 				result = verifyImageMultipleBars(log, image, barWidthRatios, barColors, barsCount, numUsedChannels, checkType);
662 			}
663 
664 			return result;
665 		}
666 
667 		default:
668 			DE_ASSERT(0);
669 			return false;
670 	};
671 }
672 
getLayerDescription(const VkImageViewType viewType,const int layer)673 std::string getLayerDescription (const VkImageViewType viewType, const int layer)
674 {
675 	std::ostringstream str;
676 	const int numCubeFaces = 6;
677 
678 	if (isCubeImageViewType(viewType))
679 		str << "cube " << (layer / numCubeFaces) << ", face " << (layer % numCubeFaces);
680 	else if (viewType == VK_IMAGE_VIEW_TYPE_3D)
681 		str << "slice z = " << layer;
682 	else
683 		str << "layer " << layer;
684 
685 	return str.str();
686 }
687 
verifyResults(tcu::TestLog & log,const TestParams & params,const VkFormat imageFormat,const void * resultData,const bool depthCheck=false,const bool stencilCheck=false)688 bool verifyResults (tcu::TestLog& log, const TestParams& params, const VkFormat imageFormat, const void* resultData, const bool depthCheck = false, const bool stencilCheck = false)
689 {
690 	const LayeredImageAccess image = LayeredImageAccess::create(getImageType(params.image.viewType), imageFormat, params.image.size, params.image.numLayers, resultData);
691 
692 	int numGoodLayers = 0;
693 
694 	for (int layerNdx = 0; layerNdx < image.getNumLayersOrSlices(); ++layerNdx)
695 	{
696 		const tcu::ConstPixelBufferAccess layerImage = image.getLayer(layerNdx);
697 
698 		log << tcu::TestLog::Message << "Verifying " << getLayerDescription(params.image.viewType, layerNdx) << tcu::TestLog::EndMessage;
699 
700 		if (verifyLayerContent(log, params.testType, layerImage, layerNdx, image.getNumLayersOrSlices(), depthCheck, stencilCheck))
701 			++numGoodLayers;
702 	}
703 
704 	return numGoodLayers == image.getNumLayersOrSlices();
705 }
706 
toGlsl(const Vec4 & v)707 std::string toGlsl (const Vec4& v)
708 {
709 	std::ostringstream str;
710 	str << "vec4(";
711 	for (int i = 0; i < 4; ++i)
712 		str << (i != 0 ? ", " : "") << de::floatToString(v[i], 1);
713 	str << ")";
714 	return str.str();
715 }
716 
initPrograms(SourceCollections & programCollection,const TestParams params)717 void initPrograms (SourceCollections& programCollection, const TestParams params)
718 {
719 	const bool geomOutputColor = (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_LAYERED_READBACK);
720 
721 	// Vertex shader
722 	{
723 		std::ostringstream src;
724 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
725 			<< "\n"
726 			<< "void main(void)\n"
727 			<< "{\n"
728 			<< "}\n";
729 
730 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
731 	}
732 
733 	// Geometry shader
734 	{
735 		const int numLayers		= static_cast<int>(params.image.viewType == VK_IMAGE_VIEW_TYPE_3D ? params.image.size.depth : params.image.numLayers);
736 
737 		const int maxVertices	= (params.testType == TEST_TYPE_DIFFERENT_CONTENT)																						? (numLayers + 1) * numLayers :
738 								  (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_LAYER_ID || params.testType == TEST_TYPE_LAYERED_READBACK)	? numLayers * 4 :
739 								  (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)																			? 6 : 4;
740 
741 		std::ostringstream src;
742 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
743 			<< "\n";
744 
745 		if (params.testType == TEST_TYPE_LAYERED_READBACK)
746 			src << "layout(binding = 0) readonly uniform Input {\n"
747 				<< "    int pass;\n"
748 				<< "} uInput;\n\n";
749 
750 		if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
751 			src << "layout(points, invocations = " << numLayers << ") in;\n";
752 		else
753 			src << "layout(points) in;\n";
754 
755 		src << "layout(triangle_strip, max_vertices = " << maxVertices << ") out;\n"
756 			<< "\n"
757 			<< (geomOutputColor ? "layout(location = 0) out vec4 vert_color;\n\n" : "")
758 			<< "out gl_PerVertex {\n"
759 			<< "    vec4 gl_Position;\n"
760 			<< "};\n"
761 			<< "\n"
762 			<< "void main(void)\n"
763 			<< "{\n";
764 
765 		std::ostringstream colorTable;
766 		{
767 			const int numColors = DE_LENGTH_OF_ARRAY(s_colors);
768 
769 			colorTable << "    const vec4 colors[" << numColors << "] = vec4[" << numColors << "](";
770 
771 			const std::string padding(colorTable.str().length(), ' ');
772 
773 			for (int i = 0; i < numColors; ++i)
774 				colorTable << (i != 0 ? ",\n" + padding : "") << toGlsl(s_colors[i]);
775 
776 			colorTable << ");\n";
777 		}
778 
779 		if (params.testType == TEST_TYPE_DEFAULT_LAYER)
780 		{
781 			src << "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
782 				<< "    EmitVertex();\n"
783 				<< "\n"
784 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
785 				<< "    EmitVertex();\n"
786 				<< "\n"
787 				<< "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
788 				<< "    EmitVertex();\n"
789 				<< "\n"
790 				<< "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
791 				<< "    EmitVertex();\n";
792 		}
793 		else if (params.testType == TEST_TYPE_SINGLE_LAYER)
794 		{
795 			const deUint32 targetLayer = getTargetLayer(params.image);
796 
797 			src << "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
798 				<< "    gl_Layer    = " << targetLayer << ";\n"
799 				<< "    EmitVertex();\n"
800 				<< "\n"
801 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
802 				<< "    gl_Layer    = " << targetLayer << ";\n"
803 				<< "    EmitVertex();\n"
804 				<< "\n"
805 				<< "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
806 				<< "    gl_Layer    = " << targetLayer << ";\n"
807 				<< "    EmitVertex();\n"
808 				<< "\n"
809 				<< "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
810 				<< "    gl_Layer    = " << targetLayer << ";\n"
811 				<< "    EmitVertex();\n";
812 		}
813 		else if (params.testType == TEST_TYPE_ALL_LAYERS)
814 		{
815 			src << colorTable.str()
816 				<< "\n"
817 				<< "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
818 				<< "        const int colorNdx = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
819 				<< "\n"
820 				<< "        gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
821 				<< "        gl_Layer    = layerNdx;\n"
822 				<< "        vert_color  = colors[colorNdx];\n"
823 				<< "        EmitVertex();\n"
824 				<< "\n"
825 				<< "        gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
826 				<< "        gl_Layer    = layerNdx;\n"
827 				<< "        vert_color  = colors[colorNdx];\n"
828 				<< "        EmitVertex();\n"
829 				<< "\n"
830 				<< "        gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
831 				<< "        gl_Layer    = layerNdx;\n"
832 				<< "        vert_color  = colors[colorNdx];\n"
833 				<< "        EmitVertex();\n"
834 				<< "\n"
835 				<< "        gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
836 				<< "        gl_Layer    = layerNdx;\n"
837 				<< "        vert_color  = colors[colorNdx];\n"
838 				<< "        EmitVertex();\n"
839 				<< "        EndPrimitive();\n"
840 				<< "    };\n";
841 		}
842 		else if (params.testType == TEST_TYPE_LAYER_ID)
843 		{
844 			src << "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
845 				<< "        gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
846 				<< "        gl_Layer    = layerNdx;\n"
847 				<< "        EmitVertex();\n"
848 				<< "\n"
849 				<< "        gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
850 				<< "        gl_Layer    = layerNdx;\n"
851 				<< "        EmitVertex();\n"
852 				<< "\n"
853 				<< "        gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
854 				<< "        gl_Layer    = layerNdx;\n"
855 				<< "        EmitVertex();\n"
856 				<< "\n"
857 				<< "        gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
858 				<< "        gl_Layer    = layerNdx;\n"
859 				<< "        EmitVertex();\n"
860 				<< "        EndPrimitive();\n"
861 				<< "    };\n";
862 		}
863 		else if (params.testType == TEST_TYPE_DIFFERENT_CONTENT)
864 		{
865 			src << "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
866 				<< "        for (int colNdx = 0; colNdx <= layerNdx; ++colNdx) {\n"
867 				<< "            const float posX = float(colNdx) / float(" << numLayers << ") * 2.0 - 1.0;\n"
868 				<< "\n"
869 				<< "            gl_Position = vec4(posX,  1.0, 0.0, 1.0);\n"
870 				<< "            gl_Layer    = layerNdx;\n"
871 				<< "            EmitVertex();\n"
872 				<< "\n"
873 				<< "            gl_Position = vec4(posX, -1.0, 0.0, 1.0);\n"
874 				<< "            gl_Layer    = layerNdx;\n"
875 				<< "            EmitVertex();\n"
876 				<< "        }\n"
877 				<< "        EndPrimitive();\n"
878 				<< "    }\n";
879 		}
880 		else if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER)
881 		{
882 			src << colorTable.str()
883 				<< "    const int colorNdx = gl_InvocationID % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
884 				<< "\n"
885 				<< "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
886 				<< "    gl_Layer    = gl_InvocationID;\n"
887 				<< "    vert_color  = colors[colorNdx];\n"
888 				<< "    EmitVertex();\n"
889 				<< "\n"
890 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
891 				<< "    gl_Layer    = gl_InvocationID;\n"
892 				<< "    vert_color  = colors[colorNdx];\n"
893 				<< "    EmitVertex();\n"
894 				<< "\n"
895 				<< "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
896 				<< "    gl_Layer    = gl_InvocationID;\n"
897 				<< "    vert_color  = colors[colorNdx];\n"
898 				<< "    EmitVertex();\n"
899 				<< "\n"
900 				<< "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
901 				<< "    gl_Layer    = gl_InvocationID;\n"
902 				<< "    vert_color  = colors[colorNdx];\n"
903 				<< "    EmitVertex();\n"
904 				<< "    EndPrimitive();\n";
905 		}
906 		else if (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
907 		{
908 			src << "    const int   layerA = gl_InvocationID;\n"
909 				<< "    const int   layerB = (gl_InvocationID + 1) % " << numLayers << ";\n"
910 				<< "    const float aEnd   = float(layerA) / float(" << numLayers << ") * 2.0 - 1.0;\n"
911 				<< "    const float bEnd   = float(layerB) / float(" << numLayers << ") * 2.0 - 1.0;\n"
912 				<< "\n"
913 				<< "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
914 				<< "    gl_Layer    = layerA;\n"
915 				<< "    EmitVertex();\n"
916 				<< "\n"
917 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
918 				<< "    gl_Layer    = layerA;\n"
919 				<< "    EmitVertex();\n"
920 				<< "\n"
921 				<< "    gl_Position = vec4(aEnd, -1.0, 0.0, 1.0);\n"
922 				<< "    gl_Layer    = layerA;\n"
923 				<< "    EmitVertex();\n"
924 				<< "    EndPrimitive();\n"
925 				<< "\n"
926 				<< "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
927 				<< "    gl_Layer    = layerB;\n"
928 				<< "    EmitVertex();\n"
929 				<< "\n"
930 				<< "    gl_Position = vec4(bEnd,  1.0, 0.0, 1.0);\n"
931 				<< "    gl_Layer    = layerB;\n"
932 				<< "    EmitVertex();\n"
933 				<< "\n"
934 				<< "    gl_Position = vec4(bEnd, -1.0, 0.0, 1.0);\n"
935 				<< "    gl_Layer    = layerB;\n"
936 				<< "    EmitVertex();\n"
937 				<< "    EndPrimitive();\n";
938 		}
939 		else if (params.testType == TEST_TYPE_LAYERED_READBACK)
940 		{
941 			src << colorTable.str()
942 				<< "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
943 				<< "        const int   colorNdx   = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
944 				<< "        const vec3  passColor0 = (uInput.pass == 0 ? 0.5 :  1.0) * vec3(colors[colorNdx]);\n"
945 				<< "        const vec4  passColor  = vec4(passColor0, 1.0);\n"
946 				<< "        const float posX       = (uInput.pass == 0 ? 0.0 : -0.5);\n"
947 				<< "        const float posZ       = float(layerNdx + 1 - uInput.pass) / float(" << 2*numLayers << ");\n"
948 				<< "\n"
949 				<< "        gl_Position = vec4(-1.0, -1.0, posZ, 1.0);\n"
950 				<< "        gl_Layer    = layerNdx;\n"
951 				<< "        vert_color  = passColor;\n"
952 				<< "        EmitVertex();\n"
953 				<< "\n"
954 				<< "        gl_Position = vec4(-1.0,  1.0, posZ, 1.0);\n"
955 				<< "        gl_Layer    = layerNdx;\n"
956 				<< "        vert_color  = passColor;\n"
957 				<< "        EmitVertex();\n"
958 				<< "\n"
959 				<< "        gl_Position = vec4(posX, -1.0, posZ, 1.0);\n"
960 				<< "        gl_Layer    = layerNdx;\n"
961 				<< "        vert_color  = passColor;\n"
962 				<< "        EmitVertex();\n"
963 				<< "\n"
964 				<< "        gl_Position = vec4(posX,  1.0, posZ, 1.0);\n"
965 				<< "        gl_Layer    = layerNdx;\n"
966 				<< "        vert_color  = passColor;\n"
967 				<< "        EmitVertex();\n"
968 				<< "\n"
969 				<< "        EndPrimitive();\n"
970 				<< "    }\n";
971 		}
972 		else
973 			DE_ASSERT(0);
974 
975 		src <<	"}\n";	// end main
976 
977 		programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
978 	}
979 
980 	// Fragment shader
981 	{
982 		std::ostringstream src;
983 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
984 			<< "\n"
985 			<< "layout(location = 0) out vec4 o_color;\n"
986 			<< (geomOutputColor ? "layout(location = 0) in  vec4 vert_color;\n" : "")
987 			<< "\n"
988 			<< "void main(void)\n"
989 			<< "{\n";
990 
991 		if (params.testType == TEST_TYPE_LAYER_ID)
992 		{
993 			// This code must be in sync with verifyLayerContent()
994 			src << "    o_color = vec4( (gl_Layer    % 2) == 1 ? 1.0 : 0.5,\n"
995 				<< "                   ((gl_Layer/2) % 2) == 1 ? 1.0 : 0.5,\n"
996 				<< "                     gl_Layer         == 0 ? 1.0 : 0.0,\n"
997 				<< "                                             1.0);\n";
998 		}
999 		else if (geomOutputColor)
1000 			src << "    o_color = vert_color;\n";
1001 		else
1002 			src << "    o_color = vec4(1.0);\n";
1003 
1004 		src << "}\n";
1005 
1006 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1007 	}
1008 }
1009 
test(Context & context,const TestParams params)1010 tcu::TestStatus test (Context& context, const TestParams params)
1011 {
1012 	if (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType &&
1013 		(!isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_maintenance1")))
1014 		TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
1015 
1016 	const DeviceInterface&			vk						= context.getDeviceInterface();
1017 	const InstanceInterface&		vki						= context.getInstanceInterface();
1018 	const VkDevice					device					= context.getDevice();
1019 	const VkPhysicalDevice			physDevice				= context.getPhysicalDevice();
1020 	const deUint32					queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
1021 	const VkQueue					queue					= context.getUniversalQueue();
1022 	Allocator&						allocator				= context.getDefaultAllocator();
1023 
1024 	checkGeometryShaderSupport(vki, physDevice);
1025 
1026 	const VkFormat					colorFormat				= VK_FORMAT_R8G8B8A8_UNORM;
1027 	const deUint32					numLayers				= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
1028 	const Vec4						clearColor				= Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1029 	const VkDeviceSize				colorBufferSize			= params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * tcu::getPixelSize(mapVkFormat(colorFormat));
1030 	const VkImageCreateFlags		imageCreateFlags		= (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
1031 															  (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
1032 	const VkImageViewType			viewType				= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
1033 
1034 	const Unique<VkImage>			colorImage				(makeImage				(vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
1035 																					 params.image.numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1036 	const UniquePtr<Allocation>		colorImageAlloc			(bindImage				(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1037 	const Unique<VkImageView>		colorAttachment			(makeImageView			(vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
1038 
1039 	const Unique<VkBuffer>			colorBuffer				(makeBuffer				(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
1040 	const UniquePtr<Allocation>		colorBufferAlloc		(bindBuffer				(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1041 
1042 	const Unique<VkShaderModule>	vertexModule			(createShaderModule		(vk, device, context.getBinaryCollection().get("vert"), 0u));
1043 	const Unique<VkShaderModule>	geometryModule			(createShaderModule		(vk, device, context.getBinaryCollection().get("geom"), 0u));
1044 	const Unique<VkShaderModule>	fragmentModule			(createShaderModule		(vk, device, context.getBinaryCollection().get("frag"), 0u));
1045 
1046 	const Unique<VkRenderPass>		renderPass				(makeRenderPass			(vk, device, colorFormat));
1047 	const Unique<VkFramebuffer>		framebuffer				(makeFramebuffer		(vk, device, *renderPass, &*colorAttachment, 1u, params.image.size.width,  params.image.size.height, numLayers));
1048 	const Unique<VkPipelineLayout>	pipelineLayout			(makePipelineLayout		(vk, device));
1049 	const Unique<VkPipeline>		pipeline				(makeGraphicsPipeline	(vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule,
1050 																					 makeExtent2D(params.image.size.width, params.image.size.height)));
1051 	const Unique<VkCommandPool>		cmdPool					(createCommandPool		(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1052 	const Unique<VkCommandBuffer>	cmdBuffer				(allocateCommandBuffer	(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1053 
1054 	zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
1055 
1056 	beginCommandBuffer(vk, *cmdBuffer);
1057 
1058 	beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, params.image.size.width, params.image.size.height), clearColor);
1059 
1060 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1061 	vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1062 	endRenderPass(vk, *cmdBuffer);
1063 
1064 	// Prepare color image for copy
1065 	{
1066 		const VkImageSubresourceRange	colorSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers);
1067 		const VkImageMemoryBarrier		barriers[] =
1068 		{
1069 			{
1070 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
1071 				DE_NULL,										// const void*				pNext;
1072 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			outputMask;
1073 				VK_ACCESS_TRANSFER_READ_BIT,					// VkAccessFlags			inputMask;
1074 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			oldLayout;
1075 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,			// VkImageLayout			newLayout;
1076 				VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
1077 				VK_QUEUE_FAMILY_IGNORED,						// deUint32					destQueueFamilyIndex;
1078 				*colorImage,									// VkImage					image;
1079 				colorSubresourceRange,							// VkImageSubresourceRange	subresourceRange;
1080 			},
1081 		};
1082 
1083 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1084 			0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1085 	}
1086 	// Color image -> host buffer
1087 	{
1088 		const VkBufferImageCopy region =
1089 		{
1090 			0ull,																						// VkDeviceSize                bufferOffset;
1091 			0u,																							// uint32_t                    bufferRowLength;
1092 			0u,																							// uint32_t                    bufferImageHeight;
1093 			makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, params.image.numLayers),		// VkImageSubresourceLayers    imageSubresource;
1094 			makeOffset3D(0, 0, 0),																		// VkOffset3D                  imageOffset;
1095 			params.image.size,																			// VkExtent3D                  imageExtent;
1096 		};
1097 
1098 		vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
1099 	}
1100 	// Buffer write barrier
1101 	{
1102 		const VkBufferMemoryBarrier barriers[] =
1103 		{
1104 			{
1105 				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// VkStructureType    sType;
1106 				DE_NULL,										// const void*        pNext;
1107 				VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags      srcAccessMask;
1108 				VK_ACCESS_HOST_READ_BIT,						// VkAccessFlags      dstAccessMask;
1109 				VK_QUEUE_FAMILY_IGNORED,						// uint32_t           srcQueueFamilyIndex;
1110 				VK_QUEUE_FAMILY_IGNORED,						// uint32_t           dstQueueFamilyIndex;
1111 				*colorBuffer,									// VkBuffer           buffer;
1112 				0ull,											// VkDeviceSize       offset;
1113 				VK_WHOLE_SIZE,									// VkDeviceSize       size;
1114 			},
1115 		};
1116 
1117 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1118 			0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u);
1119 	}
1120 
1121 	endCommandBuffer(vk, *cmdBuffer);
1122 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1123 
1124 	invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSize);
1125 
1126 	if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1127 		return tcu::TestStatus::fail("Rendered images are incorrect");
1128 	else
1129 		return tcu::TestStatus::pass("OK");
1130 }
1131 
testLayeredReadBack(Context & context,const TestParams params)1132 tcu::TestStatus testLayeredReadBack (Context& context, const TestParams params)
1133 {
1134 	if (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType &&
1135 		(!isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_maintenance1")))
1136 		TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
1137 
1138 	const DeviceInterface&				vk					= context.getDeviceInterface();
1139 	const InstanceInterface&			vki					= context.getInstanceInterface();
1140 	const VkDevice						device				= context.getDevice();
1141 	const VkPhysicalDevice				physDevice			= context.getPhysicalDevice();
1142 	const deUint32						queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1143 	const VkQueue						queue				= context.getUniversalQueue();
1144 	Allocator&							allocator			= context.getDefaultAllocator();
1145 
1146 	checkGeometryShaderSupport(vki, physDevice);
1147 
1148 	const size_t						passCount			= 2;
1149 	const deUint32						numLayers			= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
1150 	const VkImageCreateFlags			imageCreateFlags	= (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
1151 															  (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
1152 	const VkImageViewType				viewType			= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
1153 	const VkImageType					imageType			= getImageType(params.image.viewType);
1154 	const VkExtent2D					imageExtent2D		= makeExtent2D(params.image.size.width, params.image.size.height);
1155 
1156 	const VkFormat						colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
1157 	const deUint32						colorImagePixelSize	= static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(colorFormat)));
1158 	const VkDeviceSize					colorBufferSize		= params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * colorImagePixelSize;
1159 	const VkImageUsageFlags				colorImageUsage		= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1160 
1161 	const bool							dsUsed				= (VK_IMAGE_VIEW_TYPE_3D != params.image.viewType);
1162 	const VkFormat						dsFormat			= VK_FORMAT_D24_UNORM_S8_UINT;
1163 	const deUint32						dsImagePixelSize	= static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(dsFormat)));
1164 	const VkImageUsageFlags				dsImageUsage		= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1165 	const VkImageAspectFlags			dsAspectFlags		= VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
1166 	const VkDeviceSize					depthBufferSize		= params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * dsImagePixelSize;
1167 
1168 	const VkFormat						stencilBufferFormat	= getStencilBufferFormat(dsFormat);
1169 	const deUint32						stencilPixelSize	= static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(stencilBufferFormat)));
1170 	const VkDeviceSize					stencilBufferSize	= params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * stencilPixelSize;
1171 
1172 	checkImageFormatProperties(vki, physDevice, imageType, VK_IMAGE_TILING_OPTIMAL, dsImageUsage, imageCreateFlags, dsFormat, params.image.size, params.image.numLayers);
1173 
1174 	const Unique<VkImage>				colorImage			(makeImage				(vk, device, makeImageCreateInfo(imageCreateFlags, imageType, colorFormat, params.image.size, params.image.numLayers, colorImageUsage)));
1175 	const UniquePtr<Allocation>			colorImageAlloc		(bindImage				(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1176 	const Unique<VkImageView>			colorAttachment		(makeImageView			(vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
1177 	const Unique<VkBuffer>				colorBuffer			(makeBuffer				(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
1178 	const UniquePtr<Allocation>			colorBufferAlloc	(bindBuffer				(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1179 
1180 	const Unique<VkImage>				dsImage				(makeImage				(vk, device, makeImageCreateInfo(imageCreateFlags, imageType, dsFormat, params.image.size, params.image.numLayers, dsImageUsage)));
1181 	const UniquePtr<Allocation>			dsImageAlloc		(bindImage				(vk, device, allocator, *dsImage, MemoryRequirement::Any));
1182 	const Unique<VkImageView>			dsAttachment		(makeImageView			(vk, device, *dsImage, viewType, dsFormat, makeImageSubresourceRange(dsAspectFlags, 0u, 1u, 0u, numLayers)));
1183 	const Unique<VkBuffer>				depthBuffer			(makeBuffer				(vk, device, makeBufferCreateInfo(depthBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
1184 	const UniquePtr<Allocation>			depthBufferAlloc	(bindBuffer				(vk, device, allocator, *depthBuffer, MemoryRequirement::HostVisible));
1185 	const Unique<VkBuffer>				stencilBuffer		(makeBuffer				(vk, device, makeBufferCreateInfo(stencilBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
1186 	const UniquePtr<Allocation>			stencilBufferAlloc	(bindBuffer				(vk, device, allocator, *stencilBuffer, MemoryRequirement::HostVisible));
1187 
1188 	const VkImageView					attachments[]		= {*colorAttachment, *dsAttachment};
1189 	const deUint32						attachmentsCount	= dsUsed ? DE_LENGTH_OF_ARRAY(attachments) : 1u;
1190 
1191 	const Unique<VkShaderModule>		vertexModule		(createShaderModule		(vk, device, context.getBinaryCollection().get("vert"), 0u));
1192 	const Unique<VkShaderModule>		geometryModule		(createShaderModule		(vk, device, context.getBinaryCollection().get("geom"), 0u));
1193 	const Unique<VkShaderModule>		fragmentModule		(createShaderModule		(vk, device, context.getBinaryCollection().get("frag"), 0u));
1194 
1195 	const Unique<VkRenderPass>			renderPass			(makeRenderPass			(vk, device, colorFormat, dsFormat, dsUsed));
1196 	const Unique<VkFramebuffer>			framebuffer			(makeFramebuffer		(vk, device, *renderPass, attachments, attachmentsCount, params.image.size.width, params.image.size.height, numLayers));
1197 
1198 	const Move<VkDescriptorPool>		descriptorPool		= DescriptorPoolBuilder()
1199 															  .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, passCount)
1200 															  .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, passCount);
1201 	const Move<VkDescriptorSetLayout>	descriptorSetLayout	= DescriptorSetLayoutBuilder()
1202 															  .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_GEOMETRY_BIT)
1203 															  .build(vk, device);
1204 	const Move<VkDescriptorSet>			descriptorSet[]		=
1205 	{
1206 		makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout),
1207 		makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout),
1208 	};
1209 
1210 	const size_t						uniformBufSize		= sizeof(deUint32);
1211 	const VkBufferCreateInfo			uniformBufCI		= makeBufferCreateInfo(uniformBufSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1212 	const Move<VkBuffer>				uniformBuf[]		= { createBuffer(vk, device, &uniformBufCI), createBuffer(vk, device, &uniformBufCI) };
1213 	const MovePtr<Allocation>			uniformBufAlloc[]	=
1214 	{
1215 		allocator.allocate(getBufferMemoryRequirements(vk, device, *uniformBuf[0]), MemoryRequirement::HostVisible),
1216 		allocator.allocate(getBufferMemoryRequirements(vk, device, *uniformBuf[1]), MemoryRequirement::HostVisible),
1217 	};
1218 	const VkDescriptorBufferInfo		uniformBufDesc[]	=
1219 	{
1220 		makeDescriptorBufferInfo(*uniformBuf[0], 0ull, uniformBufSize),
1221 		makeDescriptorBufferInfo(*uniformBuf[1], 0ull, uniformBufSize),
1222 	};
1223 
1224 	const Unique<VkPipelineLayout>		pipelineLayout		(makePipelineLayout		(vk, device, *descriptorSetLayout));
1225 	const Unique<VkPipeline>			pipeline			(makeGraphicsPipeline	(vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule, imageExtent2D, dsUsed));
1226 	const Unique<VkCommandPool>			cmdPool				(createCommandPool		(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1227 	const Unique<VkCommandBuffer>		cmdBuffer			(allocateCommandBuffer	(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1228 	const VkImageSubresourceRange		colorSubresRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers);
1229 	const VkImageSubresourceRange		dsSubresRange		= makeImageSubresourceRange(dsAspectFlags, 0u, 1u, 0u, params.image.numLayers);
1230 	const VkImageMemoryBarrier			colorPassBarrier	= makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1231 																VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresRange);
1232 	const VkImageMemoryBarrier			dsPassBarrier		= makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
1233 																VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *dsImage, dsSubresRange);
1234 	std::string							result;
1235 
1236 	beginCommandBuffer(vk, *cmdBuffer);
1237 	{
1238 		const VkImageMemoryBarrier		colorBarrier	= makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1239 																				 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, *colorImage, colorSubresRange);
1240 		const VkImageMemoryBarrier		dsBarrier		= makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1241 																				 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, *dsImage, dsSubresRange);
1242 
1243 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorBarrier);
1244 
1245 		if (dsUsed)
1246 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsBarrier);
1247 
1248 		for (deUint32 layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1249 		{
1250 			const deUint32		imageDepth	= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? layerNdx :       0u;
1251 			const deUint32		layer		= (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ?       0u : layerNdx;
1252 			const VkOffset3D	imageOffset = makeOffset3D(0u, 0u, imageDepth);
1253 			const VkExtent3D	imageExtent = makeExtent3D(params.image.size.width, params.image.size.height, 1u);
1254 
1255 			// Clear color image with initial value
1256 			{
1257 				const tcu::Vec4					clearColor				= scaleColor(s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)], 0.25f);
1258 				const deUint32					bufferSliceSize			= params.image.size.width * params.image.size.height * colorImagePixelSize;
1259 				const VkDeviceSize				bufferOffset			= layerNdx * bufferSliceSize;
1260 				const VkImageSubresourceLayers	imageSubresource		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, layer, 1u);
1261 				const VkBufferImageCopy			bufferImageCopyRegion	= makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
1262 
1263 				fillBuffer(vk, device, *colorBufferAlloc, bufferOffset, bufferSliceSize, colorFormat, clearColor);
1264 				vk.cmdCopyBufferToImage(*cmdBuffer, *colorBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1265 			}
1266 
1267 			// Clear depth image with initial value
1268 			if (dsUsed)
1269 			{
1270 				const float						depthValue				= 1.0f;
1271 				const deUint32					bufferSliceSize			= params.image.size.width * params.image.size.height * dsImagePixelSize;
1272 				const VkDeviceSize				bufferOffset			= layerNdx * bufferSliceSize;
1273 				const VkImageSubresourceLayers	imageSubresource		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, layer, 1u);
1274 				const VkBufferImageCopy			bufferImageCopyRegion	= makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
1275 
1276 				fillBuffer(vk, device, *depthBufferAlloc, bufferOffset, bufferSliceSize, dsFormat, depthValue);
1277 				vk.cmdCopyBufferToImage(*cmdBuffer, *depthBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1278 			}
1279 
1280 			// Clear stencil image with initial value
1281 			if (dsUsed)
1282 			{
1283 				const deUint8					stencilValue			= 0;
1284 				const deUint32					bufferSliceSize			= params.image.size.width * params.image.size.height * stencilPixelSize;
1285 				const VkDeviceSize				bufferOffset			= layerNdx * bufferSliceSize;
1286 				const VkImageSubresourceLayers	imageSubresource		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, layer, 1u);
1287 				const VkBufferImageCopy			bufferImageCopyRegion	= makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
1288 				deUint8*						bufferStart				= static_cast<deUint8*>((*stencilBufferAlloc).getHostPtr());
1289 				deUint8*						bufferLayerStart		= &bufferStart[bufferOffset];
1290 
1291 				deMemset(bufferLayerStart, stencilValue, bufferSliceSize);
1292 				flushMappedMemoryRange(vk, device, stencilBufferAlloc->getMemory(), stencilBufferAlloc->getOffset() + bufferOffset, bufferSliceSize);
1293 				vk.cmdCopyBufferToImage(*cmdBuffer, *stencilBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1294 			}
1295 		}
1296 	}
1297 	// Change images layouts
1298 	{
1299 		const VkImageMemoryBarrier		colorBarrier	= makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1300 																				 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresRange);
1301 		const VkImageMemoryBarrier		dsBarrier		= makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
1302 																				 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *dsImage, dsSubresRange);
1303 
1304 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorBarrier);
1305 
1306 		if (dsUsed)
1307 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsBarrier);
1308 	}
1309 
1310 	for (deUint32 pass = 0; pass < passCount; ++pass)
1311 	{
1312 		DE_ASSERT(sizeof(pass) == uniformBufSize);
1313 
1314 		VK_CHECK(vk.bindBufferMemory(device, *uniformBuf[pass], uniformBufAlloc[pass]->getMemory(), uniformBufAlloc[pass]->getOffset()));
1315 		deMemcpy(uniformBufAlloc[pass]->getHostPtr(), &pass, uniformBufSize);
1316 		flushMappedMemoryRange(vk, device, uniformBufAlloc[pass]->getMemory(), uniformBufAlloc[pass]->getOffset(), uniformBufSize);
1317 
1318 		DescriptorSetUpdateBuilder()
1319 			.writeSingle(*descriptorSet[pass], DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufDesc[pass])
1320 			.update(vk, device);
1321 
1322 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet[pass], 0u, DE_NULL);
1323 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(imageExtent2D));
1324 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1325 		vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1326 		endRenderPass(vk, *cmdBuffer);
1327 
1328 		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);
1329 
1330 		if (dsUsed)
1331 			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);
1332 	}
1333 	endCommandBuffer(vk, *cmdBuffer);
1334 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1335 
1336 	zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
1337 	zeroBuffer(vk, device, *depthBufferAlloc, depthBufferSize);
1338 	zeroBuffer(vk, device, *stencilBufferAlloc, stencilBufferSize);
1339 
1340 	beginCommandBuffer(vk, *cmdBuffer);
1341 	{
1342 		// Copy color image
1343 		{
1344 			const VkImageMemoryBarrier	preCopyBarrier	= makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1345 															VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorImage, colorSubresRange);
1346 			const VkBufferImageCopy		region			= makeBufferImageCopy(params.image.size, makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, params.image.numLayers));
1347 			const VkBufferMemoryBarrier	postCopyBarrier	= makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, VK_WHOLE_SIZE);
1348 
1349 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1350 			vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
1351 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &postCopyBarrier, DE_NULL, 0u);
1352 		}
1353 
1354 		// Depth/Stencil image copy
1355 		if (dsUsed)
1356 		{
1357 			const VkImageMemoryBarrier	preCopyBarrier		= makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1358 																VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dsImage, dsSubresRange);
1359 			const VkBufferImageCopy		depthCopyRegion		= makeBufferImageCopy(params.image.size, makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, params.image.numLayers));
1360 			const VkBufferImageCopy		stencilCopyRegion	= makeBufferImageCopy(params.image.size, makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, params.image.numLayers));
1361 			const VkBufferMemoryBarrier	postCopyBarriers[]	=
1362 			{
1363 				makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *depthBuffer, 0ull, VK_WHOLE_SIZE),
1364 				makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *stencilBuffer, 0ull, VK_WHOLE_SIZE),
1365 			};
1366 
1367 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1368 			vk.cmdCopyImageToBuffer(*cmdBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *depthBuffer, 1u, &depthCopyRegion);
1369 			vk.cmdCopyImageToBuffer(*cmdBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *stencilBuffer, 1u, &stencilCopyRegion);
1370 			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);
1371 		}
1372 	}
1373 	endCommandBuffer(vk, *cmdBuffer);
1374 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1375 
1376 	invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSize);
1377 	invalidateMappedMemoryRange(vk, device, depthBufferAlloc->getMemory(), depthBufferAlloc->getOffset(), depthBufferSize);
1378 	invalidateMappedMemoryRange(vk, device, stencilBufferAlloc->getMemory(), stencilBufferAlloc->getOffset(), stencilBufferSize);
1379 
1380 	if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1381 		result += " Color";
1382 
1383 	if (dsUsed)
1384 	{
1385 		if (!verifyResults(context.getTestContext().getLog(), params, dsFormat, depthBufferAlloc->getHostPtr(), true, false))
1386 			result += " Depth";
1387 
1388 		if (!verifyResults(context.getTestContext().getLog(), params, stencilBufferFormat, stencilBufferAlloc->getHostPtr(), false, true))
1389 			result += " Stencil";
1390 	}
1391 
1392 	if (result.empty())
1393 		return tcu::TestStatus::pass("OK");
1394 	else
1395 		return tcu::TestStatus::fail("Following parts of image are incorrect:" + result);
1396 }
1397 
1398 } // anonymous
1399 
createLayeredRenderingTests(tcu::TestContext & testCtx)1400 tcu::TestCaseGroup* createLayeredRenderingTests (tcu::TestContext& testCtx)
1401 {
1402 	MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "layered", "Layered rendering tests."));
1403 
1404 	const struct
1405 	{
1406 		TestType		test;
1407 		const char*		name;
1408 		const char*		description;
1409 	} testTypes[] =
1410 	{
1411 		{ TEST_TYPE_DEFAULT_LAYER,					"render_to_default_layer",			"Render to the default layer"															},
1412 		{ TEST_TYPE_SINGLE_LAYER,					"render_to_one",					"Render to one layer"																	},
1413 		{ TEST_TYPE_ALL_LAYERS,						"render_to_all",					"Render to all layers"																	},
1414 		{ TEST_TYPE_DIFFERENT_CONTENT,				"render_different_content",			"Render different data to different layers"												},
1415 		{ TEST_TYPE_LAYER_ID,						"fragment_layer",					"Read gl_Layer in fragment shader"														},
1416 		{ TEST_TYPE_INVOCATION_PER_LAYER,			"invocation_per_layer",				"Render to multiple layers with multiple invocations, one invocation per layer"			},
1417 		{ TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION,	"multiple_layers_per_invocation",	"Render to multiple layers with multiple invocations, multiple layers per invocation",	},
1418 		{ TEST_TYPE_LAYERED_READBACK,				"readback",							"Render to multiple layers with two passes to check LOAD_OP_LOAD capability"			},
1419 	};
1420 
1421 	const ImageParams imageParams[] =
1422 	{
1423 		{ VK_IMAGE_VIEW_TYPE_1D_ARRAY,		{ 64,  1, 1 },	4	},
1424 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		{ 64, 64, 1 },	4	},
1425 		{ VK_IMAGE_VIEW_TYPE_CUBE,			{ 64, 64, 1 },	6	},
1426 		{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	{ 64, 64, 1 },	2*6	},
1427 		{ VK_IMAGE_VIEW_TYPE_3D,			{ 64, 64, 8 },	1	}
1428 	};
1429 
1430 	for (int imageParamNdx = 0; imageParamNdx < DE_LENGTH_OF_ARRAY(imageParams); ++imageParamNdx)
1431 	{
1432 		MovePtr<tcu::TestCaseGroup> viewTypeGroup(new tcu::TestCaseGroup(testCtx, getShortImageViewTypeName(imageParams[imageParamNdx].viewType).c_str(), ""));
1433 
1434 		for (int testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx)
1435 		{
1436 			const TestParams params =
1437 			{
1438 				testTypes[testTypeNdx].test,
1439 				imageParams[imageParamNdx],
1440 			};
1441 
1442 			if (testTypes[testTypeNdx].test == TEST_TYPE_LAYERED_READBACK)
1443 				addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, initPrograms, testLayeredReadBack, params);
1444 			else
1445 				addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, initPrograms, test, params);
1446 		}
1447 
1448 		group->addChild(viewTypeGroup.release());
1449 	}
1450 
1451 	return group.release();
1452 }
1453 
1454 } // geometry
1455 } // vkt
1456