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