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