• 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::__anon71da35050111::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::__anon71da35050111::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::__anon71da35050111::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::__anon71da35050111::TestParams396 	TestParams (void)
397 		: numLayers			()
398 		, sampleSource		(SAMPLE_SOURCE_IMAGE)
399 		, numColorSamples	()
400 		, colorFormat		()
401 	{
402 	}
403 };
404 
checkRequirements(Context & context,TestParams params)405 void checkRequirements (Context& context, TestParams params)
406 {
407 	context.requireDeviceFunctionality("VK_AMD_shader_fragment_mask");
408 
409 	// In the subpass input case we have to store fetch results into a buffer for subsequent verification in a compute shader.
410 	const bool requireFragmentStores = (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT);
411 
412 	const VkPhysicalDeviceLimits& limits = context.getDeviceProperties().limits;
413 
414 	if ((limits.framebufferColorSampleCounts & params.numColorSamples) == 0u)
415 		TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported");
416 
417 	if ((isIntFormat(params.colorFormat) || isUintFormat(params.colorFormat)))
418 	{
419 		if ((limits.sampledImageIntegerSampleCounts & params.numColorSamples) == 0u)
420 			TCU_THROW(NotSupportedError, "sampledImageIntegerSampleCounts: sample count not supported");
421 	}
422 	else
423 	{
424 		if ((limits.sampledImageColorSampleCounts & params.numColorSamples) == 0u)
425 			TCU_THROW(NotSupportedError, "sampledImageColorSampleCounts: sample count not supported");
426 	}
427 
428 	if (requireFragmentStores)
429 	{
430 		if (!context.getDeviceFeatures().fragmentStoresAndAtomics)
431 			TCU_THROW(NotSupportedError, "fragmentStoresAndAtomics: feature not supported");
432 	}
433 }
434 
435 //! Common data used by the test
436 struct WorkingData
437 {
438 	deUint32						numVertices;				//!< Number of vertices defined in the vertex buffer
439 	Move<VkBuffer>					vertexBuffer;
440 	MovePtr<Allocation>				vertexBufferAlloc;
441 	Move<VkImage>					colorImage;					//!< Color image
442 	MovePtr<Allocation>				colorImageAlloc;
443 	Move<VkImageView>				colorImageView;				//!< Color image view spanning all layers
444 	Move<VkBuffer>					colorBuffer;				//!< Buffer used to copy image data
445 	MovePtr<Allocation>				colorBufferAlloc;
446 	VkDeviceSize					colorBufferSize;
447 	Move<VkSampler>					defaultSampler;				//!< Dummy sampler, we are using texel fetches
448 
WorkingDatavkt::pipeline::__anon71da35050111::WorkingData449 	WorkingData (void)
450 		: numVertices		()
451 		, colorBufferSize	()
452 	{
453 	}
454 };
455 
initPrograms(SourceCollections & programCollection,const TestParams params)456 void initPrograms (SourceCollections& programCollection, const TestParams params)
457 {
458 	std::string	colorType;					//!< color pixel type used by image functions
459 	std::string	colorBufferType;			//!< packed pixel type as stored in a ssbo
460 	std::string colorBufferPack;			//!< a cast or a function call when writing back color format to the ssbo
461 	std::string	colorFragInQualifier;		//!< fragment shader color input qualifier
462 	std::string samplerPrefix;				//!< u, i, or empty
463 
464 	switch (params.colorFormat)
465 	{
466 		case VK_FORMAT_R8G8B8A8_UNORM:
467 			colorType				= "vec4";
468 			colorBufferType			= "uint";
469 			colorBufferPack			= "packUnorm4x8";
470 			break;
471 
472 		case VK_FORMAT_R32_UINT:
473 			colorType				= "uint";
474 			colorBufferType			= "uint";
475 			colorBufferPack			= colorBufferType;
476 			colorFragInQualifier	= "flat";
477 			samplerPrefix			= "u";
478 			break;
479 
480 		case VK_FORMAT_R32_SINT:
481 			colorType				= "int";
482 			colorBufferType			= "int";
483 			colorBufferPack			= colorBufferType;
484 			colorFragInQualifier	= "flat";
485 			samplerPrefix			= "i";
486 			break;
487 
488 		default:
489 			DE_FATAL("initPrograms not handled for this color format");
490 			break;
491 	}
492 
493 	// Vertex shader - position and color
494 	{
495 		std::ostringstream src;
496 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
497 			<< "\n"
498 			<< "layout(location = 0) in  vec4 in_position;\n"
499 			<< "layout(location = 1) in  " << colorType << " in_color;\n"
500 			<< "layout(location = 0) out " << colorType << " o_color;\n"
501 			<< "\n"
502 			<< "out gl_PerVertex {\n"
503 			<< "    vec4 gl_Position;\n"
504 			<< "};\n"
505 			<< "\n"
506 			<< "void main(void)\n"
507 			<< "{\n"
508 			// Introduce a variance in geometry per instance index which maps to the image layer
509 			<< "    float a   = 0.25 * float(gl_InstanceIndex);\n"
510 			<< "    mat3 rm   = mat3( cos(a), sin(a), 0.0,\n"
511 			<< "                     -sin(a), cos(a), 0.0,\n"
512 			<< "                         0.0,    0.0, 1.0);\n"
513 			<< "    vec2 rpos = (rm * vec3(in_position.xy, 1.0)).xy;\n"
514 			<< "\n"
515 			<< "    gl_Position = vec4(rpos, in_position.zw);\n"
516 			<< "    o_color     = in_color;\n"
517 			<< "}\n";
518 
519 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
520 	}
521 
522 	// Vertex shader - no vertex data, fill viewport with one primitive
523 	{
524 		std::ostringstream src;
525 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
526 			<< "\n"
527 			<< "out gl_PerVertex {\n"
528 			<< "    vec4 gl_Position;\n"
529 			<< "};\n"
530 			<< "\n"
531 			<< "void main(void)\n"
532 			<< "{\n"
533 			// Specify an oversized triangle covering the whole viewport.
534 			<< "    switch (gl_VertexIndex)\n"
535 			<< "    {\n"
536 			<< "        case 0:\n"
537 			<< "            gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
538 			<< "            break;\n"
539 			<< "        case 1:\n"
540 			<< "            gl_Position = vec4(-1.0,  3.0, 0.0, 1.0);\n"
541 			<< "            break;\n"
542 			<< "        case 2:\n"
543 			<< "            gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
544 			<< "            break;\n"
545 			<< "    }\n"
546 			<< "}\n";
547 
548 		programCollection.glslSources.add("vert_full") << glu::VertexSource(src.str());
549 	}
550 
551 	// Fragment shader - output color from VS
552 	{
553 		std::ostringstream src;
554 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
555 			<< "\n"
556 			<< "layout(location = 0) in " << colorFragInQualifier << " " << colorType << " in_color;\n"
557 			<< "layout(location = 0) out " << colorType << " o_color;\n"
558 			<< "\n"
559 			<< "void main(void)\n"
560 			<< "{\n"
561 			<< "    o_color = in_color;\n"
562 			<< "}\n";
563 
564 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
565 	}
566 
567 	// Fragment shader - FMASK fetch from an input attachment
568 	if (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT)
569 	{
570 		std::ostringstream src;
571 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
572 			<< "#extension GL_AMD_shader_fragment_mask : enable\n"
573 			<< "\n"
574 			<< "layout(set = 0, binding = 0) uniform " << samplerPrefix << "sampler2DMS" << (params.numLayers > 1 ? "Array" : "") << " u_image;\n"
575 			<< "layout(set = 0, binding = 1, std430) writeonly buffer ColorOutput {\n"
576 			<< "    " << colorBufferType << " color[];\n"
577 			<< "} sb_out;\n"
578 			<< "layout(input_attachment_index = " << params.numLayers << ", set = 0, binding = 2) uniform " << samplerPrefix << "subpassInputMS" << " input_attach;\n"
579 			<< "\n"
580 			<< "void main(void)\n"
581 			<< "{\n"
582 			<< "    ivec2 p            = ivec2(gl_FragCoord.xy);\n"
583 			<< "    int   width        = " << params.renderSize.x() << ";\n"
584 			<< "    int   numSamples   = " << static_cast<deUint32>(params.numColorSamples) << ";\n"
585 			<< "    int   colorOutNdx  = numSamples * (p.x + width * p.y);\n"
586 			<< "\n"
587 			<< "    uint mask = fragmentMaskFetchAMD(input_attach);\n"
588 			<< "    for (int sampleNdx = 0; sampleNdx < numSamples; ++sampleNdx)\n"
589 			<< "    {\n"
590 			<< "        int fragNdx = int((mask >> (4 * sampleNdx)) & 0xf);\n"
591 			<< "        " << samplerPrefix << "vec4 color = fragmentFetchAMD(input_attach, fragNdx);\n"
592 			<< "        sb_out.color[colorOutNdx + sampleNdx] = " << colorBufferPack << "(color);\n"
593 			<< "    }\n"
594 			<< "}\n";
595 
596 		programCollection.glslSources.add("frag_fmask_fetch") << glu::FragmentSource(src.str());
597 	}
598 
599 	// Generate compute shaders
600 	const struct ComputeShaderParams
601 	{
602 		const char*		name;
603 		bool			isFmaskFetch;
604 		bool			enabled;
605 	} computeShaders[] =
606 	{
607 		// name					// FMASK?	// enabled?
608 		{ "comp_fetch",			false,		true,													},
609 		{ "comp_fmask_fetch",	true,		(params.sampleSource != SAMPLE_SOURCE_SUBPASS_INPUT)	},
610 	};
611 
612 	for (const ComputeShaderParams* pShaderParams = computeShaders; pShaderParams != DE_ARRAY_END(computeShaders); ++pShaderParams)
613 	if (pShaderParams->enabled)
614 	{
615 		const std::string samplingPos = (params.numLayers == 1 ? "ivec2(gl_WorkGroupID.xy)"
616 															   : "ivec3(gl_WorkGroupID)");
617 		std::ostringstream src;
618 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
619 			<< (pShaderParams->isFmaskFetch ? "#extension GL_AMD_shader_fragment_mask : enable\n" : "")
620 			<< "#define NUM_SAMPLES " << static_cast<deUint32>(params.numColorSamples) << "\n"
621 			<< "\n"
622 			<< "layout(local_size_x = NUM_SAMPLES) in;\n"	// one work group per pixel, each sample gets a local invocation
623 			<< "\n"
624 			<< "layout(set = 0, binding = 0) uniform " << samplerPrefix << "sampler2DMS" << (params.numLayers > 1 ? "Array" : "") << " u_image;\n"
625 			<< "layout(set = 0, binding = 1, std430) writeonly buffer ColorOutput {\n"
626 			<< "    " << colorBufferType << " color[];\n"
627 			<< "} sb_out;\n"
628 			<< "\n"
629 			<< "void main(void)\n"
630 			<< "{\n"
631 			<< "    int sampleNdx   = int(gl_LocalInvocationID.x);\n"
632 			<< "    int colorOutNdx = NUM_SAMPLES * int(gl_WorkGroupID.x +\n"
633 			<< "                                        gl_WorkGroupID.y * gl_NumWorkGroups.x +\n"
634 			<< "                                        gl_WorkGroupID.z * gl_NumWorkGroups.x * gl_NumWorkGroups.y);\n"
635 			<< "\n";
636 		if (pShaderParams->isFmaskFetch)
637 		{
638 			src << "    uint  mask    = fragmentMaskFetchAMD(u_image, " << samplingPos << ");\n"
639 				<< "    int   fragNdx = int((mask >> (4 * sampleNdx)) & 0xf);\n"
640 				<< "    " << samplerPrefix << "vec4 color = fragmentFetchAMD(u_image, " << samplingPos << ", fragNdx);\n"
641 				<< "    sb_out.color[colorOutNdx + sampleNdx] = " << colorBufferPack << "(color);\n";
642 		}
643 		else
644 		{
645 			src << "    " << samplerPrefix << "vec4 color = texelFetch(u_image, " << samplingPos << ", sampleNdx);\n"
646 				<< "    sb_out.color[colorOutNdx + sampleNdx] = " << colorBufferPack << "(color);\n";
647 		}
648 		src << "}\n";
649 
650 		programCollection.glslSources.add(pShaderParams->name) << glu::ComputeSource(src.str());
651 	}
652 }
653 
genClearValues(const VkFormat format,const deUint32 count)654 std::vector<VkClearValue> genClearValues (const VkFormat format, const deUint32 count)
655 {
656 	std::vector<VkClearValue>	clearValues;
657 	de::Random					rng (332);
658 
659 	switch (format)
660 	{
661 		case VK_FORMAT_R8G8B8A8_UNORM:
662 			for (deUint32 i = 0u; i < count; ++i)
663 				clearValues.push_back(makeClearValueColorF32(rng.getFloat(), rng.getFloat(), rng.getFloat(), 1.0f));
664 			break;
665 
666 		case VK_FORMAT_R32_UINT:
667 		case VK_FORMAT_R32_SINT:
668 			for (deUint32 i = 0u; i < count; ++i)
669 				clearValues.push_back(makeClearValueColorU32(rng.getUint32(), 0u, 0u, 0u));
670 			break;
671 
672 		default:
673 			DE_FATAL("Clear color not defined for this format");
674 			break;
675 	}
676 
677 	return clearValues;
678 }
679 
680 //! For subpass load case draw and fetch must happen within the same render pass.
drawAndSampleInputAttachment(Context & context,const TestParams & params,WorkingData & wd)681 void drawAndSampleInputAttachment (Context& context, const TestParams& params, WorkingData& wd)
682 {
683 	DE_ASSERT(params.numLayers == 1u);	// subpass load with single-layer image
684 
685 	const DeviceInterface&	vk		= context.getDeviceInterface();
686 	const VkDevice			device	= context.getDevice();
687 
688 	Move<VkRenderPass>		renderPass;
689 	Move<VkFramebuffer>		framebuffer;
690 
691 	// Create descriptor set
692 	const Unique<VkDescriptorSetLayout> descriptorSetLayout (DescriptorSetLayoutBuilder()
693 		.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	VK_SHADER_STAGE_FRAGMENT_BIT, &wd.defaultSampler.get())
694 		.addSingleBinding		(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,			VK_SHADER_STAGE_FRAGMENT_BIT)
695 		.addSingleBinding		(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,		VK_SHADER_STAGE_FRAGMENT_BIT)
696 		.build(vk, device));
697 
698 	const Unique<VkDescriptorPool> descriptorPool (DescriptorPoolBuilder()
699 		.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
700 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
701 		.addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
702 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
703 
704 	const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
705 
706 	{
707 		const VkDescriptorImageInfo		colorImageInfo	= makeDescriptorImageInfo(DE_NULL, *wd.colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
708 		const VkDescriptorBufferInfo	bufferInfo		= makeDescriptorBufferInfo(*wd.colorBuffer, 0u, wd.colorBufferSize);
709 
710 		DescriptorSetUpdateBuilder	builder;
711 
712 		builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &colorImageInfo);
713 		builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,		 &bufferInfo);
714 
715 		if (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT)
716 			builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &colorImageInfo);
717 
718 		builder.update(vk, device);
719 	}
720 
721 	// Create a render pass and a framebuffer
722 	{
723 		std::vector<VkSubpassDescription>		subpasses;
724 		std::vector<VkSubpassDependency>		subpassDependencies;
725 		std::vector<VkImageView>				attachments;
726 		std::vector<VkAttachmentDescription>	attachmentDescriptions;
727 		std::vector<VkAttachmentReference>		attachmentReferences;
728 
729 		// Reserve capacity to avoid invalidating pointers to elements
730 		attachmentReferences.reserve(2);	// color image + input attachment
731 
732 		// Create a MS draw subpass
733 		{
734 			attachments.push_back(*wd.colorImageView);
735 
736 			attachmentDescriptions.push_back(makeAttachmentDescription(
737 				(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFlags		flags;
738 				params.colorFormat,												// VkFormat							format;
739 				params.numColorSamples,											// VkSampleCountFlagBits			samples;
740 				VK_ATTACHMENT_LOAD_OP_CLEAR,									// VkAttachmentLoadOp				loadOp;
741 				VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp				storeOp;
742 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp				stencilLoadOp;
743 				VK_ATTACHMENT_STORE_OP_DONT_CARE,								// VkAttachmentStoreOp				stencilStoreOp;
744 				VK_IMAGE_LAYOUT_UNDEFINED,										// VkImageLayout					initialLayout;
745 				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL						// VkImageLayout					finalLayout;
746 			));
747 
748 			attachmentReferences.push_back(makeAttachmentReference(static_cast<deUint32>(attachmentReferences.size()),	VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
749 			const VkAttachmentReference* colorRef = &attachmentReferences.back();
750 
751 			const VkSubpassDescription subpassDescription =
752 			{
753 				(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags       flags;
754 				VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint             pipelineBindPoint;
755 				0u,													// uint32_t                        inputAttachmentCount;
756 				DE_NULL,											// const VkAttachmentReference*    pInputAttachments;
757 				1u,													// uint32_t                        colorAttachmentCount;
758 				colorRef,											// const VkAttachmentReference*    pColorAttachments;
759 				DE_NULL,											// const VkAttachmentReference*    pResolveAttachments;
760 				DE_NULL,											// const VkAttachmentReference*    pDepthStencilAttachment;
761 				0u,													// uint32_t                        preserveAttachmentCount;
762 				DE_NULL,											// const uint32_t*                 pPreserveAttachments;
763 			};
764 
765 			subpasses.push_back(subpassDescription);
766 		}
767 
768 		// Create a sampling subpass
769 		{
770 			attachmentReferences.push_back(makeAttachmentReference(0u, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL));
771 			const VkAttachmentReference* inputRef = &attachmentReferences.back();
772 
773 			// No color attachment, side effects only
774 			VkSubpassDescription subpassDescription =
775 			{
776 				(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags       flags;
777 				VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint             pipelineBindPoint;
778 				1u,													// uint32_t                        inputAttachmentCount;
779 				inputRef,											// const VkAttachmentReference*    pInputAttachments;
780 				0u,													// uint32_t                        colorAttachmentCount;
781 				DE_NULL,											// const VkAttachmentReference*    pColorAttachments;
782 				DE_NULL,											// const VkAttachmentReference*    pResolveAttachments;
783 				DE_NULL,											// const VkAttachmentReference*    pDepthStencilAttachment;
784 				0u,													// uint32_t                        preserveAttachmentCount;
785 				DE_NULL,											// const uint32_t*                 pPreserveAttachments;
786 			};
787 
788 			subpasses.push_back(subpassDescription);
789 		}
790 
791 		// Serialize the subpasses
792 		{
793 			const VkAccessFlags	dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
794 											  | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
795 											  | VK_ACCESS_SHADER_WRITE_BIT;
796 			const VkSubpassDependency	dependency	=
797 			{
798 				0u,																							// uint32_t                srcSubpass;
799 				1u,																							// uint32_t                dstSubpass;
800 				VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,		// VkPipelineStageFlags    srcStageMask;
801 				VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,														// VkPipelineStageFlags    dstStageMask;
802 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,														// VkAccessFlags           srcAccessMask;
803 				dstAccessMask,																				// VkAccessFlags           dstAccessMask;
804 				VK_DEPENDENCY_BY_REGION_BIT,																// VkDependencyFlags       dependencyFlags;
805 			};
806 			subpassDependencies.push_back(dependency);
807 		}
808 
809 		VkRenderPassCreateInfo renderPassInfo =
810 		{
811 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,				// VkStructureType					sType;
812 			DE_NULL,												// const void*						pNext;
813 			(VkRenderPassCreateFlags)0,								// VkRenderPassCreateFlags			flags;
814 			static_cast<deUint32>(attachmentDescriptions.size()),	// deUint32							attachmentCount;
815 			dataOrNullPtr(attachmentDescriptions),					// const VkAttachmentDescription*	pAttachments;
816 			static_cast<deUint32>(subpasses.size()),				// deUint32							subpassCount;
817 			dataOrNullPtr(subpasses),								// const VkSubpassDescription*		pSubpasses;
818 			static_cast<deUint32>(subpassDependencies.size()),		// deUint32							dependencyCount;
819 			dataOrNullPtr(subpassDependencies),						// const VkSubpassDependency*		pDependencies;
820 		};
821 
822 		renderPass  = createRenderPass(vk, device, &renderPassInfo);
823 		framebuffer = makeFramebuffer (vk, device, *renderPass, static_cast<deUint32>(attachments.size()), dataOrNullPtr(attachments), params.renderSize.x(), params.renderSize.y());
824 	}
825 
826 	const Unique<VkShaderModule>	vertexModuleDraw	(createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
827 	const Unique<VkShaderModule>	fragmentModuleDraw	(createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
828 
829 	// Create pipelines for MS draw
830 	const Unique<VkPipelineLayout>	pipelineLayout		(makePipelineLayout(vk, device, *descriptorSetLayout));
831 	const Unique<VkPipeline>		pipelineDraw		(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModuleDraw, *fragmentModuleDraw,
832 																			  true/*use vertex attribs*/, getVertexInputColorFormat(params.colorFormat), true/*use color attach*/, 0u/*subpass*/,
833 																			  params.renderSize, params.numColorSamples));
834 
835 	// Sampling pass is single-sampled, output to storage buffer
836 	const Unique<VkShaderModule>	vertexModuleSample		(createShaderModule(vk, device, context.getBinaryCollection().get("vert_full"), 0u));
837 	const Unique<VkShaderModule>	fragmentModuleSample	(createShaderModule(vk, device, context.getBinaryCollection().get("frag_fmask_fetch"), 0u));
838 
839 	// Sampling pipeline
840 	const Unique<VkPipeline>		pipelineSample		(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModuleSample, *fragmentModuleSample,
841 																			  false/*use vertex attribs*/, VK_FORMAT_UNDEFINED, false/*no color output*/, 1u/*subpass*/,
842 																			  params.renderSize, VK_SAMPLE_COUNT_1_BIT));
843 
844 	const Unique<VkCommandPool>		cmdPool		(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
845 	const Unique<VkCommandBuffer>	cmdBuffer	(makeCommandBuffer(vk, device, *cmdPool));
846 
847 	beginCommandBuffer(vk, *cmdBuffer);
848 
849 	{
850 		// Generate clear values
851 		std::vector<VkClearValue> clearValues = genClearValues(params.colorFormat, params.numLayers);
852 
853 		const VkRect2D renderArea =
854 		{
855 			{ 0u, 0u },
856 			{ params.renderSize.x(), params.renderSize.y() }
857 		};
858 
859 		const VkRenderPassBeginInfo renderPassBeginInfo =
860 		{
861 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,			// VkStructureType         sType;
862 			DE_NULL,											// const void*             pNext;
863 			*renderPass,										// VkRenderPass            renderPass;
864 			*framebuffer,										// VkFramebuffer           framebuffer;
865 			renderArea,											// VkRect2D                renderArea;
866 			static_cast<deUint32>(clearValues.size()),			// uint32_t                clearValueCount;
867 			dataOrNullPtr(clearValues),							// const VkClearValue*     pClearValues;
868 		};
869 		vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
870 	}
871 
872 	vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
873 
874 	{
875 		const VkDeviceSize vertexBufferOffset = 0ull;
876 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset);
877 	}
878 
879 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineDraw);
880 	vk.cmdDraw(*cmdBuffer, wd.numVertices, 1u, 0u, 0u);
881 
882 	vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
883 
884 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineSample);
885 	vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u);	// fill the framebuffer, geometry defined in the VS
886 
887 	vk.cmdEndRenderPass(*cmdBuffer);
888 
889 	// Buffer write barrier
890 	{
891 		const VkBufferMemoryBarrier barrier =
892 		{
893 			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// VkStructureType    sType;
894 			DE_NULL,										// const void*        pNext;
895 			VK_ACCESS_SHADER_WRITE_BIT,						// VkAccessFlags      srcAccessMask;
896 			VK_ACCESS_HOST_READ_BIT,						// VkAccessFlags      dstAccessMask;
897 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t           srcQueueFamilyIndex;
898 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t           dstQueueFamilyIndex;
899 			*wd.colorBuffer,								// VkBuffer           buffer;
900 			0ull,											// VkDeviceSize       offset;
901 			VK_WHOLE_SIZE,									// VkDeviceSize       size;
902 		};
903 
904 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 1u, &barrier, DE_NULL, 0u);
905 	}
906 
907 	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
908 	submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
909 
910 	invalidateMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
911 }
912 
913 //! Only draw a multisampled image
draw(Context & context,const TestParams & params,WorkingData & wd)914 void draw (Context& context, const TestParams& params, WorkingData& wd)
915 {
916 	const DeviceInterface&	vk		= context.getDeviceInterface();
917 	const VkDevice			device	= context.getDevice();
918 
919 	std::vector<ImageViewSp>	imageViews;
920 	Move<VkRenderPass>			renderPass;
921 	Move<VkFramebuffer>			framebuffer;
922 
923 	// Create color attachments
924 	for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
925 	{
926 		imageViews.push_back(ImageViewSp(new Unique<VkImageView>(
927 			makeImageView(vk, device, *wd.colorImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u)))));
928 	}
929 
930 	// Create a render pass and a framebuffer
931 	{
932 		std::vector<VkSubpassDescription>		subpasses;
933 		std::vector<VkImageView>				attachments;
934 		std::vector<VkAttachmentDescription>	attachmentDescriptions;
935 		std::vector<VkAttachmentReference>		attachmentReferences;
936 
937 		// Reserve capacity to avoid invalidating pointers to elements
938 		attachmentReferences.reserve(params.numLayers);
939 
940 		// Create MS draw subpasses
941 		for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
942 		{
943 			attachments.push_back(**imageViews[layerNdx]);
944 
945 			attachmentDescriptions.push_back(makeAttachmentDescription(
946 				(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFlags		flags;
947 				params.colorFormat,												// VkFormat							format;
948 				params.numColorSamples,											// VkSampleCountFlagBits			samples;
949 				VK_ATTACHMENT_LOAD_OP_CLEAR,									// VkAttachmentLoadOp				loadOp;
950 				VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp				storeOp;
951 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp				stencilLoadOp;
952 				VK_ATTACHMENT_STORE_OP_DONT_CARE,								// VkAttachmentStoreOp				stencilStoreOp;
953 				VK_IMAGE_LAYOUT_UNDEFINED,										// VkImageLayout					initialLayout;
954 				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL						// VkImageLayout					finalLayout;
955 			));
956 
957 			attachmentReferences.push_back(makeAttachmentReference(static_cast<deUint32>(attachmentReferences.size()),	VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
958 			const VkAttachmentReference* colorRef = &attachmentReferences.back();
959 
960 			const VkSubpassDescription subpassDescription =
961 			{
962 				(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags       flags;
963 				VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint             pipelineBindPoint;
964 				0u,													// uint32_t                        inputAttachmentCount;
965 				DE_NULL,											// const VkAttachmentReference*    pInputAttachments;
966 				1u,													// uint32_t                        colorAttachmentCount;
967 				colorRef,											// const VkAttachmentReference*    pColorAttachments;
968 				DE_NULL,											// const VkAttachmentReference*    pResolveAttachments;
969 				DE_NULL,											// const VkAttachmentReference*    pDepthStencilAttachment;
970 				0u,													// uint32_t                        preserveAttachmentCount;
971 				DE_NULL,											// const uint32_t*                 pPreserveAttachments;
972 			};
973 
974 			subpasses.push_back(subpassDescription);
975 		}
976 
977 		// All MS image drawing subpasses are independent
978 		VkRenderPassCreateInfo renderPassInfo =
979 		{
980 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,				// VkStructureType					sType;
981 			DE_NULL,												// const void*						pNext;
982 			(VkRenderPassCreateFlags)0,								// VkRenderPassCreateFlags			flags;
983 			static_cast<deUint32>(attachmentDescriptions.size()),	// deUint32							attachmentCount;
984 			dataOrNullPtr(attachmentDescriptions),					// const VkAttachmentDescription*	pAttachments;
985 			static_cast<deUint32>(subpasses.size()),				// deUint32							subpassCount;
986 			dataOrNullPtr(subpasses),								// const VkSubpassDescription*		pSubpasses;
987 			0u,														// deUint32							dependencyCount;
988 			DE_NULL,												// const VkSubpassDependency*		pDependencies;
989 		};
990 
991 		renderPass  = createRenderPass(vk, device, &renderPassInfo);
992 		framebuffer = makeFramebuffer (vk, device, *renderPass, static_cast<deUint32>(attachments.size()), dataOrNullPtr(attachments), params.renderSize.x(), params.renderSize.y());
993 	}
994 
995 	std::vector<PipelineSp>			pipelines;
996 	const Unique<VkPipelineLayout>	pipelineLayout		(makePipelineLayout(vk, device));
997 	const Unique<VkShaderModule>	vertexModuleDraw	(createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
998 	const Unique<VkShaderModule>	fragmentModuleDraw	(createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
999 
1000 	// Create pipelines for MS draw
1001 	for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
1002 	{
1003 		pipelines.push_back(PipelineSp(new Unique<VkPipeline>(
1004 			makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModuleDraw, *fragmentModuleDraw,
1005 								 true /*use vertex attribs*/, getVertexInputColorFormat(params.colorFormat), true/*use color attachment*/, layerNdx /*subpass*/,
1006 								 params.renderSize, params.numColorSamples))));
1007 	}
1008 
1009 	const Unique<VkCommandPool>		cmdPool		(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
1010 	const Unique<VkCommandBuffer>	cmdBuffer	(makeCommandBuffer(vk, device, *cmdPool));
1011 
1012 	beginCommandBuffer(vk, *cmdBuffer);
1013 
1014 	{
1015 		// Generate clear values
1016 		std::vector<VkClearValue> clearValues = genClearValues(params.colorFormat, params.numLayers);
1017 
1018 		const VkRect2D renderArea =
1019 		{
1020 			{ 0u, 0u },
1021 			{ params.renderSize.x(), params.renderSize.y() }
1022 		};
1023 
1024 		const VkRenderPassBeginInfo renderPassBeginInfo =
1025 		{
1026 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,			// VkStructureType         sType;
1027 			DE_NULL,											// const void*             pNext;
1028 			*renderPass,										// VkRenderPass            renderPass;
1029 			*framebuffer,										// VkFramebuffer           framebuffer;
1030 			renderArea,											// VkRect2D                renderArea;
1031 			static_cast<deUint32>(clearValues.size()),			// uint32_t                clearValueCount;
1032 			dataOrNullPtr(clearValues),							// const VkClearValue*     pClearValues;
1033 		};
1034 		vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1035 	}
1036 
1037 	{
1038 		const VkDeviceSize vertexBufferOffset = 0ull;
1039 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset);
1040 	}
1041 
1042 	for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
1043 	{
1044 		if (layerNdx != 0u)
1045 			vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1046 
1047 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[layerNdx]);
1048 		vk.cmdDraw(*cmdBuffer, wd.numVertices, 1u, 0u, layerNdx);	// pass instance index to slightly change geometry per layer
1049 	}
1050 
1051 	vk.cmdEndRenderPass(*cmdBuffer);
1052 
1053 	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1054 	submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1055 }
1056 
1057 //! 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)1058 void dispatchSampleImage (Context& context, const TestParams& params, WorkingData& wd, const std::string& shaderName)
1059 {
1060 	const DeviceInterface&	vk		= context.getDeviceInterface();
1061 	const VkDevice			device	= context.getDevice();
1062 
1063 	// Create descriptor set
1064 
1065 	const Unique<VkDescriptorSetLayout> descriptorSetLayout(
1066 		DescriptorSetLayoutBuilder()
1067 		.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	VK_SHADER_STAGE_COMPUTE_BIT, &wd.defaultSampler.get())
1068 		.addSingleBinding		(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,			VK_SHADER_STAGE_COMPUTE_BIT)
1069 		.build(vk, device));
1070 
1071 	const Unique<VkDescriptorPool> descriptorPool(
1072 		DescriptorPoolBuilder()
1073 		.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1074 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1075 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1076 
1077 	const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1078 
1079 	{
1080 		const VkDescriptorImageInfo		colorImageInfo		= makeDescriptorImageInfo(DE_NULL, *wd.colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1081 		const VkDescriptorBufferInfo	resultBufferInfo	= makeDescriptorBufferInfo(*wd.colorBuffer, 0ull, wd.colorBufferSize);
1082 
1083 		DescriptorSetUpdateBuilder	builder;
1084 
1085 		builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &colorImageInfo);
1086 		builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,		  &resultBufferInfo);
1087 
1088 		builder.update(vk, device);
1089 	}
1090 
1091 	// Pipeline
1092 
1093 	const Unique<VkShaderModule>	shaderModule	(createShaderModule(vk, device, context.getBinaryCollection().get(shaderName), 0u));
1094 	const Unique<VkPipelineLayout>	pipelineLayout	(makePipelineLayout(vk, device, *descriptorSetLayout));
1095 	const Unique<VkPipeline>		pipeline		(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule, DE_NULL));
1096 
1097 	const Unique<VkCommandPool>		cmdPool		(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
1098 	const Unique<VkCommandBuffer>	cmdBuffer	(makeCommandBuffer(vk, device, *cmdPool));
1099 
1100 	beginCommandBuffer(vk, *cmdBuffer);
1101 
1102 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
1103 	vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1104 
1105 	vk.cmdDispatch(*cmdBuffer, params.renderSize.x(), params.renderSize.y(), params.numLayers);
1106 
1107 	{
1108 		const VkBufferMemoryBarrier barrier =
1109 		{
1110 			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// VkStructureType    sType;
1111 			DE_NULL,										// const void*        pNext;
1112 			VK_ACCESS_SHADER_WRITE_BIT,						// VkAccessFlags      srcAccessMask;
1113 			VK_ACCESS_HOST_READ_BIT,						// VkAccessFlags      dstAccessMask;
1114 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t           srcQueueFamilyIndex;
1115 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t           dstQueueFamilyIndex;
1116 			*wd.colorBuffer,								// VkBuffer           buffer;
1117 			0ull,											// VkDeviceSize       offset;
1118 			VK_WHOLE_SIZE,									// VkDeviceSize       size;
1119 		};
1120 
1121 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0,
1122 			(const VkMemoryBarrier*)DE_NULL, 1u, &barrier, 0u, (const VkImageMemoryBarrier*)DE_NULL);
1123 	}
1124 
1125 	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1126 	submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1127 
1128 	invalidateMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1129 }
1130 
1131 //! 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)1132 tcu::ConstPixelBufferAccess getSingleSampledAccess (const void* const imageData, const TestParams& params, const deUint32 sampleNdx, const deUint32 layerNdx)
1133 {
1134 	const deUint32		numSamples	= static_cast<deUint32>(params.numColorSamples);
1135 	const deUint32		pixelSize	= tcu::getPixelSize(mapVkFormat(params.colorFormat));
1136 	const deUint32		rowSize		= pixelSize * params.renderSize.x();
1137 	const deUint32		layerSize	= rowSize * params.renderSize.y();
1138 	const deUint8*		src			= static_cast<const deUint8*>(imageData)
1139 									+ (layerNdx * numSamples * layerSize)
1140 									+ (sampleNdx * pixelSize);
1141 	const tcu::IVec3	size		(params.renderSize.x(), params.renderSize.y(), 1);
1142 	const tcu::IVec3	pitch		(numSamples * pixelSize,
1143 									 numSamples * rowSize,
1144 									 numSamples * layerSize);
1145 	return tcu::ConstPixelBufferAccess(mapVkFormat(params.colorFormat), size, pitch, src);
1146 }
1147 
test(Context & context,const TestParams params)1148 tcu::TestStatus test (Context& context, const TestParams params)
1149 {
1150 	WorkingData				wd;
1151 	const DeviceInterface&	vk		  = context.getDeviceInterface();
1152 	const VkDevice			device	  = context.getDevice();
1153 	MovePtr<Allocator>		allocator = MovePtr<Allocator>(new SimpleAllocator(vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
1154 
1155 	// Initialize resources
1156 	{
1157 		const VkImageUsageFlags	msImageUsage	= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
1158 												| VK_IMAGE_USAGE_SAMPLED_BIT
1159 												| (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT ? VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT : (VkImageUsageFlagBits)0);
1160 		wd.colorImage		= makeImage(vk, device, params.colorFormat, params.renderSize, params.numLayers, params.numColorSamples, msImageUsage);
1161 		wd.colorImageAlloc	= bindImage(vk, device, *allocator, *wd.colorImage, MemoryRequirement::Any);
1162 		wd.colorImageView	= makeImageView(vk, device, *wd.colorImage, (params.numLayers == 1u ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY), params.colorFormat,
1163 											makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.numLayers));
1164 
1165 		wd.defaultSampler	= makeSampler(vk, device);
1166 
1167 		// Color buffer is meant to hold data for all layers and all samples of the image.
1168 		// Data is tightly packed layer by layer, for each pixel all samples are laid out together starting with sample 0.
1169 		// E.g.: pixel(0,0)sample(0)sample(1), pixel(1,0)sample(0)sample(1), ...
1170 		wd.colorBufferSize	= static_cast<VkDeviceSize>(tcu::getPixelSize(mapVkFormat(params.colorFormat))
1171 														* params.renderSize.x() * params.renderSize.y() * params.numLayers * static_cast<deUint32>(params.numColorSamples));
1172 		wd.colorBuffer		= makeBuffer(vk, device, wd.colorBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1173 		wd.colorBufferAlloc	= bindBuffer(vk, device, *allocator, *wd.colorBuffer, MemoryRequirement::HostVisible);
1174 
1175 		deMemset(wd.colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(wd.colorBufferSize));
1176 		flushMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1177 
1178 		const std::vector<PositionColor>	vertices			= genShapes(params.colorFormat);
1179 		const VkDeviceSize					vertexBufferSize	= static_cast<VkDeviceSize>(sizeof(vertices[0]) * vertices.size());
1180 
1181 		wd.numVertices			= static_cast<deUint32>(vertices.size());
1182 		wd.vertexBuffer			= makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1183 		wd.vertexBufferAlloc	= bindBuffer(vk, device, *allocator, *wd.vertexBuffer, MemoryRequirement::HostVisible);
1184 
1185 		deMemcpy(wd.vertexBufferAlloc->getHostPtr(), dataOrNullPtr(vertices), static_cast<std::size_t>(vertexBufferSize));
1186 		flushMappedMemoryRange(vk, device, wd.vertexBufferAlloc->getMemory(), wd.vertexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1187 	}
1188 
1189 	if (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT)
1190 	{
1191 		// Create a multisample image and sample from it
1192 		drawAndSampleInputAttachment (context, params, wd);
1193 	}
1194 	else
1195 	{
1196 		// Draw the image, then sample from it in a CS
1197 		draw				(context, params, wd);
1198 		dispatchSampleImage (context, params, wd, "comp_fmask_fetch");
1199 	}
1200 
1201 	// Copy the result
1202 	std::vector<deUint8> fmaskFetchColorBuffer (static_cast<deUint32>(wd.colorBufferSize));
1203 	deMemcpy(&fmaskFetchColorBuffer[0], wd.colorBufferAlloc->getHostPtr(), static_cast<std::size_t>(wd.colorBufferSize));
1204 
1205 	// Clear the color buffer, just to be sure we're getting the new data
1206 	deMemset(wd.colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(wd.colorBufferSize));
1207 	flushMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1208 
1209 	// Sample image using the standard texel fetch
1210 	dispatchSampleImage (context, params, wd, "comp_fetch");
1211 
1212 	// Verify the images
1213 	{
1214 		const void* const fmaskResult	 = dataOrNullPtr(fmaskFetchColorBuffer);
1215 		const void* const expectedResult = wd.colorBufferAlloc->getHostPtr();
1216 
1217 		DE_ASSERT(!isFloatFormat(params.colorFormat));	// we're using int compare
1218 
1219 		// Mismatch, do image compare to pinpoint the failure
1220 		for (deUint32 layerNdx  = 0u; layerNdx  < params.numLayers;								 ++layerNdx)
1221 		for (deUint32 sampleNdx = 0u; sampleNdx < static_cast<deUint32>(params.numColorSamples); ++sampleNdx)
1222 		{
1223 			const std::string					imageName	= "layer_" + de::toString(layerNdx) + "_sample_" + de::toString(sampleNdx);
1224 			const std::string					imageDesc	= "Layer " + de::toString(layerNdx) + " Sample " + de::toString(sampleNdx);
1225 			const tcu::ConstPixelBufferAccess	expected	= getSingleSampledAccess(expectedResult, params, sampleNdx, layerNdx);
1226 			const tcu::ConstPixelBufferAccess	actual		= getSingleSampledAccess(fmaskResult,	 params, sampleNdx, layerNdx);
1227 			const UVec4							threshold	(0);	// should match exactly
1228 
1229 			const bool ok = tcu::intThresholdCompare(context.getTestContext().getLog(), imageName.c_str(), imageDesc.c_str(),
1230 													 expected, actual, threshold, tcu::COMPARE_LOG_RESULT);
1231 
1232 			if (!ok)
1233 				return tcu::TestStatus::fail("Some texels were incorrect");
1234 		}
1235 	}
1236 
1237 	return tcu::TestStatus::pass("Pass");
1238 }
1239 
getFormatShortString(const VkFormat format)1240 std::string getFormatShortString (const VkFormat format)
1241 {
1242 	std::string s(de::toLower(getFormatName(format)));
1243 	return s.substr(10);
1244 }
1245 
createShaderFragmentMaskTestsInGroup(tcu::TestCaseGroup * rootGroup)1246 void createShaderFragmentMaskTestsInGroup (tcu::TestCaseGroup* rootGroup)
1247 {
1248 	// Per spec, the following formats must support color attachment and sampled image
1249 	const VkFormat colorFormats[] =
1250 	{
1251 		VK_FORMAT_R8G8B8A8_UNORM,
1252 		VK_FORMAT_R32_UINT,
1253 		VK_FORMAT_R32_SINT,
1254 	};
1255 
1256 	const VkSampleCountFlagBits	sampleCounts[] =
1257 	{
1258 		VK_SAMPLE_COUNT_2_BIT,
1259 		VK_SAMPLE_COUNT_4_BIT,
1260 		VK_SAMPLE_COUNT_8_BIT,
1261 		VK_SAMPLE_COUNT_16_BIT,
1262 	};
1263 
1264 	const struct SourceCase
1265 	{
1266 		const char*			name;
1267 		deUint32			numLayers;
1268 		SampleSource		sampleSource;
1269 	} sourceCases[] =
1270 	{
1271 		{ "image_2d",		1u,	SAMPLE_SOURCE_IMAGE			},
1272 		{ "image_2d_array",	3u,	SAMPLE_SOURCE_IMAGE			},
1273 		{ "subpass_input",	1u,	SAMPLE_SOURCE_SUBPASS_INPUT	},
1274 	};
1275 
1276 	// Test 1: Compare fragments fetched via FMASK and an ordinary texel fetch
1277 	{
1278 		for (const VkSampleCountFlagBits* pSampleCount = sampleCounts; pSampleCount != DE_ARRAY_END(sampleCounts); ++pSampleCount)
1279 		{
1280 			MovePtr<tcu::TestCaseGroup> sampleCountGroup (new tcu::TestCaseGroup(rootGroup->getTestContext(), ("samples_" + de::toString(*pSampleCount)).c_str(), ""));
1281 			for (const SourceCase* pSourceCase = sourceCases; pSourceCase != DE_ARRAY_END(sourceCases); ++pSourceCase)
1282 			{
1283 				MovePtr<tcu::TestCaseGroup> sourceGroup (new tcu::TestCaseGroup(rootGroup->getTestContext(), pSourceCase->name, ""));
1284 				for (const VkFormat* pColorFormat = colorFormats; pColorFormat != DE_ARRAY_END(colorFormats); ++pColorFormat)
1285 				{
1286 					TestParams params;
1287 					params.renderSize		= UVec2(32, 32);
1288 					params.colorFormat		= *pColorFormat;
1289 					params.numColorSamples	= *pSampleCount;
1290 					params.numLayers		= pSourceCase->numLayers;
1291 					params.sampleSource		= pSourceCase->sampleSource;
1292 
1293 					addFunctionCaseWithPrograms(sourceGroup.get(), getFormatShortString(*pColorFormat), "", checkRequirements, initPrograms, test, params);
1294 				}
1295 				sampleCountGroup->addChild(sourceGroup.release());
1296 			}
1297 			rootGroup->addChild(sampleCountGroup.release());
1298 		}
1299 	}
1300 }
1301 
1302 } // anonymous ns
1303 
createMultisampleShaderFragmentMaskTests(tcu::TestContext & testCtx)1304 tcu::TestCaseGroup* createMultisampleShaderFragmentMaskTests (tcu::TestContext& testCtx)
1305 {
1306 	return createTestGroup(testCtx, "shader_fragment_mask", "Access raw texel values in a compressed MSAA surface", createShaderFragmentMaskTestsInGroup);
1307 }
1308 
1309 } // pipeline
1310 } // vkt
1311