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