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