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