• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 Advanced Micro Devices, Inc.
6  * Copyright (c) 2019 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Tests for VK_AMD_shader_fragment_mask
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktPipelineMultisampleShaderFragmentMaskTests.hpp"
26 #include "vktPipelineMakeUtil.hpp"
27 #include "vktTestCase.hpp"
28 #include "vktTestCaseUtil.hpp"
29 #include "vktTestGroupUtil.hpp"
30 
31 #include "vkCmdUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkPlatform.hpp"
34 #include "vkMemUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkRefUtil.hpp"
38 #include "vkBuilderUtil.hpp"
39 #include "vkPrograms.hpp"
40 #include "vkImageUtil.hpp"
41 
42 #include "deUniquePtr.hpp"
43 #include "deSharedPtr.hpp"
44 #include "deRandom.hpp"
45 
46 #include "tcuVector.hpp"
47 #include "tcuTestLog.hpp"
48 #include "tcuImageCompare.hpp"
49 #include "tcuTestLog.hpp"
50 #include "tcuTextureUtil.hpp"
51 
52 #include <string>
53 #include <vector>
54 
55 namespace vkt
56 {
57 namespace pipeline
58 {
59 namespace
60 {
61 using namespace vk;
62 using de::UniquePtr;
63 using de::MovePtr;
64 using de::SharedPtr;
65 using tcu::UVec2;
66 using tcu::UVec4;
67 using tcu::Vec2;
68 using tcu::Vec4;
69 
70 typedef SharedPtr<Unique<VkImageView> >		ImageViewSp;
71 typedef SharedPtr<Unique<VkPipeline> >		PipelineSp;
72 
73 struct PositionColor
74 {
75 	tcu::Vec4	        position;
76 	VkClearColorValue	color;
77 
PositionColorvkt::pipeline::__anonb8f720ed0111::PositionColor78 	PositionColor (const tcu::Vec4& pos, const tcu::UVec4& col) : position(pos)
79     {
80         deMemcpy(color.uint32, col.getPtr(), sizeof(color.uint32));
81     }
82 
PositionColorvkt::pipeline::__anonb8f720ed0111::PositionColor83 	PositionColor (const tcu::Vec4& pos, const tcu::Vec4&  col) : position(pos)
84     {
85         deMemcpy(color.float32, col.getPtr(), sizeof(color.float32));
86     }
87 
PositionColorvkt::pipeline::__anonb8f720ed0111::PositionColor88 	PositionColor (const PositionColor& rhs)
89 		: position	(rhs.position)
90         , color     (rhs.color)
91 	{
92 	}
93 };
94 
95 //! Make a dummy sampler.
makeSampler(const DeviceInterface & vk,const VkDevice device)96 Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice device)
97 {
98 	const VkSamplerCreateInfo samplerParams =
99 	{
100 		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,			// VkStructureType         sType;
101 		DE_NULL,										// const void*             pNext;
102 		(VkSamplerCreateFlags)0,						// VkSamplerCreateFlags    flags;
103 		VK_FILTER_NEAREST,								// VkFilter                magFilter;
104 		VK_FILTER_NEAREST,								// VkFilter                minFilter;
105 		VK_SAMPLER_MIPMAP_MODE_NEAREST,					// VkSamplerMipmapMode     mipmapMode;
106 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode    addressModeU;
107 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode    addressModeV;
108 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode    addressModeW;
109 		0.0f,											// float                   mipLodBias;
110 		VK_FALSE,										// VkBool32                anisotropyEnable;
111 		1.0f,											// float                   maxAnisotropy;
112 		VK_FALSE,										// VkBool32                compareEnable;
113 		VK_COMPARE_OP_ALWAYS,							// VkCompareOp             compareOp;
114 		0.0f,											// float                   minLod;
115 		0.0f,											// float                   maxLod;
116 		VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,		// VkBorderColor           borderColor;
117 		VK_FALSE,										// VkBool32                unnormalizedCoordinates;
118 	};
119 	return createSampler(vk, device, &samplerParams);
120 }
121 
makeImage(const DeviceInterface & vk,const VkDevice device,const VkFormat format,const UVec2 & size,const deUint32 layers,const VkSampleCountFlagBits samples,const VkImageUsageFlags usage)122 Move<VkImage> makeImage (const DeviceInterface&			vk,
123 						 const VkDevice					device,
124 						 const VkFormat					format,
125 						 const UVec2&					size,
126 						 const deUint32					layers,
127 						 const VkSampleCountFlagBits	samples,
128 						 const VkImageUsageFlags		usage)
129 {
130 	const VkImageCreateInfo imageParams =
131 	{
132 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
133 		DE_NULL,										// const void*				pNext;
134 		(VkImageCreateFlags)0,							// VkImageCreateFlags		flags;
135 		VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
136 		format,											// VkFormat					format;
137 		makeExtent3D(size.x(), size.y(), 1),			// VkExtent3D				extent;
138 		1u,												// deUint32					mipLevels;
139 		layers,											// deUint32					arrayLayers;
140 		samples,										// VkSampleCountFlagBits	samples;
141 		VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
142 		usage,											// VkImageUsageFlags		usage;
143 		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
144 		0u,												// deUint32					queueFamilyIndexCount;
145 		DE_NULL,										// const deUint32*			pQueueFamilyIndices;
146 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout;
147 	};
148 	return createImage(vk, device, &imageParams);
149 }
150 
151 //! Create a test-specific MSAA pipeline
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const bool useVertexInput,const VkFormat vertexAttribColorFormat,const bool useColorAttachment,const deUint32 subpassNdx,const UVec2 & renderSize,const VkSampleCountFlagBits numSamples)152 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&					vk,
153 									   const VkDevice							device,
154 									   const VkPipelineLayout					pipelineLayout,
155 									   const VkRenderPass						renderPass,
156 									   const VkShaderModule						vertexModule,
157 									   const VkShaderModule						fragmentModule,
158 									   const bool								useVertexInput,
159 									   const VkFormat							vertexAttribColorFormat,
160 									   const bool								useColorAttachment,
161 									   const deUint32							subpassNdx,
162 									   const UVec2&								renderSize,
163 									   const VkSampleCountFlagBits				numSamples)
164 {
165 	std::vector<VkVertexInputBindingDescription>	vertexInputBindingDescriptions;
166 	std::vector<VkVertexInputAttributeDescription>	vertexInputAttributeDescriptions;
167 
168 	// Vertex attributes: position and color
169 	if (useVertexInput)
170 	{
171 		vertexInputBindingDescriptions.push_back  (makeVertexInputBindingDescription  (0u, sizeof(PositionColor), VK_VERTEX_INPUT_RATE_VERTEX));
172 		vertexInputAttributeDescriptions.push_back(makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u));
173 		vertexInputAttributeDescriptions.push_back(makeVertexInputAttributeDescription(1u, 0u, vertexAttribColorFormat, sizeof(Vec4)));
174 	}
175 
176 	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
177 	{
178 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
179 		DE_NULL,														// const void*								pNext;
180 		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags	flags;
181 		static_cast<deUint32>(vertexInputBindingDescriptions.size()),	// uint32_t									vertexBindingDescriptionCount;
182 		dataOrNullPtr(vertexInputBindingDescriptions),					// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
183 		static_cast<deUint32>(vertexInputAttributeDescriptions.size()),	// uint32_t									vertexAttributeDescriptionCount;
184 		dataOrNullPtr(vertexInputAttributeDescriptions),				// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
185 	};
186 
187 	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
188 	{
189 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
190 		DE_NULL,														// const void*								pNext;
191 		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags	flags;
192 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology						topology;
193 		VK_FALSE,														// VkBool32									primitiveRestartEnable;
194 	};
195 
196 	const VkViewport viewport =
197 	{
198 		0.0f, 0.0f,																	// x, y
199 		static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),		// widht, height
200 		0.0f, 1.0f																	// minDepth, maxDepth
201 	};
202 
203 	const VkRect2D scissor =
204 	{
205 		makeOffset2D(0, 0),
206 		makeExtent2D(renderSize.x(), renderSize.y()),
207 	};
208 
209 	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
210 	{
211 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType						sType;
212 		DE_NULL,														// const void*							pNext;
213 		(VkPipelineViewportStateCreateFlags)0,							// VkPipelineViewportStateCreateFlags	flags;
214 		1u,																// uint32_t								viewportCount;
215 		&viewport,														// const VkViewport*					pViewports;
216 		1u,																// uint32_t								scissorCount;
217 		&scissor,														// const VkRect2D*						pScissors;
218 	};
219 
220 	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
221 	{
222 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	// VkStructureType							sType;
223 		DE_NULL,													// const void*								pNext;
224 		(VkPipelineRasterizationStateCreateFlags)0,					// VkPipelineRasterizationStateCreateFlags	flags;
225 		VK_FALSE,													// VkBool32									depthClampEnable;
226 		VK_FALSE,													// VkBool32									rasterizerDiscardEnable;
227 		VK_POLYGON_MODE_FILL,										// VkPolygonMode							polygonMode;
228 		VK_CULL_MODE_NONE,											// VkCullModeFlags							cullMode;
229 		VK_FRONT_FACE_COUNTER_CLOCKWISE,							// VkFrontFace								frontFace;
230 		VK_FALSE,													// VkBool32									depthBiasEnable;
231 		0.0f,														// float									depthBiasConstantFactor;
232 		0.0f,														// float									depthBiasClamp;
233 		0.0f,														// float									depthBiasSlopeFactor;
234 		1.0f,														// float									lineWidth;
235 	};
236 
237 	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
238 	{
239 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
240 		DE_NULL,													// const void*								pNext;
241 		(VkPipelineMultisampleStateCreateFlags)0,					// VkPipelineMultisampleStateCreateFlags	flags;
242 		numSamples,													// VkSampleCountFlagBits					rasterizationSamples;
243 		VK_FALSE,													// VkBool32									sampleShadingEnable;
244 		1.0f,														// float									minSampleShading;
245 		DE_NULL,													// const VkSampleMask*						pSampleMask;
246 		VK_FALSE,													// VkBool32									alphaToCoverageEnable;
247 		VK_FALSE													// VkBool32									alphaToOneEnable;
248 	};
249 
250 	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
251 	{
252 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
253 		DE_NULL,													// const void*								pNext;
254 		(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags	flags;
255 		VK_FALSE,													// VkBool32									depthTestEnable;
256 		VK_TRUE,													// VkBool32									depthWriteEnable;
257 		VK_COMPARE_OP_ALWAYS,										// VkCompareOp								depthCompareOp;
258 		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
259 		VK_FALSE,													// VkBool32									stencilTestEnable;
260 		VkStencilOpState(),											// VkStencilOpState							front;
261 		VkStencilOpState(),											// VkStencilOpState							back;
262 		0.0f,														// float									minDepthBounds;
263 		1.0f,														// float									maxDepthBounds;
264 	};
265 
266 	const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
267 	const VkPipelineColorBlendAttachmentState defaultBlendAttachmentState =
268 	{
269 		VK_FALSE,				// VkBool32					blendEnable;
270 		VK_BLEND_FACTOR_ONE,	// VkBlendFactor			srcColorBlendFactor;
271 		VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			dstColorBlendFactor;
272 		VK_BLEND_OP_ADD,		// VkBlendOp				colorBlendOp;
273 		VK_BLEND_FACTOR_ONE,	// VkBlendFactor			srcAlphaBlendFactor;
274 		VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			dstAlphaBlendFactor;
275 		VK_BLEND_OP_ADD,		// VkBlendOp				alphaBlendOp;
276 		colorComponentsAll,		// VkColorComponentFlags	colorWriteMask;
277 	};
278 
279 	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
280 	{
281 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
282 		DE_NULL,													// const void*									pNext;
283 		(VkPipelineColorBlendStateCreateFlags)0,					// VkPipelineColorBlendStateCreateFlags			flags;
284 		VK_FALSE,													// VkBool32										logicOpEnable;
285 		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
286 		(useColorAttachment ? 1u : 0u),								// deUint32										attachmentCount;
287 		&defaultBlendAttachmentState,								// const VkPipelineColorBlendAttachmentState*	pAttachments;
288 		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConstants[4];
289 	};
290 
291 	const VkPipelineShaderStageCreateInfo pShaderStages[] =
292 	{
293 		{
294 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
295 			DE_NULL,												// const void*							pNext;
296 			(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
297 			VK_SHADER_STAGE_VERTEX_BIT,								// VkShaderStageFlagBits				stage;
298 			vertexModule,											// VkShaderModule						module;
299 			"main",													// const char*							pName;
300 			DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
301 		},
302 		{
303 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
304 			DE_NULL,												// const void*							pNext;
305 			(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
306 			VK_SHADER_STAGE_FRAGMENT_BIT,							// VkShaderStageFlagBits				stage;
307 			fragmentModule,											// VkShaderModule						module;
308 			"main",													// const char*							pName;
309 			DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
310 		}
311 	};
312 
313 	const VkGraphicsPipelineCreateInfo	graphicsPipelineInfo =
314 	{
315 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
316 		DE_NULL,											// const void*										pNext;
317 		(VkPipelineCreateFlags)0,							// VkPipelineCreateFlags							flags;
318 		DE_LENGTH_OF_ARRAY(pShaderStages),					// deUint32											stageCount;
319 		pShaderStages,										// const VkPipelineShaderStageCreateInfo*			pStages;
320 		&vertexInputStateInfo,								// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
321 		&pipelineInputAssemblyStateInfo,					// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
322 		DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
323 		&pipelineViewportStateInfo,							// const VkPipelineViewportStateCreateInfo*			pViewportState;
324 		&pipelineRasterizationStateInfo,					// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
325 		&pipelineMultisampleStateInfo,						// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
326 		&pipelineDepthStencilStateInfo,						// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
327 		&pipelineColorBlendStateInfo,						// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
328 		DE_NULL,											// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
329 		pipelineLayout,										// VkPipelineLayout									layout;
330 		renderPass,											// VkRenderPass										renderPass;
331 		subpassNdx,											// deUint32											subpass;
332 		DE_NULL,											// VkPipeline										basePipelineHandle;
333 		-1,													// deInt32											basePipelineIndex;
334 	};
335 
336 	return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
337 }
338 
genShapes(const VkFormat colorFormat)339 std::vector<PositionColor> genShapes (const VkFormat colorFormat)
340 {
341 	std::vector<PositionColor> vertices;
342 
343 	if (colorFormat == VK_FORMAT_R8G8B8A8_UNORM)
344 	{
345 		vertices.push_back(PositionColor(Vec4( 0.0f,  -0.75f, 0.0f, 1.0f), Vec4(0.5f, 0.5f, 0.5f, 1.0f)));
346 		vertices.push_back(PositionColor(Vec4(-0.75f,  0.75f, 0.0f, 1.0f), Vec4(1.0f, 0.5f, 0.5f, 1.0f)));
347 		vertices.push_back(PositionColor(Vec4( 0.75f,  0.65f, 0.0f, 1.0f), Vec4(0.0f, 0.5f, 1.0f, 1.0f)));
348 	}
349 	else
350 	{
351 		vertices.push_back(PositionColor(Vec4( 0.0f,  -0.75f, 0.0f, 1.0f), UVec4(0xabcdu, 0u, 0u, 0u)));
352 		vertices.push_back(PositionColor(Vec4(-0.75f,  0.75f, 0.0f, 1.0f), UVec4(0xbcdeu, 0u, 0u, 0u)));
353 		vertices.push_back(PositionColor(Vec4( 0.75f,  0.65f, 0.0f, 1.0f), UVec4(0xcdefu, 0u, 0u, 0u)));
354 	}
355 
356 	return vertices;
357 }
358 
359 //! Map color image format to a convenient format used in vertex attributes
getVertexInputColorFormat(const VkFormat colorImageFormat)360 VkFormat getVertexInputColorFormat (const VkFormat colorImageFormat)
361 {
362 	switch (tcu::getTextureChannelClass(mapVkFormat(colorImageFormat).type))
363 	{
364 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
365 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
366 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
367 			return VK_FORMAT_R32G32B32A32_SFLOAT;
368 
369 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
370 			return VK_FORMAT_R32G32B32A32_SINT;
371 
372 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
373 			return VK_FORMAT_R32G32B32A32_UINT;
374 
375 		default:
376 			DE_ASSERT(0);
377 			return VK_FORMAT_UNDEFINED;
378 	}
379 }
380 
381 enum SampleSource
382 {
383 	SAMPLE_SOURCE_IMAGE,			//!< texel fetch from an image
384 	SAMPLE_SOURCE_SUBPASS_INPUT,	//!< texel fetch from an input attachment
385 };
386 
387 //! The parameters that define a test case
388 struct TestParams
389 {
390 	UVec2					renderSize;
391 	deUint32				numLayers;			//!< 1 or N for layered image
392 	SampleSource			sampleSource;		//!< source of texel fetch
393 	VkSampleCountFlagBits	numColorSamples;
394 	VkFormat				colorFormat;		//!< Color attachment format
395 
TestParamsvkt::pipeline::__anonb8f720ed0111::TestParams396 	TestParams (void)
397 		: numLayers			()
398 		, numColorSamples	()
399 		, colorFormat		()
400 	{
401 	}
402 };
403 
checkRequirements(Context & context,TestParams params)404 void checkRequirements (Context& context, TestParams params)
405 {
406 	context.requireDeviceFunctionality("VK_AMD_shader_fragment_mask");
407 
408 	// In the subpass input case we have to store fetch results into a buffer for subsequent verification in a compute shader.
409 	const bool requireFragmentStores = (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT);
410 
411 	const VkPhysicalDeviceLimits& limits = context.getDeviceProperties().limits;
412 
413 	if ((limits.framebufferColorSampleCounts & params.numColorSamples) == 0u)
414 		TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported");
415 
416 	if ((isIntFormat(params.colorFormat) || isUintFormat(params.colorFormat)))
417 	{
418 		if ((limits.sampledImageIntegerSampleCounts & params.numColorSamples) == 0u)
419 			TCU_THROW(NotSupportedError, "sampledImageIntegerSampleCounts: sample count not supported");
420 	}
421 	else
422 	{
423 		if ((limits.sampledImageColorSampleCounts & params.numColorSamples) == 0u)
424 			TCU_THROW(NotSupportedError, "sampledImageColorSampleCounts: sample count not supported");
425 	}
426 
427 	if (requireFragmentStores)
428 	{
429 		if (!context.getDeviceFeatures().fragmentStoresAndAtomics)
430 			TCU_THROW(NotSupportedError, "fragmentStoresAndAtomics: feature not supported");
431 	}
432 }
433 
434 //! Common data used by the test
435 struct WorkingData
436 {
437 	deUint32						numVertices;				//!< Number of vertices defined in the vertex buffer
438 	Move<VkBuffer>					vertexBuffer;
439 	MovePtr<Allocation>				vertexBufferAlloc;
440 	Move<VkImage>					colorImage;					//!< Color image
441 	MovePtr<Allocation>				colorImageAlloc;
442 	Move<VkImageView>				colorImageView;				//!< Color image view spanning all layers
443 	Move<VkBuffer>					colorBuffer;				//!< Buffer used to copy image data
444 	MovePtr<Allocation>				colorBufferAlloc;
445 	VkDeviceSize					colorBufferSize;
446 	Move<VkSampler>					defaultSampler;				//!< Dummy sampler, we are using texel fetches
447 
WorkingDatavkt::pipeline::__anonb8f720ed0111::WorkingData448 	WorkingData (void)
449 		: numVertices		()
450 		, colorBufferSize	()
451 	{
452 	}
453 };
454 
initPrograms(SourceCollections & programCollection,const TestParams params)455 void initPrograms (SourceCollections& programCollection, const TestParams params)
456 {
457 	std::string	colorType;					//!< color pixel type used by image functions
458 	std::string	colorBufferType;			//!< packed pixel type as stored in a ssbo
459 	std::string colorBufferPack;			//!< a cast or a function call when writing back color format to the ssbo
460 	std::string	colorFragInQualifier;		//!< fragment shader color input qualifier
461 	std::string samplerPrefix;				//!< u, i, or empty
462 
463 	switch (params.colorFormat)
464 	{
465 		case VK_FORMAT_R8G8B8A8_UNORM:
466 			colorType				= "vec4";
467 			colorBufferType			= "uint";
468 			colorBufferPack			= "packUnorm4x8";
469 			break;
470 
471 		case VK_FORMAT_R32_UINT:
472 			colorType				= "uint";
473 			colorBufferType			= "uint";
474 			colorBufferPack			= colorBufferType;
475 			colorFragInQualifier	= "flat";
476 			samplerPrefix			= "u";
477 			break;
478 
479 		case VK_FORMAT_R32_SINT:
480 			colorType				= "int";
481 			colorBufferType			= "int";
482 			colorBufferPack			= colorBufferType;
483 			colorFragInQualifier	= "flat";
484 			samplerPrefix			= "i";
485 			break;
486 
487 		default:
488 			DE_FATAL("initPrograms not handled for this color format");
489 			break;
490 	}
491 
492 	// Vertex shader - position and color
493 	{
494 		std::ostringstream src;
495 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
496 			<< "\n"
497 			<< "layout(location = 0) in  vec4 in_position;\n"
498 			<< "layout(location = 1) in  " << colorType << " in_color;\n"
499 			<< "layout(location = 0) out " << colorType << " o_color;\n"
500 			<< "\n"
501 			<< "out gl_PerVertex {\n"
502 			<< "    vec4 gl_Position;\n"
503 			<< "};\n"
504 			<< "\n"
505 			<< "void main(void)\n"
506 			<< "{\n"
507 			// Introduce a variance in geometry per instance index which maps to the image layer
508 			<< "    float a   = 0.25 * float(gl_InstanceIndex);\n"
509 			<< "    mat3 rm   = mat3( cos(a), sin(a), 0.0,\n"
510 			<< "                     -sin(a), cos(a), 0.0,\n"
511 			<< "                         0.0,    0.0, 1.0);\n"
512 			<< "    vec2 rpos = (rm * vec3(in_position.xy, 1.0)).xy;\n"
513 			<< "\n"
514 			<< "    gl_Position = vec4(rpos, in_position.zw);\n"
515 			<< "    o_color     = in_color;\n"
516 			<< "}\n";
517 
518 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
519 	}
520 
521 	// Vertex shader - no vertex data, fill viewport with one primitive
522 	{
523 		std::ostringstream src;
524 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
525 			<< "\n"
526 			<< "out gl_PerVertex {\n"
527 			<< "    vec4 gl_Position;\n"
528 			<< "};\n"
529 			<< "\n"
530 			<< "void main(void)\n"
531 			<< "{\n"
532 			// Specify an oversized triangle covering the whole viewport.
533 			<< "    switch (gl_VertexIndex)\n"
534 			<< "    {\n"
535 			<< "        case 0:\n"
536 			<< "            gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
537 			<< "            break;\n"
538 			<< "        case 1:\n"
539 			<< "            gl_Position = vec4(-1.0,  3.0, 0.0, 1.0);\n"
540 			<< "            break;\n"
541 			<< "        case 2:\n"
542 			<< "            gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
543 			<< "            break;\n"
544 			<< "    }\n"
545 			<< "}\n";
546 
547 		programCollection.glslSources.add("vert_full") << glu::VertexSource(src.str());
548 	}
549 
550 	// Fragment shader - output color from VS
551 	{
552 		std::ostringstream src;
553 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
554 			<< "\n"
555 			<< "layout(location = 0) in " << colorFragInQualifier << " " << colorType << " in_color;\n"
556 			<< "layout(location = 0) out " << colorType << " o_color;\n"
557 			<< "\n"
558 			<< "void main(void)\n"
559 			<< "{\n"
560 			<< "    o_color = in_color;\n"
561 			<< "}\n";
562 
563 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
564 	}
565 
566 	// Fragment shader - FMASK fetch from an input attachment
567 	if (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT)
568 	{
569 		std::ostringstream src;
570 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
571 			<< "#extension GL_AMD_shader_fragment_mask : enable\n"
572 			<< "\n"
573 			<< "layout(set = 0, binding = 0) uniform " << samplerPrefix << "sampler2DMS" << (params.numLayers > 1 ? "Array" : "") << " u_image;\n"
574 			<< "layout(set = 0, binding = 1, std430) writeonly buffer ColorOutput {\n"
575 			<< "    " << colorBufferType << " color[];\n"
576 			<< "} sb_out;\n"
577 			<< "layout(input_attachment_index = " << params.numLayers << ", set = 0, binding = 2) uniform " << samplerPrefix << "subpassInputMS" << " input_attach;\n"
578 			<< "\n"
579 			<< "void main(void)\n"
580 			<< "{\n"
581 			<< "    ivec2 p            = ivec2(gl_FragCoord.xy);\n"
582 			<< "    int   width        = " << params.renderSize.x() << ";\n"
583 			<< "    int   numSamples   = " << static_cast<deUint32>(params.numColorSamples) << ";\n"
584 			<< "    int   colorOutNdx  = numSamples * (p.x + width * p.y);\n"
585 			<< "\n"
586 			<< "    uint mask = fragmentMaskFetchAMD(input_attach);\n"
587 			<< "    for (int sampleNdx = 0; sampleNdx < numSamples; ++sampleNdx)\n"
588 			<< "    {\n"
589 			<< "        int fragNdx = int((mask >> (4 * sampleNdx)) & 0xf);\n"
590 			<< "        " << samplerPrefix << "vec4 color = fragmentFetchAMD(input_attach, fragNdx);\n"
591 			<< "        sb_out.color[colorOutNdx + sampleNdx] = " << colorBufferPack << "(color);\n"
592 			<< "    }\n"
593 			<< "}\n";
594 
595 		programCollection.glslSources.add("frag_fmask_fetch") << glu::FragmentSource(src.str());
596 	}
597 
598 	// Generate compute shaders
599 	const struct ComputeShaderParams
600 	{
601 		const char*		name;
602 		bool			isFmaskFetch;
603 		bool			enabled;
604 	} computeShaders[] =
605 	{
606 		// name					// FMASK?	// enabled?
607 		{ "comp_fetch",			false,		true,													},
608 		{ "comp_fmask_fetch",	true,		(params.sampleSource != SAMPLE_SOURCE_SUBPASS_INPUT)	},
609 	};
610 
611 	for (const ComputeShaderParams* pShaderParams = computeShaders; pShaderParams != DE_ARRAY_END(computeShaders); ++pShaderParams)
612 	if (pShaderParams->enabled)
613 	{
614 		const std::string samplingPos = (params.numLayers == 1 ? "ivec2(gl_WorkGroupID.xy)"
615 															   : "ivec3(gl_WorkGroupID)");
616 		std::ostringstream src;
617 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
618 			<< (pShaderParams->isFmaskFetch ? "#extension GL_AMD_shader_fragment_mask : enable\n" : "")
619 			<< "#define NUM_SAMPLES " << static_cast<deUint32>(params.numColorSamples) << "\n"
620 			<< "\n"
621 			<< "layout(local_size_x = NUM_SAMPLES) in;\n"	// one work group per pixel, each sample gets a local invocation
622 			<< "\n"
623 			<< "layout(set = 0, binding = 0) uniform " << samplerPrefix << "sampler2DMS" << (params.numLayers > 1 ? "Array" : "") << " u_image;\n"
624 			<< "layout(set = 0, binding = 1, std430) writeonly buffer ColorOutput {\n"
625 			<< "    " << colorBufferType << " color[];\n"
626 			<< "} sb_out;\n"
627 			<< "\n"
628 			<< "void main(void)\n"
629 			<< "{\n"
630 			<< "    int sampleNdx   = int(gl_LocalInvocationID.x);\n"
631 			<< "    int colorOutNdx = NUM_SAMPLES * int(gl_WorkGroupID.x +\n"
632 			<< "                                        gl_WorkGroupID.y * gl_NumWorkGroups.x +\n"
633 			<< "                                        gl_WorkGroupID.z * gl_NumWorkGroups.x * gl_NumWorkGroups.y);\n"
634 			<< "\n";
635 		if (pShaderParams->isFmaskFetch)
636 		{
637 			src << "    uint  mask    = fragmentMaskFetchAMD(u_image, " << samplingPos << ");\n"
638 				<< "    int   fragNdx = int((mask >> (4 * sampleNdx)) & 0xf);\n"
639 				<< "    " << samplerPrefix << "vec4 color = fragmentFetchAMD(u_image, " << samplingPos << ", fragNdx);\n"
640 				<< "    sb_out.color[colorOutNdx + sampleNdx] = " << colorBufferPack << "(color);\n";
641 		}
642 		else
643 		{
644 			src << "    " << samplerPrefix << "vec4 color = texelFetch(u_image, " << samplingPos << ", sampleNdx);\n"
645 				<< "    sb_out.color[colorOutNdx + sampleNdx] = " << colorBufferPack << "(color);\n";
646 		}
647 		src << "}\n";
648 
649 		programCollection.glslSources.add(pShaderParams->name) << glu::ComputeSource(src.str());
650 	}
651 }
652 
genClearValues(const VkFormat format,const deUint32 count)653 std::vector<VkClearValue> genClearValues (const VkFormat format, const deUint32 count)
654 {
655 	std::vector<VkClearValue>	clearValues;
656 	de::Random					rng (332);
657 
658 	switch (format)
659 	{
660 		case VK_FORMAT_R8G8B8A8_UNORM:
661 			for (deUint32 i = 0u; i < count; ++i)
662 				clearValues.push_back(makeClearValueColorF32(rng.getFloat(), rng.getFloat(), rng.getFloat(), 1.0f));
663 			break;
664 
665 		case VK_FORMAT_R32_UINT:
666 		case VK_FORMAT_R32_SINT:
667 			for (deUint32 i = 0u; i < count; ++i)
668 				clearValues.push_back(makeClearValueColorU32(rng.getUint32(), 0u, 0u, 0u));
669 			break;
670 
671 		default:
672 			DE_FATAL("Clear color not defined for this format");
673 			break;
674 	}
675 
676 	return clearValues;
677 }
678 
679 //! For subpass load case draw and fetch must happen within the same render pass.
drawAndSampleInputAttachment(Context & context,const TestParams & params,WorkingData & wd)680 void drawAndSampleInputAttachment (Context& context, const TestParams& params, WorkingData& wd)
681 {
682 	DE_ASSERT(params.numLayers == 1u);	// subpass load with single-layer image
683 
684 	const DeviceInterface&	vk		= context.getDeviceInterface();
685 	const VkDevice			device	= context.getDevice();
686 
687 	Move<VkRenderPass>		renderPass;
688 	Move<VkFramebuffer>		framebuffer;
689 
690 	// Create descriptor set
691 	const Unique<VkDescriptorSetLayout> descriptorSetLayout (DescriptorSetLayoutBuilder()
692 		.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	VK_SHADER_STAGE_FRAGMENT_BIT, &wd.defaultSampler.get())
693 		.addSingleBinding		(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,			VK_SHADER_STAGE_FRAGMENT_BIT)
694 		.addSingleBinding		(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,		VK_SHADER_STAGE_FRAGMENT_BIT)
695 		.build(vk, device));
696 
697 	const Unique<VkDescriptorPool> descriptorPool (DescriptorPoolBuilder()
698 		.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
699 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
700 		.addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
701 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
702 
703 	const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
704 
705 	{
706 		const VkDescriptorImageInfo		colorImageInfo	= makeDescriptorImageInfo(DE_NULL, *wd.colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
707 		const VkDescriptorBufferInfo	bufferInfo		= makeDescriptorBufferInfo(*wd.colorBuffer, 0u, wd.colorBufferSize);
708 
709 		DescriptorSetUpdateBuilder	builder;
710 
711 		builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &colorImageInfo);
712 		builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,		 &bufferInfo);
713 
714 		if (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT)
715 			builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &colorImageInfo);
716 
717 		builder.update(vk, device);
718 	}
719 
720 	// Create a render pass and a framebuffer
721 	{
722 		std::vector<VkSubpassDescription>		subpasses;
723 		std::vector<VkSubpassDependency>		subpassDependencies;
724 		std::vector<VkImageView>				attachments;
725 		std::vector<VkAttachmentDescription>	attachmentDescriptions;
726 		std::vector<VkAttachmentReference>		attachmentReferences;
727 
728 		// Reserve capacity to avoid invalidating pointers to elements
729 		attachmentReferences.reserve(2);	// color image + input attachment
730 
731 		// Create a MS draw subpass
732 		{
733 			attachments.push_back(*wd.colorImageView);
734 
735 			attachmentDescriptions.push_back(makeAttachmentDescription(
736 				(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFlags		flags;
737 				params.colorFormat,												// VkFormat							format;
738 				params.numColorSamples,											// VkSampleCountFlagBits			samples;
739 				VK_ATTACHMENT_LOAD_OP_CLEAR,									// VkAttachmentLoadOp				loadOp;
740 				VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp				storeOp;
741 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp				stencilLoadOp;
742 				VK_ATTACHMENT_STORE_OP_DONT_CARE,								// VkAttachmentStoreOp				stencilStoreOp;
743 				VK_IMAGE_LAYOUT_UNDEFINED,										// VkImageLayout					initialLayout;
744 				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL						// VkImageLayout					finalLayout;
745 			));
746 
747 			attachmentReferences.push_back(makeAttachmentReference(static_cast<deUint32>(attachmentReferences.size()),	VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
748 			const VkAttachmentReference* colorRef = &attachmentReferences.back();
749 
750 			const VkSubpassDescription subpassDescription =
751 			{
752 				(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags       flags;
753 				VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint             pipelineBindPoint;
754 				0u,													// uint32_t                        inputAttachmentCount;
755 				DE_NULL,											// const VkAttachmentReference*    pInputAttachments;
756 				1u,													// uint32_t                        colorAttachmentCount;
757 				colorRef,											// const VkAttachmentReference*    pColorAttachments;
758 				DE_NULL,											// const VkAttachmentReference*    pResolveAttachments;
759 				DE_NULL,											// const VkAttachmentReference*    pDepthStencilAttachment;
760 				0u,													// uint32_t                        preserveAttachmentCount;
761 				DE_NULL,											// const uint32_t*                 pPreserveAttachments;
762 			};
763 
764 			subpasses.push_back(subpassDescription);
765 		}
766 
767 		// Create a sampling subpass
768 		{
769 			attachmentReferences.push_back(makeAttachmentReference(0u, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL));
770 			const VkAttachmentReference* inputRef = &attachmentReferences.back();
771 
772 			// No color attachment, side effects only
773 			VkSubpassDescription subpassDescription =
774 			{
775 				(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags       flags;
776 				VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint             pipelineBindPoint;
777 				1u,													// uint32_t                        inputAttachmentCount;
778 				inputRef,											// const VkAttachmentReference*    pInputAttachments;
779 				0u,													// uint32_t                        colorAttachmentCount;
780 				DE_NULL,											// const VkAttachmentReference*    pColorAttachments;
781 				DE_NULL,											// const VkAttachmentReference*    pResolveAttachments;
782 				DE_NULL,											// const VkAttachmentReference*    pDepthStencilAttachment;
783 				0u,													// uint32_t                        preserveAttachmentCount;
784 				DE_NULL,											// const uint32_t*                 pPreserveAttachments;
785 			};
786 
787 			subpasses.push_back(subpassDescription);
788 		}
789 
790 		// Serialize the subpasses
791 		{
792 			const VkAccessFlags	dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
793 											  | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
794 											  | VK_ACCESS_SHADER_WRITE_BIT;
795 			const VkSubpassDependency	dependency	=
796 			{
797 				0u,																							// uint32_t                srcSubpass;
798 				1u,																							// uint32_t                dstSubpass;
799 				VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,		// VkPipelineStageFlags    srcStageMask;
800 				VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,														// VkPipelineStageFlags    dstStageMask;
801 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,														// VkAccessFlags           srcAccessMask;
802 				dstAccessMask,																				// VkAccessFlags           dstAccessMask;
803 				VK_DEPENDENCY_BY_REGION_BIT,																// VkDependencyFlags       dependencyFlags;
804 			};
805 			subpassDependencies.push_back(dependency);
806 		}
807 
808 		VkRenderPassCreateInfo renderPassInfo =
809 		{
810 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,				// VkStructureType					sType;
811 			DE_NULL,												// const void*						pNext;
812 			(VkRenderPassCreateFlags)0,								// VkRenderPassCreateFlags			flags;
813 			static_cast<deUint32>(attachmentDescriptions.size()),	// deUint32							attachmentCount;
814 			dataOrNullPtr(attachmentDescriptions),					// const VkAttachmentDescription*	pAttachments;
815 			static_cast<deUint32>(subpasses.size()),				// deUint32							subpassCount;
816 			dataOrNullPtr(subpasses),								// const VkSubpassDescription*		pSubpasses;
817 			static_cast<deUint32>(subpassDependencies.size()),		// deUint32							dependencyCount;
818 			dataOrNullPtr(subpassDependencies),						// const VkSubpassDependency*		pDependencies;
819 		};
820 
821 		renderPass  = createRenderPass(vk, device, &renderPassInfo);
822 		framebuffer = makeFramebuffer (vk, device, *renderPass, static_cast<deUint32>(attachments.size()), dataOrNullPtr(attachments), params.renderSize.x(), params.renderSize.y());
823 	}
824 
825 	const Unique<VkShaderModule>	vertexModuleDraw	(createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
826 	const Unique<VkShaderModule>	fragmentModuleDraw	(createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
827 
828 	// Create pipelines for MS draw
829 	const Unique<VkPipelineLayout>	pipelineLayout		(makePipelineLayout(vk, device, *descriptorSetLayout));
830 	const Unique<VkPipeline>		pipelineDraw		(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModuleDraw, *fragmentModuleDraw,
831 																			  true/*use vertex attribs*/, getVertexInputColorFormat(params.colorFormat), true/*use color attach*/, 0u/*subpass*/,
832 																			  params.renderSize, params.numColorSamples));
833 
834 	// Sampling pass is single-sampled, output to storage buffer
835 	const Unique<VkShaderModule>	vertexModuleSample		(createShaderModule(vk, device, context.getBinaryCollection().get("vert_full"), 0u));
836 	const Unique<VkShaderModule>	fragmentModuleSample	(createShaderModule(vk, device, context.getBinaryCollection().get("frag_fmask_fetch"), 0u));
837 
838 	// Sampling pipeline
839 	const Unique<VkPipeline>		pipelineSample		(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModuleSample, *fragmentModuleSample,
840 																			  false/*use vertex attribs*/, VK_FORMAT_UNDEFINED, false/*no color output*/, 1u/*subpass*/,
841 																			  params.renderSize, VK_SAMPLE_COUNT_1_BIT));
842 
843 	const Unique<VkCommandPool>		cmdPool		(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
844 	const Unique<VkCommandBuffer>	cmdBuffer	(makeCommandBuffer(vk, device, *cmdPool));
845 
846 	beginCommandBuffer(vk, *cmdBuffer);
847 
848 	{
849 		// Generate clear values
850 		std::vector<VkClearValue> clearValues = genClearValues(params.colorFormat, params.numLayers);
851 
852 		const VkRect2D renderArea =
853 		{
854 			{ 0u, 0u },
855 			{ params.renderSize.x(), params.renderSize.y() }
856 		};
857 
858 		const VkRenderPassBeginInfo renderPassBeginInfo =
859 		{
860 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,			// VkStructureType         sType;
861 			DE_NULL,											// const void*             pNext;
862 			*renderPass,										// VkRenderPass            renderPass;
863 			*framebuffer,										// VkFramebuffer           framebuffer;
864 			renderArea,											// VkRect2D                renderArea;
865 			static_cast<deUint32>(clearValues.size()),			// uint32_t                clearValueCount;
866 			dataOrNullPtr(clearValues),							// const VkClearValue*     pClearValues;
867 		};
868 		vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
869 	}
870 
871 	vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
872 
873 	{
874 		const VkDeviceSize vertexBufferOffset = 0ull;
875 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset);
876 	}
877 
878 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineDraw);
879 	vk.cmdDraw(*cmdBuffer, wd.numVertices, 1u, 0u, 0u);
880 
881 	vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
882 
883 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineSample);
884 	vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u);	// fill the framebuffer, geometry defined in the VS
885 
886 	vk.cmdEndRenderPass(*cmdBuffer);
887 
888 	// Buffer write barrier
889 	{
890 		const VkBufferMemoryBarrier barrier =
891 		{
892 			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// VkStructureType    sType;
893 			DE_NULL,										// const void*        pNext;
894 			VK_ACCESS_SHADER_WRITE_BIT,						// VkAccessFlags      srcAccessMask;
895 			VK_ACCESS_HOST_READ_BIT,						// VkAccessFlags      dstAccessMask;
896 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t           srcQueueFamilyIndex;
897 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t           dstQueueFamilyIndex;
898 			*wd.colorBuffer,								// VkBuffer           buffer;
899 			0ull,											// VkDeviceSize       offset;
900 			VK_WHOLE_SIZE,									// VkDeviceSize       size;
901 		};
902 
903 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 1u, &barrier, DE_NULL, 0u);
904 	}
905 
906 	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
907 	submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
908 
909 	invalidateMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
910 }
911 
912 //! Only draw a multisampled image
draw(Context & context,const TestParams & params,WorkingData & wd)913 void draw (Context& context, const TestParams& params, WorkingData& wd)
914 {
915 	const DeviceInterface&	vk		= context.getDeviceInterface();
916 	const VkDevice			device	= context.getDevice();
917 
918 	std::vector<ImageViewSp>	imageViews;
919 	Move<VkRenderPass>			renderPass;
920 	Move<VkFramebuffer>			framebuffer;
921 
922 	// Create color attachments
923 	for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
924 	{
925 		imageViews.push_back(ImageViewSp(new Unique<VkImageView>(
926 			makeImageView(vk, device, *wd.colorImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u)))));
927 	}
928 
929 	// Create a render pass and a framebuffer
930 	{
931 		std::vector<VkSubpassDescription>		subpasses;
932 		std::vector<VkImageView>				attachments;
933 		std::vector<VkAttachmentDescription>	attachmentDescriptions;
934 		std::vector<VkAttachmentReference>		attachmentReferences;
935 
936 		// Reserve capacity to avoid invalidating pointers to elements
937 		attachmentReferences.reserve(params.numLayers);
938 
939 		// Create MS draw subpasses
940 		for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
941 		{
942 			attachments.push_back(**imageViews[layerNdx]);
943 
944 			attachmentDescriptions.push_back(makeAttachmentDescription(
945 				(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFlags		flags;
946 				params.colorFormat,												// VkFormat							format;
947 				params.numColorSamples,											// VkSampleCountFlagBits			samples;
948 				VK_ATTACHMENT_LOAD_OP_CLEAR,									// VkAttachmentLoadOp				loadOp;
949 				VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp				storeOp;
950 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp				stencilLoadOp;
951 				VK_ATTACHMENT_STORE_OP_DONT_CARE,								// VkAttachmentStoreOp				stencilStoreOp;
952 				VK_IMAGE_LAYOUT_UNDEFINED,										// VkImageLayout					initialLayout;
953 				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL						// VkImageLayout					finalLayout;
954 			));
955 
956 			attachmentReferences.push_back(makeAttachmentReference(static_cast<deUint32>(attachmentReferences.size()),	VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
957 			const VkAttachmentReference* colorRef = &attachmentReferences.back();
958 
959 			const VkSubpassDescription subpassDescription =
960 			{
961 				(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags       flags;
962 				VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint             pipelineBindPoint;
963 				0u,													// uint32_t                        inputAttachmentCount;
964 				DE_NULL,											// const VkAttachmentReference*    pInputAttachments;
965 				1u,													// uint32_t                        colorAttachmentCount;
966 				colorRef,											// const VkAttachmentReference*    pColorAttachments;
967 				DE_NULL,											// const VkAttachmentReference*    pResolveAttachments;
968 				DE_NULL,											// const VkAttachmentReference*    pDepthStencilAttachment;
969 				0u,													// uint32_t                        preserveAttachmentCount;
970 				DE_NULL,											// const uint32_t*                 pPreserveAttachments;
971 			};
972 
973 			subpasses.push_back(subpassDescription);
974 		}
975 
976 		// All MS image drawing subpasses are independent
977 		VkRenderPassCreateInfo renderPassInfo =
978 		{
979 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,				// VkStructureType					sType;
980 			DE_NULL,												// const void*						pNext;
981 			(VkRenderPassCreateFlags)0,								// VkRenderPassCreateFlags			flags;
982 			static_cast<deUint32>(attachmentDescriptions.size()),	// deUint32							attachmentCount;
983 			dataOrNullPtr(attachmentDescriptions),					// const VkAttachmentDescription*	pAttachments;
984 			static_cast<deUint32>(subpasses.size()),				// deUint32							subpassCount;
985 			dataOrNullPtr(subpasses),								// const VkSubpassDescription*		pSubpasses;
986 			0u,														// deUint32							dependencyCount;
987 			DE_NULL,												// const VkSubpassDependency*		pDependencies;
988 		};
989 
990 		renderPass  = createRenderPass(vk, device, &renderPassInfo);
991 		framebuffer = makeFramebuffer (vk, device, *renderPass, static_cast<deUint32>(attachments.size()), dataOrNullPtr(attachments), params.renderSize.x(), params.renderSize.y());
992 	}
993 
994 	std::vector<PipelineSp>			pipelines;
995 	const Unique<VkPipelineLayout>	pipelineLayout		(makePipelineLayout(vk, device));
996 	const Unique<VkShaderModule>	vertexModuleDraw	(createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
997 	const Unique<VkShaderModule>	fragmentModuleDraw	(createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
998 
999 	// Create pipelines for MS draw
1000 	for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
1001 	{
1002 		pipelines.push_back(PipelineSp(new Unique<VkPipeline>(
1003 			makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModuleDraw, *fragmentModuleDraw,
1004 								 true /*use vertex attribs*/, getVertexInputColorFormat(params.colorFormat), true/*use color attachment*/, layerNdx /*subpass*/,
1005 								 params.renderSize, params.numColorSamples))));
1006 	}
1007 
1008 	const Unique<VkCommandPool>		cmdPool		(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
1009 	const Unique<VkCommandBuffer>	cmdBuffer	(makeCommandBuffer(vk, device, *cmdPool));
1010 
1011 	beginCommandBuffer(vk, *cmdBuffer);
1012 
1013 	{
1014 		// Generate clear values
1015 		std::vector<VkClearValue> clearValues = genClearValues(params.colorFormat, params.numLayers);
1016 
1017 		const VkRect2D renderArea =
1018 		{
1019 			{ 0u, 0u },
1020 			{ params.renderSize.x(), params.renderSize.y() }
1021 		};
1022 
1023 		const VkRenderPassBeginInfo renderPassBeginInfo =
1024 		{
1025 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,			// VkStructureType         sType;
1026 			DE_NULL,											// const void*             pNext;
1027 			*renderPass,										// VkRenderPass            renderPass;
1028 			*framebuffer,										// VkFramebuffer           framebuffer;
1029 			renderArea,											// VkRect2D                renderArea;
1030 			static_cast<deUint32>(clearValues.size()),			// uint32_t                clearValueCount;
1031 			dataOrNullPtr(clearValues),							// const VkClearValue*     pClearValues;
1032 		};
1033 		vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1034 	}
1035 
1036 	{
1037 		const VkDeviceSize vertexBufferOffset = 0ull;
1038 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset);
1039 	}
1040 
1041 	for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
1042 	{
1043 		if (layerNdx != 0u)
1044 			vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1045 
1046 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[layerNdx]);
1047 		vk.cmdDraw(*cmdBuffer, wd.numVertices, 1u, 0u, layerNdx);	// pass instance index to slightly change geometry per layer
1048 	}
1049 
1050 	vk.cmdEndRenderPass(*cmdBuffer);
1051 
1052 	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1053 	submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1054 }
1055 
1056 //! Sample from an image in a compute shader, storing the result in a color buffer
dispatchSampleImage(Context & context,const TestParams & params,WorkingData & wd,const std::string & shaderName)1057 void dispatchSampleImage (Context& context, const TestParams& params, WorkingData& wd, const std::string& shaderName)
1058 {
1059 	const DeviceInterface&	vk		= context.getDeviceInterface();
1060 	const VkDevice			device	= context.getDevice();
1061 
1062 	// Create descriptor set
1063 
1064 	const Unique<VkDescriptorSetLayout> descriptorSetLayout(
1065 		DescriptorSetLayoutBuilder()
1066 		.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	VK_SHADER_STAGE_COMPUTE_BIT, &wd.defaultSampler.get())
1067 		.addSingleBinding		(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,			VK_SHADER_STAGE_COMPUTE_BIT)
1068 		.build(vk, device));
1069 
1070 	const Unique<VkDescriptorPool> descriptorPool(
1071 		DescriptorPoolBuilder()
1072 		.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1073 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1074 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1075 
1076 	const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1077 
1078 	{
1079 		const VkDescriptorImageInfo		colorImageInfo		= makeDescriptorImageInfo(DE_NULL, *wd.colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1080 		const VkDescriptorBufferInfo	resultBufferInfo	= makeDescriptorBufferInfo(*wd.colorBuffer, 0ull, wd.colorBufferSize);
1081 
1082 		DescriptorSetUpdateBuilder	builder;
1083 
1084 		builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &colorImageInfo);
1085 		builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,		  &resultBufferInfo);
1086 
1087 		builder.update(vk, device);
1088 	}
1089 
1090 	// Pipeline
1091 
1092 	const Unique<VkShaderModule>	shaderModule	(createShaderModule(vk, device, context.getBinaryCollection().get(shaderName), 0u));
1093 	const Unique<VkPipelineLayout>	pipelineLayout	(makePipelineLayout(vk, device, *descriptorSetLayout));
1094 	const Unique<VkPipeline>		pipeline		(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule, DE_NULL));
1095 
1096 	const Unique<VkCommandPool>		cmdPool		(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
1097 	const Unique<VkCommandBuffer>	cmdBuffer	(makeCommandBuffer(vk, device, *cmdPool));
1098 
1099 	beginCommandBuffer(vk, *cmdBuffer);
1100 
1101 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
1102 	vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1103 
1104 	vk.cmdDispatch(*cmdBuffer, params.renderSize.x(), params.renderSize.y(), params.numLayers);
1105 
1106 	{
1107 		const VkBufferMemoryBarrier barrier =
1108 		{
1109 			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// VkStructureType    sType;
1110 			DE_NULL,										// const void*        pNext;
1111 			VK_ACCESS_SHADER_WRITE_BIT,						// VkAccessFlags      srcAccessMask;
1112 			VK_ACCESS_HOST_READ_BIT,						// VkAccessFlags      dstAccessMask;
1113 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t           srcQueueFamilyIndex;
1114 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t           dstQueueFamilyIndex;
1115 			*wd.colorBuffer,								// VkBuffer           buffer;
1116 			0ull,											// VkDeviceSize       offset;
1117 			VK_WHOLE_SIZE,									// VkDeviceSize       size;
1118 		};
1119 
1120 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0,
1121 			(const VkMemoryBarrier*)DE_NULL, 1u, &barrier, 0u, (const VkImageMemoryBarrier*)DE_NULL);
1122 	}
1123 
1124 	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1125 	submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1126 
1127 	invalidateMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1128 }
1129 
1130 //! Get a single-sampled image access from a multisampled color buffer with samples packed per pixel
getSingleSampledAccess(const void * const imageData,const TestParams & params,const deUint32 sampleNdx,const deUint32 layerNdx)1131 tcu::ConstPixelBufferAccess getSingleSampledAccess (const void* const imageData, const TestParams& params, const deUint32 sampleNdx, const deUint32 layerNdx)
1132 {
1133 	const deUint32		numSamples	= static_cast<deUint32>(params.numColorSamples);
1134 	const deUint32		pixelSize	= tcu::getPixelSize(mapVkFormat(params.colorFormat));
1135 	const deUint32		rowSize		= pixelSize * params.renderSize.x();
1136 	const deUint32		layerSize	= rowSize * params.renderSize.y();
1137 	const deUint8*		src			= static_cast<const deUint8*>(imageData)
1138 									+ (layerNdx * numSamples * layerSize)
1139 									+ (sampleNdx * pixelSize);
1140 	const tcu::IVec3	size		(params.renderSize.x(), params.renderSize.y(), 1);
1141 	const tcu::IVec3	pitch		(numSamples * pixelSize,
1142 									 numSamples * rowSize,
1143 									 numSamples * layerSize);
1144 	return tcu::ConstPixelBufferAccess(mapVkFormat(params.colorFormat), size, pitch, src);
1145 }
1146 
test(Context & context,const TestParams params)1147 tcu::TestStatus test (Context& context, const TestParams params)
1148 {
1149 	WorkingData				wd;
1150 	const DeviceInterface&	vk		  = context.getDeviceInterface();
1151 	const VkDevice			device	  = context.getDevice();
1152 	MovePtr<Allocator>		allocator = MovePtr<Allocator>(new SimpleAllocator(vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
1153 
1154 	// Initialize resources
1155 	{
1156 		const VkImageUsageFlags	msImageUsage	= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
1157 												| VK_IMAGE_USAGE_SAMPLED_BIT
1158 												| (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT ? VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT : (VkImageUsageFlagBits)0);
1159 		wd.colorImage		= makeImage(vk, device, params.colorFormat, params.renderSize, params.numLayers, params.numColorSamples, msImageUsage);
1160 		wd.colorImageAlloc	= bindImage(vk, device, *allocator, *wd.colorImage, MemoryRequirement::Any);
1161 		wd.colorImageView	= makeImageView(vk, device, *wd.colorImage, (params.numLayers == 1u ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY), params.colorFormat,
1162 											makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.numLayers));
1163 
1164 		wd.defaultSampler	= makeSampler(vk, device);
1165 
1166 		// Color buffer is meant to hold data for all layers and all samples of the image.
1167 		// Data is tightly packed layer by layer, for each pixel all samples are laid out together starting with sample 0.
1168 		// E.g.: pixel(0,0)sample(0)sample(1), pixel(1,0)sample(0)sample(1), ...
1169 		wd.colorBufferSize	= static_cast<VkDeviceSize>(tcu::getPixelSize(mapVkFormat(params.colorFormat))
1170 														* params.renderSize.x() * params.renderSize.y() * params.numLayers * static_cast<deUint32>(params.numColorSamples));
1171 		wd.colorBuffer		= makeBuffer(vk, device, wd.colorBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1172 		wd.colorBufferAlloc	= bindBuffer(vk, device, *allocator, *wd.colorBuffer, MemoryRequirement::HostVisible);
1173 
1174 		deMemset(wd.colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(wd.colorBufferSize));
1175 		flushMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1176 
1177 		const std::vector<PositionColor>	vertices			= genShapes(params.colorFormat);
1178 		const VkDeviceSize					vertexBufferSize	= static_cast<VkDeviceSize>(sizeof(vertices[0]) * vertices.size());
1179 
1180 		wd.numVertices			= static_cast<deUint32>(vertices.size());
1181 		wd.vertexBuffer			= makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1182 		wd.vertexBufferAlloc	= bindBuffer(vk, device, *allocator, *wd.vertexBuffer, MemoryRequirement::HostVisible);
1183 
1184 		deMemcpy(wd.vertexBufferAlloc->getHostPtr(), dataOrNullPtr(vertices), static_cast<std::size_t>(vertexBufferSize));
1185 		flushMappedMemoryRange(vk, device, wd.vertexBufferAlloc->getMemory(), wd.vertexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1186 	}
1187 
1188 	if (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT)
1189 	{
1190 		// Create a multisample image and sample from it
1191 		drawAndSampleInputAttachment (context, params, wd);
1192 	}
1193 	else
1194 	{
1195 		// Draw the image, then sample from it in a CS
1196 		draw				(context, params, wd);
1197 		dispatchSampleImage (context, params, wd, "comp_fmask_fetch");
1198 	}
1199 
1200 	// Copy the result
1201 	std::vector<deUint8> fmaskFetchColorBuffer (static_cast<deUint32>(wd.colorBufferSize));
1202 	deMemcpy(&fmaskFetchColorBuffer[0], wd.colorBufferAlloc->getHostPtr(), static_cast<std::size_t>(wd.colorBufferSize));
1203 
1204 	// Clear the color buffer, just to be sure we're getting the new data
1205 	deMemset(wd.colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(wd.colorBufferSize));
1206 	flushMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1207 
1208 	// Sample image using the standard texel fetch
1209 	dispatchSampleImage (context, params, wd, "comp_fetch");
1210 
1211 	// Verify the images
1212 	{
1213 		const void* const fmaskResult	 = dataOrNullPtr(fmaskFetchColorBuffer);
1214 		const void* const expectedResult = wd.colorBufferAlloc->getHostPtr();
1215 
1216 		DE_ASSERT(!isFloatFormat(params.colorFormat));	// we're using int compare
1217 
1218 		// Mismatch, do image compare to pinpoint the failure
1219 		for (deUint32 layerNdx  = 0u; layerNdx  < params.numLayers;								 ++layerNdx)
1220 		for (deUint32 sampleNdx = 0u; sampleNdx < static_cast<deUint32>(params.numColorSamples); ++sampleNdx)
1221 		{
1222 			const std::string					imageName	= "layer_" + de::toString(layerNdx) + "_sample_" + de::toString(sampleNdx);
1223 			const std::string					imageDesc	= "Layer " + de::toString(layerNdx) + " Sample " + de::toString(sampleNdx);
1224 			const tcu::ConstPixelBufferAccess	expected	= getSingleSampledAccess(expectedResult, params, sampleNdx, layerNdx);
1225 			const tcu::ConstPixelBufferAccess	actual		= getSingleSampledAccess(fmaskResult,	 params, sampleNdx, layerNdx);
1226 			const UVec4							threshold	(0);	// should match exactly
1227 
1228 			const bool ok = tcu::intThresholdCompare(context.getTestContext().getLog(), imageName.c_str(), imageDesc.c_str(),
1229 													 expected, actual, threshold, tcu::COMPARE_LOG_RESULT);
1230 
1231 			if (!ok)
1232 				return tcu::TestStatus::fail("Some texels were incorrect");
1233 		}
1234 	}
1235 
1236 	return tcu::TestStatus::pass("Pass");
1237 }
1238 
getFormatShortString(const VkFormat format)1239 std::string getFormatShortString (const VkFormat format)
1240 {
1241 	std::string s(de::toLower(getFormatName(format)));
1242 	return s.substr(10);
1243 }
1244 
createShaderFragmentMaskTestsInGroup(tcu::TestCaseGroup * rootGroup)1245 void createShaderFragmentMaskTestsInGroup (tcu::TestCaseGroup* rootGroup)
1246 {
1247 	// Per spec, the following formats must support color attachment and sampled image
1248 	const VkFormat colorFormats[] =
1249 	{
1250 		VK_FORMAT_R8G8B8A8_UNORM,
1251 		VK_FORMAT_R32_UINT,
1252 		VK_FORMAT_R32_SINT,
1253 	};
1254 
1255 	const VkSampleCountFlagBits	sampleCounts[] =
1256 	{
1257 		VK_SAMPLE_COUNT_2_BIT,
1258 		VK_SAMPLE_COUNT_4_BIT,
1259 		VK_SAMPLE_COUNT_8_BIT,
1260 		VK_SAMPLE_COUNT_16_BIT,
1261 	};
1262 
1263 	const struct SourceCase
1264 	{
1265 		const char*			name;
1266 		deUint32			numLayers;
1267 		SampleSource		sampleSource;
1268 	} sourceCases[] =
1269 	{
1270 		{ "image_2d",		1u,	SAMPLE_SOURCE_IMAGE			},
1271 		{ "image_2d_array",	3u,	SAMPLE_SOURCE_IMAGE			},
1272 		{ "subpass_input",	1u,	SAMPLE_SOURCE_SUBPASS_INPUT	},
1273 	};
1274 
1275 	// Test 1: Compare fragments fetched via FMASK and an ordinary texel fetch
1276 	{
1277 		for (const VkSampleCountFlagBits* pSampleCount = sampleCounts; pSampleCount != DE_ARRAY_END(sampleCounts); ++pSampleCount)
1278 		{
1279 			MovePtr<tcu::TestCaseGroup> sampleCountGroup (new tcu::TestCaseGroup(rootGroup->getTestContext(), ("samples_" + de::toString(*pSampleCount)).c_str(), ""));
1280 			for (const SourceCase* pSourceCase = sourceCases; pSourceCase != DE_ARRAY_END(sourceCases); ++pSourceCase)
1281 			{
1282 				MovePtr<tcu::TestCaseGroup> sourceGroup (new tcu::TestCaseGroup(rootGroup->getTestContext(), pSourceCase->name, ""));
1283 				for (const VkFormat* pColorFormat = colorFormats; pColorFormat != DE_ARRAY_END(colorFormats); ++pColorFormat)
1284 				{
1285 					TestParams params;
1286 					params.renderSize		= UVec2(32, 32);
1287 					params.colorFormat		= *pColorFormat;
1288 					params.numColorSamples	= *pSampleCount;
1289 					params.numLayers		= pSourceCase->numLayers;
1290 					params.sampleSource		= pSourceCase->sampleSource;
1291 
1292 					addFunctionCaseWithPrograms(sourceGroup.get(), getFormatShortString(*pColorFormat), "", checkRequirements, initPrograms, test, params);
1293 				}
1294 				sampleCountGroup->addChild(sourceGroup.release());
1295 			}
1296 			rootGroup->addChild(sampleCountGroup.release());
1297 		}
1298 	}
1299 }
1300 
1301 } // anonymous ns
1302 
createMultisampleShaderFragmentMaskTests(tcu::TestContext & testCtx)1303 tcu::TestCaseGroup* createMultisampleShaderFragmentMaskTests (tcu::TestContext& testCtx)
1304 {
1305 	return createTestGroup(testCtx, "shader_fragment_mask", "Access raw texel values in a compressed MSAA surface", createShaderFragmentMaskTestsInGroup);
1306 }
1307 
1308 } // pipeline
1309 } // vkt
1310