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