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