1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2023 LunarG, Inc.
7  * Copyright (c) 2023 Nintendo
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Multisample image Tests
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktPipelineMultisampleImageTests.hpp"
27 #include "vktPipelineMakeUtil.hpp"
28 #include "vktTestCase.hpp"
29 #include "vktTestCaseUtil.hpp"
30 #include "vktPipelineVertexUtil.hpp"
31 #include "vktTestGroupUtil.hpp"
32 
33 #include "vkMemUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkRefUtil.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkPrograms.hpp"
39 #include "vkImageUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkObjUtil.hpp"
42 
43 #include "tcuTextureUtil.hpp"
44 #include "tcuTestLog.hpp"
45 
46 #include "deUniquePtr.hpp"
47 #include "deSharedPtr.hpp"
48 
49 #include <string>
50 
51 namespace vkt
52 {
53 namespace pipeline
54 {
55 namespace
56 {
57 using namespace vk;
58 using de::UniquePtr;
59 using de::MovePtr;
60 using de::SharedPtr;
61 using tcu::IVec2;
62 using tcu::Vec4;
63 
64 typedef SharedPtr<Unique<VkImageView> >	ImageViewSp;
65 typedef SharedPtr<Unique<VkPipeline> >	PipelineSp;
66 
67 //! Test case parameters
68 struct CaseDef
69 {
70 	PipelineConstructionType	pipelineConstructionType;
71 	IVec2						renderSize;
72 	int							numLayers;
73 	VkFormat					colorFormat;
74 	VkSampleCountFlagBits		numSamples;
75 	bool						colorSamples;
76 };
77 
78 template<typename T>
makeSharedPtr(Move<T> move)79 inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move)
80 {
81 	return SharedPtr<Unique<T> >(new Unique<T>(move));
82 }
83 
84 template<typename T>
sizeInBytes(const std::vector<T>& vec)85 inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
86 {
87 	return vec.size() * sizeof(vec[0]);
88 }
89 
90 //! Create a vector of derived pipelines, each with an increasing subpass index
makeGraphicsPipelines(const DeviceInterface& vk, const VkDevice device, const deUint32 numSubpasses, const VkPipelineLayout pipelineLayout, const VkRenderPass renderPass, const ShaderWrapper vertexModule, const ShaderWrapper fragmentModule, const IVec2 renderSize, const VkSampleCountFlagBits numSamples, const VkPrimitiveTopology topology)91 std::vector<PipelineSp> makeGraphicsPipelines (const DeviceInterface&		vk,
92 											   const VkDevice				device,
93 											   const deUint32				numSubpasses,
94 											   const VkPipelineLayout		pipelineLayout,
95 											   const VkRenderPass			renderPass,
96 											   const ShaderWrapper			vertexModule,
97 											   const ShaderWrapper			fragmentModule,
98 											   const IVec2					renderSize,
99 											   const VkSampleCountFlagBits	numSamples,
100 											   const VkPrimitiveTopology	topology)
101 {
102 	const VkVertexInputBindingDescription vertexInputBindingDescription =
103 	{
104 		0u,								// uint32_t				binding;
105 		sizeof(Vertex4RGBA),			// uint32_t				stride;
106 		VK_VERTEX_INPUT_RATE_VERTEX,	// VkVertexInputRate	inputRate;
107 	};
108 
109 	const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
110 	{
111 		{
112 			0u,									// uint32_t			location;
113 			0u,									// uint32_t			binding;
114 			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat			format;
115 			0u,									// uint32_t			offset;
116 		},
117 		{
118 			1u,									// uint32_t			location;
119 			0u,									// uint32_t			binding;
120 			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat			format;
121 			sizeof(Vec4),						// uint32_t			offset;
122 		},
123 	};
124 
125 	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
126 	{
127 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType                             sType;
128 		DE_NULL,														// const void*                                 pNext;
129 		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags       flags;
130 		1u,																// uint32_t                                    vertexBindingDescriptionCount;
131 		&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
132 		DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),			// uint32_t                                    vertexAttributeDescriptionCount;
133 		vertexInputAttributeDescriptions,								// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
134 	};
135 
136 	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
137 	{
138 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType                             sType;
139 		DE_NULL,														// const void*                                 pNext;
140 		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags     flags;
141 		topology,														// VkPrimitiveTopology                         topology;
142 		VK_FALSE,														// VkBool32                                    primitiveRestartEnable;
143 	};
144 
145 	const VkViewport	viewport	= makeViewport(renderSize);
146 	const VkRect2D		scissor		= makeRect2D(renderSize);
147 
148 	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
149 	{
150 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType                             sType;
151 		DE_NULL,														// const void*                                 pNext;
152 		(VkPipelineViewportStateCreateFlags)0,							// VkPipelineViewportStateCreateFlags          flags;
153 		1u,																// uint32_t                                    viewportCount;
154 		&viewport,														// const VkViewport*                           pViewports;
155 		1u,																// uint32_t                                    scissorCount;
156 		&scissor,														// const VkRect2D*                             pScissors;
157 	};
158 
159 	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
160 	{
161 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType                          sType;
162 		DE_NULL,														// const void*                              pNext;
163 		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags  flags;
164 		VK_FALSE,														// VkBool32                                 depthClampEnable;
165 		VK_FALSE,														// VkBool32                                 rasterizerDiscardEnable;
166 		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
167 		VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
168 		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
169 		VK_FALSE,														// VkBool32									depthBiasEnable;
170 		0.0f,															// float									depthBiasConstantFactor;
171 		0.0f,															// float									depthBiasClamp;
172 		0.0f,															// float									depthBiasSlopeFactor;
173 		1.0f,															// float									lineWidth;
174 	};
175 
176 	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
177 	{
178 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
179 		DE_NULL,														// const void*								pNext;
180 		(VkPipelineMultisampleStateCreateFlags)0,						// VkPipelineMultisampleStateCreateFlags	flags;
181 		numSamples,														// VkSampleCountFlagBits					rasterizationSamples;
182 		VK_FALSE,														// VkBool32									sampleShadingEnable;
183 		0.0f,															// float									minSampleShading;
184 		DE_NULL,														// const VkSampleMask*						pSampleMask;
185 		VK_FALSE,														// VkBool32									alphaToCoverageEnable;
186 		VK_FALSE														// VkBool32									alphaToOneEnable;
187 	};
188 
189 	const VkStencilOpState stencilOpState = makeStencilOpState(
190 		VK_STENCIL_OP_KEEP,				// stencil fail
191 		VK_STENCIL_OP_KEEP,				// depth & stencil pass
192 		VK_STENCIL_OP_KEEP,				// depth only fail
193 		VK_COMPARE_OP_ALWAYS,			// compare op
194 		0u,								// compare mask
195 		0u,								// write mask
196 		0u);							// reference
197 
198 	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
199 	{
200 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,		// VkStructureType							sType;
201 		DE_NULL,														// const void*								pNext;
202 		(VkPipelineDepthStencilStateCreateFlags)0,						// VkPipelineDepthStencilStateCreateFlags	flags;
203 		VK_FALSE,														// VkBool32									depthTestEnable;
204 		VK_FALSE,														// VkBool32									depthWriteEnable;
205 		VK_COMPARE_OP_LESS,												// VkCompareOp								depthCompareOp;
206 		VK_FALSE,														// VkBool32									depthBoundsTestEnable;
207 		VK_FALSE,														// VkBool32									stencilTestEnable;
208 		stencilOpState,													// VkStencilOpState							front;
209 		stencilOpState,													// VkStencilOpState							back;
210 		0.0f,															// float									minDepthBounds;
211 		1.0f,															// float									maxDepthBounds;
212 	};
213 
214 	const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
215 	// Number of blend attachments must equal the number of color attachments during any subpass.
216 	const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
217 	{
218 		VK_FALSE,						// VkBool32					blendEnable;
219 		VK_BLEND_FACTOR_ONE,			// VkBlendFactor			srcColorBlendFactor;
220 		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstColorBlendFactor;
221 		VK_BLEND_OP_ADD,				// VkBlendOp				colorBlendOp;
222 		VK_BLEND_FACTOR_ONE,			// VkBlendFactor			srcAlphaBlendFactor;
223 		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstAlphaBlendFactor;
224 		VK_BLEND_OP_ADD,				// VkBlendOp				alphaBlendOp;
225 		colorComponentsAll,				// VkColorComponentFlags	colorWriteMask;
226 	};
227 
228 	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
229 	{
230 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,		// VkStructureType								sType;
231 		DE_NULL,														// const void*									pNext;
232 		(VkPipelineColorBlendStateCreateFlags)0,						// VkPipelineColorBlendStateCreateFlags			flags;
233 		VK_FALSE,														// VkBool32										logicOpEnable;
234 		VK_LOGIC_OP_COPY,												// VkLogicOp									logicOp;
235 		1u,																// deUint32										attachmentCount;
236 		&pipelineColorBlendAttachmentState,								// const VkPipelineColorBlendAttachmentState*	pAttachments;
237 		{ 0.0f, 0.0f, 0.0f, 0.0f },										// float										blendConstants[4];
238 	};
239 
240 	const VkPipelineShaderStageCreateInfo pShaderStages[] =
241 	{
242 		{
243 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
244 			DE_NULL,													// const void*							pNext;
245 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
246 			VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStageFlagBits				stage;
247 			vertexModule.getModule(),									// VkShaderModule						module;
248 			"main",														// const char*							pName;
249 			DE_NULL,													// const VkSpecializationInfo*			pSpecializationInfo;
250 		},
251 		{
252 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
253 			DE_NULL,													// const void*							pNext;
254 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
255 			VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlagBits				stage;
256 			fragmentModule.getModule(),									// VkShaderModule						module;
257 			"main",														// const char*							pName;
258 			DE_NULL,													// const VkSpecializationInfo*			pSpecializationInfo;
259 		}
260 	};
261 
262 	DE_ASSERT(numSubpasses > 0u);
263 
264 	std::vector<VkGraphicsPipelineCreateInfo>	graphicsPipelineInfos	(0);
265 	std::vector<VkPipeline>						rawPipelines			(numSubpasses, DE_NULL);
266 
267 	{
268 #ifndef CTS_USES_VULKANSC
269 		const VkPipelineCreateFlags firstPipelineFlags	= (numSubpasses > 1u ? VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT
270 																			: VkPipelineCreateFlagBits(0));
271 #else
272 		const VkPipelineCreateFlags firstPipelineFlags	= VkPipelineCreateFlagBits(0);
273 #endif // CTS_USES_VULKANSC
274 
275 		VkGraphicsPipelineCreateInfo createInfo			=
276 		{
277 			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
278 			DE_NULL,											// const void*										pNext;
279 			firstPipelineFlags,									// VkPipelineCreateFlags							flags;
280 			DE_LENGTH_OF_ARRAY(pShaderStages),					// deUint32											stageCount;
281 			pShaderStages,										// const VkPipelineShaderStageCreateInfo*			pStages;
282 			&vertexInputStateInfo,								// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
283 			&pipelineInputAssemblyStateInfo,					// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
284 			DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
285 			&pipelineViewportStateInfo,							// const VkPipelineViewportStateCreateInfo*			pViewportState;
286 			&pipelineRasterizationStateInfo,					// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
287 			&pipelineMultisampleStateInfo,						// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
288 			&pipelineDepthStencilStateInfo,						// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
289 			&pipelineColorBlendStateInfo,						// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
290 			DE_NULL,											// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
291 			pipelineLayout,										// VkPipelineLayout									layout;
292 			renderPass,											// VkRenderPass										renderPass;
293 			0u,													// deUint32											subpass;
294 			DE_NULL,											// VkPipeline										basePipelineHandle;
295 			0u,													// deInt32											basePipelineIndex;
296 		};
297 
298 		graphicsPipelineInfos.push_back					(createInfo);
299 
300 #ifndef CTS_USES_VULKANSC
301 		createInfo.flags								= VK_PIPELINE_CREATE_DERIVATIVE_BIT;
302 		createInfo.basePipelineIndex					= 0;
303 #endif // CTS_USES_VULKANSC
304 
305 		for (deUint32 subpassNdx = 1u; subpassNdx < numSubpasses; ++subpassNdx)
306 		{
307 			createInfo.subpass = subpassNdx;
308 			graphicsPipelineInfos.push_back(createInfo);
309 		}
310 	}
311 
312 	VK_CHECK(vk.createGraphicsPipelines(device, DE_NULL, static_cast<deUint32>(graphicsPipelineInfos.size()), &graphicsPipelineInfos[0], DE_NULL, &rawPipelines[0]));
313 
314 	std::vector<PipelineSp>	pipelines;
315 
316 	for (std::vector<VkPipeline>::const_iterator it = rawPipelines.begin(); it != rawPipelines.end(); ++it)
317 		pipelines.push_back(makeSharedPtr(Move<VkPipeline>(check<VkPipeline>(*it), Deleter<VkPipeline>(vk, device, DE_NULL))));
318 
319 	return pipelines;
320 }
321 
322 //! Create a vector of pipelines, each with an increasing subpass index
preparePipelineWrapper(GraphicsPipelineWrapper& gpw, const deUint32 subpassNdx, const PipelineLayoutWrapper& pipelineLayout, const VkRenderPass renderPass, const ShaderWrapper vertexModule, const ShaderWrapper fragmentModule, const IVec2 renderSize, const VkSampleCountFlagBits numSamples, const VkPrimitiveTopology topology)323 void preparePipelineWrapper (GraphicsPipelineWrapper&		gpw,
324 							 const deUint32					subpassNdx,
325 							 const PipelineLayoutWrapper&	pipelineLayout,
326 							 const VkRenderPass				renderPass,
327 							 const ShaderWrapper			vertexModule,
328 							 const ShaderWrapper			fragmentModule,
329 							 const IVec2					renderSize,
330 							 const VkSampleCountFlagBits	numSamples,
331 							 const VkPrimitiveTopology		topology)
332 {
333 	const VkVertexInputBindingDescription vertexInputBindingDescription =
334 	{
335 		0u,								// uint32_t				binding;
336 		sizeof(Vertex4RGBA),			// uint32_t				stride;
337 		VK_VERTEX_INPUT_RATE_VERTEX,	// VkVertexInputRate	inputRate;
338 	};
339 
340 	const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
341 	{
342 		{
343 			0u,									// uint32_t			location;
344 			0u,									// uint32_t			binding;
345 			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat			format;
346 			0u,									// uint32_t			offset;
347 		},
348 		{
349 			1u,									// uint32_t			location;
350 			0u,									// uint32_t			binding;
351 			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat			format;
352 			sizeof(Vec4),						// uint32_t			offset;
353 		},
354 	};
355 
356 	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
357 	{
358 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType                             sType;
359 		DE_NULL,														// const void*                                 pNext;
360 		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags       flags;
361 		1u,																// uint32_t                                    vertexBindingDescriptionCount;
362 		&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
363 		DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),			// uint32_t                                    vertexAttributeDescriptionCount;
364 		vertexInputAttributeDescriptions,								// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
365 	};
366 
367 	const std::vector<VkViewport>	viewport	{ makeViewport(renderSize) };
368 	const std::vector<VkRect2D>		scissor		{ makeRect2D(renderSize) };
369 
370 	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
371 	{
372 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
373 		DE_NULL,														// const void*								pNext;
374 		(VkPipelineMultisampleStateCreateFlags)0,						// VkPipelineMultisampleStateCreateFlags	flags;
375 		numSamples,														// VkSampleCountFlagBits					rasterizationSamples;
376 		VK_FALSE,														// VkBool32									sampleShadingEnable;
377 		0.0f,															// float									minSampleShading;
378 		DE_NULL,														// const VkSampleMask*						pSampleMask;
379 		VK_FALSE,														// VkBool32									alphaToCoverageEnable;
380 		VK_FALSE														// VkBool32									alphaToOneEnable;
381 	};
382 
383 	const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
384 	// Number of blend attachments must equal the number of color attachments during any subpass.
385 	const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
386 	{
387 		VK_FALSE,						// VkBool32					blendEnable;
388 		VK_BLEND_FACTOR_ONE,			// VkBlendFactor			srcColorBlendFactor;
389 		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstColorBlendFactor;
390 		VK_BLEND_OP_ADD,				// VkBlendOp				colorBlendOp;
391 		VK_BLEND_FACTOR_ONE,			// VkBlendFactor			srcAlphaBlendFactor;
392 		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstAlphaBlendFactor;
393 		VK_BLEND_OP_ADD,				// VkBlendOp				alphaBlendOp;
394 		colorComponentsAll,				// VkColorComponentFlags	colorWriteMask;
395 	};
396 
397 	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
398 	{
399 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,		// VkStructureType								sType;
400 		DE_NULL,														// const void*									pNext;
401 		(VkPipelineColorBlendStateCreateFlags)0,						// VkPipelineColorBlendStateCreateFlags			flags;
402 		VK_FALSE,														// VkBool32										logicOpEnable;
403 		VK_LOGIC_OP_COPY,												// VkLogicOp									logicOp;
404 		1u,																// deUint32										attachmentCount;
405 		&pipelineColorBlendAttachmentState,								// const VkPipelineColorBlendAttachmentState*	pAttachments;
406 		{ 0.0f, 0.0f, 0.0f, 0.0f },										// float										blendConstants[4];
407 	};
408 
409 	gpw.setDefaultTopology(topology)
410 	   .setDefaultRasterizationState()
411 	   .setDefaultDepthStencilState()
412 	   .setupVertexInputState(&vertexInputStateInfo)
413 	   .setupPreRasterizationShaderState(viewport,
414 			scissor,
415 			pipelineLayout,
416 			renderPass,
417 			subpassNdx,
418 			vertexModule)
419 	   .setupFragmentShaderState(pipelineLayout, renderPass, subpassNdx, fragmentModule, DE_NULL, &pipelineMultisampleStateInfo)
420 	   .setupFragmentOutputState(renderPass, subpassNdx, &pipelineColorBlendStateInfo, &pipelineMultisampleStateInfo)
421 	   .setMonolithicPipelineLayout(pipelineLayout)
422 	   .buildPipeline();
423 }
424 
425 //! Make a render pass with one subpass per color attachment and one attachment per image layer.
makeMultisampleRenderPass(const DeviceInterface& vk, const VkDevice device, const PipelineConstructionType pipelineConstructionType, const VkFormat colorFormat, const VkSampleCountFlagBits numSamples, const deUint32 numLayers)426 RenderPassWrapper makeMultisampleRenderPass (const DeviceInterface&			vk,
427 											 const VkDevice					device,
428 											 const PipelineConstructionType	pipelineConstructionType,
429 											 const VkFormat					colorFormat,
430 											 const VkSampleCountFlagBits	numSamples,
431 											 const deUint32					numLayers)
432 {
433 	const VkAttachmentDescription colorAttachmentDescription =
434 	{
435 		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
436 		colorFormat,										// VkFormat							format;
437 		numSamples,											// VkSampleCountFlagBits			samples;
438 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
439 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
440 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
441 		VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
442 		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					initialLayout;
443 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
444 	};
445 	const std::vector<VkAttachmentDescription> attachmentDescriptions(numLayers, colorAttachmentDescription);
446 
447 	// Create a subpass for each attachment (each attachement is a layer of an arrayed image).
448 
449 	std::vector<VkAttachmentReference>	colorAttachmentReferences(numLayers);
450 	std::vector<VkSubpassDescription>	subpasses;
451 
452 	for (deUint32 i = 0; i < numLayers; ++i)
453 	{
454 		const VkAttachmentReference attachmentRef =
455 		{
456 			i,												// deUint32			attachment;
457 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL		// VkImageLayout	layout;
458 		};
459 		colorAttachmentReferences[i] = attachmentRef;
460 
461 		const VkSubpassDescription subpassDescription =
462 		{
463 			(VkSubpassDescriptionFlags)0,					// VkSubpassDescriptionFlags		flags;
464 			VK_PIPELINE_BIND_POINT_GRAPHICS,				// VkPipelineBindPoint				pipelineBindPoint;
465 			0u,												// deUint32							inputAttachmentCount;
466 			DE_NULL,										// const VkAttachmentReference*		pInputAttachments;
467 			1u,												// deUint32							colorAttachmentCount;
468 			&colorAttachmentReferences[i],					// const VkAttachmentReference*		pColorAttachments;
469 			DE_NULL,										// const VkAttachmentReference*		pResolveAttachments;
470 			DE_NULL,										// const VkAttachmentReference*		pDepthStencilAttachment;
471 			0u,												// deUint32							preserveAttachmentCount;
472 			DE_NULL											// const deUint32*					pPreserveAttachments;
473 		};
474 		subpasses.push_back(subpassDescription);
475 	}
476 
477 	const VkRenderPassCreateInfo renderPassInfo =
478 	{
479 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,				// VkStructureType					sType;
480 		DE_NULL,												// const void*						pNext;
481 		(VkRenderPassCreateFlags)0,								// VkRenderPassCreateFlags			flags;
482 		static_cast<deUint32>(attachmentDescriptions.size()),	// deUint32							attachmentCount;
483 		&attachmentDescriptions[0],								// const VkAttachmentDescription*	pAttachments;
484 		static_cast<deUint32>(subpasses.size()),				// deUint32							subpassCount;
485 		&subpasses[0],											// const VkSubpassDescription*		pSubpasses;
486 		0u,														// deUint32							dependencyCount;
487 		DE_NULL													// const VkSubpassDependency*		pDependencies;
488 	};
489 
490 	return RenderPassWrapper(pipelineConstructionType, vk, device, &renderPassInfo);
491 }
492 
493 //! A single-attachment, single-subpass render pass.
makeSimpleRenderPass(const DeviceInterface& vk, const VkDevice device, const PipelineConstructionType pipelineConstructionType, const VkFormat colorFormat)494 RenderPassWrapper makeSimpleRenderPass (const DeviceInterface&			vk,
495 										const VkDevice					device,
496 										const PipelineConstructionType	pipelineConstructionType,
497 										const VkFormat					colorFormat)
498 {
499 	const VkAttachmentDescription colorAttachmentDescription =
500 	{
501 		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
502 		colorFormat,										// VkFormat							format;
503 		VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
504 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
505 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
506 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
507 		VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
508 		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					initialLayout;
509 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
510 	};
511 
512 	const VkAttachmentReference colorAttachmentRef =
513 	{
514 		0u,													// deUint32			attachment;
515 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
516 	};
517 
518 	const VkSubpassDescription subpassDescription =
519 	{
520 		(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags		flags;
521 		VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
522 		0u,													// deUint32							inputAttachmentCount;
523 		DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
524 		1u,													// deUint32							colorAttachmentCount;
525 		&colorAttachmentRef,								// const VkAttachmentReference*		pColorAttachments;
526 		DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
527 		DE_NULL,											// const VkAttachmentReference*		pDepthStencilAttachment;
528 		0u,													// deUint32							preserveAttachmentCount;
529 		DE_NULL												// const deUint32*					pPreserveAttachments;
530 	};
531 
532 	const VkRenderPassCreateInfo renderPassInfo =
533 	{
534 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
535 		DE_NULL,											// const void*						pNext;
536 		(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
537 		1u,													// deUint32							attachmentCount;
538 		&colorAttachmentDescription,						// const VkAttachmentDescription*	pAttachments;
539 		1u,													// deUint32							subpassCount;
540 		&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
541 		0u,													// deUint32							dependencyCount;
542 		DE_NULL												// const VkSubpassDependency*		pDependencies;
543 	};
544 
545 	return RenderPassWrapper(pipelineConstructionType, vk, device, &renderPassInfo);
546 }
547 
makeImage(const DeviceInterface& vk, const VkDevice device, const VkFormat format, const IVec2& size, const deUint32 numLayers, const VkSampleCountFlagBits samples, const VkImageUsageFlags usage)548 Move<VkImage> makeImage (const DeviceInterface& vk, const VkDevice device, const VkFormat format, const IVec2& size, const deUint32 numLayers, const VkSampleCountFlagBits samples, const VkImageUsageFlags usage)
549 {
550 	const VkImageCreateInfo imageParams =
551 	{
552 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
553 		DE_NULL,										// const void*				pNext;
554 		(VkImageCreateFlags)0,							// VkImageCreateFlags		flags;
555 		VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
556 		format,											// VkFormat					format;
557 		makeExtent3D(size.x(), size.y(), 1),			// VkExtent3D				extent;
558 		1u,												// deUint32					mipLevels;
559 		numLayers,										// deUint32					arrayLayers;
560 		samples,										// VkSampleCountFlagBits	samples;
561 		VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
562 		usage,											// VkImageUsageFlags		usage;
563 		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
564 		0u,												// deUint32					queueFamilyIndexCount;
565 		DE_NULL,										// const deUint32*			pQueueFamilyIndices;
566 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout;
567 	};
568 	return createImage(vk, device, &imageParams);
569 }
570 
571 //! Make a simplest sampler.
makeSampler(const DeviceInterface& vk, const VkDevice device)572 Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice device)
573 {
574 	const VkSamplerCreateInfo samplerParams =
575 	{
576 		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,			// VkStructureType			sType;
577 		DE_NULL,										// const void*				pNext;
578 		(VkSamplerCreateFlags)0,						// VkSamplerCreateFlags		flags;
579 		VK_FILTER_NEAREST,								// VkFilter					magFilter;
580 		VK_FILTER_NEAREST,								// VkFilter					minFilter;
581 		VK_SAMPLER_MIPMAP_MODE_NEAREST,					// VkSamplerMipmapMode		mipmapMode;
582 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode		addressModeU;
583 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode		addressModeV;
584 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode		addressModeW;
585 		0.0f,											// float					mipLodBias;
586 		VK_FALSE,										// VkBool32					anisotropyEnable;
587 		1.0f,											// float					maxAnisotropy;
588 		VK_FALSE,										// VkBool32					compareEnable;
589 		VK_COMPARE_OP_ALWAYS,							// VkCompareOp				compareOp;
590 		0.0f,											// float					minLod;
591 		0.0f,											// float					maxLod;
592 		VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,		// VkBorderColor			borderColor;
593 		VK_FALSE,										// VkBool32					unnormalizedCoordinates;
594 	};
595 	return createSampler(vk, device, &samplerParams);
596 }
597 
makeColorSubresourceRange(const int baseArrayLayer, const int layerCount)598 inline VkImageSubresourceRange makeColorSubresourceRange (const int baseArrayLayer, const int layerCount)
599 {
600 	return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
601 }
602 
makeColorSubresourceLayers(const int baseArrayLayer, const int layerCount)603 inline VkImageSubresourceLayers makeColorSubresourceLayers (const int baseArrayLayer, const int layerCount)
604 {
605 	return makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
606 }
607 
checkImageFormatRequirements(const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkSampleCountFlagBits sampleCount, const VkFormat format, const VkImageUsageFlags usage)608 void checkImageFormatRequirements (const InstanceInterface&		vki,
609 								   const VkPhysicalDevice		physDevice,
610 								   const VkSampleCountFlagBits	sampleCount,
611 								   const VkFormat				format,
612 								   const VkImageUsageFlags		usage)
613 {
614 	VkPhysicalDeviceFeatures	features;
615 	vki.getPhysicalDeviceFeatures(physDevice, &features);
616 
617 	if (((usage & VK_IMAGE_USAGE_STORAGE_BIT) != 0) && !features.shaderStorageImageMultisample)
618 		TCU_THROW(NotSupportedError, "Multisampled storage images are not supported");
619 
620 	VkImageFormatProperties		imageFormatProperties;
621 	const VkResult				imageFormatResult		= vki.getPhysicalDeviceImageFormatProperties(
622 		physDevice, format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage, (VkImageCreateFlags)0, &imageFormatProperties);
623 
624 	if (imageFormatResult == VK_ERROR_FORMAT_NOT_SUPPORTED)
625 		TCU_THROW(NotSupportedError, "Image format is not supported");
626 
627 	if ((imageFormatProperties.sampleCounts & sampleCount) != sampleCount)
628 		TCU_THROW(NotSupportedError, "Requested sample count is not supported");
629 }
630 
631 //! The default foreground color.
getPrimitiveColor(void)632 inline Vec4 getPrimitiveColor (void)
633 {
634 	return Vec4(1.0f, 0.0f, 0.0f, 1.0f);
635 }
636 
637 //! Get a reference clear value based on color format.
getClearValue(const VkFormat format)638 VkClearValue getClearValue (const VkFormat format)
639 {
640 	if (isUintFormat(format) || isIntFormat(format))
641 		return makeClearValueColorU32(16, 32, 64, 96);
642 	else
643 		return makeClearValueColorF32(0.0f, 0.0f, 1.0f, 1.0f);
644 }
645 
getColorFormatStr(const int numComponents, const bool isUint, const bool isSint)646 std::string getColorFormatStr (const int numComponents, const bool isUint, const bool isSint)
647 {
648 	std::ostringstream str;
649 	if (numComponents == 1)
650 		str << (isUint ? "uint" : isSint ? "int" : "float");
651 	else
652 		str << (isUint ? "u" : isSint ? "i" : "") << "vec" << numComponents;
653 
654 	return str.str();
655 }
656 
getSamplerTypeStr(const int numLayers, const bool isUint, const bool isSint)657 std::string getSamplerTypeStr (const int numLayers, const bool isUint, const bool isSint)
658 {
659 	std::ostringstream str;
660 	str << (isUint ? "u" : isSint ? "i" : "") << "sampler2DMS" << (numLayers > 1 ? "Array" : "");
661 	return str.str();
662 }
663 
664 //! Generate a gvec4 color literal.
665 template<typename T>
getColorStr(const T* data, int numComponents, const bool isUint, const bool isSint)666 std::string getColorStr (const T* data, int numComponents, const bool isUint, const bool isSint)
667 {
668 	const int maxIndex = 3;  // 4 components max
669 
670 	std::ostringstream str;
671 	str << (isUint ? "u" : isSint ? "i" : "") << "vec4(";
672 
673 	for (int i = 0; i < numComponents; ++i)
674 	{
675 		str << data[i]
676 			<< (i < maxIndex ? ", " : "");
677 	}
678 
679 	for (int i = numComponents; i < maxIndex + 1; ++i)
680 	{
681 		str << (i == maxIndex ? 1 : 0)
682 			<< (i <  maxIndex ? ", " : "");
683 	}
684 
685 	str << ")";
686 	return str.str();
687 }
688 
689 //! Clear color literal value used by the sampling shader.
690 std::string getReferenceClearColorStr (const VkFormat format, const int numComponents, const bool isUint, const bool isSint)
691 {
692 	const VkClearColorValue clearColor = getClearValue(format).color;
693 	if (isUint)
694 		return getColorStr(clearColor.uint32, numComponents, isUint, isSint);
695 	else if (isSint)
696 		return getColorStr(clearColor.int32, numComponents, isUint, isSint);
697 	else
698 		return getColorStr(clearColor.float32, numComponents, isUint, isSint);
699 }
700 
701 //! Primitive color literal value used by the sampling shader.
702 std::string getReferencePrimitiveColorStr (int numComponents, const bool isUint, const bool isSint)
703 {
704 	const Vec4 color = getPrimitiveColor();
705 	return getColorStr(color.getPtr(), numComponents, isUint, isSint);
706 }
707 
708 inline int getNumSamples (const VkSampleCountFlagBits samples)
709 {
710 	return static_cast<int>(samples);	// enum bitmask actually matches the number of samples
711 }
712 
713 //! A flat-colored shape with sharp angles to make antialiasing visible.
714 std::vector<Vertex4RGBA> genTriangleVertices (void)
715 {
716 	static const Vertex4RGBA data[] =
717 	{
718 		{
719 			Vec4(-1.0f, 0.0f, 0.0f, 1.0f),
720 			getPrimitiveColor(),
721 		},
722 		{
723 			Vec4(0.8f, 0.2f, 0.0f, 1.0f),
724 			getPrimitiveColor(),
725 		},
726 		{
727 			Vec4(0.8f, -0.2f, 0.0f, 1.0f),
728 			getPrimitiveColor(),
729 		},
730 	};
731 	return std::vector<Vertex4RGBA>(data, data + DE_LENGTH_OF_ARRAY(data));
732 }
733 
734 Vec4 sampleIndexToColor (deUint32 index)
735 {
736 	Vec4 res = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
737 
738 	if (index & 0x01) res += Vec4(0.5f, 0.0f, 0.0f, 0.0f);
739 	if (index & 0x02) res += Vec4(0.0f, 0.5f, 0.0f, 0.0f);
740 	if (index & 0x04) res += Vec4(0.0f, 0.0f, 0.5f, 0.0f);
741 
742 	if (index & 0x08) res += Vec4(0.5f, 0.0f, 0.0f, 0.0f);
743 	if (index & 0x10) res += Vec4(0.0f, 0.5f, 0.0f, 0.0f);
744 	if (index & 0x20) res += Vec4(0.0f, 0.0f, 0.5f, 0.0f);
745 
746 	return res;
747 }
748 
749 float* getStandardSampleLocations (VkSampleCountFlagBits samples)
750 {
751 	static float standardSampleLocations_1[1 * 2] = {
752 		0.5f, 0.5f,
753 	};
754 
755 	static float standardSampleLocations_2[2 * 2] = {
756 		0.75f, 0.75f,
757 		0.25f, 0.25f,
758 	};
759 
760 	static float standardSampleLocations_4[4 * 2] = {
761 		0.375f, 0.125f,
762 		0.875f, 0.375f,
763 		0.125f, 0.625f,
764 		0.625f, 0.875f,
765 	};
766 
767 	static float standardSampleLocations_8[8 * 2] = {
768 		0.5625f, 0.3125f,
769 		0.4375f, 0.6875f,
770 		0.8125f, 0.5625f,
771 		0.3125f, 0.1875f,
772 		0.1875f, 0.8125f,
773 		0.0625f, 0.4375f,
774 		0.6875f, 0.9375f,
775 		0.9375f, 0.0625f,
776 	};
777 
778 	static float standardSampleLocations_16[16 * 2] = {
779 		0.5625f, 0.5625f,
780 		0.4375f, 0.3125f,
781 		0.3125f, 0.625f,
782 		0.75f, 0.4375f,
783 		0.1875f, 0.375f,
784 		0.625f, 0.8125f,
785 		0.8125f, 0.6875f,
786 		0.6875f, 0.1875f,
787 		0.375f, 0.875f,
788 		0.5f, 0.0625f,
789 		0.25f, 0.125f,
790 		0.125f, 0.75f,
791 		0.0f, 0.5f,
792 		0.9375f, 0.25f,
793 		0.875f, 0.9375f,
794 		0.0625f, 0.0f,
795 	};
796 
797 	switch (samples)
798 	{
799 	case VK_SAMPLE_COUNT_1_BIT:
800 		return standardSampleLocations_1;
801 	case VK_SAMPLE_COUNT_2_BIT:
802 		return standardSampleLocations_2;
803 	case VK_SAMPLE_COUNT_4_BIT:
804 		return standardSampleLocations_4;
805 	case VK_SAMPLE_COUNT_8_BIT:
806 		return standardSampleLocations_8;
807 	case VK_SAMPLE_COUNT_16_BIT:
808 		return standardSampleLocations_16;
809 	default:
810 		TCU_THROW(InternalError, "Unknown multisample bit configuration requested");
811 	}
812 }
813 
814 //! A flat-colored shapes plotted at standard sample points.
815 std::vector<Vertex4RGBA> genPerSampleTriangleVertices (VkSampleCountFlagBits samples)
816 {
817 	float*						coordinates		= getStandardSampleLocations(samples);
818 	const float					triangleSize	= 1.0f / (static_cast<float>(samples) * 2.0f);
819 	std::vector<Vertex4RGBA>	res;
820 
821 	for (deUint32 i = 0; i < static_cast<deUint32>(samples); i++)
822 	{
823 		Vertex4RGBA data[] =
824 		{
825 			{
826 				Vec4(0 + coordinates[i * 2 + 0] * 2 - 1, -triangleSize + coordinates[i * 2 + 1] * 2 - 1, 0.0f, 1.0f),
827 				sampleIndexToColor(i),
828 			},
829 			{
830 				Vec4(-triangleSize + coordinates[i * 2 + 0] * 2 - 1, triangleSize + coordinates[i * 2 + 1] * 2 - 1, 0.0f, 1.0f),
831 				sampleIndexToColor(i),
832 			},
833 			{
834 				Vec4(triangleSize + coordinates[i * 2 + 0] * 2 - 1, triangleSize + coordinates[i * 2 + 1] * 2 - 1, 0.0f, 1.0f),
835 				sampleIndexToColor(i),
836 			},
837 		};
838 		res.push_back(data[0]);
839 		res.push_back(data[1]);
840 		res.push_back(data[2]);
841 	}
842 	return res;
843 }
844 
845 //! A full-viewport quad. Use with TRIANGLE_STRIP topology.
846 std::vector<Vertex4RGBA> genFullQuadVertices (void)
847 {
848 	static const Vertex4RGBA data[] =
849 	{
850 		{
851 			Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
852 			Vec4(), // unused
853 		},
854 		{
855 			Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
856 			Vec4(), // unused
857 		},
858 		{
859 			Vec4(1.0f, -1.0f, 0.0f, 1.0f),
860 			Vec4(), // unused
861 		},
862 		{
863 			Vec4(1.0f, 1.0f, 0.0f, 1.0f),
864 			Vec4(), // unused
865 		},
866 	};
867 	return std::vector<Vertex4RGBA>(data, data + DE_LENGTH_OF_ARRAY(data));
868 }
869 
870 std::string getShaderImageFormatQualifier (const tcu::TextureFormat& format)
871 {
872 	const char* orderPart;
873 	const char* typePart;
874 
875 	switch (format.order)
876 	{
877 		case tcu::TextureFormat::R:		orderPart = "r";	break;
878 		case tcu::TextureFormat::RG:	orderPart = "rg";	break;
879 		case tcu::TextureFormat::RGB:	orderPart = "rgb";	break;
880 		case tcu::TextureFormat::RGBA:	orderPart = "rgba";	break;
881 
882 		default:
883 			DE_ASSERT(false);
884 			orderPart = DE_NULL;
885 	}
886 
887 	switch (format.type)
888 	{
889 		case tcu::TextureFormat::FLOAT:				typePart = "32f";		break;
890 		case tcu::TextureFormat::HALF_FLOAT:		typePart = "16f";		break;
891 
892 		case tcu::TextureFormat::UNSIGNED_INT32:	typePart = "32ui";		break;
893 		case tcu::TextureFormat::UNSIGNED_INT16:	typePart = "16ui";		break;
894 		case tcu::TextureFormat::UNSIGNED_INT8:		typePart = "8ui";		break;
895 
896 		case tcu::TextureFormat::SIGNED_INT32:		typePart = "32i";		break;
897 		case tcu::TextureFormat::SIGNED_INT16:		typePart = "16i";		break;
898 		case tcu::TextureFormat::SIGNED_INT8:		typePart = "8i";		break;
899 
900 		case tcu::TextureFormat::UNORM_INT16:		typePart = "16";		break;
901 		case tcu::TextureFormat::UNORM_INT8:		typePart = "8";			break;
902 
903 		case tcu::TextureFormat::SNORM_INT16:		typePart = "16_snorm";	break;
904 		case tcu::TextureFormat::SNORM_INT8:		typePart = "8_snorm";	break;
905 
906 		default:
907 			DE_ASSERT(false);
908 			typePart = DE_NULL;
909 	}
910 
911 	return std::string() + orderPart + typePart;
912 }
913 
914 std::string getShaderMultisampledImageType (const tcu::TextureFormat& format, const int numLayers)
915 {
916 	const std::string formatPart = tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" :
917 								   tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER   ? "i" : "";
918 
919 	std::ostringstream str;
920 	str << formatPart << "image2DMS" << (numLayers > 1 ? "Array" : "");
921 
922 	return str.str();
923 }
924 
925 void addSimpleVertexAndFragmentPrograms (SourceCollections& programCollection, const CaseDef caseDef)
926 {
927 	const int	numComponents	= tcu::getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order);
928 	const bool	isUint			= isUintFormat(caseDef.colorFormat);
929 	const bool	isSint			= isIntFormat(caseDef.colorFormat);
930 
931 	// Vertex shader
932 	{
933 		std::ostringstream src;
934 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
935 			<< "\n"
936 			<< "layout(location = 0) in  vec4 in_position;\n"
937 			<< "layout(location = 1) in  vec4 in_color;\n"
938 			<< "layout(location = 0) out vec4 o_color;\n"
939 			<< "\n"
940 			<< "out gl_PerVertex {\n"
941 			<< "    vec4 gl_Position;\n"
942 			<< "};\n"
943 			<< "\n"
944 			<< "void main(void)\n"
945 			<< "{\n"
946 			<< "    gl_Position = in_position;\n"
947 			<< "    o_color     = in_color;\n"
948 			<< "}\n";
949 
950 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
951 	}
952 
953 	// Fragment shader
954 	{
955 		const std::string colorFormat = getColorFormatStr(numComponents, isUint, isSint);
956 
957 		std::ostringstream src;
958 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
959 			<< "\n"
960 			<< "layout(location = 0) in  vec4 in_color;\n"
961 			<< "layout(location = 0) out " << colorFormat << " o_color;\n"
962 			<< "\n"
963 			<< "void main(void)\n"
964 			<< "{\n"
965 			<< "    o_color = " << colorFormat << "("		// float color will be converted to int/uint here if needed
966 			<< (numComponents == 1 ? "in_color.r"   :
967 				numComponents == 2 ? "in_color.rg"  :
968 				numComponents == 3 ? "in_color.rgb" : "in_color") << ");\n"
969 			<< "}\n";
970 
971 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
972 	}
973 }
974 
975 //! Synchronously render to a multisampled color image.
976 void renderMultisampledImage (Context& context, const CaseDef& caseDef, const VkImage colorImage)
977 {
978 	const InstanceInterface&		vki					= context.getInstanceInterface();
979 	const DeviceInterface&			vk					= context.getDeviceInterface();
980 	const VkPhysicalDevice			physicalDevice		= context.getPhysicalDevice();
981 	const VkDevice					device				= context.getDevice();
982 	const VkQueue					queue				= context.getUniversalQueue();
983 	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
984 	Allocator&						allocator			= context.getDefaultAllocator();
985 
986 	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
987 	const Unique<VkCommandBuffer>	cmdBuffer			(makeCommandBuffer(vk, device, *cmdPool));
988 
989 	{
990 		// Create an image view (attachment) for each layer of the image
991 		std::vector<ImageViewSp>	colorAttachments;
992 		std::vector<VkImage>		images;
993 		std::vector<VkImageView>	attachmentHandles;
994 		for (int i = 0; i < caseDef.numLayers; ++i)
995 		{
996 			colorAttachments.push_back(makeSharedPtr(makeImageView(
997 				vk, device, colorImage, VK_IMAGE_VIEW_TYPE_2D, caseDef.colorFormat, makeColorSubresourceRange(i, 1))));
998 			images.push_back(colorImage);
999 			attachmentHandles.push_back(**colorAttachments.back());
1000 		}
1001 
1002 		// Vertex buffer
1003 		const std::vector<Vertex4RGBA>	vertices			= caseDef.colorSamples ? genPerSampleTriangleVertices(caseDef.numSamples) : genTriangleVertices();
1004 		const VkDeviceSize				vertexBufferSize	= sizeInBytes(vertices);
1005 		const Unique<VkBuffer>			vertexBuffer		(makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
1006 		const UniquePtr<Allocation>		vertexBufferAlloc	(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
1007 
1008 		{
1009 			deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1010 			flushAlloc(vk, device, *vertexBufferAlloc);
1011 		}
1012 
1013 		const ShaderWrapper						vertexModule	(ShaderWrapper				(vk, device, context.getBinaryCollection().get("vert"), 0u));
1014 		const ShaderWrapper						fragmentModule	(ShaderWrapper				(vk, device, context.getBinaryCollection().get("frag"), 0u));
1015 		RenderPassWrapper						renderPass		(makeMultisampleRenderPass	(vk, device, caseDef.pipelineConstructionType, caseDef.colorFormat, caseDef.numSamples, caseDef.numLayers));
1016 		renderPass.createFramebuffer(vk, device, caseDef.numLayers, &images[0], &attachmentHandles[0], static_cast<deUint32>(caseDef.renderSize.x()),  static_cast<deUint32>(caseDef.renderSize.y()));
1017 		const PipelineLayoutWrapper				pipelineLayout	(caseDef.pipelineConstructionType, vk, device);
1018 		const bool								isMonolithic	(caseDef.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC);
1019 		std::vector<PipelineSp>					pipelinesSp;
1020 		std::vector<GraphicsPipelineWrapper>	pipelineWrapper;
1021 
1022 		if (isMonolithic)
1023 		{
1024 			pipelinesSp = makeGraphicsPipelines(vk, device, caseDef.numLayers, *pipelineLayout, *renderPass, vertexModule, fragmentModule,
1025 												caseDef.renderSize, caseDef.numSamples, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
1026 		}
1027 		else
1028 		{
1029 			// we can't create a vector of derived pipelines with GraphicsPipelineWrapper
1030 			pipelineWrapper.reserve(caseDef.numLayers);
1031 			for (int subpassNdx = 0; subpassNdx < caseDef.numLayers; ++subpassNdx)
1032 			{
1033 				pipelineWrapper.emplace_back(vki, vk, physicalDevice, device, context.getDeviceExtensions(), caseDef.pipelineConstructionType);
1034 				preparePipelineWrapper(pipelineWrapper.back(), subpassNdx, pipelineLayout, *renderPass, vertexModule, fragmentModule,
1035 									   caseDef.renderSize, caseDef.numSamples, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
1036 			}
1037 		}
1038 
1039 		beginCommandBuffer(vk, *cmdBuffer);
1040 
1041 		const std::vector<VkClearValue> clearValues(caseDef.numLayers, getClearValue(caseDef.colorFormat));
1042 
1043 		renderPass.begin(vk, *cmdBuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y()), (deUint32)clearValues.size(), &clearValues[0]);
1044 		{
1045 			const VkDeviceSize vertexBufferOffset = 0ull;
1046 			vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1047 		}
1048 
1049 		for (int layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
1050 		{
1051 			if (layerNdx != 0)
1052 				renderPass.nextSubpass(vk, *cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1053 
1054 			if (isMonolithic)
1055 				vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelinesSp[layerNdx]);
1056 			else
1057 				pipelineWrapper[layerNdx].bind(*cmdBuffer);
1058 			vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
1059 		}
1060 
1061 		renderPass.end(vk, *cmdBuffer);
1062 
1063 		endCommandBuffer(vk, *cmdBuffer);
1064 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1065 	}
1066 }
1067 
1068 namespace SampledImage
1069 {
1070 
1071 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
1072 {
1073 	// Pass 1: Render to texture
1074 
1075 	addSimpleVertexAndFragmentPrograms(programCollection, caseDef);
1076 
1077 	// Pass 2: Sample texture
1078 
1079 	// Vertex shader
1080 	{
1081 		std::ostringstream src;
1082 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1083 			<< "\n"
1084 			<< "layout(location = 0) in  vec4  in_position;\n"
1085 			<< "\n"
1086 			<< "out gl_PerVertex {\n"
1087 			<< "    vec4 gl_Position;\n"
1088 			<< "};\n"
1089 			<< "\n"
1090 			<< "void main(void)\n"
1091 			<< "{\n"
1092 			<< "    gl_Position = in_position;\n"
1093 			<< "}\n";
1094 
1095 		programCollection.glslSources.add("sample_vert") << glu::VertexSource(src.str());
1096 	}
1097 
1098 	// Fragment shader
1099 	{
1100 		const int			numComponents		= tcu::getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order);
1101 		const bool			isUint				= isUintFormat(caseDef.colorFormat);
1102 		const bool			isSint				= isIntFormat(caseDef.colorFormat);
1103 		const std::string	texelFormatStr		= (isUint ? "uvec4" : isSint ? "ivec4" : "vec4");
1104 		const std::string	refClearColor		= getReferenceClearColorStr(caseDef.colorFormat, numComponents, isUint, isSint);
1105 		const std::string	refPrimitiveColor	= getReferencePrimitiveColorStr(numComponents, isUint, isSint);
1106 		const std::string	samplerTypeStr		= getSamplerTypeStr(caseDef.numLayers, isUint, isSint);
1107 
1108 		std::ostringstream src;
1109 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1110 			<< "\n"
1111 			<< "layout(location = 0) out uvec2 o_status;\n"
1112 			<< "\n"
1113 			<< "layout(set = 0, binding = 0) uniform " << samplerTypeStr << " colorTexture;\n"
1114 			<< "\n"
1115 			<< "void main(void)\n"
1116 			<< "{\n"
1117 			<< "    uint clearColorCount = 0;\n"
1118 			<< "    uint primitiveColorCount = 0;\n"
1119 			<< "\n";
1120 
1121 		if (caseDef.numLayers == 1)
1122 			src << "    for (int sampleNdx = 0; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n"
1123 				<< "        " << texelFormatStr << " color = texelFetch(colorTexture, ivec2(gl_FragCoord.xy), sampleNdx);\n"
1124 				<< "        if (color == " << refClearColor << ")\n"
1125 				<< "            ++clearColorCount;\n"
1126 				<< "        else if (color == " << refPrimitiveColor << ")\n"
1127 				<< "            ++primitiveColorCount;\n"
1128 				<< "    }\n";
1129 		else
1130 			src << "    for (int layerNdx = 0; layerNdx < " << caseDef.numLayers << "; ++layerNdx)\n"
1131 				<< "    for (int sampleNdx = 0; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n"
1132 				<< "        " << texelFormatStr << " color = texelFetch(colorTexture, ivec3(gl_FragCoord.xy, layerNdx), sampleNdx);\n"
1133 				<< "        if (color == " << refClearColor << ")\n"
1134 				<< "            ++clearColorCount;\n"
1135 				<< "        else if (color == " << refPrimitiveColor << ")\n"
1136 				<< "            ++primitiveColorCount;\n"
1137 				<< "    }\n";
1138 
1139 		src << "\n"
1140 			<< "    o_status = uvec2(clearColorCount, primitiveColorCount);\n"
1141 			<< "}\n";
1142 
1143 		programCollection.glslSources.add("sample_frag") << glu::FragmentSource(src.str());
1144 	}
1145 }
1146 
1147 void checkSupport (Context& context, const CaseDef caseDef)
1148 {
1149 	const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
1150 
1151 	checkImageFormatRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), caseDef.numSamples, caseDef.colorFormat, colorImageUsage);
1152 	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), caseDef.pipelineConstructionType);
1153 
1154 #ifndef CTS_USES_VULKANSC
1155 	if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
1156 		!context.getPortabilitySubsetFeatures().multisampleArrayImage &&
1157 		(caseDef.numSamples != VK_SAMPLE_COUNT_1_BIT) && (caseDef.numLayers != 1))
1158 	{
1159 		TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Implementation does not support image array with multiple samples per texel");
1160 	}
1161 #endif // CTS_USES_VULKANSC
1162 }
1163 
1164 tcu::TestStatus test (Context& context, const CaseDef caseDef)
1165 {
1166 	const InstanceInterface&	vki					= context.getInstanceInterface();
1167 	const DeviceInterface&		vk					= context.getDeviceInterface();
1168 	const VkPhysicalDevice		physicalDevice		= context.getPhysicalDevice();
1169 	const VkDevice				device				= context.getDevice();
1170 	const VkQueue				queue				= context.getUniversalQueue();
1171 	const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1172 	Allocator&					allocator			= context.getDefaultAllocator();
1173 
1174 	const VkImageUsageFlags		colorImageUsage		= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
1175 
1176 	{
1177 		tcu::TestLog& log = context.getTestContext().getLog();
1178 		log << tcu::LogSection("Description", "")
1179 			<< tcu::TestLog::Message << "Rendering to a multisampled image. Expecting all samples to be either a clear color or a primitive color." << tcu::TestLog::EndMessage
1180 			<< tcu::TestLog::Message << "Sampling from the texture with texelFetch (OpImageFetch)." << tcu::TestLog::EndMessage
1181 			<< tcu::TestLog::EndSection;
1182 	}
1183 
1184 	// Multisampled color image
1185 	const Unique<VkImage>			colorImage		(makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, caseDef.numSamples, colorImageUsage));
1186 	const UniquePtr<Allocation>		colorImageAlloc	(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1187 
1188 	const Unique<VkCommandPool>		cmdPool			(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1189 	const Unique<VkCommandBuffer>	cmdBuffer		(makeCommandBuffer(vk, device, *cmdPool));
1190 
1191 	// Step 1: Render to texture
1192 	{
1193 		renderMultisampledImage(context, caseDef, *colorImage);
1194 	}
1195 
1196 	// Step 2: Sample texture
1197 	{
1198 		// Color image view
1199 		const VkImageViewType			colorImageViewType	= (caseDef.numLayers == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY);
1200 		const Unique<VkImageView>		colorImageView		(makeImageView(vk, device, *colorImage, colorImageViewType, caseDef.colorFormat, makeColorSubresourceRange(0, caseDef.numLayers)));
1201 		const Unique<VkSampler>			colorSampler		(makeSampler(vk, device));
1202 
1203 		// Checksum image
1204 		const VkFormat					checksumFormat		= VK_FORMAT_R8G8_UINT;
1205 		const Unique<VkImage>			checksumImage		(makeImage(vk, device, checksumFormat, caseDef.renderSize, 1u, VK_SAMPLE_COUNT_1_BIT,
1206 																	   VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
1207 		const UniquePtr<Allocation>		checksumImageAlloc	(bindImage(vk, device, allocator, *checksumImage, MemoryRequirement::Any));
1208 		const Unique<VkImageView>		checksumImageView	(makeImageView(vk, device, *checksumImage, VK_IMAGE_VIEW_TYPE_2D, checksumFormat, makeColorSubresourceRange(0, 1)));
1209 
1210 		// Checksum buffer (for host reading)
1211 		const VkDeviceSize				checksumBufferSize	= caseDef.renderSize.x() * caseDef.renderSize.y() * tcu::getPixelSize(mapVkFormat(checksumFormat));
1212 		const Unique<VkBuffer>			checksumBuffer		(makeBuffer(vk, device, checksumBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1213 		const UniquePtr<Allocation>		checksumBufferAlloc	(bindBuffer(vk, device, allocator, *checksumBuffer, MemoryRequirement::HostVisible));
1214 
1215 		zeroBuffer(vk, device, *checksumBufferAlloc, checksumBufferSize);
1216 
1217 		// Vertex buffer
1218 		const std::vector<Vertex4RGBA>	vertices			= genFullQuadVertices();
1219 		const VkDeviceSize				vertexBufferSize	= sizeInBytes(vertices);
1220 		const Unique<VkBuffer>			vertexBuffer		(makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
1221 		const UniquePtr<Allocation>		vertexBufferAlloc	(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
1222 
1223 		{
1224 			deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1225 			flushAlloc(vk, device, *vertexBufferAlloc);
1226 		}
1227 
1228 		// Descriptors
1229 		// \note OpImageFetch doesn't use a sampler, but in GLSL texelFetch needs a sampler2D which translates to a combined image sampler in Vulkan.
1230 
1231 		const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
1232 			.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &colorSampler.get())
1233 			.build(vk, device));
1234 
1235 		const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
1236 			.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1237 			.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1238 
1239 		const Unique<VkDescriptorSet>	descriptorSet		(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1240 		const VkDescriptorImageInfo		imageDescriptorInfo	= makeDescriptorImageInfo(DE_NULL, *colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1241 
1242 		DescriptorSetUpdateBuilder()
1243 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageDescriptorInfo)
1244 			.update(vk, device);
1245 
1246 		const ShaderWrapper						vertexModule	(ShaderWrapper			(vk, device, context.getBinaryCollection().get("sample_vert"), 0u));
1247 		const ShaderWrapper						fragmentModule	(ShaderWrapper			(vk, device, context.getBinaryCollection().get("sample_frag"), 0u));
1248 		RenderPassWrapper						renderPass		(caseDef.pipelineConstructionType, vk, device, checksumFormat);
1249 		renderPass.createFramebuffer(vk, device, 1u, &checksumImage.get(), &checksumImageView.get(), static_cast<deUint32>(caseDef.renderSize.x()),  static_cast<deUint32>(caseDef.renderSize.y()));
1250 		const PipelineLayoutWrapper				pipelineLayout	(caseDef.pipelineConstructionType, vk, device, *descriptorSetLayout);
1251 
1252 		const bool								isMonolithic	(caseDef.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC);
1253 		std::vector<PipelineSp>					pipelinesSp;
1254 		std::vector<GraphicsPipelineWrapper>	pipelineWrapper;
1255 
1256 		if (isMonolithic)
1257 		{
1258 			pipelinesSp = makeGraphicsPipelines(vk, device, 1u, *pipelineLayout, *renderPass, vertexModule, fragmentModule,
1259 												caseDef.renderSize, VK_SAMPLE_COUNT_1_BIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
1260 		}
1261 		else
1262 		{
1263 			pipelineWrapper.emplace_back(vki, vk, physicalDevice, device, context.getDeviceExtensions(), caseDef.pipelineConstructionType);
1264 			preparePipelineWrapper(pipelineWrapper.back(), 0u, pipelineLayout, *renderPass, vertexModule, fragmentModule,
1265 								   caseDef.renderSize, VK_SAMPLE_COUNT_1_BIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
1266 		}
1267 
1268 		beginCommandBuffer(vk, *cmdBuffer);
1269 
1270 		// Prepare for sampling in the fragment shader
1271 		{
1272 			const VkImageMemoryBarrier barriers[] =
1273 			{
1274 				{
1275 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,						// VkStructureType			sType;
1276 					DE_NULL,													// const void*				pNext;
1277 					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,						// VkAccessFlags			outputMask;
1278 					VK_ACCESS_SHADER_READ_BIT,									// VkAccessFlags			inputMask;
1279 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,					// VkImageLayout			oldLayout;
1280 					VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,					// VkImageLayout			newLayout;
1281 					VK_QUEUE_FAMILY_IGNORED,									// deUint32					srcQueueFamilyIndex;
1282 					VK_QUEUE_FAMILY_IGNORED,									// deUint32					destQueueFamilyIndex;
1283 					*colorImage,												// VkImage					image;
1284 					makeColorSubresourceRange(0, caseDef.numLayers),			// VkImageSubresourceRange	subresourceRange;
1285 				},
1286 			};
1287 
1288 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
1289 				0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1290 		}
1291 
1292 		renderPass.begin(vk, *cmdBuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y()), tcu::UVec4(0u));
1293 
1294 		if (isMonolithic)
1295 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelinesSp.back());
1296 		else
1297 			pipelineWrapper.back().bind(*cmdBuffer);
1298 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1299 		{
1300 			const VkDeviceSize vertexBufferOffset = 0ull;
1301 			vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1302 		}
1303 
1304 		vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
1305 		renderPass.end(vk, *cmdBuffer);
1306 
1307 		copyImageToBuffer(vk, *cmdBuffer, *checksumImage, *checksumBuffer, caseDef.renderSize);
1308 
1309 		endCommandBuffer(vk, *cmdBuffer);
1310 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1311 
1312 		// Verify result
1313 
1314 		{
1315 			invalidateAlloc(vk, device, *checksumBufferAlloc);
1316 
1317 			const tcu::ConstPixelBufferAccess	access						(mapVkFormat(checksumFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), 1, checksumBufferAlloc->getHostPtr());
1318 			const deUint32						numExpectedChecksum			= getNumSamples(caseDef.numSamples) * caseDef.numLayers;
1319 			bool								multipleColorsPerTexelFound	= false;
1320 
1321 			for (int y = 0; y < caseDef.renderSize.y(); ++y)
1322 			for (int x = 0; x < caseDef.renderSize.x(); ++x)
1323 			{
1324 				deUint32 clearColorCount		= access.getPixelUint(x, y).x();
1325 				deUint32 primitiveColorCount	= access.getPixelUint(x, y).y();
1326 
1327 				if ((clearColorCount + primitiveColorCount) != numExpectedChecksum)
1328 					return tcu::TestStatus::fail("Some samples have incorrect color");
1329 
1330 				if ((clearColorCount > 0) && (primitiveColorCount > 0))
1331 					multipleColorsPerTexelFound = true;
1332 			}
1333 
1334 			// For a multisampled image, we are expecting some texels to have samples of both clear color and primitive color
1335 			if (!multipleColorsPerTexelFound)
1336 				return tcu::TestStatus::fail("Could not find texels with samples of both clear color and primitive color");
1337 		}
1338 	}
1339 
1340 	return tcu::TestStatus::pass("OK");
1341 }
1342 
1343 } // SampledImage ns
1344 
1345 namespace StorageImage
1346 {
1347 
1348 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
1349 {
1350 	// Vertex & fragment
1351 
1352 	addSimpleVertexAndFragmentPrograms(programCollection, caseDef);
1353 
1354 	// Compute
1355 	{
1356 		const std::string	imageTypeStr		= getShaderMultisampledImageType(mapVkFormat(caseDef.colorFormat), caseDef.numLayers);
1357 		const std::string	formatQualifierStr	= getShaderImageFormatQualifier(mapVkFormat(caseDef.colorFormat));
1358 		const std::string	signednessPrefix	= isUintFormat(caseDef.colorFormat) ? "u" : isIntFormat(caseDef.colorFormat) ? "i" : "";
1359 		const std::string	gvec4Expr			= signednessPrefix + "vec4";
1360 		const std::string	texelCoordStr		= (caseDef.numLayers == 1 ? "ivec2(gx, gy)" : "ivec3(gx, gy, gz)");
1361 
1362 		std::ostringstream src;
1363 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1364 			<< "layout(local_size_x = 1) in;\n"
1365 			<< "layout(set = 0, binding = 0, " << formatQualifierStr << ") uniform " << imageTypeStr << " u_msImage;\n"
1366 			<< "\n"
1367 			<< "void main(void)\n"
1368 			<< "{\n"
1369 			<< "    int gx = int(gl_GlobalInvocationID.x);\n"
1370 			<< "    int gy = int(gl_GlobalInvocationID.y);\n"
1371 			<< "    int gz = int(gl_GlobalInvocationID.z);\n"
1372 			<< "\n"
1373 			<< "    " << gvec4Expr << " prevColor = imageLoad(u_msImage, " << texelCoordStr << ", 0);\n"
1374 			<< "    for (int sampleNdx = 1; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n"
1375 			<< "        " << gvec4Expr << " color = imageLoad(u_msImage, " << texelCoordStr << ", sampleNdx);\n"
1376 			<< "        imageStore(u_msImage, " << texelCoordStr <<", sampleNdx, prevColor);\n"
1377 			<< "        prevColor = color;\n"
1378 			<< "    }\n"
1379 			<< "    imageStore(u_msImage, " << texelCoordStr <<", 0, prevColor);\n"
1380 			<< "}\n";
1381 
1382 		programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
1383 	}
1384 }
1385 
1386 //! Render a MS image, resolve it, and copy result to resolveBuffer.
1387 void renderAndResolve (Context& context, const CaseDef& caseDef, const VkBuffer resolveBuffer, const bool useComputePass)
1388 {
1389 	const DeviceInterface&		vk					= context.getDeviceInterface();
1390 	const VkDevice				device				= context.getDevice();
1391 	const VkQueue				queue				= context.getUniversalQueue();
1392 	const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1393 	Allocator&					allocator			= context.getDefaultAllocator();
1394 
1395 	// Multisampled color image
1396 	const Unique<VkImage>			colorImage			(makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, caseDef.numSamples,
1397 																   VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT));
1398 	const UniquePtr<Allocation>		colorImageAlloc		(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1399 
1400 	const Unique<VkImage>			resolveImage		(makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, VK_SAMPLE_COUNT_1_BIT,
1401 																   VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT));
1402 	const UniquePtr<Allocation>		resolveImageAlloc	(bindImage(vk, device, allocator, *resolveImage, MemoryRequirement::Any));
1403 
1404 	const Unique<VkCommandPool>		cmdPool				(createCommandPool  (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1405 	const Unique<VkCommandBuffer>	cmdBuffer			(makeCommandBuffer(vk, device, *cmdPool));
1406 
1407 	// Working image barrier, we change it based on which rendering stages were executed so far.
1408 	VkImageMemoryBarrier colorImageBarrier =
1409 	{
1410 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,						// VkStructureType			sType;
1411 		DE_NULL,													// const void*				pNext;
1412 		(VkAccessFlags)0,											// VkAccessFlags			outputMask;
1413 		(VkAccessFlags)0,											// VkAccessFlags			inputMask;
1414 		VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout			oldLayout;
1415 		VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout			newLayout;
1416 		VK_QUEUE_FAMILY_IGNORED,									// deUint32					srcQueueFamilyIndex;
1417 		VK_QUEUE_FAMILY_IGNORED,									// deUint32					destQueueFamilyIndex;
1418 		*colorImage,												// VkImage					image;
1419 		makeColorSubresourceRange(0, caseDef.numLayers),			// VkImageSubresourceRange	subresourceRange;
1420 	};
1421 
1422 	// Pass 1: Render an image
1423 	{
1424 		renderMultisampledImage(context, caseDef, *colorImage);
1425 
1426 		colorImageBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1427 		colorImageBarrier.oldLayout		= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1428 	}
1429 
1430 	// Pass 2: Compute shader
1431 	if (useComputePass)
1432 	{
1433 		// Descriptors
1434 
1435 		Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
1436 			.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1437 			.build(vk, device));
1438 
1439 		Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
1440 			.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u)
1441 			.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1442 
1443 		const Unique<VkImageView>		colorImageView		(makeImageView(vk, device, *colorImage,
1444 																			(caseDef.numLayers == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY),
1445 																			caseDef.colorFormat, makeColorSubresourceRange(0, caseDef.numLayers)));
1446 		const Unique<VkDescriptorSet>	descriptorSet		(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1447 		const VkDescriptorImageInfo		descriptorImageInfo	= makeDescriptorImageInfo(DE_NULL, *colorImageView, VK_IMAGE_LAYOUT_GENERAL);
1448 
1449 		DescriptorSetUpdateBuilder()
1450 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
1451 			.update(vk, device);
1452 
1453 		const Unique<VkPipelineLayout>	pipelineLayout	(makePipelineLayout	(vk, device, *descriptorSetLayout));
1454 		const Unique<VkShaderModule>	shaderModule	(createShaderModule	(vk, device, context.getBinaryCollection().get("comp"), 0));
1455 		const Unique<VkPipeline>		pipeline		(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
1456 
1457 		beginCommandBuffer(vk, *cmdBuffer);
1458 
1459 		// Image layout for load/stores
1460 		{
1461 			colorImageBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
1462 			colorImageBarrier.newLayout		= VK_IMAGE_LAYOUT_GENERAL;
1463 
1464 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1465 				0u, DE_NULL, 0u, DE_NULL, 1u, &colorImageBarrier);
1466 
1467 			colorImageBarrier.srcAccessMask = colorImageBarrier.dstAccessMask;
1468 			colorImageBarrier.oldLayout		= colorImageBarrier.newLayout;
1469 		}
1470 		// Dispatch
1471 		{
1472 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
1473 			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1474 			vk.cmdDispatch(*cmdBuffer, caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers);
1475 		}
1476 
1477 		endCommandBuffer(vk, *cmdBuffer);
1478 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1479 	}
1480 
1481 	// Resolve and verify the image
1482 	{
1483 		beginCommandBuffer(vk, *cmdBuffer);
1484 
1485 		// Prepare for resolve
1486 		{
1487 			colorImageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1488 			colorImageBarrier.newLayout		= VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
1489 
1490 			const VkImageMemoryBarrier	barriers[]		=
1491 			{
1492 				colorImageBarrier,
1493 				{
1494 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,						// VkStructureType			sType;
1495 					DE_NULL,													// const void*				pNext;
1496 					(VkAccessFlags)0,											// VkAccessFlags			outputMask;
1497 					VK_ACCESS_TRANSFER_WRITE_BIT,								// VkAccessFlags			inputMask;
1498 					VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout			oldLayout;
1499 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,						// VkImageLayout			newLayout;
1500 					VK_QUEUE_FAMILY_IGNORED,									// deUint32					srcQueueFamilyIndex;
1501 					VK_QUEUE_FAMILY_IGNORED,									// deUint32					destQueueFamilyIndex;
1502 					*resolveImage,												// VkImage					image;
1503 					makeColorSubresourceRange(0, caseDef.numLayers),			// VkImageSubresourceRange	subresourceRange;
1504 				},
1505 			};
1506 
1507 			const VkPipelineStageFlags	srcStageMask	= (colorImageBarrier.srcAccessMask == VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)
1508 														? VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
1509 														: VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
1510 
1511 			vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1512 				0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1513 
1514 			colorImageBarrier.srcAccessMask = colorImageBarrier.dstAccessMask;
1515 			colorImageBarrier.oldLayout		= colorImageBarrier.newLayout;
1516 		}
1517 		// Resolve the image
1518 		{
1519 			const VkImageResolve resolveRegion =
1520 			{
1521 				makeColorSubresourceLayers(0, caseDef.numLayers),					// VkImageSubresourceLayers    srcSubresource;
1522 				makeOffset3D(0, 0, 0),												// VkOffset3D                  srcOffset;
1523 				makeColorSubresourceLayers(0, caseDef.numLayers),					// VkImageSubresourceLayers    dstSubresource;
1524 				makeOffset3D(0, 0, 0),												// VkOffset3D                  dstOffset;
1525 				makeExtent3D(caseDef.renderSize.x(), caseDef.renderSize.y(), 1u),	// VkExtent3D                  extent;
1526 			};
1527 
1528 			vk.cmdResolveImage(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *resolveImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &resolveRegion);
1529 		}
1530 
1531 		copyImageToBuffer(vk, *cmdBuffer, *resolveImage, resolveBuffer, caseDef.renderSize, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, caseDef.numLayers);
1532 
1533 		endCommandBuffer(vk, *cmdBuffer);
1534 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1535 	}
1536 }
1537 
1538 //! Exact image compare, but allow for some error when color format is integer.
1539 bool compareImages (tcu::TestLog& log, const CaseDef& caseDef, const tcu::ConstPixelBufferAccess layeredReferenceImage, const tcu::ConstPixelBufferAccess layeredActualImage)
1540 {
1541 	DE_ASSERT(caseDef.numSamples > 1);
1542 
1543 	const Vec4	goodColor			= Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1544 	const Vec4	badColor			= Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1545 	const bool	isAnyIntFormat		= isIntFormat(caseDef.colorFormat) || isUintFormat(caseDef.colorFormat);
1546 
1547 	// 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.
1548 	const int	badPixelTolerance	= (isAnyIntFormat ? 2 * caseDef.renderSize.x() : 0);
1549 	int			goodLayers			= 0;
1550 
1551 	for (int layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
1552 	{
1553 		const tcu::ConstPixelBufferAccess	referenceImage	= tcu::getSubregion(layeredReferenceImage, 0, 0, layerNdx, caseDef.renderSize.x(), caseDef.renderSize.y(), 1);
1554 		const tcu::ConstPixelBufferAccess	actualImage		= tcu::getSubregion(layeredActualImage, 0, 0, layerNdx, caseDef.renderSize.x(), caseDef.renderSize.y(), 1);
1555 		const std::string					imageName		= "color layer " + de::toString(layerNdx);
1556 
1557 		tcu::TextureLevel		errorMaskStorage	(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), caseDef.renderSize.x(), caseDef.renderSize.y());
1558 		tcu::PixelBufferAccess	errorMask			= errorMaskStorage.getAccess();
1559 		int						numBadPixels		= 0;
1560 
1561 		for (int y = 0; y < caseDef.renderSize.y(); ++y)
1562 		for (int x = 0; x < caseDef.renderSize.x(); ++x)
1563 		{
1564 			if (isAnyIntFormat && (referenceImage.getPixelInt(x, y) == actualImage.getPixelInt(x, y)))
1565 				errorMask.setPixel(goodColor, x, y);
1566 			else if (referenceImage.getPixel(x, y) == actualImage.getPixel(x, y))
1567 				errorMask.setPixel(goodColor, x, y);
1568 			else
1569 			{
1570 				++numBadPixels;
1571 				errorMask.setPixel(badColor, x, y);
1572 			}
1573 		}
1574 
1575 		if (numBadPixels <= badPixelTolerance)
1576 		{
1577 			++goodLayers;
1578 
1579 			log << tcu::TestLog::ImageSet(imageName, imageName)
1580 				<< tcu::TestLog::Image("Result",	"Result",		actualImage)
1581 				<< tcu::TestLog::EndImageSet;
1582 		}
1583 		else
1584 		{
1585 			log << tcu::TestLog::ImageSet(imageName, imageName)
1586 				<< tcu::TestLog::Image("Result",	"Result",		actualImage)
1587 				<< tcu::TestLog::Image("Reference",	"Reference",	referenceImage)
1588 				<< tcu::TestLog::Image("ErrorMask",	"Error mask",	errorMask)
1589 				<< tcu::TestLog::EndImageSet;
1590 		}
1591 	}
1592 
1593 	if (goodLayers == caseDef.numLayers)
1594 	{
1595 		log << tcu::TestLog::Message << "All rendered images are correct." << tcu::TestLog::EndMessage;
1596 		return true;
1597 	}
1598 	else
1599 	{
1600 		log << tcu::TestLog::Message << "FAILED: Some rendered images were incorrect." << tcu::TestLog::EndMessage;
1601 		return false;
1602 	}
1603 }
1604 
1605 void checkSupport (Context& context, const CaseDef caseDef)
1606 {
1607 	const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
1608 
1609 	checkImageFormatRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), caseDef.numSamples, caseDef.colorFormat, colorImageUsage);
1610 	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), caseDef.pipelineConstructionType);
1611 }
1612 
1613 tcu::TestStatus test (Context& context, const CaseDef caseDef)
1614 {
1615 	const DeviceInterface&		vk					= context.getDeviceInterface();
1616 	const VkDevice				device				= context.getDevice();
1617 	Allocator&					allocator			= context.getDefaultAllocator();
1618 
1619 	{
1620 		tcu::TestLog& log = context.getTestContext().getLog();
1621 		log << tcu::LogSection("Description", "")
1622 			<< tcu::TestLog::Message << "Rendering to a multisampled image. Image will be processed with a compute shader using OpImageRead and OpImageWrite." << tcu::TestLog::EndMessage
1623 			<< 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
1624 			<< tcu::TestLog::EndSection;
1625 	}
1626 
1627 	// Host-readable buffer
1628 	const VkDeviceSize				resolveBufferSize			= caseDef.renderSize.x() * caseDef.renderSize.y() * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat));
1629 	const Unique<VkBuffer>			resolveImageOneBuffer		(makeBuffer(vk, device, resolveBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1630 	const UniquePtr<Allocation>		resolveImageOneBufferAlloc	(bindBuffer(vk, device, allocator, *resolveImageOneBuffer, MemoryRequirement::HostVisible));
1631 	const Unique<VkBuffer>			resolveImageTwoBuffer		(makeBuffer(vk, device, resolveBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1632 	const UniquePtr<Allocation>		resolveImageTwoBufferAlloc	(bindBuffer(vk, device, allocator, *resolveImageTwoBuffer, MemoryRequirement::HostVisible));
1633 
1634 	zeroBuffer(vk, device, *resolveImageOneBufferAlloc, resolveBufferSize);
1635 	zeroBuffer(vk, device, *resolveImageTwoBufferAlloc, resolveBufferSize);
1636 
1637 	// Render: repeat the same rendering twice to avoid non-essential API calls and layout transitions (e.g. copy).
1638 	{
1639 		renderAndResolve(context, caseDef, *resolveImageOneBuffer, false);	// Pass 1: render a basic multisampled image
1640 		renderAndResolve(context, caseDef, *resolveImageTwoBuffer, true);	// Pass 2: the same but altered with a compute shader
1641 	}
1642 
1643 	// Verify
1644 	{
1645 		invalidateAlloc(vk, device, *resolveImageOneBufferAlloc);
1646 		invalidateAlloc(vk, device, *resolveImageTwoBufferAlloc);
1647 
1648 		const tcu::PixelBufferAccess		layeredImageOne	(mapVkFormat(caseDef.colorFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers, resolveImageOneBufferAlloc->getHostPtr());
1649 		const tcu::ConstPixelBufferAccess	layeredImageTwo	(mapVkFormat(caseDef.colorFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers, resolveImageTwoBufferAlloc->getHostPtr());
1650 
1651 		// Check all layers
1652 		if (!compareImages(context.getTestContext().getLog(), caseDef, layeredImageOne, layeredImageTwo))
1653 			return tcu::TestStatus::fail("Rendered images are not correct");
1654 	}
1655 
1656 	return tcu::TestStatus::pass("OK");
1657 }
1658 
1659 } // StorageImage ns
1660 
1661 
1662 namespace StandardSamplePosition
1663 {
1664 
1665 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
1666 {
1667 	// Pass 1: Render to texture
1668 
1669 	addSimpleVertexAndFragmentPrograms(programCollection, caseDef);
1670 
1671 	// Pass 2: Sample texture
1672 
1673 	// Vertex shader
1674 	{
1675 		std::ostringstream src;
1676 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1677 			<< "\n"
1678 			<< "layout(location = 0) in  vec4  in_position;\n"
1679 			<< "\n"
1680 			<< "out gl_PerVertex {\n"
1681 			<< "    vec4 gl_Position;\n"
1682 			<< "};\n"
1683 			<< "\n"
1684 			<< "void main(void)\n"
1685 			<< "{\n"
1686 			<< "    gl_Position = in_position;\n"
1687 			<< "}\n";
1688 
1689 		programCollection.glslSources.add("sample_vert") << glu::VertexSource(src.str());
1690 	}
1691 
1692 	// Fragment shader
1693 	{
1694 		std::ostringstream src;
1695 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1696 			<< "\n"
1697 			<< "layout(location = 0) out uint o_status;\n"
1698 			<< "\n"
1699 			<< "layout(set = 0, binding = 0) uniform sampler2DMS colorTexture;\n"
1700 			<< "\n"
1701 			<< "void main(void)\n"
1702 			<< "{\n"
1703 			<< "    uint result = 0;\n"
1704 			<< "    vec4 a, b;\n\n"
1705 			<< "\n";
1706 
1707 		for (deUint32 sampleNdx = 0; sampleNdx < (deUint32)caseDef.numSamples; sampleNdx++)
1708 		{
1709 			Vec4 expectedColor = sampleIndexToColor(sampleNdx);
1710 
1711 			src << "    a = texelFetch(colorTexture, ivec2(0,0), " << sampleNdx << ");\n"
1712 				   "    b = vec4(" << expectedColor.x() << ", " << expectedColor.y() << ", " << expectedColor.z() << ", 1.0);\n"
1713 				   "    if (abs(a.x - b.x) > 0.1 || abs(a.y - b.y) > 0.1 || abs(a.z - b.z) > 0.1) result++;\n";
1714 		}
1715 
1716 		src << "\n"
1717 			<< "    o_status = result;\n"
1718 			<< "}\n";
1719 
1720 		programCollection.glslSources.add("sample_frag") << glu::FragmentSource(src.str());
1721 	}
1722 }
1723 
1724 void checkSupport (Context& context, const CaseDef caseDef)
1725 {
1726 	const VkImageUsageFlags colorImageUsage		= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
1727 	const VkPhysicalDeviceProperties props		= getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice());
1728 
1729 	checkImageFormatRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), caseDef.numSamples, caseDef.colorFormat, colorImageUsage);
1730 
1731 	if (!props.limits.standardSampleLocations)
1732 		TCU_THROW(NotSupportedError, "Device does not support standard sample locations.");
1733 
1734 	if (caseDef.numSamples == VK_SAMPLE_COUNT_32_BIT ||
1735 		caseDef.numSamples == VK_SAMPLE_COUNT_64_BIT)
1736 	{
1737 		TCU_THROW(InternalError, "Standard does not define sample positions for 32x or 64x multisample modes");
1738 	}
1739 
1740 	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), caseDef.pipelineConstructionType);
1741 }
1742 
1743 tcu::TestStatus test (Context& context, const CaseDef caseDef)
1744 {
1745 	const InstanceInterface&	vki					= context.getInstanceInterface();
1746 	const DeviceInterface&		vk					= context.getDeviceInterface();
1747 	const VkPhysicalDevice		physicalDevice		= context.getPhysicalDevice();
1748 	const VkDevice				device				= context.getDevice();
1749 	const VkQueue				queue				= context.getUniversalQueue();
1750 	const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1751 	Allocator&					allocator			= context.getDefaultAllocator();
1752 
1753 	const VkImageUsageFlags		colorImageUsage		= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
1754 
1755 	{
1756 		tcu::TestLog& log = context.getTestContext().getLog();
1757 		log << tcu::LogSection("Description", "")
1758 			<< tcu::TestLog::Message << "Rendering to a multisampled image. Expecting samples to have specified colors." << tcu::TestLog::EndMessage
1759 			<< tcu::TestLog::Message << "Sampling from the texture with texelFetch (OpImageFetch)." << tcu::TestLog::EndMessage
1760 			<< tcu::TestLog::EndSection;
1761 	}
1762 
1763 	// Multisampled color image
1764 	const Unique<VkImage>			colorImage		(makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, caseDef.numSamples, colorImageUsage));
1765 	const UniquePtr<Allocation>		colorImageAlloc	(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1766 
1767 	const Unique<VkCommandPool>		cmdPool			(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1768 	const Unique<VkCommandBuffer>	cmdBuffer		(makeCommandBuffer(vk, device, *cmdPool));
1769 
1770 	// Step 1: Render to texture
1771 	{
1772 		renderMultisampledImage(context, caseDef, *colorImage);
1773 	}
1774 
1775 	// Step 2: Sample texture
1776 	{
1777 		// Color image view
1778 		const VkImageViewType			colorImageViewType	= (caseDef.numLayers == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY);
1779 		const Unique<VkImageView>		colorImageView		(makeImageView(vk, device, *colorImage, colorImageViewType, caseDef.colorFormat, makeColorSubresourceRange(0, caseDef.numLayers)));
1780 		const Unique<VkSampler>			colorSampler		(makeSampler(vk, device));
1781 
1782 		// Checksum image
1783 		const VkFormat					checksumFormat		= VK_FORMAT_R8_UINT;
1784 		const Unique<VkImage>			checksumImage		(makeImage(vk, device, checksumFormat, caseDef.renderSize, 1u, VK_SAMPLE_COUNT_1_BIT,
1785 																	   VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
1786 		const UniquePtr<Allocation>		checksumImageAlloc	(bindImage(vk, device, allocator, *checksumImage, MemoryRequirement::Any));
1787 		const Unique<VkImageView>		checksumImageView	(makeImageView(vk, device, *checksumImage, VK_IMAGE_VIEW_TYPE_2D, checksumFormat, makeColorSubresourceRange(0, 1)));
1788 
1789 		// Checksum buffer (for host reading)
1790 		const VkDeviceSize				checksumBufferSize	= caseDef.renderSize.x() * caseDef.renderSize.y() * tcu::getPixelSize(mapVkFormat(checksumFormat));
1791 		const Unique<VkBuffer>			checksumBuffer		(makeBuffer(vk, device, checksumBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1792 		const UniquePtr<Allocation>		checksumBufferAlloc	(bindBuffer(vk, device, allocator, *checksumBuffer, MemoryRequirement::HostVisible));
1793 
1794 		zeroBuffer(vk, device, *checksumBufferAlloc, checksumBufferSize);
1795 
1796 		// Vertex buffer
1797 		const std::vector<Vertex4RGBA>	vertices			= genFullQuadVertices();
1798 		const VkDeviceSize				vertexBufferSize	= sizeInBytes(vertices);
1799 		const Unique<VkBuffer>			vertexBuffer		(makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
1800 		const UniquePtr<Allocation>		vertexBufferAlloc	(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
1801 
1802 		{
1803 			deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1804 			flushAlloc(vk, device, *vertexBufferAlloc);
1805 		}
1806 
1807 		// Descriptors
1808 		// \note OpImageFetch doesn't use a sampler, but in GLSL texelFetch needs a sampler2D which translates to a combined image sampler in Vulkan.
1809 
1810 		const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
1811 			.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &colorSampler.get())
1812 			.build(vk, device));
1813 
1814 		const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
1815 			.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1816 			.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1817 
1818 		const Unique<VkDescriptorSet>	descriptorSet		(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1819 		const VkDescriptorImageInfo		imageDescriptorInfo	= makeDescriptorImageInfo(DE_NULL, *colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1820 
1821 		DescriptorSetUpdateBuilder()
1822 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageDescriptorInfo)
1823 			.update(vk, device);
1824 
1825 		const ShaderWrapper						vertexModule	(ShaderWrapper			(vk, device, context.getBinaryCollection().get("sample_vert"), 0u));
1826 		const ShaderWrapper						fragmentModule	(ShaderWrapper			(vk, device, context.getBinaryCollection().get("sample_frag"), 0u));
1827 		RenderPassWrapper						renderPass		(makeSimpleRenderPass	(vk, device, caseDef.pipelineConstructionType, checksumFormat));
1828 		renderPass.createFramebuffer(vk, device, 1u, &checksumImage.get(), &checksumImageView.get(), static_cast<deUint32>(caseDef.renderSize.x()),  static_cast<deUint32>(caseDef.renderSize.y()));
1829 		const PipelineLayoutWrapper				pipelineLayout	(caseDef.pipelineConstructionType, vk, device, *descriptorSetLayout);
1830 		const bool								isMonolithic	(caseDef.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC);
1831 		std::vector<PipelineSp>					pipelinesSp;
1832 		std::vector<GraphicsPipelineWrapper>	pipelineWrapper;
1833 
1834 		if (isMonolithic)
1835 		{
1836 			pipelinesSp = makeGraphicsPipelines(vk, device, 1u, *pipelineLayout, *renderPass, vertexModule, fragmentModule,
1837 												caseDef.renderSize, VK_SAMPLE_COUNT_1_BIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
1838 		}
1839 		else
1840 		{
1841 			pipelineWrapper.emplace_back(vki, vk, physicalDevice, device, context.getDeviceExtensions(), caseDef.pipelineConstructionType);
1842 			preparePipelineWrapper(pipelineWrapper.back(), 0u, pipelineLayout, *renderPass, vertexModule, fragmentModule,
1843 								   caseDef.renderSize, VK_SAMPLE_COUNT_1_BIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
1844 		}
1845 
1846 		beginCommandBuffer(vk, *cmdBuffer);
1847 
1848 		// Prepare for sampling in the fragment shader
1849 		{
1850 			const VkImageMemoryBarrier barriers[] =
1851 			{
1852 				{
1853 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,						// VkStructureType			sType;
1854 					DE_NULL,													// const void*				pNext;
1855 					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,						// VkAccessFlags			outputMask;
1856 					VK_ACCESS_SHADER_READ_BIT,									// VkAccessFlags			inputMask;
1857 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,					// VkImageLayout			oldLayout;
1858 					VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,					// VkImageLayout			newLayout;
1859 					VK_QUEUE_FAMILY_IGNORED,									// deUint32					srcQueueFamilyIndex;
1860 					VK_QUEUE_FAMILY_IGNORED,									// deUint32					destQueueFamilyIndex;
1861 					*colorImage,												// VkImage					image;
1862 					makeColorSubresourceRange(0, caseDef.numLayers),			// VkImageSubresourceRange	subresourceRange;
1863 				},
1864 			};
1865 
1866 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
1867 				0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1868 		}
1869 
1870 		renderPass.begin(vk, *cmdBuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y()), tcu::UVec4(0u));
1871 
1872 		if (isMonolithic)
1873 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelinesSp.back());
1874 		else
1875 			pipelineWrapper.back().bind(*cmdBuffer);
1876 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1877 		{
1878 			const VkDeviceSize vertexBufferOffset = 0ull;
1879 			vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1880 		}
1881 
1882 		vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
1883 		renderPass.end(vk, *cmdBuffer);
1884 
1885 		copyImageToBuffer(vk, *cmdBuffer, *checksumImage, *checksumBuffer, caseDef.renderSize);
1886 
1887 		endCommandBuffer(vk, *cmdBuffer);
1888 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1889 
1890 		// Verify result
1891 
1892 		{
1893 			invalidateAlloc(vk, device, *checksumBufferAlloc);
1894 
1895 			const tcu::ConstPixelBufferAccess	access						(mapVkFormat(checksumFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), 1, checksumBufferAlloc->getHostPtr());
1896 
1897 			deUint32 result		= access.getPixelUint(0, 0).x();
1898 
1899 			if (result)
1900 				return tcu::TestStatus::fail(std::to_string(result) + " multisamples have unexpected color.");
1901 		}
1902 	}
1903 
1904 	return tcu::TestStatus::pass("OK");
1905 }
1906 
1907 } // StandardSamplePosition ns
1908 
1909 
1910 std::string getSizeLayerString (const IVec2& size, const int numLayers)
1911 {
1912 	std::ostringstream str;
1913 	str << size.x() << "x" << size.y() << "_" << numLayers;
1914 	return str.str();
1915 }
1916 
1917 std::string getFormatString (const VkFormat format)
1918 {
1919 	std::string name(getFormatName(format));
1920 	return de::toLower(name.substr(10));
1921 }
1922 
1923 void addTestCasesWithFunctions (tcu::TestCaseGroup*						group,
1924 								FunctionSupport1<CaseDef>::Function		checkSupport,
1925 								FunctionPrograms1<CaseDef>::Function	initPrograms,
1926 								FunctionInstance1<CaseDef>::Function	testFunc,
1927 								PipelineConstructionType				pipelineConstructionType)
1928 {
1929 	const IVec2 size[] =
1930 	{
1931 		IVec2(64, 64),
1932 		IVec2(79, 31),
1933 	};
1934 	const int numLayers[] =
1935 	{
1936 		1, 4
1937 	};
1938 	const VkSampleCountFlagBits samples[] =
1939 	{
1940 		VK_SAMPLE_COUNT_2_BIT,
1941 		VK_SAMPLE_COUNT_4_BIT,
1942 		VK_SAMPLE_COUNT_8_BIT,
1943 		VK_SAMPLE_COUNT_16_BIT,
1944 		VK_SAMPLE_COUNT_32_BIT,
1945 		VK_SAMPLE_COUNT_64_BIT,
1946 	};
1947 	const VkFormat format[] =
1948 	{
1949 		VK_FORMAT_R8G8B8A8_UNORM,
1950 		VK_FORMAT_R32_UINT,
1951 		VK_FORMAT_R16G16_SINT,
1952 		VK_FORMAT_R32G32B32A32_SFLOAT,
1953 	};
1954 
1955 	for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(size); ++sizeNdx)
1956 	for (int layerNdx = 0; layerNdx < DE_LENGTH_OF_ARRAY(numLayers); ++layerNdx)
1957 	{
1958 		MovePtr<tcu::TestCaseGroup>	sizeLayerGroup(new tcu::TestCaseGroup(group->getTestContext(), getSizeLayerString(size[sizeNdx], numLayers[layerNdx]).c_str()));
1959 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(format); ++formatNdx)
1960 		{
1961 			MovePtr<tcu::TestCaseGroup>	formatGroup(new tcu::TestCaseGroup(group->getTestContext(), getFormatString(format[formatNdx]).c_str()));
1962 			for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); ++samplesNdx)
1963 			{
1964 				std::ostringstream caseName;
1965 				caseName << "samples_" << getNumSamples(samples[samplesNdx]);
1966 
1967 				const CaseDef caseDef
1968 				{
1969 					pipelineConstructionType,	// PipelineConstructionType	pipelineConstructionType;
1970 					size[sizeNdx],				// IVec2					renderSize;
1971 					numLayers[layerNdx],		// int						numLayers;
1972 					format[formatNdx],			// VkFormat					colorFormat;
1973 					samples[samplesNdx],		// VkSampleCountFlagBits	numSamples;
1974 					false,						// bool						colorQuad;
1975 				};
1976 
1977 				addFunctionCaseWithPrograms(formatGroup.get(), caseName.str(), checkSupport, initPrograms, testFunc, caseDef);
1978 			}
1979 			sizeLayerGroup->addChild(formatGroup.release());
1980 		}
1981 		group->addChild(sizeLayerGroup.release());
1982 	}
1983 }
1984 
1985 void addStandardSamplePositionTestCasesWithFunctions (tcu::TestCaseGroup*					group,
1986 													  FunctionSupport1<CaseDef>::Function	checkSupport,
1987 													  FunctionPrograms1<CaseDef>::Function	initPrograms,
1988 													  FunctionInstance1<CaseDef>::Function	testFunc,
1989 													  PipelineConstructionType				pipelineConstructionType)
1990 {
1991 	const VkSampleCountFlagBits samples[] =
1992 	{
1993 		VK_SAMPLE_COUNT_2_BIT,
1994 		VK_SAMPLE_COUNT_4_BIT,
1995 		VK_SAMPLE_COUNT_8_BIT,
1996 		VK_SAMPLE_COUNT_16_BIT,
1997 		VK_SAMPLE_COUNT_32_BIT,
1998 		VK_SAMPLE_COUNT_64_BIT,
1999 	};
2000 	const VkFormat format[] =
2001 	{
2002 		VK_FORMAT_R8G8B8A8_UNORM,
2003 		VK_FORMAT_R32G32B32A32_SFLOAT,
2004 	};
2005 
2006 	for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(format); ++formatNdx)
2007 	{
2008 		MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(group->getTestContext(), getFormatString(format[formatNdx]).c_str()));
2009 		for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); ++samplesNdx)
2010 		{
2011 			std::ostringstream caseName;
2012 			caseName << "samples_" << getNumSamples(samples[samplesNdx]);
2013 
2014 			const CaseDef caseDef
2015 			{
2016 				pipelineConstructionType,	// PipelineConstructionType	pipelineConstructionType;
2017 				IVec2(1,1),					// IVec2					renderSize;
2018 				1,							// int						numLayers;
2019 				format[formatNdx],			// VkFormat					colorFormat;
2020 				samples[samplesNdx],		// VkSampleCountFlagBits	numSamples;
2021 				true,						// bool						colorQuad;
2022 			};
2023 
2024 			addFunctionCaseWithPrograms(formatGroup.get(), caseName.str(), checkSupport, initPrograms, testFunc, caseDef);
2025 		}
2026 		group->addChild(formatGroup.release());
2027 	}
2028 }
2029 
2030 void createSampledImageTestsInGroup (tcu::TestCaseGroup* group, PipelineConstructionType pipelineConstructionType)
2031 {
2032 	addTestCasesWithFunctions(group, SampledImage::checkSupport, SampledImage::initPrograms, SampledImage::test, pipelineConstructionType);
2033 }
2034 
2035 void createStorageImageTestsInGroup (tcu::TestCaseGroup* group, PipelineConstructionType pipelineConstructionType)
2036 {
2037 	addTestCasesWithFunctions(group, StorageImage::checkSupport, StorageImage::initPrograms, StorageImage::test, pipelineConstructionType);
2038 }
2039 
2040 void createStandardSamplePositionTestsInGroup (tcu::TestCaseGroup* group, PipelineConstructionType pipelineConstructionType)
2041 {
2042 	addStandardSamplePositionTestCasesWithFunctions(group, StandardSamplePosition::checkSupport, StandardSamplePosition::initPrograms, StandardSamplePosition::test, pipelineConstructionType);
2043 }
2044 
2045 } // anonymous ns
2046 
2047 //! Render to a multisampled image and sample from it in a fragment shader.
2048 tcu::TestCaseGroup* createMultisampleSampledImageTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
2049 {
2050 	return createTestGroup(testCtx, "sampled_image", createSampledImageTestsInGroup, pipelineConstructionType);
2051 }
2052 
2053 //! Render to a multisampled image and access it with load/stores in a compute shader.
2054 tcu::TestCaseGroup* createMultisampleStorageImageTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
2055 {
2056 	return createTestGroup(testCtx, "storage_image", createStorageImageTestsInGroup, pipelineConstructionType);
2057 }
2058 
2059 //! Render to a multisampled image and verify standard multisample positions.
2060 tcu::TestCaseGroup* createMultisampleStandardSamplePositionTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
2061 {
2062 	return createTestGroup(testCtx, "standardsampleposition", createStandardSamplePositionTestsInGroup, pipelineConstructionType);
2063 }
2064 
2065 } // pipeline
2066 } // vkt
2067