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