1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Multisample image Tests
22 *//*--------------------------------------------------------------------*/
23
24#include "vktPipelineMultisampleImageTests.hpp"
25#include "vktPipelineMakeUtil.hpp"
26#include "vktTestCase.hpp"
27#include "vktTestCaseUtil.hpp"
28#include "vktPipelineVertexUtil.hpp"
29#include "vktTestGroupUtil.hpp"
30
31#include "vkMemUtil.hpp"
32#include "vkQueryUtil.hpp"
33#include "vkTypeUtil.hpp"
34#include "vkRefUtil.hpp"
35#include "vkBuilderUtil.hpp"
36#include "vkPrograms.hpp"
37#include "vkImageUtil.hpp"
38
39#include "tcuTextureUtil.hpp"
40#include "tcuTestLog.hpp"
41
42#include "deUniquePtr.hpp"
43#include "deSharedPtr.hpp"
44
45#include <string>
46
47namespace vkt
48{
49namespace pipeline
50{
51namespace
52{
53using namespace vk;
54using de::UniquePtr;
55using de::MovePtr;
56using de::SharedPtr;
57using tcu::IVec2;
58using tcu::Vec4;
59
60typedef SharedPtr<Unique<VkImageView> >	ImageViewSp;
61typedef SharedPtr<Unique<VkPipeline> >	PipelineSp;
62
63//! Test case parameters
64struct CaseDef
65{
66	IVec2					renderSize;
67	int						numLayers;
68	VkFormat				colorFormat;
69	VkSampleCountFlagBits	numSamples;
70};
71
72template<typename T>
73inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move)
74{
75	return SharedPtr<Unique<T> >(new Unique<T>(move));
76}
77
78template<typename T>
79inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
80{
81	return vec.size() * sizeof(vec[0]);
82}
83
84//! Create a vector of derived pipelines, each with an increasing subpass index
85std::vector<PipelineSp> makeGraphicsPipelines (const DeviceInterface&		vk,
86											   const VkDevice				device,
87											   const deUint32				numSubpasses,
88											   const VkPipelineLayout		pipelineLayout,
89											   const VkRenderPass			renderPass,
90											   const VkShaderModule			vertexModule,
91											   const VkShaderModule			fragmentModule,
92											   const IVec2					renderSize,
93											   const VkSampleCountFlagBits	numSamples,
94											   const VkPrimitiveTopology	topology)
95{
96	const VkVertexInputBindingDescription vertexInputBindingDescription =
97	{
98		0u,								// uint32_t				binding;
99		sizeof(Vertex4RGBA),			// uint32_t				stride;
100		VK_VERTEX_INPUT_RATE_VERTEX,	// VkVertexInputRate	inputRate;
101	};
102
103	const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
104	{
105		{
106			0u,									// uint32_t			location;
107			0u,									// uint32_t			binding;
108			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat			format;
109			0u,									// uint32_t			offset;
110		},
111		{
112			1u,									// uint32_t			location;
113			0u,									// uint32_t			binding;
114			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat			format;
115			sizeof(Vec4),						// uint32_t			offset;
116		},
117	};
118
119	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
120	{
121		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType                             sType;
122		DE_NULL,														// const void*                                 pNext;
123		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags       flags;
124		1u,																// uint32_t                                    vertexBindingDescriptionCount;
125		&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
126		DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),			// uint32_t                                    vertexAttributeDescriptionCount;
127		vertexInputAttributeDescriptions,								// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
128	};
129
130	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
131	{
132		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType                             sType;
133		DE_NULL,														// const void*                                 pNext;
134		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags     flags;
135		topology,														// VkPrimitiveTopology                         topology;
136		VK_FALSE,														// VkBool32                                    primitiveRestartEnable;
137	};
138
139	const VkViewport viewport = makeViewport(
140		0.0f, 0.0f,
141		static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
142		0.0f, 1.0f);
143
144	const VkRect2D scissor = {
145		makeOffset2D(0, 0),
146		makeExtent2D(renderSize.x(), renderSize.y()),
147	};
148
149	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
150	{
151		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType                             sType;
152		DE_NULL,														// const void*                                 pNext;
153		(VkPipelineViewportStateCreateFlags)0,							// VkPipelineViewportStateCreateFlags          flags;
154		1u,																// uint32_t                                    viewportCount;
155		&viewport,														// const VkViewport*                           pViewports;
156		1u,																// uint32_t                                    scissorCount;
157		&scissor,														// const VkRect2D*                             pScissors;
158	};
159
160	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
161	{
162		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType                          sType;
163		DE_NULL,														// const void*                              pNext;
164		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags  flags;
165		VK_FALSE,														// VkBool32                                 depthClampEnable;
166		VK_FALSE,														// VkBool32                                 rasterizerDiscardEnable;
167		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
168		VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
169		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
170		VK_FALSE,														// VkBool32									depthBiasEnable;
171		0.0f,															// float									depthBiasConstantFactor;
172		0.0f,															// float									depthBiasClamp;
173		0.0f,															// float									depthBiasSlopeFactor;
174		1.0f,															// float									lineWidth;
175	};
176
177	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
178	{
179		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
180		DE_NULL,														// const void*								pNext;
181		(VkPipelineMultisampleStateCreateFlags)0,						// VkPipelineMultisampleStateCreateFlags	flags;
182		numSamples,														// VkSampleCountFlagBits					rasterizationSamples;
183		VK_FALSE,														// VkBool32									sampleShadingEnable;
184		0.0f,															// float									minSampleShading;
185		DE_NULL,														// const VkSampleMask*						pSampleMask;
186		VK_FALSE,														// VkBool32									alphaToCoverageEnable;
187		VK_FALSE														// VkBool32									alphaToOneEnable;
188	};
189
190	const VkStencilOpState stencilOpState = makeStencilOpState(
191		VK_STENCIL_OP_KEEP,				// stencil fail
192		VK_STENCIL_OP_KEEP,				// depth & stencil pass
193		VK_STENCIL_OP_KEEP,				// depth only fail
194		VK_COMPARE_OP_ALWAYS,			// compare op
195		0u,								// compare mask
196		0u,								// write mask
197		0u);							// reference
198
199	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
200	{
201		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,		// VkStructureType							sType;
202		DE_NULL,														// const void*								pNext;
203		(VkPipelineDepthStencilStateCreateFlags)0,						// VkPipelineDepthStencilStateCreateFlags	flags;
204		VK_FALSE,														// VkBool32									depthTestEnable;
205		VK_FALSE,														// VkBool32									depthWriteEnable;
206		VK_COMPARE_OP_LESS,												// VkCompareOp								depthCompareOp;
207		VK_FALSE,														// VkBool32									depthBoundsTestEnable;
208		VK_FALSE,														// VkBool32									stencilTestEnable;
209		stencilOpState,													// VkStencilOpState							front;
210		stencilOpState,													// VkStencilOpState							back;
211		0.0f,															// float									minDepthBounds;
212		1.0f,															// float									maxDepthBounds;
213	};
214
215	const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
216	// Number of blend attachments must equal the number of color attachments during any subpass.
217	const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
218	{
219		VK_FALSE,						// VkBool32					blendEnable;
220		VK_BLEND_FACTOR_ONE,			// VkBlendFactor			srcColorBlendFactor;
221		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstColorBlendFactor;
222		VK_BLEND_OP_ADD,				// VkBlendOp				colorBlendOp;
223		VK_BLEND_FACTOR_ONE,			// VkBlendFactor			srcAlphaBlendFactor;
224		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstAlphaBlendFactor;
225		VK_BLEND_OP_ADD,				// VkBlendOp				alphaBlendOp;
226		colorComponentsAll,				// VkColorComponentFlags	colorWriteMask;
227	};
228
229	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
230	{
231		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,		// VkStructureType								sType;
232		DE_NULL,														// const void*									pNext;
233		(VkPipelineColorBlendStateCreateFlags)0,						// VkPipelineColorBlendStateCreateFlags			flags;
234		VK_FALSE,														// VkBool32										logicOpEnable;
235		VK_LOGIC_OP_COPY,												// VkLogicOp									logicOp;
236		1u,																// deUint32										attachmentCount;
237		&pipelineColorBlendAttachmentState,								// const VkPipelineColorBlendAttachmentState*	pAttachments;
238		{ 0.0f, 0.0f, 0.0f, 0.0f },										// float										blendConstants[4];
239	};
240
241	const VkPipelineShaderStageCreateInfo pShaderStages[] =
242	{
243		{
244			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
245			DE_NULL,													// const void*							pNext;
246			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
247			VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStageFlagBits				stage;
248			vertexModule,												// VkShaderModule						module;
249			"main",														// const char*							pName;
250			DE_NULL,													// const VkSpecializationInfo*			pSpecializationInfo;
251		},
252		{
253			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
254			DE_NULL,													// const void*							pNext;
255			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
256			VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlagBits				stage;
257			fragmentModule,												// VkShaderModule						module;
258			"main",														// const char*							pName;
259			DE_NULL,													// const VkSpecializationInfo*			pSpecializationInfo;
260		}
261	};
262
263	DE_ASSERT(numSubpasses > 0u);
264
265	std::vector<VkGraphicsPipelineCreateInfo>	graphicsPipelineInfos	(0);
266	std::vector<VkPipeline>						rawPipelines			(numSubpasses, DE_NULL);
267
268	{
269		const VkPipelineCreateFlags firstPipelineFlags = (numSubpasses > 1u ? VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT
270																			: (VkPipelineCreateFlagBits)0);
271
272		VkGraphicsPipelineCreateInfo createInfo =
273		{
274			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
275			DE_NULL,											// const void*										pNext;
276			firstPipelineFlags,									// VkPipelineCreateFlags							flags;
277			DE_LENGTH_OF_ARRAY(pShaderStages),					// deUint32											stageCount;
278			pShaderStages,										// const VkPipelineShaderStageCreateInfo*			pStages;
279			&vertexInputStateInfo,								// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
280			&pipelineInputAssemblyStateInfo,					// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
281			DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
282			&pipelineViewportStateInfo,							// const VkPipelineViewportStateCreateInfo*			pViewportState;
283			&pipelineRasterizationStateInfo,					// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
284			&pipelineMultisampleStateInfo,						// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
285			&pipelineDepthStencilStateInfo,						// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
286			&pipelineColorBlendStateInfo,						// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
287			DE_NULL,											// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
288			pipelineLayout,										// VkPipelineLayout									layout;
289			renderPass,											// VkRenderPass										renderPass;
290			0u,													// deUint32											subpass;
291			DE_NULL,											// VkPipeline										basePipelineHandle;
292			-1,													// deInt32											basePipelineIndex;
293		};
294
295		graphicsPipelineInfos.push_back(createInfo);
296
297		createInfo.flags				= VK_PIPELINE_CREATE_DERIVATIVE_BIT;
298		createInfo.basePipelineIndex	= 0;
299
300		for (deUint32 subpassNdx = 1u; subpassNdx < numSubpasses; ++subpassNdx)
301		{
302			createInfo.subpass = subpassNdx;
303			graphicsPipelineInfos.push_back(createInfo);
304		}
305	}
306
307	VK_CHECK(vk.createGraphicsPipelines(device, DE_NULL, static_cast<deUint32>(graphicsPipelineInfos.size()), &graphicsPipelineInfos[0], DE_NULL, &rawPipelines[0]));
308
309	std::vector<PipelineSp>	pipelines;
310
311	for (std::vector<VkPipeline>::const_iterator it = rawPipelines.begin(); it != rawPipelines.end(); ++it)
312		pipelines.push_back(makeSharedPtr(Move<VkPipeline>(check<VkPipeline>(*it), Deleter<VkPipeline>(vk, device, DE_NULL))));
313
314	return pipelines;
315}
316
317//! Make a render pass with one subpass per color attachment and one attachment per image layer.
318Move<VkRenderPass> makeMultisampleRenderPass (const DeviceInterface&		vk,
319											  const VkDevice				device,
320											  const VkFormat				colorFormat,
321											  const VkSampleCountFlagBits	numSamples,
322											  const deUint32				numLayers)
323{
324	const VkAttachmentDescription colorAttachmentDescription =
325	{
326		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
327		colorFormat,										// VkFormat							format;
328		numSamples,											// VkSampleCountFlagBits			samples;
329		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
330		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
331		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
332		VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
333		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					initialLayout;
334		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
335	};
336	const std::vector<VkAttachmentDescription> attachmentDescriptions(numLayers, colorAttachmentDescription);
337
338	// Create a subpass for each attachment (each attachement is a layer of an arrayed image).
339
340	std::vector<VkAttachmentReference>	colorAttachmentReferences(numLayers);
341	std::vector<VkSubpassDescription>	subpasses;
342
343	for (deUint32 i = 0; i < numLayers; ++i)
344	{
345		const VkAttachmentReference attachmentRef =
346		{
347			i,												// deUint32			attachment;
348			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL		// VkImageLayout	layout;
349		};
350		colorAttachmentReferences[i] = attachmentRef;
351
352		const VkSubpassDescription subpassDescription =
353		{
354			(VkSubpassDescriptionFlags)0,					// VkSubpassDescriptionFlags		flags;
355			VK_PIPELINE_BIND_POINT_GRAPHICS,				// VkPipelineBindPoint				pipelineBindPoint;
356			0u,												// deUint32							inputAttachmentCount;
357			DE_NULL,										// const VkAttachmentReference*		pInputAttachments;
358			1u,												// deUint32							colorAttachmentCount;
359			&colorAttachmentReferences[i],					// const VkAttachmentReference*		pColorAttachments;
360			DE_NULL,										// const VkAttachmentReference*		pResolveAttachments;
361			DE_NULL,										// const VkAttachmentReference*		pDepthStencilAttachment;
362			0u,												// deUint32							preserveAttachmentCount;
363			DE_NULL											// const deUint32*					pPreserveAttachments;
364		};
365		subpasses.push_back(subpassDescription);
366	}
367
368	const VkRenderPassCreateInfo renderPassInfo =
369	{
370		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,				// VkStructureType					sType;
371		DE_NULL,												// const void*						pNext;
372		(VkRenderPassCreateFlags)0,								// VkRenderPassCreateFlags			flags;
373		static_cast<deUint32>(attachmentDescriptions.size()),	// deUint32							attachmentCount;
374		&attachmentDescriptions[0],								// const VkAttachmentDescription*	pAttachments;
375		static_cast<deUint32>(subpasses.size()),				// deUint32							subpassCount;
376		&subpasses[0],											// const VkSubpassDescription*		pSubpasses;
377		0u,														// deUint32							dependencyCount;
378		DE_NULL													// const VkSubpassDependency*		pDependencies;
379	};
380
381	return createRenderPass(vk, device, &renderPassInfo);
382}
383
384//! A single-attachment, single-subpass render pass.
385Move<VkRenderPass> makeSimpleRenderPass (const DeviceInterface&	vk,
386									     const VkDevice			device,
387										 const VkFormat			colorFormat)
388{
389	const VkAttachmentDescription colorAttachmentDescription =
390	{
391		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
392		colorFormat,										// VkFormat							format;
393		VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
394		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
395		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
396		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
397		VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
398		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					initialLayout;
399		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
400	};
401
402	const VkAttachmentReference colorAttachmentRef =
403	{
404		0u,													// deUint32			attachment;
405		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
406	};
407
408	const VkSubpassDescription subpassDescription =
409	{
410		(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags		flags;
411		VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
412		0u,													// deUint32							inputAttachmentCount;
413		DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
414		1u,													// deUint32							colorAttachmentCount;
415		&colorAttachmentRef,								// const VkAttachmentReference*		pColorAttachments;
416		DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
417		DE_NULL,											// const VkAttachmentReference*		pDepthStencilAttachment;
418		0u,													// deUint32							preserveAttachmentCount;
419		DE_NULL												// const deUint32*					pPreserveAttachments;
420	};
421
422	const VkRenderPassCreateInfo renderPassInfo =
423	{
424		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
425		DE_NULL,											// const void*						pNext;
426		(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
427		1u,													// deUint32							attachmentCount;
428		&colorAttachmentDescription,						// const VkAttachmentDescription*	pAttachments;
429		1u,													// deUint32							subpassCount;
430		&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
431		0u,													// deUint32							dependencyCount;
432		DE_NULL												// const VkSubpassDependency*		pDependencies;
433	};
434
435	return createRenderPass(vk, device, &renderPassInfo);
436}
437
438Move<VkImage> makeImage (const DeviceInterface& vk, const VkDevice device, const VkFormat format, const IVec2& size, const deUint32 numLayers, const VkSampleCountFlagBits samples, const VkImageUsageFlags usage)
439{
440	const VkImageCreateInfo imageParams =
441	{
442		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
443		DE_NULL,										// const void*				pNext;
444		(VkImageCreateFlags)0,							// VkImageCreateFlags		flags;
445		VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
446		format,											// VkFormat					format;
447		makeExtent3D(size.x(), size.y(), 1),			// VkExtent3D				extent;
448		1u,												// deUint32					mipLevels;
449		numLayers,										// deUint32					arrayLayers;
450		samples,										// VkSampleCountFlagBits	samples;
451		VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
452		usage,											// VkImageUsageFlags		usage;
453		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
454		0u,												// deUint32					queueFamilyIndexCount;
455		DE_NULL,										// const deUint32*			pQueueFamilyIndices;
456		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout;
457	};
458	return createImage(vk, device, &imageParams);
459}
460
461//! Make a simplest sampler.
462Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice device)
463{
464	const VkSamplerCreateInfo samplerParams =
465	{
466		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,			// VkStructureType         sType;
467		DE_NULL,										// const void*             pNext;
468		(VkSamplerCreateFlags)0,						// VkSamplerCreateFlags    flags;
469		VK_FILTER_NEAREST,								// VkFilter                magFilter;
470		VK_FILTER_NEAREST,								// VkFilter                minFilter;
471		VK_SAMPLER_MIPMAP_MODE_NEAREST,					// VkSamplerMipmapMode     mipmapMode;
472		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode    addressModeU;
473		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode    addressModeV;
474		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode    addressModeW;
475		0.0f,											// float                   mipLodBias;
476		VK_FALSE,										// VkBool32                anisotropyEnable;
477		1.0f,											// float                   maxAnisotropy;
478		VK_FALSE,										// VkBool32                compareEnable;
479		VK_COMPARE_OP_ALWAYS,							// VkCompareOp             compareOp;
480		0.0f,											// float                   minLod;
481		0.0f,											// float                   maxLod;
482		VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,		// VkBorderColor           borderColor;
483		VK_FALSE,										// VkBool32                unnormalizedCoordinates;
484	};
485	return createSampler(vk, device, &samplerParams);
486}
487
488inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
489{
490	const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage);
491	return createBuffer(vk, device, &bufferCreateInfo);
492}
493
494inline VkImageSubresourceRange makeColorSubresourceRange (const int baseArrayLayer, const int layerCount)
495{
496	return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
497}
498
499inline VkImageSubresourceLayers makeColorSubresourceLayers (const int baseArrayLayer, const int layerCount)
500{
501	return makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
502}
503
504void checkImageFormatRequirements (const InstanceInterface&		vki,
505								   const VkPhysicalDevice		physDevice,
506								   const VkSampleCountFlagBits	sampleCount,
507								   const VkFormat				format,
508								   const VkImageUsageFlags		usage)
509{
510	VkPhysicalDeviceFeatures	features;
511	vki.getPhysicalDeviceFeatures(physDevice, &features);
512
513	if (((usage & VK_IMAGE_USAGE_STORAGE_BIT) != 0) && !features.shaderStorageImageMultisample)
514		TCU_THROW(NotSupportedError, "Multisampled storage images are not supported");
515
516	VkImageFormatProperties		imageFormatProperties;
517	const VkResult				imageFormatResult		= vki.getPhysicalDeviceImageFormatProperties(
518		physDevice, format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage, (VkImageCreateFlags)0, &imageFormatProperties);
519
520	if (imageFormatResult == VK_ERROR_FORMAT_NOT_SUPPORTED)
521		TCU_THROW(NotSupportedError, "Image format is not supported");
522
523	if ((imageFormatProperties.sampleCounts & sampleCount) != sampleCount)
524		TCU_THROW(NotSupportedError, "Requested sample count is not supported");
525}
526
527void zeroBuffer (const DeviceInterface& vk, const VkDevice device, const Allocation& alloc, const VkDeviceSize bufferSize)
528{
529	deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(bufferSize));
530	flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), bufferSize);
531}
532
533//! The default foreground color.
534inline Vec4 getPrimitiveColor (void)
535{
536	return Vec4(1.0f, 0.0f, 0.0f, 1.0f);
537}
538
539//! Get a reference clear value based on color format.
540VkClearValue getClearValue (const VkFormat format)
541{
542	if (isUintFormat(format) || isIntFormat(format))
543		return makeClearValueColorU32(16, 32, 64, 96);
544	else
545		return makeClearValueColorF32(0.0f, 0.0f, 1.0f, 1.0f);
546}
547
548std::string getColorFormatStr (const int numComponents, const bool isUint, const bool isSint)
549{
550	std::ostringstream str;
551	if (numComponents == 1)
552		str << (isUint ? "uint" : isSint ? "int" : "float");
553	else
554		str << (isUint ? "u" : isSint ? "i" : "") << "vec" << numComponents;
555
556	return str.str();
557}
558
559std::string getSamplerTypeStr (const int numLayers, const bool isUint, const bool isSint)
560{
561	std::ostringstream str;
562	str << (isUint ? "u" : isSint ? "i" : "") << "sampler2DMS" << (numLayers > 1 ? "Array" : "");
563	return str.str();
564}
565
566//! Generate a gvec4 color literal.
567template<typename T>
568std::string getColorStr (const T* data, int numComponents, const bool isUint, const bool isSint)
569{
570	const int maxIndex = 3;  // 4 components max
571
572	std::ostringstream str;
573	str << (isUint ? "u" : isSint ? "i" : "") << "vec4(";
574
575	for (int i = 0; i < numComponents; ++i)
576	{
577		str << data[i]
578			<< (i < maxIndex ? ", " : "");
579	}
580
581	for (int i = numComponents; i < maxIndex + 1; ++i)
582	{
583		str << (i == maxIndex ? 1 : 0)
584			<< (i <  maxIndex ? ", " : "");
585	}
586
587	str << ")";
588	return str.str();
589}
590
591//! Clear color literal value used by the sampling shader.
592std::string getReferenceClearColorStr (const VkFormat format, const int numComponents, const bool isUint, const bool isSint)
593{
594	const VkClearColorValue clearColor = getClearValue(format).color;
595	if (isUint)
596		return getColorStr(clearColor.uint32, numComponents, isUint, isSint);
597	else if (isSint)
598		return getColorStr(clearColor.int32, numComponents, isUint, isSint);
599	else
600		return getColorStr(clearColor.float32, numComponents, isUint, isSint);
601}
602
603//! Primitive color literal value used by the sampling shader.
604std::string getReferencePrimitiveColorStr (int numComponents, const bool isUint, const bool isSint)
605{
606	const Vec4 color = getPrimitiveColor();
607	return getColorStr(color.getPtr(), numComponents, isUint, isSint);
608}
609
610inline int getNumSamples (const VkSampleCountFlagBits samples)
611{
612	return static_cast<int>(samples);	// enum bitmask actually matches the number of samples
613}
614
615//! A flat-colored shape with sharp angles to make antialiasing visible.
616std::vector<Vertex4RGBA> genTriangleVertices (void)
617{
618	static const Vertex4RGBA data[] =
619	{
620		{
621			Vec4(-1.0f, 0.0f, 0.0f, 1.0f),
622			getPrimitiveColor(),
623		},
624		{
625			Vec4(0.8f, 0.2f, 0.0f, 1.0f),
626			getPrimitiveColor(),
627		},
628		{
629			Vec4(0.8f, -0.2f, 0.0f, 1.0f),
630			getPrimitiveColor(),
631		},
632	};
633	return std::vector<Vertex4RGBA>(data, data + DE_LENGTH_OF_ARRAY(data));
634}
635
636//! A full-viewport quad. Use with TRIANGLE_STRIP topology.
637std::vector<Vertex4RGBA> genFullQuadVertices (void)
638{
639	static const Vertex4RGBA data[] =
640	{
641		{
642			Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
643			Vec4(), // unused
644		},
645		{
646			Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
647			Vec4(), // unused
648		},
649		{
650			Vec4(1.0f, -1.0f, 0.0f, 1.0f),
651			Vec4(), // unused
652		},
653		{
654			Vec4(1.0f, 1.0f, 0.0f, 1.0f),
655			Vec4(), // unused
656		},
657	};
658	return std::vector<Vertex4RGBA>(data, data + DE_LENGTH_OF_ARRAY(data));
659}
660
661std::string getShaderImageFormatQualifier (const tcu::TextureFormat& format)
662{
663	const char* orderPart;
664	const char* typePart;
665
666	switch (format.order)
667	{
668		case tcu::TextureFormat::R:		orderPart = "r";	break;
669		case tcu::TextureFormat::RG:	orderPart = "rg";	break;
670		case tcu::TextureFormat::RGB:	orderPart = "rgb";	break;
671		case tcu::TextureFormat::RGBA:	orderPart = "rgba";	break;
672
673		default:
674			DE_ASSERT(false);
675			orderPart = DE_NULL;
676	}
677
678	switch (format.type)
679	{
680		case tcu::TextureFormat::FLOAT:				typePart = "32f";		break;
681		case tcu::TextureFormat::HALF_FLOAT:		typePart = "16f";		break;
682
683		case tcu::TextureFormat::UNSIGNED_INT32:	typePart = "32ui";		break;
684		case tcu::TextureFormat::UNSIGNED_INT16:	typePart = "16ui";		break;
685		case tcu::TextureFormat::UNSIGNED_INT8:		typePart = "8ui";		break;
686
687		case tcu::TextureFormat::SIGNED_INT32:		typePart = "32i";		break;
688		case tcu::TextureFormat::SIGNED_INT16:		typePart = "16i";		break;
689		case tcu::TextureFormat::SIGNED_INT8:		typePart = "8i";		break;
690
691		case tcu::TextureFormat::UNORM_INT16:		typePart = "16";		break;
692		case tcu::TextureFormat::UNORM_INT8:		typePart = "8";			break;
693
694		case tcu::TextureFormat::SNORM_INT16:		typePart = "16_snorm";	break;
695		case tcu::TextureFormat::SNORM_INT8:		typePart = "8_snorm";	break;
696
697		default:
698			DE_ASSERT(false);
699			typePart = DE_NULL;
700	}
701
702	return std::string() + orderPart + typePart;
703}
704
705std::string getShaderMultisampledImageType (const tcu::TextureFormat& format, const int numLayers)
706{
707	const std::string formatPart = tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" :
708								   tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER   ? "i" : "";
709
710	std::ostringstream str;
711	str << formatPart << "image2DMS" << (numLayers > 1 ? "Array" : "");
712
713	return str.str();
714}
715
716void addSimpleVertexAndFragmentPrograms (SourceCollections& programCollection, const CaseDef caseDef)
717{
718	const int	numComponents	= tcu::getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order);
719	const bool	isUint			= isUintFormat(caseDef.colorFormat);
720	const bool	isSint			= isIntFormat(caseDef.colorFormat);
721
722	// Vertex shader
723	{
724		std::ostringstream src;
725		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
726			<< "\n"
727			<< "layout(location = 0) in  vec4 in_position;\n"
728			<< "layout(location = 1) in  vec4 in_color;\n"
729			<< "layout(location = 0) out vec4 o_color;\n"
730			<< "\n"
731			<< "out gl_PerVertex {\n"
732			<< "    vec4 gl_Position;\n"
733			<< "};\n"
734			<< "\n"
735			<< "void main(void)\n"
736			<< "{\n"
737			<< "    gl_Position = in_position;\n"
738			<< "    o_color     = in_color;\n"
739			<< "}\n";
740
741		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
742	}
743
744	// Fragment shader
745	{
746		const std::string colorFormat = getColorFormatStr(numComponents, isUint, isSint);
747
748		std::ostringstream src;
749		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
750			<< "\n"
751			<< "layout(location = 0) in  vec4 in_color;\n"
752			<< "layout(location = 0) out " << colorFormat << " o_color;\n"
753			<< "\n"
754			<< "void main(void)\n"
755			<< "{\n"
756			<< "    o_color = " << colorFormat << "("		// float color will be converted to int/uint here if needed
757			<< (numComponents == 1 ? "in_color.r"   :
758				numComponents == 2 ? "in_color.rg"  :
759				numComponents == 3 ? "in_color.rgb" : "in_color") << ");\n"
760			<< "}\n";
761
762		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
763	}
764}
765
766//! Synchronously render to a multisampled color image.
767void renderMultisampledImage (Context& context, const CaseDef& caseDef, const VkImage colorImage)
768{
769	const DeviceInterface&			vk					= context.getDeviceInterface();
770	const VkDevice					device				= context.getDevice();
771	const VkQueue					queue				= context.getUniversalQueue();
772	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
773	Allocator&						allocator			= context.getDefaultAllocator();
774
775	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
776	const Unique<VkCommandBuffer>	cmdBuffer			(makeCommandBuffer(vk, device, *cmdPool));
777
778	const VkRect2D renderArea = {
779		makeOffset2D(0, 0),
780		makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()),
781	};
782
783	{
784		// Create an image view (attachment) for each layer of the image
785		std::vector<ImageViewSp>	colorAttachments;
786		std::vector<VkImageView>	attachmentHandles;
787		for (int i = 0; i < caseDef.numLayers; ++i)
788		{
789			colorAttachments.push_back(makeSharedPtr(makeImageView(
790				vk, device, colorImage, VK_IMAGE_VIEW_TYPE_2D, caseDef.colorFormat, makeColorSubresourceRange(i, 1))));
791			attachmentHandles.push_back(**colorAttachments.back());
792		}
793
794		// Vertex buffer
795		const std::vector<Vertex4RGBA>	vertices			= genTriangleVertices();
796		const VkDeviceSize				vertexBufferSize	= sizeInBytes(vertices);
797		const Unique<VkBuffer>			vertexBuffer		(makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
798		const UniquePtr<Allocation>		vertexBufferAlloc	(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
799
800		{
801			deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
802			flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
803		}
804
805		const Unique<VkShaderModule>	vertexModule	(createShaderModule			(vk, device, context.getBinaryCollection().get("vert"), 0u));
806		const Unique<VkShaderModule>	fragmentModule	(createShaderModule			(vk, device, context.getBinaryCollection().get("frag"), 0u));
807		const Unique<VkRenderPass>		renderPass		(makeMultisampleRenderPass	(vk, device, caseDef.colorFormat, caseDef.numSamples, caseDef.numLayers));
808		const Unique<VkFramebuffer>		framebuffer		(makeFramebuffer			(vk, device, *renderPass, caseDef.numLayers, &attachmentHandles[0],
809																					 static_cast<deUint32>(caseDef.renderSize.x()),  static_cast<deUint32>(caseDef.renderSize.y())));
810		const Unique<VkPipelineLayout>	pipelineLayout	(makePipelineLayout			(vk, device));
811		const std::vector<PipelineSp>	pipelines		(makeGraphicsPipelines		(vk, device, caseDef.numLayers, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
812																					 caseDef.renderSize, caseDef.numSamples, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
813
814		beginCommandBuffer(vk, *cmdBuffer);
815
816		const std::vector<VkClearValue> clearValues(caseDef.numLayers, getClearValue(caseDef.colorFormat));
817
818		const VkRenderPassBeginInfo renderPassBeginInfo = {
819			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,		// VkStructureType         sType;
820			DE_NULL,										// const void*             pNext;
821			*renderPass,									// VkRenderPass            renderPass;
822			*framebuffer,									// VkFramebuffer           framebuffer;
823			renderArea,										// VkRect2D                renderArea;
824			static_cast<deUint32>(clearValues.size()),		// uint32_t                clearValueCount;
825			&clearValues[0],								// const VkClearValue*     pClearValues;
826		};
827		vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
828
829		{
830			const VkDeviceSize vertexBufferOffset = 0ull;
831			vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
832		}
833
834		for (int layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
835		{
836			if (layerNdx != 0)
837				vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
838
839			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[layerNdx]);
840
841			vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
842		}
843
844		vk.cmdEndRenderPass(*cmdBuffer);
845
846		VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
847		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
848	}
849}
850
851namespace SampledImage
852{
853
854void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
855{
856	// Pass 1: Render to texture
857
858	addSimpleVertexAndFragmentPrograms(programCollection, caseDef);
859
860	// Pass 2: Sample texture
861
862	// Vertex shader
863	{
864		std::ostringstream src;
865		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
866			<< "\n"
867			<< "layout(location = 0) in  vec4  in_position;\n"
868			<< "\n"
869			<< "out gl_PerVertex {\n"
870			<< "    vec4 gl_Position;\n"
871			<< "};\n"
872			<< "\n"
873			<< "void main(void)\n"
874			<< "{\n"
875			<< "    gl_Position = in_position;\n"
876			<< "}\n";
877
878		programCollection.glslSources.add("sample_vert") << glu::VertexSource(src.str());
879	}
880
881	// Fragment shader
882	{
883		const int			numComponents		= tcu::getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order);
884		const bool			isUint				= isUintFormat(caseDef.colorFormat);
885		const bool			isSint				= isIntFormat(caseDef.colorFormat);
886		const std::string	texelFormatStr		= (isUint ? "uvec4" : isSint ? "ivec4" : "vec4");
887		const std::string	refClearColor		= getReferenceClearColorStr(caseDef.colorFormat, numComponents, isUint, isSint);
888		const std::string	refPrimitiveColor	= getReferencePrimitiveColorStr(numComponents, isUint, isSint);
889		const std::string	samplerTypeStr		= getSamplerTypeStr(caseDef.numLayers, isUint, isSint);
890
891		std::ostringstream src;
892		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
893			<< "\n"
894			<< "layout(location = 0) out int o_status;\n"
895			<< "\n"
896			<< "layout(set = 0, binding = 0) uniform " << samplerTypeStr << " colorTexture;\n"
897			<< "\n"
898			<< "void main(void)\n"
899			<< "{\n"
900			<< "    int checksum = 0;\n"
901			<< "\n";
902
903		if (caseDef.numLayers == 1)
904			src << "    for (int sampleNdx = 0; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n"
905				<< "        " << texelFormatStr << " color = texelFetch(colorTexture, ivec2(gl_FragCoord.xy), sampleNdx);\n"
906				<< "        if (color == " << refClearColor << " || color == " << refPrimitiveColor << ")\n"
907				<< "            ++checksum;\n"
908				<< "    }\n";
909		else
910			src << "    for (int layerNdx = 0; layerNdx < " << caseDef.numLayers << "; ++layerNdx)\n"
911				<< "    for (int sampleNdx = 0; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n"
912				<< "        " << texelFormatStr << " color = texelFetch(colorTexture, ivec3(gl_FragCoord.xy, layerNdx), sampleNdx);\n"
913				<< "        if (color == " << refClearColor << " || color == " << refPrimitiveColor << ")\n"
914				<< "            ++checksum;\n"
915				<< "    }\n";
916
917		src << "\n"
918			<< "    o_status = checksum;\n"
919			<< "}\n";
920
921		programCollection.glslSources.add("sample_frag") << glu::FragmentSource(src.str());
922	}
923}
924
925tcu::TestStatus test (Context& context, const CaseDef caseDef)
926{
927	const DeviceInterface&		vk					= context.getDeviceInterface();
928	const InstanceInterface&	vki					= context.getInstanceInterface();
929	const VkDevice				device				= context.getDevice();
930	const VkPhysicalDevice		physDevice			= context.getPhysicalDevice();
931	const VkQueue				queue				= context.getUniversalQueue();
932	const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
933	Allocator&					allocator			= context.getDefaultAllocator();
934
935	const VkImageUsageFlags		colorImageUsage		= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
936
937	checkImageFormatRequirements(vki, physDevice, caseDef.numSamples, caseDef.colorFormat, colorImageUsage);
938
939	{
940		tcu::TestLog& log = context.getTestContext().getLog();
941		log << tcu::LogSection("Description", "")
942			<< tcu::TestLog::Message << "Rendering to a multisampled image. Expecting all samples to be either a clear color or a primitive color." << tcu::TestLog::EndMessage
943			<< tcu::TestLog::Message << "Sampling from the texture with texelFetch (OpImageFetch)." << tcu::TestLog::EndMessage
944			<< tcu::TestLog::EndSection;
945	}
946
947	// Multisampled color image
948	const Unique<VkImage>			colorImage		(makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, caseDef.numSamples, colorImageUsage));
949	const UniquePtr<Allocation>		colorImageAlloc	(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
950
951	const Unique<VkCommandPool>		cmdPool			(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
952	const Unique<VkCommandBuffer>	cmdBuffer		(makeCommandBuffer(vk, device, *cmdPool));
953
954	const VkRect2D renderArea = {
955		makeOffset2D(0, 0),
956		makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()),
957	};
958
959	// Step 1: Render to texture
960	{
961		renderMultisampledImage(context, caseDef, *colorImage);
962	}
963
964	// Step 2: Sample texture
965	{
966		// Color image view
967		const VkImageViewType			colorImageViewType	= (caseDef.numLayers == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY);
968		const Unique<VkImageView>		colorImageView		(makeImageView(vk, device, *colorImage, colorImageViewType, caseDef.colorFormat, makeColorSubresourceRange(0, caseDef.numLayers)));
969		const Unique<VkSampler>			colorSampler		(makeSampler(vk, device));
970
971		// Checksum image
972		const VkFormat					checksumFormat		= VK_FORMAT_R32_SINT;
973		const Unique<VkImage>			checksumImage		(makeImage(vk, device, checksumFormat, caseDef.renderSize, 1u, VK_SAMPLE_COUNT_1_BIT,
974																	   VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
975		const UniquePtr<Allocation>		checksumImageAlloc	(bindImage(vk, device, allocator, *checksumImage, MemoryRequirement::Any));
976		const Unique<VkImageView>		checksumImageView	(makeImageView(vk, device, *checksumImage, VK_IMAGE_VIEW_TYPE_2D, checksumFormat, makeColorSubresourceRange(0, 1)));
977
978		// Checksum buffer (for host reading)
979		const VkDeviceSize				checksumBufferSize	= caseDef.renderSize.x() * caseDef.renderSize.y() * tcu::getPixelSize(mapVkFormat(checksumFormat));
980		const Unique<VkBuffer>			checksumBuffer		(makeBuffer(vk, device, checksumBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
981		const UniquePtr<Allocation>		checksumBufferAlloc	(bindBuffer(vk, device, allocator, *checksumBuffer, MemoryRequirement::HostVisible));
982
983		zeroBuffer(vk, device, *checksumBufferAlloc, checksumBufferSize);
984
985		// Vertex buffer
986		const std::vector<Vertex4RGBA>	vertices			= genFullQuadVertices();
987		const VkDeviceSize				vertexBufferSize	= sizeInBytes(vertices);
988		const Unique<VkBuffer>			vertexBuffer		(makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
989		const UniquePtr<Allocation>		vertexBufferAlloc	(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
990
991		{
992			deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
993			flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
994		}
995
996		// Descriptors
997		// \note OpImageFetch doesn't use a sampler, but in GLSL texelFetch needs a sampler2D which translates to a combined image sampler in Vulkan.
998
999		const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
1000			.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &colorSampler.get())
1001			.build(vk, device));
1002
1003		const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
1004			.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1005			.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1006
1007		const Unique<VkDescriptorSet>	descriptorSet		(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1008		const VkDescriptorImageInfo		imageDescriptorInfo	= makeDescriptorImageInfo(DE_NULL, *colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1009
1010		DescriptorSetUpdateBuilder()
1011			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageDescriptorInfo)
1012			.update(vk, device);
1013
1014		const Unique<VkShaderModule>	vertexModule	(createShaderModule		(vk, device, context.getBinaryCollection().get("sample_vert"), 0u));
1015		const Unique<VkShaderModule>	fragmentModule	(createShaderModule		(vk, device, context.getBinaryCollection().get("sample_frag"), 0u));
1016		const Unique<VkRenderPass>		renderPass		(makeSimpleRenderPass	(vk, device, checksumFormat));
1017		const Unique<VkFramebuffer>		framebuffer		(makeFramebuffer		(vk, device, *renderPass, 1u, &checksumImageView.get(),
1018																				 static_cast<deUint32>(caseDef.renderSize.x()),  static_cast<deUint32>(caseDef.renderSize.y())));
1019		const Unique<VkPipelineLayout>	pipelineLayout	(makePipelineLayout		(vk, device, *descriptorSetLayout));
1020		const std::vector<PipelineSp>	pipelines		(makeGraphicsPipelines	(vk, device, 1u, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
1021																				 caseDef.renderSize, VK_SAMPLE_COUNT_1_BIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP));
1022
1023		beginCommandBuffer(vk, *cmdBuffer);
1024
1025		// Prepare for sampling in the fragment shader
1026		{
1027			const VkImageMemoryBarrier barriers[] =
1028			{
1029				{
1030					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,						// VkStructureType			sType;
1031					DE_NULL,													// const void*				pNext;
1032					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,						// VkAccessFlags			outputMask;
1033					VK_ACCESS_SHADER_READ_BIT,									// VkAccessFlags			inputMask;
1034					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,					// VkImageLayout			oldLayout;
1035					VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,					// VkImageLayout			newLayout;
1036					VK_QUEUE_FAMILY_IGNORED,									// deUint32					srcQueueFamilyIndex;
1037					VK_QUEUE_FAMILY_IGNORED,									// deUint32					destQueueFamilyIndex;
1038					*colorImage,												// VkImage					image;
1039					makeColorSubresourceRange(0, caseDef.numLayers),			// VkImageSubresourceRange	subresourceRange;
1040				},
1041			};
1042
1043			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
1044				0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1045		}
1046
1047		const VkClearValue clearValue = makeClearValueColorU32(0u, 0u, 0u, 0u);
1048
1049		const VkRenderPassBeginInfo renderPassBeginInfo = {
1050			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,							// VkStructureType         sType;
1051			DE_NULL,															// const void*             pNext;
1052			*renderPass,														// VkRenderPass            renderPass;
1053			*framebuffer,														// VkFramebuffer           framebuffer;
1054			renderArea,															// VkRect2D                renderArea;
1055			1u,																	// uint32_t                clearValueCount;
1056			&clearValue,														// const VkClearValue*     pClearValues;
1057		};
1058		vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1059
1060		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines.back());
1061		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1062		{
1063			const VkDeviceSize vertexBufferOffset = 0ull;
1064			vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1065		}
1066
1067		vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
1068		vk.cmdEndRenderPass(*cmdBuffer);
1069
1070		// Prepare checksum image for copy
1071		{
1072			const VkImageMemoryBarrier barriers[] =
1073			{
1074				{
1075					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,						// VkStructureType			sType;
1076					DE_NULL,													// const void*				pNext;
1077					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,						// VkAccessFlags			outputMask;
1078					VK_ACCESS_TRANSFER_READ_BIT,								// VkAccessFlags			inputMask;
1079					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,					// VkImageLayout			oldLayout;
1080					VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,						// VkImageLayout			newLayout;
1081					VK_QUEUE_FAMILY_IGNORED,									// deUint32					srcQueueFamilyIndex;
1082					VK_QUEUE_FAMILY_IGNORED,									// deUint32					destQueueFamilyIndex;
1083					*checksumImage,												// VkImage					image;
1084					makeColorSubresourceRange(0, 1),							// VkImageSubresourceRange	subresourceRange;
1085				},
1086			};
1087
1088			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1089				0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1090		}
1091		// Checksum image -> host buffer
1092		{
1093			const VkBufferImageCopy region =
1094			{
1095				0ull,																		// VkDeviceSize                bufferOffset;
1096				0u,																			// uint32_t                    bufferRowLength;
1097				0u,																			// uint32_t                    bufferImageHeight;
1098				makeColorSubresourceLayers(0, 1),											// VkImageSubresourceLayers    imageSubresource;
1099				makeOffset3D(0, 0, 0),														// VkOffset3D                  imageOffset;
1100				makeExtent3D(caseDef.renderSize.x(), caseDef.renderSize.y(), 1u),			// VkExtent3D                  imageExtent;
1101			};
1102
1103			vk.cmdCopyImageToBuffer(*cmdBuffer, *checksumImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *checksumBuffer, 1u, &region);
1104		}
1105		// Buffer write barrier
1106		{
1107			const VkBufferMemoryBarrier barriers[] =
1108			{
1109				{
1110					VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// VkStructureType    sType;
1111					DE_NULL,										// const void*        pNext;
1112					VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags      srcAccessMask;
1113					VK_ACCESS_HOST_READ_BIT,						// VkAccessFlags      dstAccessMask;
1114					VK_QUEUE_FAMILY_IGNORED,						// uint32_t           srcQueueFamilyIndex;
1115					VK_QUEUE_FAMILY_IGNORED,						// uint32_t           dstQueueFamilyIndex;
1116					*checksumBuffer,								// VkBuffer           buffer;
1117					0ull,											// VkDeviceSize       offset;
1118					checksumBufferSize,								// VkDeviceSize       size;
1119				},
1120			};
1121
1122			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1123				0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u);
1124		}
1125
1126		VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1127		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1128
1129		// Verify result
1130
1131		{
1132			invalidateMappedMemoryRange(vk, device, checksumBufferAlloc->getMemory(), 0ull, checksumBufferSize);
1133
1134			const tcu::ConstPixelBufferAccess access(mapVkFormat(checksumFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), 1, checksumBufferAlloc->getHostPtr());
1135			const int numExpectedChecksum = getNumSamples(caseDef.numSamples) * caseDef.numLayers;
1136
1137			for (int y = 0; y < caseDef.renderSize.y(); ++y)
1138			for (int x = 0; x < caseDef.renderSize.x(); ++x)
1139			{
1140				if (access.getPixelInt(x, y).x() != numExpectedChecksum)
1141					return tcu::TestStatus::fail("Some samples have incorrect color");
1142			}
1143		}
1144	}
1145
1146	return tcu::TestStatus::pass("OK");
1147}
1148
1149} // SampledImage ns
1150
1151namespace StorageImage
1152{
1153
1154void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
1155{
1156	// Vertex & fragment
1157
1158	addSimpleVertexAndFragmentPrograms(programCollection, caseDef);
1159
1160	// Compute
1161	{
1162		const std::string	imageTypeStr		= getShaderMultisampledImageType(mapVkFormat(caseDef.colorFormat), caseDef.numLayers);
1163		const std::string	formatQualifierStr	= getShaderImageFormatQualifier(mapVkFormat(caseDef.colorFormat));
1164		const std::string	signednessPrefix	= isUintFormat(caseDef.colorFormat) ? "u" : isIntFormat(caseDef.colorFormat) ? "i" : "";
1165		const std::string	gvec4Expr			= signednessPrefix + "vec4";
1166		const std::string	texelCoordStr		= (caseDef.numLayers == 1 ? "ivec2(gx, gy)" : "ivec3(gx, gy, gz)");
1167
1168		std::ostringstream src;
1169		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1170			<< "layout(local_size_x = 1) in;\n"
1171			<< "layout(set = 0, binding = 0, " << formatQualifierStr << ") uniform " << imageTypeStr << " u_msImage;\n"
1172			<< "\n"
1173			<< "void main(void)\n"
1174			<< "{\n"
1175			<< "    int gx = int(gl_GlobalInvocationID.x);\n"
1176			<< "    int gy = int(gl_GlobalInvocationID.y);\n"
1177			<< "    int gz = int(gl_GlobalInvocationID.z);\n"
1178			<< "\n"
1179			<< "    " << gvec4Expr << " prevColor = imageLoad(u_msImage, " << texelCoordStr << ", 0);\n"
1180			<< "    for (int sampleNdx = 1; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n"
1181			<< "        " << gvec4Expr << " color = imageLoad(u_msImage, " << texelCoordStr << ", sampleNdx);\n"
1182			<< "        imageStore(u_msImage, " << texelCoordStr <<", sampleNdx, prevColor);\n"
1183			<< "        prevColor = color;\n"
1184			<< "    }\n"
1185			<< "    imageStore(u_msImage, " << texelCoordStr <<", 0, prevColor);\n"
1186			<< "}\n";
1187
1188		programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
1189	}
1190}
1191
1192//! Render a MS image, resolve it, and copy result to resolveBuffer.
1193void renderAndResolve (Context& context, const CaseDef& caseDef, const VkBuffer resolveBuffer, const bool useComputePass)
1194{
1195	const DeviceInterface&		vk					= context.getDeviceInterface();
1196	const VkDevice				device				= context.getDevice();
1197	const VkQueue				queue				= context.getUniversalQueue();
1198	const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1199	Allocator&					allocator			= context.getDefaultAllocator();
1200
1201	// Multisampled color image
1202	const Unique<VkImage>			colorImage			(makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, caseDef.numSamples,
1203																   VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT));
1204	const UniquePtr<Allocation>		colorImageAlloc		(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1205
1206	const Unique<VkImage>			resolveImage		(makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, VK_SAMPLE_COUNT_1_BIT,
1207																   VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT));
1208	const UniquePtr<Allocation>		resolveImageAlloc	(bindImage(vk, device, allocator, *resolveImage, MemoryRequirement::Any));
1209
1210	const Unique<VkCommandPool>		cmdPool				(createCommandPool  (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1211	const Unique<VkCommandBuffer>	cmdBuffer			(makeCommandBuffer(vk, device, *cmdPool));
1212
1213	// Working image barrier, we change it based on which rendering stages were executed so far.
1214	VkImageMemoryBarrier colorImageBarrier =
1215	{
1216		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,						// VkStructureType			sType;
1217		DE_NULL,													// const void*				pNext;
1218		(VkAccessFlags)0,											// VkAccessFlags			outputMask;
1219		(VkAccessFlags)0,											// VkAccessFlags			inputMask;
1220		VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout			oldLayout;
1221		VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout			newLayout;
1222		VK_QUEUE_FAMILY_IGNORED,									// deUint32					srcQueueFamilyIndex;
1223		VK_QUEUE_FAMILY_IGNORED,									// deUint32					destQueueFamilyIndex;
1224		*colorImage,												// VkImage					image;
1225		makeColorSubresourceRange(0, caseDef.numLayers),			// VkImageSubresourceRange	subresourceRange;
1226	};
1227
1228	// Pass 1: Render an image
1229	{
1230		renderMultisampledImage(context, caseDef, *colorImage);
1231
1232		colorImageBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1233		colorImageBarrier.oldLayout		= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1234	}
1235
1236	// Pass 2: Compute shader
1237	if (useComputePass)
1238	{
1239		// Descriptors
1240
1241		Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
1242			.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1243			.build(vk, device));
1244
1245		Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
1246			.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u)
1247			.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1248
1249		const Unique<VkImageView>		colorImageView		(makeImageView(vk, device, *colorImage,
1250																			(caseDef.numLayers == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY),
1251																			caseDef.colorFormat, makeColorSubresourceRange(0, caseDef.numLayers)));
1252		const Unique<VkDescriptorSet>	descriptorSet		(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1253		const VkDescriptorImageInfo		descriptorImageInfo	= makeDescriptorImageInfo(DE_NULL, *colorImageView, VK_IMAGE_LAYOUT_GENERAL);
1254
1255		DescriptorSetUpdateBuilder()
1256			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
1257			.update(vk, device);
1258
1259		const Unique<VkPipelineLayout>	pipelineLayout	(makePipelineLayout	(vk, device, *descriptorSetLayout));
1260		const Unique<VkShaderModule>	shaderModule	(createShaderModule	(vk, device, context.getBinaryCollection().get("comp"), 0));
1261		const Unique<VkPipeline>		pipeline		(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule, DE_NULL));
1262
1263		beginCommandBuffer(vk, *cmdBuffer);
1264
1265		// Image layout for load/stores
1266		{
1267			colorImageBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
1268			colorImageBarrier.newLayout		= VK_IMAGE_LAYOUT_GENERAL;
1269
1270			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1271				0u, DE_NULL, 0u, DE_NULL, 1u, &colorImageBarrier);
1272
1273			colorImageBarrier.srcAccessMask = colorImageBarrier.dstAccessMask;
1274			colorImageBarrier.oldLayout		= colorImageBarrier.newLayout;
1275		}
1276		// Dispatch
1277		{
1278			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
1279			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1280			vk.cmdDispatch(*cmdBuffer, caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers);
1281		}
1282
1283		VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1284		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1285	}
1286
1287	// Resolve and verify the image
1288	{
1289		beginCommandBuffer(vk, *cmdBuffer);
1290
1291		// Prepare for resolve
1292		{
1293			colorImageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1294			colorImageBarrier.newLayout		= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
1295
1296			const VkImageMemoryBarrier barriers[] =
1297			{
1298				colorImageBarrier,
1299				{
1300					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,						// VkStructureType			sType;
1301					DE_NULL,													// const void*				pNext;
1302					(VkAccessFlags)0,											// VkAccessFlags			outputMask;
1303					VK_ACCESS_TRANSFER_WRITE_BIT,								// VkAccessFlags			inputMask;
1304					VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout			oldLayout;
1305					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,						// VkImageLayout			newLayout;
1306					VK_QUEUE_FAMILY_IGNORED,									// deUint32					srcQueueFamilyIndex;
1307					VK_QUEUE_FAMILY_IGNORED,									// deUint32					destQueueFamilyIndex;
1308					*resolveImage,												// VkImage					image;
1309					makeColorSubresourceRange(0, caseDef.numLayers),			// VkImageSubresourceRange	subresourceRange;
1310				},
1311			};
1312
1313			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1314				0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1315
1316			colorImageBarrier.srcAccessMask = colorImageBarrier.dstAccessMask;
1317			colorImageBarrier.oldLayout		= colorImageBarrier.newLayout;
1318		}
1319		// Resolve the image
1320		{
1321			const VkImageResolve resolveRegion =
1322			{
1323				makeColorSubresourceLayers(0, caseDef.numLayers),					// VkImageSubresourceLayers    srcSubresource;
1324				makeOffset3D(0, 0, 0),												// VkOffset3D                  srcOffset;
1325				makeColorSubresourceLayers(0, caseDef.numLayers),					// VkImageSubresourceLayers    dstSubresource;
1326				makeOffset3D(0, 0, 0),												// VkOffset3D                  dstOffset;
1327				makeExtent3D(caseDef.renderSize.x(), caseDef.renderSize.y(), 1u),	// VkExtent3D                  extent;
1328			};
1329
1330			vk.cmdResolveImage(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *resolveImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &resolveRegion);
1331		}
1332		// Prepare resolve image for copy
1333		{
1334			const VkImageMemoryBarrier barriers[] =
1335			{
1336				{
1337					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,						// VkStructureType			sType;
1338					DE_NULL,													// const void*				pNext;
1339					VK_ACCESS_TRANSFER_WRITE_BIT,								// VkAccessFlags			outputMask;
1340					VK_ACCESS_TRANSFER_READ_BIT,								// VkAccessFlags			inputMask;
1341					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,						// VkImageLayout			oldLayout;
1342					VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,						// VkImageLayout			newLayout;
1343					VK_QUEUE_FAMILY_IGNORED,									// deUint32					srcQueueFamilyIndex;
1344					VK_QUEUE_FAMILY_IGNORED,									// deUint32					destQueueFamilyIndex;
1345					*resolveImage,												// VkImage					image;
1346					makeColorSubresourceRange(0, caseDef.numLayers),			// VkImageSubresourceRange	subresourceRange;
1347				},
1348			};
1349
1350			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1351				0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1352		}
1353		// Copy resolved image to host-readable buffer
1354		{
1355			const VkBufferImageCopy copyRegion =
1356			{
1357				0ull,																// VkDeviceSize                bufferOffset;
1358				0u,																	// uint32_t                    bufferRowLength;
1359				0u,																	// uint32_t                    bufferImageHeight;
1360				makeColorSubresourceLayers(0, caseDef.numLayers),					// VkImageSubresourceLayers    imageSubresource;
1361				makeOffset3D(0, 0, 0),												// VkOffset3D                  imageOffset;
1362				makeExtent3D(caseDef.renderSize.x(), caseDef.renderSize.y(), 1u),	// VkExtent3D                  imageExtent;
1363			};
1364
1365			vk.cmdCopyImageToBuffer(*cmdBuffer, *resolveImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, resolveBuffer, 1u, &copyRegion);
1366		}
1367
1368		VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1369		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1370	}
1371}
1372
1373//! Exact image compare, but allow for some error when color format is integer.
1374bool compareImages (tcu::TestLog& log, const CaseDef& caseDef, const tcu::ConstPixelBufferAccess layeredReferenceImage, const tcu::ConstPixelBufferAccess layeredActualImage)
1375{
1376	DE_ASSERT(caseDef.numSamples > 1);
1377
1378	const Vec4	goodColor			= Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1379	const Vec4	badColor			= Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1380	const bool	isAnyIntFormat		= isIntFormat(caseDef.colorFormat) || isUintFormat(caseDef.colorFormat);
1381
1382	// There should be no mismatched pixels for non-integer formats. Otherwise we may get a wrong color in a location where sample coverage isn't exactly 0 or 1.
1383	const int	badPixelTolerance	= (isAnyIntFormat ? 2 * caseDef.renderSize.x() : 0);
1384	int			goodLayers			= 0;
1385
1386	for (int layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
1387	{
1388		const tcu::ConstPixelBufferAccess	referenceImage	= tcu::getSubregion(layeredReferenceImage, 0, 0, layerNdx, caseDef.renderSize.x(), caseDef.renderSize.y(), 1);
1389		const tcu::ConstPixelBufferAccess	actualImage		= tcu::getSubregion(layeredActualImage, 0, 0, layerNdx, caseDef.renderSize.x(), caseDef.renderSize.y(), 1);
1390		const std::string					imageName		= "color layer " + de::toString(layerNdx);
1391
1392		tcu::TextureLevel		errorMaskStorage	(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), caseDef.renderSize.x(), caseDef.renderSize.y());
1393		tcu::PixelBufferAccess	errorMask			= errorMaskStorage.getAccess();
1394		int						numBadPixels		= 0;
1395
1396		for (int y = 0; y < caseDef.renderSize.y(); ++y)
1397		for (int x = 0; x < caseDef.renderSize.x(); ++x)
1398		{
1399			if (isAnyIntFormat && (referenceImage.getPixelInt(x, y) == actualImage.getPixelInt(x, y)))
1400				errorMask.setPixel(goodColor, x, y);
1401			else if (referenceImage.getPixel(x, y) == actualImage.getPixel(x, y))
1402				errorMask.setPixel(goodColor, x, y);
1403			else
1404			{
1405				++numBadPixels;
1406				errorMask.setPixel(badColor, x, y);
1407			}
1408		}
1409
1410		if (numBadPixels <= badPixelTolerance)
1411		{
1412			++goodLayers;
1413
1414			log << tcu::TestLog::ImageSet(imageName, imageName)
1415				<< tcu::TestLog::Image("Result",	"Result",		actualImage)
1416				<< tcu::TestLog::EndImageSet;
1417		}
1418		else
1419		{
1420			log << tcu::TestLog::ImageSet(imageName, imageName)
1421				<< tcu::TestLog::Image("Result",	"Result",		actualImage)
1422				<< tcu::TestLog::Image("Reference",	"Reference",	referenceImage)
1423				<< tcu::TestLog::Image("ErrorMask",	"Error mask",	errorMask)
1424				<< tcu::TestLog::EndImageSet;
1425		}
1426	}
1427
1428	if (goodLayers == caseDef.numLayers)
1429	{
1430		log << tcu::TestLog::Message << "All rendered images are correct." << tcu::TestLog::EndMessage;
1431		return true;
1432	}
1433	else
1434	{
1435		log << tcu::TestLog::Message << "FAILED: Some rendered images were incorrect." << tcu::TestLog::EndMessage;
1436		return false;
1437	}
1438}
1439
1440tcu::TestStatus test (Context& context, const CaseDef caseDef)
1441{
1442	const DeviceInterface&		vk					= context.getDeviceInterface();
1443	const InstanceInterface&	vki					= context.getInstanceInterface();
1444	const VkDevice				device				= context.getDevice();
1445	const VkPhysicalDevice		physDevice			= context.getPhysicalDevice();
1446	Allocator&					allocator			= context.getDefaultAllocator();
1447
1448	checkImageFormatRequirements(vki, physDevice, caseDef.numSamples, caseDef.colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT);
1449
1450	{
1451		tcu::TestLog& log = context.getTestContext().getLog();
1452		log << tcu::LogSection("Description", "")
1453			<< tcu::TestLog::Message << "Rendering to a multisampled image. Image will be processed with a compute shader using OpImageRead and OpImageWrite." << tcu::TestLog::EndMessage
1454			<< tcu::TestLog::Message << "Expecting the processed image to be roughly the same as the input image (deviation may occur for integer formats)." << tcu::TestLog::EndMessage
1455			<< tcu::TestLog::EndSection;
1456	}
1457
1458	// Host-readable buffer
1459	const VkDeviceSize				resolveBufferSize			= caseDef.renderSize.x() * caseDef.renderSize.y() * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat));
1460	const Unique<VkBuffer>			resolveImageOneBuffer		(makeBuffer(vk, device, resolveBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1461	const UniquePtr<Allocation>		resolveImageOneBufferAlloc	(bindBuffer(vk, device, allocator, *resolveImageOneBuffer, MemoryRequirement::HostVisible));
1462	const Unique<VkBuffer>			resolveImageTwoBuffer		(makeBuffer(vk, device, resolveBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1463	const UniquePtr<Allocation>		resolveImageTwoBufferAlloc	(bindBuffer(vk, device, allocator, *resolveImageTwoBuffer, MemoryRequirement::HostVisible));
1464
1465	zeroBuffer(vk, device, *resolveImageOneBufferAlloc, resolveBufferSize);
1466	zeroBuffer(vk, device, *resolveImageTwoBufferAlloc, resolveBufferSize);
1467
1468	// Render: repeat the same rendering twice to avoid non-essential API calls and layout transitions (e.g. copy).
1469	{
1470		renderAndResolve(context, caseDef, *resolveImageOneBuffer, false);	// Pass 1: render a basic multisampled image
1471		renderAndResolve(context, caseDef, *resolveImageTwoBuffer, true);	// Pass 2: the same but altered with a compute shader
1472	}
1473
1474	// Verify
1475	{
1476		invalidateMappedMemoryRange(vk, device, resolveImageOneBufferAlloc->getMemory(), resolveImageOneBufferAlloc->getOffset(), resolveBufferSize);
1477		invalidateMappedMemoryRange(vk, device, resolveImageTwoBufferAlloc->getMemory(), resolveImageTwoBufferAlloc->getOffset(), resolveBufferSize);
1478
1479		const tcu::PixelBufferAccess		layeredImageOne	(mapVkFormat(caseDef.colorFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers, resolveImageOneBufferAlloc->getHostPtr());
1480		const tcu::ConstPixelBufferAccess	layeredImageTwo	(mapVkFormat(caseDef.colorFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers, resolveImageTwoBufferAlloc->getHostPtr());
1481
1482		// Check all layers
1483		if (!compareImages(context.getTestContext().getLog(), caseDef, layeredImageOne, layeredImageTwo))
1484			return tcu::TestStatus::fail("Rendered images are not correct");
1485	}
1486
1487	return tcu::TestStatus::pass("OK");
1488}
1489
1490} // StorageImage ns
1491
1492std::string getSizeLayerString (const IVec2& size, const int numLayers)
1493{
1494	std::ostringstream str;
1495	str << size.x() << "x" << size.y() << "_" << numLayers;
1496	return str.str();
1497}
1498
1499std::string getFormatString (const VkFormat format)
1500{
1501	std::string name(getFormatName(format));
1502	return de::toLower(name.substr(10));
1503}
1504
1505void addTestCasesWithFunctions (tcu::TestCaseGroup*						group,
1506								FunctionPrograms1<CaseDef>::Function	initPrograms,
1507								FunctionInstance1<CaseDef>::Function	testFunc)
1508{
1509	const IVec2 size[] =
1510	{
1511		IVec2(64, 64),
1512		IVec2(79, 31),
1513	};
1514	const int numLayers[] =
1515	{
1516		1, 4
1517	};
1518	const VkSampleCountFlagBits samples[] =
1519	{
1520		VK_SAMPLE_COUNT_2_BIT,
1521		VK_SAMPLE_COUNT_4_BIT,
1522		VK_SAMPLE_COUNT_8_BIT,
1523		VK_SAMPLE_COUNT_16_BIT,
1524		VK_SAMPLE_COUNT_32_BIT,
1525		VK_SAMPLE_COUNT_64_BIT,
1526	};
1527	const VkFormat format[] =
1528	{
1529		VK_FORMAT_R8G8B8A8_UNORM,
1530		VK_FORMAT_R32_UINT,
1531		VK_FORMAT_R16G16_SINT,
1532		VK_FORMAT_R32G32B32A32_SFLOAT,
1533	};
1534
1535	for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(size); ++sizeNdx)
1536	for (int layerNdx = 0; layerNdx < DE_LENGTH_OF_ARRAY(numLayers); ++layerNdx)
1537	{
1538		MovePtr<tcu::TestCaseGroup>	sizeLayerGroup(new tcu::TestCaseGroup(group->getTestContext(), getSizeLayerString(size[sizeNdx], numLayers[layerNdx]).c_str(), ""));
1539		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(format); ++formatNdx)
1540		{
1541			MovePtr<tcu::TestCaseGroup>	formatGroup(new tcu::TestCaseGroup(group->getTestContext(), getFormatString(format[formatNdx]).c_str(), ""));
1542			for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); ++samplesNdx)
1543			{
1544				std::ostringstream caseName;
1545				caseName << "samples_" << getNumSamples(samples[samplesNdx]);
1546
1547				const CaseDef caseDef =
1548				{
1549					size[sizeNdx],			// IVec2					renderSize;
1550					numLayers[layerNdx],	// int						numLayers;
1551					format[formatNdx],		// VkFormat					colorFormat;
1552					samples[samplesNdx],	// VkSampleCountFlagBits	numSamples;
1553				};
1554
1555				addFunctionCaseWithPrograms(formatGroup.get(), caseName.str(), "", initPrograms, testFunc, caseDef);
1556			}
1557			sizeLayerGroup->addChild(formatGroup.release());
1558		}
1559		group->addChild(sizeLayerGroup.release());
1560	}
1561}
1562
1563void createSampledImageTestsInGroup (tcu::TestCaseGroup* group)
1564{
1565	addTestCasesWithFunctions(group, SampledImage::initPrograms, SampledImage::test);
1566}
1567
1568void createStorageImageTestsInGroup (tcu::TestCaseGroup* group)
1569{
1570	addTestCasesWithFunctions(group, StorageImage::initPrograms, StorageImage::test);
1571}
1572
1573} // anonymous ns
1574
1575//! Render to a multisampled image and sample from it in a fragment shader.
1576tcu::TestCaseGroup* createMultisampleSampledImageTests (tcu::TestContext& testCtx)
1577{
1578	return createTestGroup(testCtx, "sampled_image", "Multisampled image direct sample access", createSampledImageTestsInGroup);
1579}
1580
1581//! Render to a multisampled image and access it with load/stores in a compute shader.
1582tcu::TestCaseGroup* createMultisampleStorageImageTests (tcu::TestContext& testCtx)
1583{
1584	return createTestGroup(testCtx, "storage_image", "Multisampled image draw and read/write in compute shader", createStorageImageTestsInGroup);
1585}
1586
1587} // pipeline
1588} // vkt
1589