1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci* Vulkan Conformance Tests
3e5c31af7Sopenharmony_ci* ------------------------
4e5c31af7Sopenharmony_ci*
5e5c31af7Sopenharmony_ci* Copyright (c) 2016 The Khronos Group Inc.
6e5c31af7Sopenharmony_ci* Copyright (c) 2023 LunarG, Inc.
7e5c31af7Sopenharmony_ci* Copyright (c) 2023 Nintendo
8e5c31af7Sopenharmony_ci*
9e5c31af7Sopenharmony_ci* Licensed under the Apache License, Version 2.0 (the "License");
10e5c31af7Sopenharmony_ci* you may not use this file except in compliance with the License.
11e5c31af7Sopenharmony_ci* You may obtain a copy of the License at
12e5c31af7Sopenharmony_ci*
13e5c31af7Sopenharmony_ci*      http://www.apache.org/licenses/LICENSE-2.0
14e5c31af7Sopenharmony_ci*
15e5c31af7Sopenharmony_ci* Unless required by applicable law or agreed to in writing, software
16e5c31af7Sopenharmony_ci* distributed under the License is distributed on an "AS IS" BASIS,
17e5c31af7Sopenharmony_ci* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18e5c31af7Sopenharmony_ci* See the License for the specific language governing permissions and
19e5c31af7Sopenharmony_ci* limitations under the License.
20e5c31af7Sopenharmony_ci*
21e5c31af7Sopenharmony_ci*//*
22e5c31af7Sopenharmony_ci* \file vktPipelineMultisampleShaderBuiltInTests.cpp
23e5c31af7Sopenharmony_ci* \brief Multisample Shader BuiltIn Tests
24e5c31af7Sopenharmony_ci*//*--------------------------------------------------------------------*/
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ci#include "vktPipelineMultisampleShaderBuiltInTests.hpp"
27e5c31af7Sopenharmony_ci#include "vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp"
28e5c31af7Sopenharmony_ci#include "vktPipelineMakeUtil.hpp"
29e5c31af7Sopenharmony_ci
30e5c31af7Sopenharmony_ci#include "vkBuilderUtil.hpp"
31e5c31af7Sopenharmony_ci#include "vkQueryUtil.hpp"
32e5c31af7Sopenharmony_ci#include "vkObjUtil.hpp"
33e5c31af7Sopenharmony_ci#include "vkImageWithMemory.hpp"
34e5c31af7Sopenharmony_ci#include "vkBufferWithMemory.hpp"
35e5c31af7Sopenharmony_ci#include "vkBarrierUtil.hpp"
36e5c31af7Sopenharmony_ci#include "vkCmdUtil.hpp"
37e5c31af7Sopenharmony_ci#include "vkTypeUtil.hpp"
38e5c31af7Sopenharmony_ci
39e5c31af7Sopenharmony_ci#include "tcuVectorUtil.hpp"
40e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
41e5c31af7Sopenharmony_ci
42e5c31af7Sopenharmony_ci#include <set>
43e5c31af7Sopenharmony_ci#include <cmath>
44e5c31af7Sopenharmony_ci
45e5c31af7Sopenharmony_ciusing std::set;
46e5c31af7Sopenharmony_ci
47e5c31af7Sopenharmony_cinamespace vkt
48e5c31af7Sopenharmony_ci{
49e5c31af7Sopenharmony_cinamespace pipeline
50e5c31af7Sopenharmony_ci{
51e5c31af7Sopenharmony_cinamespace multisample
52e5c31af7Sopenharmony_ci{
53e5c31af7Sopenharmony_ci
54e5c31af7Sopenharmony_ciusing namespace vk;
55e5c31af7Sopenharmony_ci
56e5c31af7Sopenharmony_cistruct VertexDataNdc
57e5c31af7Sopenharmony_ci{
58e5c31af7Sopenharmony_ci	VertexDataNdc (const tcu::Vec4& posNdc) : positionNdc(posNdc) {}
59e5c31af7Sopenharmony_ci
60e5c31af7Sopenharmony_ci	tcu::Vec4 positionNdc;
61e5c31af7Sopenharmony_ci};
62e5c31af7Sopenharmony_ci
63e5c31af7Sopenharmony_ciMultisampleInstanceBase::VertexDataDesc getVertexDataDescriptonNdc (void)
64e5c31af7Sopenharmony_ci{
65e5c31af7Sopenharmony_ci	MultisampleInstanceBase::VertexDataDesc vertexDataDesc;
66e5c31af7Sopenharmony_ci
67e5c31af7Sopenharmony_ci	vertexDataDesc.verticesCount	 = 4u;
68e5c31af7Sopenharmony_ci	vertexDataDesc.dataStride		 = sizeof(VertexDataNdc);
69e5c31af7Sopenharmony_ci	vertexDataDesc.dataSize			 = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
70e5c31af7Sopenharmony_ci	vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
71e5c31af7Sopenharmony_ci
72e5c31af7Sopenharmony_ci	const VkVertexInputAttributeDescription vertexAttribPositionNdc =
73e5c31af7Sopenharmony_ci	{
74e5c31af7Sopenharmony_ci		0u,											// deUint32	location;
75e5c31af7Sopenharmony_ci		0u,											// deUint32	binding;
76e5c31af7Sopenharmony_ci		VK_FORMAT_R32G32B32A32_SFLOAT,				// VkFormat	format;
77e5c31af7Sopenharmony_ci		DE_OFFSET_OF(VertexDataNdc, positionNdc),	// deUint32	offset;
78e5c31af7Sopenharmony_ci	};
79e5c31af7Sopenharmony_ci
80e5c31af7Sopenharmony_ci	vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
81e5c31af7Sopenharmony_ci
82e5c31af7Sopenharmony_ci	return vertexDataDesc;
83e5c31af7Sopenharmony_ci}
84e5c31af7Sopenharmony_ci
85e5c31af7Sopenharmony_civoid uploadVertexDataNdc (const Allocation& vertexBufferAllocation, const MultisampleInstanceBase::VertexDataDesc& vertexDataDescripton)
86e5c31af7Sopenharmony_ci{
87e5c31af7Sopenharmony_ci	std::vector<VertexDataNdc> vertices;
88e5c31af7Sopenharmony_ci
89e5c31af7Sopenharmony_ci	vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f)));
90e5c31af7Sopenharmony_ci	vertices.push_back(VertexDataNdc(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f)));
91e5c31af7Sopenharmony_ci	vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f)));
92e5c31af7Sopenharmony_ci	vertices.push_back(VertexDataNdc(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f)));
93e5c31af7Sopenharmony_ci
94e5c31af7Sopenharmony_ci	deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
95e5c31af7Sopenharmony_ci}
96e5c31af7Sopenharmony_ci
97e5c31af7Sopenharmony_cistruct VertexDataNdcScreen
98e5c31af7Sopenharmony_ci{
99e5c31af7Sopenharmony_ci	VertexDataNdcScreen (const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {}
100e5c31af7Sopenharmony_ci
101e5c31af7Sopenharmony_ci	tcu::Vec4 positionNdc;
102e5c31af7Sopenharmony_ci	tcu::Vec2 positionScreen;
103e5c31af7Sopenharmony_ci};
104e5c31af7Sopenharmony_ci
105e5c31af7Sopenharmony_ciMultisampleInstanceBase::VertexDataDesc getVertexDataDescriptonNdcScreen (void)
106e5c31af7Sopenharmony_ci{
107e5c31af7Sopenharmony_ci	MultisampleInstanceBase::VertexDataDesc vertexDataDesc;
108e5c31af7Sopenharmony_ci
109e5c31af7Sopenharmony_ci	vertexDataDesc.verticesCount	 = 4u;
110e5c31af7Sopenharmony_ci	vertexDataDesc.dataStride		 = sizeof(VertexDataNdcScreen);
111e5c31af7Sopenharmony_ci	vertexDataDesc.dataSize			 = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
112e5c31af7Sopenharmony_ci	vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
113e5c31af7Sopenharmony_ci
114e5c31af7Sopenharmony_ci	const VkVertexInputAttributeDescription vertexAttribPositionNdc =
115e5c31af7Sopenharmony_ci	{
116e5c31af7Sopenharmony_ci		0u,													// deUint32	location;
117e5c31af7Sopenharmony_ci		0u,													// deUint32	binding;
118e5c31af7Sopenharmony_ci		VK_FORMAT_R32G32B32A32_SFLOAT,						// VkFormat	format;
119e5c31af7Sopenharmony_ci		DE_OFFSET_OF(VertexDataNdcScreen, positionNdc),		// deUint32	offset;
120e5c31af7Sopenharmony_ci	};
121e5c31af7Sopenharmony_ci
122e5c31af7Sopenharmony_ci	vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
123e5c31af7Sopenharmony_ci
124e5c31af7Sopenharmony_ci	const VkVertexInputAttributeDescription vertexAttribPositionScreen =
125e5c31af7Sopenharmony_ci	{
126e5c31af7Sopenharmony_ci		1u,													// deUint32	location;
127e5c31af7Sopenharmony_ci		0u,													// deUint32	binding;
128e5c31af7Sopenharmony_ci		VK_FORMAT_R32G32_SFLOAT,							// VkFormat	format;
129e5c31af7Sopenharmony_ci		DE_OFFSET_OF(VertexDataNdcScreen, positionScreen),	// deUint32	offset;
130e5c31af7Sopenharmony_ci	};
131e5c31af7Sopenharmony_ci
132e5c31af7Sopenharmony_ci	vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen);
133e5c31af7Sopenharmony_ci
134e5c31af7Sopenharmony_ci	return vertexDataDesc;
135e5c31af7Sopenharmony_ci}
136e5c31af7Sopenharmony_ci
137e5c31af7Sopenharmony_civoid uploadVertexDataNdcScreen (const Allocation& vertexBufferAllocation, const MultisampleInstanceBase::VertexDataDesc& vertexDataDescripton, const tcu::Vec2& screenSize)
138e5c31af7Sopenharmony_ci{
139e5c31af7Sopenharmony_ci	std::vector<VertexDataNdcScreen> vertices;
140e5c31af7Sopenharmony_ci
141e5c31af7Sopenharmony_ci	vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, 0.0f)));
142e5c31af7Sopenharmony_ci	vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(screenSize.x(), 0.0f)));
143e5c31af7Sopenharmony_ci	vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, screenSize.y())));
144e5c31af7Sopenharmony_ci	vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f), tcu::Vec2(screenSize.x(), screenSize.y())));
145e5c31af7Sopenharmony_ci
146e5c31af7Sopenharmony_ci	deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
147e5c31af7Sopenharmony_ci}
148e5c31af7Sopenharmony_ci
149e5c31af7Sopenharmony_cibool checkForErrorMS (const vk::VkImageCreateInfo& imageMSInfo, const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, const deUint32 errorCompNdx)
150e5c31af7Sopenharmony_ci{
151e5c31af7Sopenharmony_ci	const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
152e5c31af7Sopenharmony_ci
153e5c31af7Sopenharmony_ci	for (deUint32 z = 0u; z < imageMSInfo.extent.depth;  ++z)
154e5c31af7Sopenharmony_ci	for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
155e5c31af7Sopenharmony_ci	for (deUint32 x = 0u; x < imageMSInfo.extent.width;  ++x)
156e5c31af7Sopenharmony_ci	{
157e5c31af7Sopenharmony_ci		for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
158e5c31af7Sopenharmony_ci		{
159e5c31af7Sopenharmony_ci			const deUint32 errorComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z)[errorCompNdx];
160e5c31af7Sopenharmony_ci
161e5c31af7Sopenharmony_ci			if (errorComponent > 0)
162e5c31af7Sopenharmony_ci				return true;
163e5c31af7Sopenharmony_ci		}
164e5c31af7Sopenharmony_ci	}
165e5c31af7Sopenharmony_ci
166e5c31af7Sopenharmony_ci	return false;
167e5c31af7Sopenharmony_ci}
168e5c31af7Sopenharmony_ci
169e5c31af7Sopenharmony_cibool checkForErrorRS (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS, const deUint32 errorCompNdx)
170e5c31af7Sopenharmony_ci{
171e5c31af7Sopenharmony_ci	for (deUint32 z = 0u; z < imageRSInfo.extent.depth;  ++z)
172e5c31af7Sopenharmony_ci	for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
173e5c31af7Sopenharmony_ci	for (deUint32 x = 0u; x < imageRSInfo.extent.width;  ++x)
174e5c31af7Sopenharmony_ci	{
175e5c31af7Sopenharmony_ci		const deUint32 errorComponent = dataRS.getPixelUint(x, y, z)[errorCompNdx];
176e5c31af7Sopenharmony_ci
177e5c31af7Sopenharmony_ci		if (errorComponent > 0)
178e5c31af7Sopenharmony_ci			return true;
179e5c31af7Sopenharmony_ci	}
180e5c31af7Sopenharmony_ci
181e5c31af7Sopenharmony_ci	return false;
182e5c31af7Sopenharmony_ci}
183e5c31af7Sopenharmony_ci
184e5c31af7Sopenharmony_citemplate <typename CaseClassName>
185e5c31af7Sopenharmony_ciclass MSCase : public MSCaseBaseResolveAndPerSampleFetch
186e5c31af7Sopenharmony_ci{
187e5c31af7Sopenharmony_cipublic:
188e5c31af7Sopenharmony_ci								MSCase			(tcu::TestContext&		testCtx,
189e5c31af7Sopenharmony_ci												 const std::string&		name,
190e5c31af7Sopenharmony_ci												 const ImageMSParams&	imageMSParams)
191e5c31af7Sopenharmony_ci								: MSCaseBaseResolveAndPerSampleFetch(testCtx, name, imageMSParams) {}
192e5c31af7Sopenharmony_ci
193e5c31af7Sopenharmony_ci	virtual void				checkSupport	(Context& context) const;
194e5c31af7Sopenharmony_ci	void						init			(void);
195e5c31af7Sopenharmony_ci	void						initPrograms	(vk::SourceCollections& programCollection) const;
196e5c31af7Sopenharmony_ci	TestInstance*				createInstance	(Context&				context) const;
197e5c31af7Sopenharmony_ci	static MultisampleCaseBase*	createCase		(tcu::TestContext&		testCtx,
198e5c31af7Sopenharmony_ci												 const std::string&		name,
199e5c31af7Sopenharmony_ci												 const ImageMSParams&	imageMSParams);
200e5c31af7Sopenharmony_ci};
201e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
202e5c31af7Sopenharmony_citemplate <typename CaseClassName>
203e5c31af7Sopenharmony_civoid MSCase<CaseClassName>::checkSupport(Context& context) const
204e5c31af7Sopenharmony_ci{
205e5c31af7Sopenharmony_ci	checkGraphicsPipelineLibrarySupport(context);
206e5c31af7Sopenharmony_ci}
207e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
208e5c31af7Sopenharmony_ci
209e5c31af7Sopenharmony_citemplate <typename CaseClassName>
210e5c31af7Sopenharmony_ciMultisampleCaseBase* MSCase<CaseClassName>::createCase (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
211e5c31af7Sopenharmony_ci{
212e5c31af7Sopenharmony_ci	return new MSCase<CaseClassName>(testCtx, name, imageMSParams);
213e5c31af7Sopenharmony_ci}
214e5c31af7Sopenharmony_ci
215e5c31af7Sopenharmony_citemplate <typename InstanceClassName>
216e5c31af7Sopenharmony_ciclass MSInstance : public MSInstanceBaseResolveAndPerSampleFetch
217e5c31af7Sopenharmony_ci{
218e5c31af7Sopenharmony_cipublic:
219e5c31af7Sopenharmony_ci													MSInstance				(Context&											context,
220e5c31af7Sopenharmony_ci																			 const ImageMSParams&								imageMSParams)
221e5c31af7Sopenharmony_ci													: MSInstanceBaseResolveAndPerSampleFetch(context, imageMSParams) {}
222e5c31af7Sopenharmony_ci
223e5c31af7Sopenharmony_ci	VertexDataDesc									getVertexDataDescripton	(void) const;
224e5c31af7Sopenharmony_ci	void											uploadVertexData		(const Allocation&									vertexBufferAllocation,
225e5c31af7Sopenharmony_ci																			 const VertexDataDesc&								vertexDataDescripton) const;
226e5c31af7Sopenharmony_ci
227e5c31af7Sopenharmony_ci	tcu::TestStatus									verifyImageData			(const vk::VkImageCreateInfo&						imageMSInfo,
228e5c31af7Sopenharmony_ci																			 const vk::VkImageCreateInfo&						imageRSInfo,
229e5c31af7Sopenharmony_ci																			 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
230e5c31af7Sopenharmony_ci																			 const tcu::ConstPixelBufferAccess&					dataRS) const;
231e5c31af7Sopenharmony_ci
232e5c31af7Sopenharmony_ci	virtual VkPipelineMultisampleStateCreateInfo	getMSStateCreateInfo	(const ImageMSParams&								imageMSParams) const
233e5c31af7Sopenharmony_ci	{
234e5c31af7Sopenharmony_ci		return MSInstanceBaseResolveAndPerSampleFetch::getMSStateCreateInfo(imageMSParams);
235e5c31af7Sopenharmony_ci	}
236e5c31af7Sopenharmony_ci};
237e5c31af7Sopenharmony_ci
238e5c31af7Sopenharmony_ciclass MSInstanceSampleID;
239e5c31af7Sopenharmony_ci
240e5c31af7Sopenharmony_citemplate<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleID>::getVertexDataDescripton (void) const
241e5c31af7Sopenharmony_ci{
242e5c31af7Sopenharmony_ci	return getVertexDataDescriptonNdc();
243e5c31af7Sopenharmony_ci}
244e5c31af7Sopenharmony_ci
245e5c31af7Sopenharmony_citemplate<> void MSInstance<MSInstanceSampleID>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
246e5c31af7Sopenharmony_ci{
247e5c31af7Sopenharmony_ci	uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
248e5c31af7Sopenharmony_ci}
249e5c31af7Sopenharmony_ci
250e5c31af7Sopenharmony_citemplate<> tcu::TestStatus MSInstance<MSInstanceSampleID>::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
251e5c31af7Sopenharmony_ci																			 const vk::VkImageCreateInfo&						imageRSInfo,
252e5c31af7Sopenharmony_ci																			 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
253e5c31af7Sopenharmony_ci																			 const tcu::ConstPixelBufferAccess&					dataRS) const
254e5c31af7Sopenharmony_ci{
255e5c31af7Sopenharmony_ci	DE_UNREF(imageRSInfo);
256e5c31af7Sopenharmony_ci	DE_UNREF(dataRS);
257e5c31af7Sopenharmony_ci
258e5c31af7Sopenharmony_ci	const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
259e5c31af7Sopenharmony_ci
260e5c31af7Sopenharmony_ci	for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
261e5c31af7Sopenharmony_ci	{
262e5c31af7Sopenharmony_ci		for (deUint32 z = 0u; z < imageMSInfo.extent.depth;  ++z)
263e5c31af7Sopenharmony_ci		for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
264e5c31af7Sopenharmony_ci		for (deUint32 x = 0u; x < imageMSInfo.extent.width;  ++x)
265e5c31af7Sopenharmony_ci		{
266e5c31af7Sopenharmony_ci			const deUint32 sampleID = dataPerSample[sampleNdx].getPixelUint(x, y, z).x();
267e5c31af7Sopenharmony_ci
268e5c31af7Sopenharmony_ci			if (sampleID != sampleNdx)
269e5c31af7Sopenharmony_ci				return tcu::TestStatus::fail("gl_SampleID does not have correct value");
270e5c31af7Sopenharmony_ci		}
271e5c31af7Sopenharmony_ci	}
272e5c31af7Sopenharmony_ci
273e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("Passed");
274e5c31af7Sopenharmony_ci}
275e5c31af7Sopenharmony_ci
276e5c31af7Sopenharmony_ciclass MSCaseSampleID;
277e5c31af7Sopenharmony_ci
278e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleID>::checkSupport (Context& context) const
279e5c31af7Sopenharmony_ci{
280e5c31af7Sopenharmony_ci	checkGraphicsPipelineLibrarySupport(context);
281e5c31af7Sopenharmony_ci	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
282e5c31af7Sopenharmony_ci}
283e5c31af7Sopenharmony_ci
284e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleID>::init (void)
285e5c31af7Sopenharmony_ci{
286e5c31af7Sopenharmony_ci	m_testCtx.getLog()
287e5c31af7Sopenharmony_ci		<< tcu::TestLog::Message
288e5c31af7Sopenharmony_ci		<< "Writing gl_SampleID to the red channel of the texture and verifying texture values.\n"
289e5c31af7Sopenharmony_ci		<< "Expecting value N at sample index N of a multisample texture.\n"
290e5c31af7Sopenharmony_ci		<< tcu::TestLog::EndMessage;
291e5c31af7Sopenharmony_ci
292e5c31af7Sopenharmony_ci	MultisampleCaseBase::init();
293e5c31af7Sopenharmony_ci}
294e5c31af7Sopenharmony_ci
295e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleID>::initPrograms (vk::SourceCollections& programCollection) const
296e5c31af7Sopenharmony_ci{
297e5c31af7Sopenharmony_ci	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
298e5c31af7Sopenharmony_ci
299e5c31af7Sopenharmony_ci	// Create vertex shader
300e5c31af7Sopenharmony_ci	std::ostringstream vs;
301e5c31af7Sopenharmony_ci
302e5c31af7Sopenharmony_ci	vs << "#version 440\n"
303e5c31af7Sopenharmony_ci		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
304e5c31af7Sopenharmony_ci		<< "\n"
305e5c31af7Sopenharmony_ci		<< "out gl_PerVertex {\n"
306e5c31af7Sopenharmony_ci		<< "	vec4  gl_Position;\n"
307e5c31af7Sopenharmony_ci		<< "};\n"
308e5c31af7Sopenharmony_ci		<< "void main (void)\n"
309e5c31af7Sopenharmony_ci		<< "{\n"
310e5c31af7Sopenharmony_ci		<< "	gl_Position	= vs_in_position_ndc;\n"
311e5c31af7Sopenharmony_ci		<< "}\n";
312e5c31af7Sopenharmony_ci
313e5c31af7Sopenharmony_ci	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
314e5c31af7Sopenharmony_ci
315e5c31af7Sopenharmony_ci	// Create fragment shader
316e5c31af7Sopenharmony_ci	std::ostringstream fs;
317e5c31af7Sopenharmony_ci
318e5c31af7Sopenharmony_ci	fs << "#version 440\n"
319e5c31af7Sopenharmony_ci		<< "\n"
320e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec4 fs_out_color;\n"
321e5c31af7Sopenharmony_ci		<< "\n"
322e5c31af7Sopenharmony_ci		<< "void main (void)\n"
323e5c31af7Sopenharmony_ci		<< "{\n"
324e5c31af7Sopenharmony_ci		<< "	fs_out_color = vec4(float(gl_SampleID) / float(255), 0.0, 0.0, 1.0);\n"
325e5c31af7Sopenharmony_ci		<< "}\n";
326e5c31af7Sopenharmony_ci
327e5c31af7Sopenharmony_ci	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
328e5c31af7Sopenharmony_ci}
329e5c31af7Sopenharmony_ci
330e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseSampleID>::createInstance (Context& context) const
331e5c31af7Sopenharmony_ci{
332e5c31af7Sopenharmony_ci	return new MSInstance<MSInstanceSampleID>(context, m_imageMSParams);
333e5c31af7Sopenharmony_ci}
334e5c31af7Sopenharmony_ci
335e5c31af7Sopenharmony_ciclass MSInstanceSamplePosDistribution;
336e5c31af7Sopenharmony_ci
337e5c31af7Sopenharmony_citemplate<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSamplePosDistribution>::getVertexDataDescripton (void) const
338e5c31af7Sopenharmony_ci{
339e5c31af7Sopenharmony_ci	return getVertexDataDescriptonNdc();
340e5c31af7Sopenharmony_ci}
341e5c31af7Sopenharmony_ci
342e5c31af7Sopenharmony_citemplate<> void MSInstance<MSInstanceSamplePosDistribution>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
343e5c31af7Sopenharmony_ci{
344e5c31af7Sopenharmony_ci	uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
345e5c31af7Sopenharmony_ci}
346e5c31af7Sopenharmony_ci
347e5c31af7Sopenharmony_citemplate<> tcu::TestStatus MSInstance<MSInstanceSamplePosDistribution>::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
348e5c31af7Sopenharmony_ci																						 const vk::VkImageCreateInfo&						imageRSInfo,
349e5c31af7Sopenharmony_ci																						 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
350e5c31af7Sopenharmony_ci																						 const tcu::ConstPixelBufferAccess&					dataRS) const
351e5c31af7Sopenharmony_ci{
352e5c31af7Sopenharmony_ci	const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
353e5c31af7Sopenharmony_ci
354e5c31af7Sopenharmony_ci	// approximate Bates distribution as normal
355e5c31af7Sopenharmony_ci	const float variance = (1.0f / (12.0f * (float)numSamples));
356e5c31af7Sopenharmony_ci	const float standardDeviation = deFloatSqrt(variance);
357e5c31af7Sopenharmony_ci
358e5c31af7Sopenharmony_ci	// 95% of means of sample positions are within 2 standard deviations if
359e5c31af7Sopenharmony_ci	// they were randomly assigned. Sample patterns are expected to be more
360e5c31af7Sopenharmony_ci	// uniform than a random pattern.
361e5c31af7Sopenharmony_ci	const float distanceThreshold = 2.0f * standardDeviation;
362e5c31af7Sopenharmony_ci
363e5c31af7Sopenharmony_ci	for (deUint32 z = 0u; z < imageRSInfo.extent.depth;  ++z)
364e5c31af7Sopenharmony_ci	for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
365e5c31af7Sopenharmony_ci	for (deUint32 x = 0u; x < imageRSInfo.extent.width;  ++x)
366e5c31af7Sopenharmony_ci	{
367e5c31af7Sopenharmony_ci		const deUint32 errorComponent = dataRS.getPixelUint(x, y, z).z();
368e5c31af7Sopenharmony_ci
369e5c31af7Sopenharmony_ci		if (errorComponent > 0)
370e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail("gl_SamplePosition is not within interval [0,1]");
371e5c31af7Sopenharmony_ci
372e5c31af7Sopenharmony_ci		if (numSamples >= VK_SAMPLE_COUNT_4_BIT)
373e5c31af7Sopenharmony_ci		{
374e5c31af7Sopenharmony_ci			const tcu::Vec2 averageSamplePos	= tcu::Vec2((float)dataRS.getPixelUint(x, y, z).x() / 255.0f, (float)dataRS.getPixelUint(x, y, z).y() / 255.0f);
375e5c31af7Sopenharmony_ci			const tcu::Vec2	distanceFromCenter	= tcu::abs(averageSamplePos - tcu::Vec2(0.5f, 0.5f));
376e5c31af7Sopenharmony_ci
377e5c31af7Sopenharmony_ci			if (distanceFromCenter.x() > distanceThreshold || distanceFromCenter.y() > distanceThreshold)
378e5c31af7Sopenharmony_ci				return tcu::TestStatus::fail("Sample positions are not uniformly distributed within the pixel");
379e5c31af7Sopenharmony_ci		}
380e5c31af7Sopenharmony_ci	}
381e5c31af7Sopenharmony_ci
382e5c31af7Sopenharmony_ci	for (deUint32 z = 0u; z < imageMSInfo.extent.depth;  ++z)
383e5c31af7Sopenharmony_ci	for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
384e5c31af7Sopenharmony_ci	for (deUint32 x = 0u; x < imageMSInfo.extent.width;  ++x)
385e5c31af7Sopenharmony_ci	{
386e5c31af7Sopenharmony_ci		std::vector<tcu::Vec2> samplePositions(numSamples);
387e5c31af7Sopenharmony_ci
388e5c31af7Sopenharmony_ci		for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
389e5c31af7Sopenharmony_ci		{
390e5c31af7Sopenharmony_ci			const deUint32 errorComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z).z();
391e5c31af7Sopenharmony_ci
392e5c31af7Sopenharmony_ci			if (errorComponent > 0)
393e5c31af7Sopenharmony_ci				return tcu::TestStatus::fail("gl_SamplePosition is not within interval [0,1]");
394e5c31af7Sopenharmony_ci
395e5c31af7Sopenharmony_ci			samplePositions[sampleNdx] = tcu::Vec2( (float)dataPerSample[sampleNdx].getPixelUint(x, y, z).x() / 255.0f,
396e5c31af7Sopenharmony_ci													(float)dataPerSample[sampleNdx].getPixelUint(x, y, z).y() / 255.0f);
397e5c31af7Sopenharmony_ci		}
398e5c31af7Sopenharmony_ci
399e5c31af7Sopenharmony_ci		for (deUint32 sampleNdxA = 0u;				sampleNdxA < numSamples; ++sampleNdxA)
400e5c31af7Sopenharmony_ci		for (deUint32 sampleNdxB = sampleNdxA + 1u; sampleNdxB < numSamples; ++sampleNdxB)
401e5c31af7Sopenharmony_ci		{
402e5c31af7Sopenharmony_ci			if (samplePositions[sampleNdxA] == samplePositions[sampleNdxB])
403e5c31af7Sopenharmony_ci				return tcu::TestStatus::fail("Two samples have the same position");
404e5c31af7Sopenharmony_ci		}
405e5c31af7Sopenharmony_ci
406e5c31af7Sopenharmony_ci		if (numSamples >= VK_SAMPLE_COUNT_4_BIT)
407e5c31af7Sopenharmony_ci		{
408e5c31af7Sopenharmony_ci			tcu::Vec2 averageSamplePos(0.0f, 0.0f);
409e5c31af7Sopenharmony_ci
410e5c31af7Sopenharmony_ci			for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
411e5c31af7Sopenharmony_ci			{
412e5c31af7Sopenharmony_ci				averageSamplePos.x() += samplePositions[sampleNdx].x();
413e5c31af7Sopenharmony_ci				averageSamplePos.y() += samplePositions[sampleNdx].y();
414e5c31af7Sopenharmony_ci			}
415e5c31af7Sopenharmony_ci
416e5c31af7Sopenharmony_ci			averageSamplePos.x() /= (float)numSamples;
417e5c31af7Sopenharmony_ci			averageSamplePos.y() /= (float)numSamples;
418e5c31af7Sopenharmony_ci
419e5c31af7Sopenharmony_ci			const tcu::Vec2	distanceFromCenter = tcu::abs(averageSamplePos - tcu::Vec2(0.5f, 0.5f));
420e5c31af7Sopenharmony_ci
421e5c31af7Sopenharmony_ci			if (distanceFromCenter.x() > distanceThreshold || distanceFromCenter.y() > distanceThreshold)
422e5c31af7Sopenharmony_ci				return tcu::TestStatus::fail("Sample positions are not uniformly distributed within the pixel");
423e5c31af7Sopenharmony_ci		}
424e5c31af7Sopenharmony_ci	}
425e5c31af7Sopenharmony_ci
426e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("Passed");
427e5c31af7Sopenharmony_ci}
428e5c31af7Sopenharmony_ci
429e5c31af7Sopenharmony_ciclass MSCaseSamplePosDistribution;
430e5c31af7Sopenharmony_ci
431e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSamplePosDistribution>::checkSupport (Context& context) const
432e5c31af7Sopenharmony_ci{
433e5c31af7Sopenharmony_ci	checkGraphicsPipelineLibrarySupport(context);
434e5c31af7Sopenharmony_ci	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
435e5c31af7Sopenharmony_ci}
436e5c31af7Sopenharmony_ci
437e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSamplePosDistribution>::init (void)
438e5c31af7Sopenharmony_ci{
439e5c31af7Sopenharmony_ci	m_testCtx.getLog()
440e5c31af7Sopenharmony_ci		<< tcu::TestLog::Message
441e5c31af7Sopenharmony_ci		<< "Verifying gl_SamplePosition value with multisample targets:\n"
442e5c31af7Sopenharmony_ci		<< "	a) Expect legal sample position.\n"
443e5c31af7Sopenharmony_ci		<< "	b) Sample position is unique within the set of all sample positions of a pixel.\n"
444e5c31af7Sopenharmony_ci		<< "	c) Sample position distribution is uniform or almost uniform.\n"
445e5c31af7Sopenharmony_ci		<< tcu::TestLog::EndMessage;
446e5c31af7Sopenharmony_ci
447e5c31af7Sopenharmony_ci	MultisampleCaseBase::init();
448e5c31af7Sopenharmony_ci}
449e5c31af7Sopenharmony_ci
450e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSamplePosDistribution>::initPrograms (vk::SourceCollections& programCollection) const
451e5c31af7Sopenharmony_ci{
452e5c31af7Sopenharmony_ci	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
453e5c31af7Sopenharmony_ci
454e5c31af7Sopenharmony_ci	// Create vertex shader
455e5c31af7Sopenharmony_ci	std::ostringstream vs;
456e5c31af7Sopenharmony_ci
457e5c31af7Sopenharmony_ci	vs << "#version 440\n"
458e5c31af7Sopenharmony_ci		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
459e5c31af7Sopenharmony_ci		<< "\n"
460e5c31af7Sopenharmony_ci		<< "out gl_PerVertex {\n"
461e5c31af7Sopenharmony_ci		<< "	vec4  gl_Position;\n"
462e5c31af7Sopenharmony_ci		<< "};\n"
463e5c31af7Sopenharmony_ci		<< "void main (void)\n"
464e5c31af7Sopenharmony_ci		<< "{\n"
465e5c31af7Sopenharmony_ci		<< "	gl_Position	= vs_in_position_ndc;\n"
466e5c31af7Sopenharmony_ci		<< "}\n";
467e5c31af7Sopenharmony_ci
468e5c31af7Sopenharmony_ci	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
469e5c31af7Sopenharmony_ci
470e5c31af7Sopenharmony_ci	// Create fragment shader
471e5c31af7Sopenharmony_ci	std::ostringstream fs;
472e5c31af7Sopenharmony_ci
473e5c31af7Sopenharmony_ci	fs << "#version 440\n"
474e5c31af7Sopenharmony_ci		<< "\n"
475e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec4 fs_out_color;\n"
476e5c31af7Sopenharmony_ci		<< "\n"
477e5c31af7Sopenharmony_ci		<< "void main (void)\n"
478e5c31af7Sopenharmony_ci		<< "{\n"
479e5c31af7Sopenharmony_ci		<< "	if (gl_SamplePosition.x < 0.0 || gl_SamplePosition.x > 1.0 || gl_SamplePosition.y < 0.0 || gl_SamplePosition.y > 1.0)\n"
480e5c31af7Sopenharmony_ci		"		fs_out_color = vec4(0.0, 0.0, 1.0, 1.0);\n"
481e5c31af7Sopenharmony_ci		"	else\n"
482e5c31af7Sopenharmony_ci		"		fs_out_color = vec4(gl_SamplePosition.x, gl_SamplePosition.y, 0.0, 1.0);\n"
483e5c31af7Sopenharmony_ci		"}\n";
484e5c31af7Sopenharmony_ci
485e5c31af7Sopenharmony_ci	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
486e5c31af7Sopenharmony_ci}
487e5c31af7Sopenharmony_ci
488e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseSamplePosDistribution>::createInstance (Context& context) const
489e5c31af7Sopenharmony_ci{
490e5c31af7Sopenharmony_ci	return new MSInstance<MSInstanceSamplePosDistribution>(context, m_imageMSParams);
491e5c31af7Sopenharmony_ci}
492e5c31af7Sopenharmony_ci
493e5c31af7Sopenharmony_ciclass MSInstanceSamplePosCorrectness;
494e5c31af7Sopenharmony_ci
495e5c31af7Sopenharmony_citemplate<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSamplePosCorrectness>::getVertexDataDescripton (void) const
496e5c31af7Sopenharmony_ci{
497e5c31af7Sopenharmony_ci	return getVertexDataDescriptonNdcScreen();
498e5c31af7Sopenharmony_ci}
499e5c31af7Sopenharmony_ci
500e5c31af7Sopenharmony_citemplate<> void MSInstance<MSInstanceSamplePosCorrectness>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
501e5c31af7Sopenharmony_ci{
502e5c31af7Sopenharmony_ci	const tcu::UVec3 layerSize = getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize);
503e5c31af7Sopenharmony_ci
504e5c31af7Sopenharmony_ci	uploadVertexDataNdcScreen(vertexBufferAllocation, vertexDataDescripton, tcu::Vec2(static_cast<float>(layerSize.x()), static_cast<float>(layerSize.y())));
505e5c31af7Sopenharmony_ci}
506e5c31af7Sopenharmony_ci
507e5c31af7Sopenharmony_citemplate<> tcu::TestStatus MSInstance<MSInstanceSamplePosCorrectness>::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
508e5c31af7Sopenharmony_ci																						 const vk::VkImageCreateInfo&						imageRSInfo,
509e5c31af7Sopenharmony_ci																						 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
510e5c31af7Sopenharmony_ci																						 const tcu::ConstPixelBufferAccess&					dataRS) const
511e5c31af7Sopenharmony_ci{
512e5c31af7Sopenharmony_ci	if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
513e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("Varying values are not sampled at gl_SamplePosition");
514e5c31af7Sopenharmony_ci
515e5c31af7Sopenharmony_ci	if (checkForErrorRS(imageRSInfo, dataRS, 0))
516e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("Varying values are not sampled at gl_SamplePosition");
517e5c31af7Sopenharmony_ci
518e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("Passed");
519e5c31af7Sopenharmony_ci}
520e5c31af7Sopenharmony_ci
521e5c31af7Sopenharmony_ciclass MSCaseSamplePosCorrectness;
522e5c31af7Sopenharmony_ci
523e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSamplePosCorrectness>::checkSupport (Context& context) const
524e5c31af7Sopenharmony_ci{
525e5c31af7Sopenharmony_ci	checkGraphicsPipelineLibrarySupport(context);
526e5c31af7Sopenharmony_ci	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
527e5c31af7Sopenharmony_ci}
528e5c31af7Sopenharmony_ci
529e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSamplePosCorrectness>::init (void)
530e5c31af7Sopenharmony_ci{
531e5c31af7Sopenharmony_ci	m_testCtx.getLog()
532e5c31af7Sopenharmony_ci		<< tcu::TestLog::Message
533e5c31af7Sopenharmony_ci		<< "Verifying gl_SamplePosition correctness:\n"
534e5c31af7Sopenharmony_ci		<< "	1) Varying values should be sampled at the sample position.\n"
535e5c31af7Sopenharmony_ci		<< "		=> fract(position_screen) == gl_SamplePosition\n"
536e5c31af7Sopenharmony_ci		<< tcu::TestLog::EndMessage;
537e5c31af7Sopenharmony_ci
538e5c31af7Sopenharmony_ci	MultisampleCaseBase::init();
539e5c31af7Sopenharmony_ci}
540e5c31af7Sopenharmony_ci
541e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSamplePosCorrectness>::initPrograms (vk::SourceCollections& programCollection) const
542e5c31af7Sopenharmony_ci{
543e5c31af7Sopenharmony_ci	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
544e5c31af7Sopenharmony_ci
545e5c31af7Sopenharmony_ci	// Create vertex shaders
546e5c31af7Sopenharmony_ci	std::ostringstream vs;
547e5c31af7Sopenharmony_ci
548e5c31af7Sopenharmony_ci	vs	<< "#version 440\n"
549e5c31af7Sopenharmony_ci		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
550e5c31af7Sopenharmony_ci		<< "layout(location = 1) in vec2 vs_in_position_screen;\n"
551e5c31af7Sopenharmony_ci		<< "\n"
552e5c31af7Sopenharmony_ci		<< "layout(location = 0) sample out vec2 vs_out_position_screen;\n"
553e5c31af7Sopenharmony_ci		<< "\n"
554e5c31af7Sopenharmony_ci		<< "out gl_PerVertex {\n"
555e5c31af7Sopenharmony_ci		<< "	vec4  gl_Position;\n"
556e5c31af7Sopenharmony_ci		<< "};\n"
557e5c31af7Sopenharmony_ci		<< "void main (void)\n"
558e5c31af7Sopenharmony_ci		<< "{\n"
559e5c31af7Sopenharmony_ci		<< "	gl_Position				= vs_in_position_ndc;\n"
560e5c31af7Sopenharmony_ci		<< "	vs_out_position_screen	= vs_in_position_screen;\n"
561e5c31af7Sopenharmony_ci		<< "}\n";
562e5c31af7Sopenharmony_ci
563e5c31af7Sopenharmony_ci	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
564e5c31af7Sopenharmony_ci
565e5c31af7Sopenharmony_ci	// Create fragment shader
566e5c31af7Sopenharmony_ci	std::ostringstream fs;
567e5c31af7Sopenharmony_ci
568e5c31af7Sopenharmony_ci	fs	<< "#version 440\n"
569e5c31af7Sopenharmony_ci		<< "layout(location = 0) sample in vec2 fs_in_position_screen;\n"
570e5c31af7Sopenharmony_ci		<< "\n"
571e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec4 fs_out_color;\n"
572e5c31af7Sopenharmony_ci		<< "\n"
573e5c31af7Sopenharmony_ci		<< "void main (void)\n"
574e5c31af7Sopenharmony_ci		<< "{\n"
575e5c31af7Sopenharmony_ci		<< "	const float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n"
576e5c31af7Sopenharmony_ci		<< "	const ivec2 nearby_pixel = ivec2(floor(fs_in_position_screen));\n"
577e5c31af7Sopenharmony_ci		<< "	bool ok	= false;\n"
578e5c31af7Sopenharmony_ci		<< "\n"
579e5c31af7Sopenharmony_ci		<< "	// sample at edge + inaccuaries may cause us to round to any neighboring pixel\n"
580e5c31af7Sopenharmony_ci		<< "	// check all neighbors for any match\n"
581e5c31af7Sopenharmony_ci		<< "	for (int dy = -1; dy <= 1; ++dy)\n"
582e5c31af7Sopenharmony_ci		<< "	for (int dx = -1; dx <= 1; ++dx)\n"
583e5c31af7Sopenharmony_ci		<< "	{\n"
584e5c31af7Sopenharmony_ci		<< "		ivec2 current_pixel			= nearby_pixel + ivec2(dx, dy);\n"
585e5c31af7Sopenharmony_ci		<< "		vec2 position_inside_pixel	= vec2(current_pixel) + gl_SamplePosition;\n"
586e5c31af7Sopenharmony_ci		<< "		vec2 position_diff			= abs(position_inside_pixel - fs_in_position_screen);\n"
587e5c31af7Sopenharmony_ci		<< "\n"
588e5c31af7Sopenharmony_ci		<< "		if (all(lessThan(position_diff, vec2(threshold))))\n"
589e5c31af7Sopenharmony_ci		<< "			ok = true;\n"
590e5c31af7Sopenharmony_ci		<< "	}\n"
591e5c31af7Sopenharmony_ci		<< "\n"
592e5c31af7Sopenharmony_ci		<< "	if (ok)\n"
593e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
594e5c31af7Sopenharmony_ci		<< "	else\n"
595e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
596e5c31af7Sopenharmony_ci		<< "}\n";
597e5c31af7Sopenharmony_ci
598e5c31af7Sopenharmony_ci	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
599e5c31af7Sopenharmony_ci}
600e5c31af7Sopenharmony_ci
601e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseSamplePosCorrectness>::createInstance (Context& context) const
602e5c31af7Sopenharmony_ci{
603e5c31af7Sopenharmony_ci	return new MSInstance<MSInstanceSamplePosCorrectness>(context, m_imageMSParams);
604e5c31af7Sopenharmony_ci}
605e5c31af7Sopenharmony_ci
606e5c31af7Sopenharmony_ciclass MSInstanceSampleMaskPattern : public MSInstanceBaseResolveAndPerSampleFetch
607e5c31af7Sopenharmony_ci{
608e5c31af7Sopenharmony_cipublic:
609e5c31af7Sopenharmony_ci											MSInstanceSampleMaskPattern	(Context&											context,
610e5c31af7Sopenharmony_ci																		 const ImageMSParams&								imageMSParams);
611e5c31af7Sopenharmony_ci
612e5c31af7Sopenharmony_ci	VkPipelineMultisampleStateCreateInfo	getMSStateCreateInfo		(const ImageMSParams&								imageMSParams) const;
613e5c31af7Sopenharmony_ci
614e5c31af7Sopenharmony_ci	const VkDescriptorSetLayout*			createMSPassDescSetLayout	(const ImageMSParams&								imageMSParams);
615e5c31af7Sopenharmony_ci
616e5c31af7Sopenharmony_ci	const VkDescriptorSet*					createMSPassDescSet			(const ImageMSParams&								imageMSParams,
617e5c31af7Sopenharmony_ci																		 const VkDescriptorSetLayout*						descSetLayout);
618e5c31af7Sopenharmony_ci
619e5c31af7Sopenharmony_ci	VertexDataDesc							getVertexDataDescripton		(void) const;
620e5c31af7Sopenharmony_ci
621e5c31af7Sopenharmony_ci	void									uploadVertexData			(const Allocation&									vertexBufferAllocation,
622e5c31af7Sopenharmony_ci																		 const VertexDataDesc&								vertexDataDescripton) const;
623e5c31af7Sopenharmony_ci
624e5c31af7Sopenharmony_ci	tcu::TestStatus							verifyImageData				(const vk::VkImageCreateInfo&						imageMSInfo,
625e5c31af7Sopenharmony_ci																		 const vk::VkImageCreateInfo&						imageRSInfo,
626e5c31af7Sopenharmony_ci																		 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
627e5c31af7Sopenharmony_ci																		 const tcu::ConstPixelBufferAccess&					dataRS) const;
628e5c31af7Sopenharmony_ciprotected:
629e5c31af7Sopenharmony_ci
630e5c31af7Sopenharmony_ci	VkSampleMask					m_sampleMask;
631e5c31af7Sopenharmony_ci	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
632e5c31af7Sopenharmony_ci	Move<VkDescriptorPool>			m_descriptorPool;
633e5c31af7Sopenharmony_ci	Move<VkDescriptorSet>			m_descriptorSet;
634e5c31af7Sopenharmony_ci	de::MovePtr<BufferWithMemory>	m_buffer;
635e5c31af7Sopenharmony_ci};
636e5c31af7Sopenharmony_ci
637e5c31af7Sopenharmony_ciMSInstanceSampleMaskPattern::MSInstanceSampleMaskPattern (Context& context, const ImageMSParams& imageMSParams) : MSInstanceBaseResolveAndPerSampleFetch(context, imageMSParams)
638e5c31af7Sopenharmony_ci{
639e5c31af7Sopenharmony_ci	m_sampleMask = 0xAAAAAAAAu & ((1u << imageMSParams.numSamples) - 1u);
640e5c31af7Sopenharmony_ci}
641e5c31af7Sopenharmony_ci
642e5c31af7Sopenharmony_ciVkPipelineMultisampleStateCreateInfo MSInstanceSampleMaskPattern::getMSStateCreateInfo (const ImageMSParams& imageMSParams) const
643e5c31af7Sopenharmony_ci{
644e5c31af7Sopenharmony_ci	const VkPipelineMultisampleStateCreateInfo multisampleStateInfo =
645e5c31af7Sopenharmony_ci	{
646e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
647e5c31af7Sopenharmony_ci		DE_NULL,														// const void*								pNext;
648e5c31af7Sopenharmony_ci		(VkPipelineMultisampleStateCreateFlags)0u,						// VkPipelineMultisampleStateCreateFlags	flags;
649e5c31af7Sopenharmony_ci		imageMSParams.numSamples,										// VkSampleCountFlagBits					rasterizationSamples;
650e5c31af7Sopenharmony_ci		VK_FALSE,														// VkBool32									sampleShadingEnable;
651e5c31af7Sopenharmony_ci		imageMSParams.shadingRate,										// float									minSampleShading;
652e5c31af7Sopenharmony_ci		&m_sampleMask,													// const VkSampleMask*						pSampleMask;
653e5c31af7Sopenharmony_ci		VK_FALSE,														// VkBool32									alphaToCoverageEnable;
654e5c31af7Sopenharmony_ci		VK_FALSE,														// VkBool32									alphaToOneEnable;
655e5c31af7Sopenharmony_ci	};
656e5c31af7Sopenharmony_ci
657e5c31af7Sopenharmony_ci	return multisampleStateInfo;
658e5c31af7Sopenharmony_ci}
659e5c31af7Sopenharmony_ci
660e5c31af7Sopenharmony_ciconst VkDescriptorSetLayout* MSInstanceSampleMaskPattern::createMSPassDescSetLayout (const ImageMSParams& imageMSParams)
661e5c31af7Sopenharmony_ci{
662e5c31af7Sopenharmony_ci	DE_UNREF(imageMSParams);
663e5c31af7Sopenharmony_ci
664e5c31af7Sopenharmony_ci	const DeviceInterface&		deviceInterface = m_context.getDeviceInterface();
665e5c31af7Sopenharmony_ci	const VkDevice				device			= m_context.getDevice();
666e5c31af7Sopenharmony_ci
667e5c31af7Sopenharmony_ci	// Create descriptor set layout
668e5c31af7Sopenharmony_ci	m_descriptorSetLayout = DescriptorSetLayoutBuilder()
669e5c31af7Sopenharmony_ci		.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
670e5c31af7Sopenharmony_ci		.build(deviceInterface, device);
671e5c31af7Sopenharmony_ci
672e5c31af7Sopenharmony_ci	return &m_descriptorSetLayout.get();
673e5c31af7Sopenharmony_ci}
674e5c31af7Sopenharmony_ci
675e5c31af7Sopenharmony_ciconst VkDescriptorSet* MSInstanceSampleMaskPattern::createMSPassDescSet (const ImageMSParams& imageMSParams, const VkDescriptorSetLayout* descSetLayout)
676e5c31af7Sopenharmony_ci{
677e5c31af7Sopenharmony_ci	DE_UNREF(imageMSParams);
678e5c31af7Sopenharmony_ci
679e5c31af7Sopenharmony_ci	const DeviceInterface&		deviceInterface = m_context.getDeviceInterface();
680e5c31af7Sopenharmony_ci	const VkDevice				device			= m_context.getDevice();
681e5c31af7Sopenharmony_ci	Allocator&					allocator		= m_context.getDefaultAllocator();
682e5c31af7Sopenharmony_ci
683e5c31af7Sopenharmony_ci	// Create descriptor pool
684e5c31af7Sopenharmony_ci	m_descriptorPool = DescriptorPoolBuilder()
685e5c31af7Sopenharmony_ci		.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u)
686e5c31af7Sopenharmony_ci		.build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
687e5c31af7Sopenharmony_ci
688e5c31af7Sopenharmony_ci	// Create descriptor set
689e5c31af7Sopenharmony_ci	m_descriptorSet = makeDescriptorSet(deviceInterface, device, *m_descriptorPool, *descSetLayout);
690e5c31af7Sopenharmony_ci
691e5c31af7Sopenharmony_ci	const VkBufferCreateInfo bufferSampleMaskInfo = makeBufferCreateInfo(sizeof(VkSampleMask), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
692e5c31af7Sopenharmony_ci
693e5c31af7Sopenharmony_ci	m_buffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(deviceInterface, device, allocator, bufferSampleMaskInfo, MemoryRequirement::HostVisible));
694e5c31af7Sopenharmony_ci
695e5c31af7Sopenharmony_ci	deMemcpy(m_buffer->getAllocation().getHostPtr(), &m_sampleMask, sizeof(VkSampleMask));
696e5c31af7Sopenharmony_ci
697e5c31af7Sopenharmony_ci	flushAlloc(deviceInterface, device, m_buffer->getAllocation());
698e5c31af7Sopenharmony_ci
699e5c31af7Sopenharmony_ci	const VkDescriptorBufferInfo descBufferInfo = makeDescriptorBufferInfo(**m_buffer, 0u, sizeof(VkSampleMask));
700e5c31af7Sopenharmony_ci
701e5c31af7Sopenharmony_ci	DescriptorSetUpdateBuilder()
702e5c31af7Sopenharmony_ci		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descBufferInfo)
703e5c31af7Sopenharmony_ci		.update(deviceInterface, device);
704e5c31af7Sopenharmony_ci
705e5c31af7Sopenharmony_ci	return &m_descriptorSet.get();
706e5c31af7Sopenharmony_ci}
707e5c31af7Sopenharmony_ci
708e5c31af7Sopenharmony_ciMultisampleInstanceBase::VertexDataDesc MSInstanceSampleMaskPattern::getVertexDataDescripton (void) const
709e5c31af7Sopenharmony_ci{
710e5c31af7Sopenharmony_ci	return getVertexDataDescriptonNdc();
711e5c31af7Sopenharmony_ci}
712e5c31af7Sopenharmony_ci
713e5c31af7Sopenharmony_civoid MSInstanceSampleMaskPattern::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
714e5c31af7Sopenharmony_ci{
715e5c31af7Sopenharmony_ci	uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
716e5c31af7Sopenharmony_ci}
717e5c31af7Sopenharmony_ci
718e5c31af7Sopenharmony_citcu::TestStatus	MSInstanceSampleMaskPattern::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
719e5c31af7Sopenharmony_ci																 const vk::VkImageCreateInfo&						imageRSInfo,
720e5c31af7Sopenharmony_ci																 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
721e5c31af7Sopenharmony_ci																 const tcu::ConstPixelBufferAccess&					dataRS) const
722e5c31af7Sopenharmony_ci{
723e5c31af7Sopenharmony_ci	DE_UNREF(imageRSInfo);
724e5c31af7Sopenharmony_ci	DE_UNREF(dataRS);
725e5c31af7Sopenharmony_ci
726e5c31af7Sopenharmony_ci	if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
727e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("gl_SampleMaskIn bits have not been killed by pSampleMask state");
728e5c31af7Sopenharmony_ci
729e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("Passed");
730e5c31af7Sopenharmony_ci}
731e5c31af7Sopenharmony_ci
732e5c31af7Sopenharmony_ciclass MSCaseSampleMaskPattern;
733e5c31af7Sopenharmony_ci
734e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleMaskPattern>::init (void)
735e5c31af7Sopenharmony_ci{
736e5c31af7Sopenharmony_ci	m_testCtx.getLog()
737e5c31af7Sopenharmony_ci		<< tcu::TestLog::Message
738e5c31af7Sopenharmony_ci		<< "Verifying gl_SampleMaskIn value with pSampleMask state. gl_SampleMaskIn does not contain any bits set that are have been killed by pSampleMask state. Expecting:\n"
739e5c31af7Sopenharmony_ci		<< "Expected result: gl_SampleMaskIn AND ~(pSampleMask) should be zero.\n"
740e5c31af7Sopenharmony_ci		<< tcu::TestLog::EndMessage;
741e5c31af7Sopenharmony_ci
742e5c31af7Sopenharmony_ci	MultisampleCaseBase::init();
743e5c31af7Sopenharmony_ci}
744e5c31af7Sopenharmony_ci
745e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleMaskPattern>::initPrograms (vk::SourceCollections& programCollection) const
746e5c31af7Sopenharmony_ci{
747e5c31af7Sopenharmony_ci	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
748e5c31af7Sopenharmony_ci
749e5c31af7Sopenharmony_ci	// Create vertex shader
750e5c31af7Sopenharmony_ci	std::ostringstream vs;
751e5c31af7Sopenharmony_ci
752e5c31af7Sopenharmony_ci	vs << "#version 440\n"
753e5c31af7Sopenharmony_ci		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
754e5c31af7Sopenharmony_ci		<< "\n"
755e5c31af7Sopenharmony_ci		<< "out gl_PerVertex {\n"
756e5c31af7Sopenharmony_ci		<< "	vec4  gl_Position;\n"
757e5c31af7Sopenharmony_ci		<< "};\n"
758e5c31af7Sopenharmony_ci		<< "void main (void)\n"
759e5c31af7Sopenharmony_ci		<< "{\n"
760e5c31af7Sopenharmony_ci		<< "	gl_Position	= vs_in_position_ndc;\n"
761e5c31af7Sopenharmony_ci		<< "}\n";
762e5c31af7Sopenharmony_ci
763e5c31af7Sopenharmony_ci	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
764e5c31af7Sopenharmony_ci
765e5c31af7Sopenharmony_ci	// Create fragment shader
766e5c31af7Sopenharmony_ci	std::ostringstream fs;
767e5c31af7Sopenharmony_ci
768e5c31af7Sopenharmony_ci	fs << "#version 440\n"
769e5c31af7Sopenharmony_ci		<< "\n"
770e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec4 fs_out_color;\n"
771e5c31af7Sopenharmony_ci		<< "\n"
772e5c31af7Sopenharmony_ci		<< "layout(set = 0, binding = 0, std140) uniform SampleMaskBlock\n"
773e5c31af7Sopenharmony_ci		<< "{\n"
774e5c31af7Sopenharmony_ci		<< "	int sampleMaskPattern;\n"
775e5c31af7Sopenharmony_ci		<< "};"
776e5c31af7Sopenharmony_ci		<< "\n"
777e5c31af7Sopenharmony_ci		<< "void main (void)\n"
778e5c31af7Sopenharmony_ci		<< "{\n"
779e5c31af7Sopenharmony_ci		<< "	if ((gl_SampleMaskIn[0] & ~sampleMaskPattern) != 0)\n"
780e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
781e5c31af7Sopenharmony_ci		<< "	else\n"
782e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
783e5c31af7Sopenharmony_ci		<< "}\n";
784e5c31af7Sopenharmony_ci
785e5c31af7Sopenharmony_ci	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
786e5c31af7Sopenharmony_ci}
787e5c31af7Sopenharmony_ci
788e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseSampleMaskPattern>::createInstance (Context& context) const
789e5c31af7Sopenharmony_ci{
790e5c31af7Sopenharmony_ci	return new MSInstanceSampleMaskPattern(context, m_imageMSParams);
791e5c31af7Sopenharmony_ci}
792e5c31af7Sopenharmony_ci
793e5c31af7Sopenharmony_ciclass MSInstanceSampleMaskBitCount;
794e5c31af7Sopenharmony_ci
795e5c31af7Sopenharmony_citemplate<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskBitCount>::getVertexDataDescripton (void) const
796e5c31af7Sopenharmony_ci{
797e5c31af7Sopenharmony_ci	return getVertexDataDescriptonNdc();
798e5c31af7Sopenharmony_ci}
799e5c31af7Sopenharmony_ci
800e5c31af7Sopenharmony_citemplate<> void MSInstance<MSInstanceSampleMaskBitCount>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
801e5c31af7Sopenharmony_ci{
802e5c31af7Sopenharmony_ci	uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
803e5c31af7Sopenharmony_ci}
804e5c31af7Sopenharmony_ci
805e5c31af7Sopenharmony_citemplate<> tcu::TestStatus MSInstance<MSInstanceSampleMaskBitCount>::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
806e5c31af7Sopenharmony_ci																						 const vk::VkImageCreateInfo&						imageRSInfo,
807e5c31af7Sopenharmony_ci																						 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
808e5c31af7Sopenharmony_ci																						 const tcu::ConstPixelBufferAccess&					dataRS) const
809e5c31af7Sopenharmony_ci{
810e5c31af7Sopenharmony_ci	DE_UNREF(imageRSInfo);
811e5c31af7Sopenharmony_ci	DE_UNREF(dataRS);
812e5c31af7Sopenharmony_ci
813e5c31af7Sopenharmony_ci	if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
814e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("gl_SampleMaskIn has an illegal number of bits for some shader invocations");
815e5c31af7Sopenharmony_ci
816e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("Passed");
817e5c31af7Sopenharmony_ci}
818e5c31af7Sopenharmony_ci
819e5c31af7Sopenharmony_ciclass MSCaseSampleMaskBitCount;
820e5c31af7Sopenharmony_ci
821e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleMaskBitCount>::checkSupport (Context& context) const
822e5c31af7Sopenharmony_ci{
823e5c31af7Sopenharmony_ci	checkGraphicsPipelineLibrarySupport(context);
824e5c31af7Sopenharmony_ci	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
825e5c31af7Sopenharmony_ci}
826e5c31af7Sopenharmony_ci
827e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleMaskBitCount>::init (void)
828e5c31af7Sopenharmony_ci{
829e5c31af7Sopenharmony_ci	m_testCtx.getLog()
830e5c31af7Sopenharmony_ci		<< tcu::TestLog::Message
831e5c31af7Sopenharmony_ci		<< "Verifying gl_SampleMaskIn.\n"
832e5c31af7Sopenharmony_ci		<< "	Fragment shader will be invoked numSamples times.\n"
833e5c31af7Sopenharmony_ci		<< "	=> gl_SampleMaskIn should have a number of bits that depends on the shading rate.\n"
834e5c31af7Sopenharmony_ci		<< tcu::TestLog::EndMessage;
835e5c31af7Sopenharmony_ci
836e5c31af7Sopenharmony_ci	MultisampleCaseBase::init();
837e5c31af7Sopenharmony_ci}
838e5c31af7Sopenharmony_ci
839e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleMaskBitCount>::initPrograms (vk::SourceCollections& programCollection) const
840e5c31af7Sopenharmony_ci{
841e5c31af7Sopenharmony_ci	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
842e5c31af7Sopenharmony_ci
843e5c31af7Sopenharmony_ci	// Create vertex shader
844e5c31af7Sopenharmony_ci	std::ostringstream vs;
845e5c31af7Sopenharmony_ci
846e5c31af7Sopenharmony_ci	vs << "#version 440\n"
847e5c31af7Sopenharmony_ci		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
848e5c31af7Sopenharmony_ci		<< "\n"
849e5c31af7Sopenharmony_ci		<< "out gl_PerVertex {\n"
850e5c31af7Sopenharmony_ci		<< "	vec4  gl_Position;\n"
851e5c31af7Sopenharmony_ci		<< "};\n"
852e5c31af7Sopenharmony_ci		<< "void main (void)\n"
853e5c31af7Sopenharmony_ci		<< "{\n"
854e5c31af7Sopenharmony_ci		<< "	gl_Position	= vs_in_position_ndc;\n"
855e5c31af7Sopenharmony_ci		<< "}\n";
856e5c31af7Sopenharmony_ci
857e5c31af7Sopenharmony_ci	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
858e5c31af7Sopenharmony_ci
859e5c31af7Sopenharmony_ci	// Create fragment shader
860e5c31af7Sopenharmony_ci	std::ostringstream fs;
861e5c31af7Sopenharmony_ci
862e5c31af7Sopenharmony_ci	// The worst case scenario would be all invocations except one covering a single sample, and then one invocation covering the rest.
863e5c31af7Sopenharmony_ci	const int minInvocations	= static_cast<int>(std::ceil(static_cast<float>(m_imageMSParams.numSamples) * m_imageMSParams.shadingRate));
864e5c31af7Sopenharmony_ci	const int minCount			= 1;
865e5c31af7Sopenharmony_ci	const int maxCount			= m_imageMSParams.numSamples - (minInvocations - 1);
866e5c31af7Sopenharmony_ci
867e5c31af7Sopenharmony_ci	fs << "#version 440\n"
868e5c31af7Sopenharmony_ci		<< "\n"
869e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec4 fs_out_color;\n"
870e5c31af7Sopenharmony_ci		<< "\n"
871e5c31af7Sopenharmony_ci		<< "void main (void)\n"
872e5c31af7Sopenharmony_ci		<< "{\n"
873e5c31af7Sopenharmony_ci		<< "	const int maskBitCount = bitCount(gl_SampleMaskIn[0]);\n"
874e5c31af7Sopenharmony_ci		<< "\n"
875e5c31af7Sopenharmony_ci		<< "	if (maskBitCount < " << minCount << " || maskBitCount > " << maxCount << ")\n"
876e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
877e5c31af7Sopenharmony_ci		<< "	else\n"
878e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
879e5c31af7Sopenharmony_ci		<< "}\n";
880e5c31af7Sopenharmony_ci
881e5c31af7Sopenharmony_ci	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
882e5c31af7Sopenharmony_ci}
883e5c31af7Sopenharmony_ci
884e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseSampleMaskBitCount>::createInstance (Context& context) const
885e5c31af7Sopenharmony_ci{
886e5c31af7Sopenharmony_ci	return new MSInstance<MSInstanceSampleMaskBitCount>(context, m_imageMSParams);
887e5c31af7Sopenharmony_ci}
888e5c31af7Sopenharmony_ci
889e5c31af7Sopenharmony_ciclass MSInstanceSampleMaskCorrectBit;
890e5c31af7Sopenharmony_ci
891e5c31af7Sopenharmony_citemplate<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskCorrectBit>::getVertexDataDescripton (void) const
892e5c31af7Sopenharmony_ci{
893e5c31af7Sopenharmony_ci	return getVertexDataDescriptonNdc();
894e5c31af7Sopenharmony_ci}
895e5c31af7Sopenharmony_ci
896e5c31af7Sopenharmony_citemplate<> void MSInstance<MSInstanceSampleMaskCorrectBit>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
897e5c31af7Sopenharmony_ci{
898e5c31af7Sopenharmony_ci	uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
899e5c31af7Sopenharmony_ci}
900e5c31af7Sopenharmony_ci
901e5c31af7Sopenharmony_citemplate<> tcu::TestStatus MSInstance<MSInstanceSampleMaskCorrectBit>::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
902e5c31af7Sopenharmony_ci																						 const vk::VkImageCreateInfo&						imageRSInfo,
903e5c31af7Sopenharmony_ci																						 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
904e5c31af7Sopenharmony_ci																						 const tcu::ConstPixelBufferAccess&					dataRS) const
905e5c31af7Sopenharmony_ci{
906e5c31af7Sopenharmony_ci	DE_UNREF(imageRSInfo);
907e5c31af7Sopenharmony_ci	DE_UNREF(dataRS);
908e5c31af7Sopenharmony_ci
909e5c31af7Sopenharmony_ci	if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
910e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("The bit corresponsing to current gl_SampleID is not set in gl_SampleMaskIn");
911e5c31af7Sopenharmony_ci
912e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("Passed");
913e5c31af7Sopenharmony_ci}
914e5c31af7Sopenharmony_ci
915e5c31af7Sopenharmony_ciclass MSCaseSampleMaskCorrectBit;
916e5c31af7Sopenharmony_ci
917e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleMaskCorrectBit>::checkSupport (Context& context) const
918e5c31af7Sopenharmony_ci{
919e5c31af7Sopenharmony_ci	checkGraphicsPipelineLibrarySupport(context);
920e5c31af7Sopenharmony_ci	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
921e5c31af7Sopenharmony_ci}
922e5c31af7Sopenharmony_ci
923e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleMaskCorrectBit>::init (void)
924e5c31af7Sopenharmony_ci{
925e5c31af7Sopenharmony_ci	m_testCtx.getLog()
926e5c31af7Sopenharmony_ci		<< tcu::TestLog::Message
927e5c31af7Sopenharmony_ci		<< "Verifying gl_SampleMaskIn.\n"
928e5c31af7Sopenharmony_ci		<< "	Fragment shader will be invoked numSamples times.\n"
929e5c31af7Sopenharmony_ci		<< "	=> In each invocation gl_SampleMaskIn should have the bit set that corresponds to gl_SampleID.\n"
930e5c31af7Sopenharmony_ci		<< tcu::TestLog::EndMessage;
931e5c31af7Sopenharmony_ci
932e5c31af7Sopenharmony_ci	MultisampleCaseBase::init();
933e5c31af7Sopenharmony_ci}
934e5c31af7Sopenharmony_ci
935e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleMaskCorrectBit>::initPrograms (vk::SourceCollections& programCollection) const
936e5c31af7Sopenharmony_ci{
937e5c31af7Sopenharmony_ci	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
938e5c31af7Sopenharmony_ci
939e5c31af7Sopenharmony_ci	// Create vertex shader
940e5c31af7Sopenharmony_ci	std::ostringstream vs;
941e5c31af7Sopenharmony_ci
942e5c31af7Sopenharmony_ci	vs << "#version 440\n"
943e5c31af7Sopenharmony_ci		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
944e5c31af7Sopenharmony_ci		<< "\n"
945e5c31af7Sopenharmony_ci		<< "out gl_PerVertex {\n"
946e5c31af7Sopenharmony_ci		<< "	vec4  gl_Position;\n"
947e5c31af7Sopenharmony_ci		<< "};\n"
948e5c31af7Sopenharmony_ci		<< "void main (void)\n"
949e5c31af7Sopenharmony_ci		<< "{\n"
950e5c31af7Sopenharmony_ci		<< "	gl_Position	= vs_in_position_ndc;\n"
951e5c31af7Sopenharmony_ci		<< "}\n";
952e5c31af7Sopenharmony_ci
953e5c31af7Sopenharmony_ci	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
954e5c31af7Sopenharmony_ci
955e5c31af7Sopenharmony_ci	// Create fragment shader
956e5c31af7Sopenharmony_ci	std::ostringstream fs;
957e5c31af7Sopenharmony_ci
958e5c31af7Sopenharmony_ci	fs << "#version 440\n"
959e5c31af7Sopenharmony_ci		<< "\n"
960e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec4 fs_out_color;\n"
961e5c31af7Sopenharmony_ci		<< "\n"
962e5c31af7Sopenharmony_ci		<< "void main (void)\n"
963e5c31af7Sopenharmony_ci		<< "{\n"
964e5c31af7Sopenharmony_ci		<< "	if (((gl_SampleMaskIn[0] >> gl_SampleID) & 0x01) == 0x01)\n"
965e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
966e5c31af7Sopenharmony_ci		<< "	else\n"
967e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
968e5c31af7Sopenharmony_ci		<< "}\n";
969e5c31af7Sopenharmony_ci
970e5c31af7Sopenharmony_ci	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
971e5c31af7Sopenharmony_ci}
972e5c31af7Sopenharmony_ci
973e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseSampleMaskCorrectBit>::createInstance (Context& context) const
974e5c31af7Sopenharmony_ci{
975e5c31af7Sopenharmony_ci	return new MSInstance<MSInstanceSampleMaskCorrectBit>(context, m_imageMSParams);
976e5c31af7Sopenharmony_ci}
977e5c31af7Sopenharmony_ci
978e5c31af7Sopenharmony_ciclass MSInstanceSampleMaskWrite;
979e5c31af7Sopenharmony_ci
980e5c31af7Sopenharmony_citemplate<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskWrite>::getVertexDataDescripton (void) const
981e5c31af7Sopenharmony_ci{
982e5c31af7Sopenharmony_ci	return getVertexDataDescriptonNdc();
983e5c31af7Sopenharmony_ci}
984e5c31af7Sopenharmony_ci
985e5c31af7Sopenharmony_citemplate<> void MSInstance<MSInstanceSampleMaskWrite>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
986e5c31af7Sopenharmony_ci{
987e5c31af7Sopenharmony_ci	uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
988e5c31af7Sopenharmony_ci}
989e5c31af7Sopenharmony_ci
990e5c31af7Sopenharmony_ci//! Creates VkPipelineMultisampleStateCreateInfo with sample shading disabled.
991e5c31af7Sopenharmony_citemplate<> VkPipelineMultisampleStateCreateInfo MSInstance<MSInstanceSampleMaskWrite>::getMSStateCreateInfo (const ImageMSParams& imageMSParams) const
992e5c31af7Sopenharmony_ci{
993e5c31af7Sopenharmony_ci	const VkPipelineMultisampleStateCreateInfo multisampleStateInfo =
994e5c31af7Sopenharmony_ci	{
995e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
996e5c31af7Sopenharmony_ci		DE_NULL,													// const void*								pNext;
997e5c31af7Sopenharmony_ci		(VkPipelineMultisampleStateCreateFlags)0u,					// VkPipelineMultisampleStateCreateFlags	flags;
998e5c31af7Sopenharmony_ci		imageMSParams.numSamples,									// VkSampleCountFlagBits					rasterizationSamples;
999e5c31af7Sopenharmony_ci		VK_FALSE,													// VkBool32									sampleShadingEnable;
1000e5c31af7Sopenharmony_ci		imageMSParams.shadingRate,									// float									minSampleShading;
1001e5c31af7Sopenharmony_ci		DE_NULL,													// const VkSampleMask*						pSampleMask;
1002e5c31af7Sopenharmony_ci		VK_FALSE,													// VkBool32									alphaToCoverageEnable;
1003e5c31af7Sopenharmony_ci		VK_FALSE,													// VkBool32									alphaToOneEnable;
1004e5c31af7Sopenharmony_ci	};
1005e5c31af7Sopenharmony_ci
1006e5c31af7Sopenharmony_ci	return multisampleStateInfo;
1007e5c31af7Sopenharmony_ci}
1008e5c31af7Sopenharmony_ci
1009e5c31af7Sopenharmony_citemplate<> tcu::TestStatus MSInstance<MSInstanceSampleMaskWrite>::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
1010e5c31af7Sopenharmony_ci																					 const vk::VkImageCreateInfo&						imageRSInfo,
1011e5c31af7Sopenharmony_ci																					 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
1012e5c31af7Sopenharmony_ci																					 const tcu::ConstPixelBufferAccess&					dataRS) const
1013e5c31af7Sopenharmony_ci{
1014e5c31af7Sopenharmony_ci	const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
1015e5c31af7Sopenharmony_ci
1016e5c31af7Sopenharmony_ci	for (deUint32 z = 0u; z < imageMSInfo.extent.depth;  ++z)
1017e5c31af7Sopenharmony_ci	for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
1018e5c31af7Sopenharmony_ci	for (deUint32 x = 0u; x < imageMSInfo.extent.width;  ++x)
1019e5c31af7Sopenharmony_ci	{
1020e5c31af7Sopenharmony_ci		for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
1021e5c31af7Sopenharmony_ci		{
1022e5c31af7Sopenharmony_ci			const deUint32 firstComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z)[0];
1023e5c31af7Sopenharmony_ci
1024e5c31af7Sopenharmony_ci			if (firstComponent != 0u && firstComponent != 255u)
1025e5c31af7Sopenharmony_ci				return tcu::TestStatus::fail("Expected color to be zero or saturated on the first channel");
1026e5c31af7Sopenharmony_ci		}
1027e5c31af7Sopenharmony_ci	}
1028e5c31af7Sopenharmony_ci
1029e5c31af7Sopenharmony_ci	for (deUint32 z = 0u; z < imageRSInfo.extent.depth;  ++z)
1030e5c31af7Sopenharmony_ci	for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
1031e5c31af7Sopenharmony_ci	for (deUint32 x = 0u; x < imageRSInfo.extent.width;  ++x)
1032e5c31af7Sopenharmony_ci	{
1033e5c31af7Sopenharmony_ci		const float firstComponent = dataRS.getPixel(x, y, z)[0];
1034e5c31af7Sopenharmony_ci
1035e5c31af7Sopenharmony_ci		if (deFloatAbs(firstComponent - 0.5f) > 0.02f)
1036e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail("Expected resolve color to be half intensity on the first channel");
1037e5c31af7Sopenharmony_ci	}
1038e5c31af7Sopenharmony_ci
1039e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("Passed");
1040e5c31af7Sopenharmony_ci}
1041e5c31af7Sopenharmony_ci
1042e5c31af7Sopenharmony_ciclass MSCaseSampleMaskWrite;
1043e5c31af7Sopenharmony_ci
1044e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleMaskWrite>::init (void)
1045e5c31af7Sopenharmony_ci{
1046e5c31af7Sopenharmony_ci	m_testCtx.getLog()
1047e5c31af7Sopenharmony_ci		<< tcu::TestLog::Message
1048e5c31af7Sopenharmony_ci		<< "Discarding half of the samples using gl_SampleMask."
1049e5c31af7Sopenharmony_ci		<< "Expecting half intensity on multisample targets (numSamples > 1)\n"
1050e5c31af7Sopenharmony_ci		<< tcu::TestLog::EndMessage;
1051e5c31af7Sopenharmony_ci
1052e5c31af7Sopenharmony_ci	MultisampleCaseBase::init();
1053e5c31af7Sopenharmony_ci}
1054e5c31af7Sopenharmony_ci
1055e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleMaskWrite>::initPrograms (vk::SourceCollections& programCollection) const
1056e5c31af7Sopenharmony_ci{
1057e5c31af7Sopenharmony_ci	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
1058e5c31af7Sopenharmony_ci
1059e5c31af7Sopenharmony_ci	// Create vertex shader
1060e5c31af7Sopenharmony_ci	std::ostringstream vs;
1061e5c31af7Sopenharmony_ci
1062e5c31af7Sopenharmony_ci	vs << "#version 440\n"
1063e5c31af7Sopenharmony_ci		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1064e5c31af7Sopenharmony_ci		<< "\n"
1065e5c31af7Sopenharmony_ci		<< "out gl_PerVertex {\n"
1066e5c31af7Sopenharmony_ci		<< "	vec4  gl_Position;\n"
1067e5c31af7Sopenharmony_ci		<< "};\n"
1068e5c31af7Sopenharmony_ci		<< "void main (void)\n"
1069e5c31af7Sopenharmony_ci		<< "{\n"
1070e5c31af7Sopenharmony_ci		<< "	gl_Position	= vs_in_position_ndc;\n"
1071e5c31af7Sopenharmony_ci		<< "}\n";
1072e5c31af7Sopenharmony_ci
1073e5c31af7Sopenharmony_ci	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1074e5c31af7Sopenharmony_ci
1075e5c31af7Sopenharmony_ci	// Create fragment shader
1076e5c31af7Sopenharmony_ci	std::ostringstream fs;
1077e5c31af7Sopenharmony_ci
1078e5c31af7Sopenharmony_ci	fs << "#version 440\n"
1079e5c31af7Sopenharmony_ci		<< "\n"
1080e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec4 fs_out_color;\n"
1081e5c31af7Sopenharmony_ci		<< "\n"
1082e5c31af7Sopenharmony_ci		<< "void main (void)\n"
1083e5c31af7Sopenharmony_ci		<< "{\n"
1084e5c31af7Sopenharmony_ci		<< "	gl_SampleMask[0] = 0xAAAAAAAA;\n"
1085e5c31af7Sopenharmony_ci		<< "\n"
1086e5c31af7Sopenharmony_ci		<< "	fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1087e5c31af7Sopenharmony_ci		<< "}\n";
1088e5c31af7Sopenharmony_ci
1089e5c31af7Sopenharmony_ci	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1090e5c31af7Sopenharmony_ci}
1091e5c31af7Sopenharmony_ci
1092e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseSampleMaskWrite>::createInstance (Context& context) const
1093e5c31af7Sopenharmony_ci{
1094e5c31af7Sopenharmony_ci	return new MSInstance<MSInstanceSampleMaskWrite>(context, m_imageMSParams);
1095e5c31af7Sopenharmony_ci}
1096e5c31af7Sopenharmony_ci
1097e5c31af7Sopenharmony_ciconst set<deUint32> kValidSquareSampleCounts =
1098e5c31af7Sopenharmony_ci{
1099e5c31af7Sopenharmony_ci	vk::VK_SAMPLE_COUNT_1_BIT,
1100e5c31af7Sopenharmony_ci	vk::VK_SAMPLE_COUNT_2_BIT,
1101e5c31af7Sopenharmony_ci	vk::VK_SAMPLE_COUNT_4_BIT,
1102e5c31af7Sopenharmony_ci	vk::VK_SAMPLE_COUNT_8_BIT,
1103e5c31af7Sopenharmony_ci	vk::VK_SAMPLE_COUNT_16_BIT,
1104e5c31af7Sopenharmony_ci};
1105e5c31af7Sopenharmony_ci
1106e5c31af7Sopenharmony_civoid assertSquareSampleCount (deUint32 sampleCount)
1107e5c31af7Sopenharmony_ci{
1108e5c31af7Sopenharmony_ci	DE_ASSERT(kValidSquareSampleCounts.find(sampleCount) != kValidSquareSampleCounts.end());
1109e5c31af7Sopenharmony_ci	DE_UNREF(sampleCount); // for release builds.
1110e5c31af7Sopenharmony_ci}
1111e5c31af7Sopenharmony_ci
1112e5c31af7Sopenharmony_ci// When dealing with N samples, each coordinate (x, y) will be used to decide which samples will be written to, using N/2 bits for
1113e5c31af7Sopenharmony_ci// each of the X and Y values. Take into account this returns 0 for 1 sample.
1114e5c31af7Sopenharmony_cideUint32 bitsPerCoord (deUint32 numSamples)
1115e5c31af7Sopenharmony_ci{
1116e5c31af7Sopenharmony_ci	assertSquareSampleCount(numSamples);
1117e5c31af7Sopenharmony_ci	return (numSamples / 2u);
1118e5c31af7Sopenharmony_ci}
1119e5c31af7Sopenharmony_ci
1120e5c31af7Sopenharmony_ci// These tests will try to verify all write or mask bit combinations for the given sample count, and will verify one combination per
1121e5c31af7Sopenharmony_ci// image pixel. This means the following image sizes need to be used:
1122e5c31af7Sopenharmony_ci//		- 2 samples: 2x2
1123e5c31af7Sopenharmony_ci//		- 4 samples: 4x4
1124e5c31af7Sopenharmony_ci//		- 8 samples: 16x16
1125e5c31af7Sopenharmony_ci//		- 16 samples: 256x256
1126e5c31af7Sopenharmony_ci// In other words, images will be square with 2^(samples-1) pixels on each side.
1127e5c31af7Sopenharmony_civk::VkExtent2D imageSize (deUint32 sampleCount)
1128e5c31af7Sopenharmony_ci{
1129e5c31af7Sopenharmony_ci	assertSquareSampleCount(sampleCount);
1130e5c31af7Sopenharmony_ci
1131e5c31af7Sopenharmony_ci	// Special case: 2x1 image (not actually square).
1132e5c31af7Sopenharmony_ci	if (sampleCount == vk::VK_SAMPLE_COUNT_1_BIT)
1133e5c31af7Sopenharmony_ci		return vk::VkExtent2D{2u, 1u};
1134e5c31af7Sopenharmony_ci
1135e5c31af7Sopenharmony_ci	// Other cases: square image as described above.
1136e5c31af7Sopenharmony_ci	const auto dim = (1u<<(sampleCount>>1u));
1137e5c31af7Sopenharmony_ci	return vk::VkExtent2D{dim, dim};
1138e5c31af7Sopenharmony_ci}
1139e5c31af7Sopenharmony_ci
1140e5c31af7Sopenharmony_civk::VkExtent3D getExtent3D (deUint32 sampleCount)
1141e5c31af7Sopenharmony_ci{
1142e5c31af7Sopenharmony_ci	const auto size = imageSize(sampleCount);
1143e5c31af7Sopenharmony_ci	return vk::VkExtent3D{size.width, size.height, 1u};
1144e5c31af7Sopenharmony_ci}
1145e5c31af7Sopenharmony_ci
1146e5c31af7Sopenharmony_cistd::string getShaderDecl (const tcu::Vec4& color)
1147e5c31af7Sopenharmony_ci{
1148e5c31af7Sopenharmony_ci	std::ostringstream declaration;
1149e5c31af7Sopenharmony_ci	declaration << "vec4(" << color.x() << ", " << color.y() << ", " << color.z() << ", " << color.w() << ")";
1150e5c31af7Sopenharmony_ci	return declaration.str();
1151e5c31af7Sopenharmony_ci}
1152e5c31af7Sopenharmony_ci
1153e5c31af7Sopenharmony_cistruct WriteSampleParams
1154e5c31af7Sopenharmony_ci{
1155e5c31af7Sopenharmony_ci	vk::PipelineConstructionType	pipelineConstructionType;
1156e5c31af7Sopenharmony_ci	vk::VkSampleCountFlagBits		sampleCount;
1157e5c31af7Sopenharmony_ci};
1158e5c31af7Sopenharmony_ci
1159e5c31af7Sopenharmony_ciclass WriteSampleTest : public vkt::TestCase
1160e5c31af7Sopenharmony_ci{
1161e5c31af7Sopenharmony_cipublic:
1162e5c31af7Sopenharmony_ci									WriteSampleTest		(tcu::TestContext& testCtx, const std::string& name, const WriteSampleParams& params)
1163e5c31af7Sopenharmony_ci										: vkt::TestCase(testCtx, name), m_params(params)
1164e5c31af7Sopenharmony_ci										{}
1165e5c31af7Sopenharmony_ci	virtual							~WriteSampleTest	(void) {}
1166e5c31af7Sopenharmony_ci
1167e5c31af7Sopenharmony_ci	virtual void					initPrograms		(vk::SourceCollections& programCollection) const;
1168e5c31af7Sopenharmony_ci	virtual vkt::TestInstance*		createInstance		(Context& context) const;
1169e5c31af7Sopenharmony_ci	virtual void					checkSupport		(Context& context) const;
1170e5c31af7Sopenharmony_ci
1171e5c31af7Sopenharmony_ci	static const tcu::Vec4			kClearColor;
1172e5c31af7Sopenharmony_ci	static const tcu::Vec4			kBadColor;
1173e5c31af7Sopenharmony_ci	static const tcu::Vec4			kGoodColor;
1174e5c31af7Sopenharmony_ci	static const tcu::Vec4			kWriteColor;
1175e5c31af7Sopenharmony_ci
1176e5c31af7Sopenharmony_ci	static constexpr vk::VkFormat	kImageFormat		= vk::VK_FORMAT_R8G8B8A8_UNORM;
1177e5c31af7Sopenharmony_ci
1178e5c31af7Sopenharmony_ci	// Keep these two in sync.
1179e5c31af7Sopenharmony_ci	static constexpr vk::VkImageUsageFlags		kUsageFlags		= (vk::VK_IMAGE_USAGE_STORAGE_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
1180e5c31af7Sopenharmony_ci	static constexpr vk::VkFormatFeatureFlags	kFeatureFlags	= (vk::VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_DST_BIT);
1181e5c31af7Sopenharmony_ci
1182e5c31af7Sopenharmony_ciprivate:
1183e5c31af7Sopenharmony_ci	WriteSampleParams		m_params;
1184e5c31af7Sopenharmony_ci};
1185e5c31af7Sopenharmony_ci
1186e5c31af7Sopenharmony_ciconst tcu::Vec4 WriteSampleTest::kClearColor	{0.0f, 0.0f, 0.0f, 1.0f};
1187e5c31af7Sopenharmony_ciconst tcu::Vec4 WriteSampleTest::kBadColor		{1.0f, 0.0f, 0.0f, 1.0f};
1188e5c31af7Sopenharmony_ciconst tcu::Vec4 WriteSampleTest::kGoodColor		{0.0f, 1.0f, 0.0f, 1.0f};
1189e5c31af7Sopenharmony_ciconst tcu::Vec4 WriteSampleTest::kWriteColor	{0.0f, 0.0f, 1.0f, 1.0f};
1190e5c31af7Sopenharmony_ci
1191e5c31af7Sopenharmony_ciclass WriteSampleTestInstance : public vkt::TestInstance
1192e5c31af7Sopenharmony_ci{
1193e5c31af7Sopenharmony_cipublic:
1194e5c31af7Sopenharmony_ci								WriteSampleTestInstance		(vkt::Context& context, const WriteSampleParams& params)
1195e5c31af7Sopenharmony_ci									: vkt::TestInstance(context), m_params(params)
1196e5c31af7Sopenharmony_ci									{}
1197e5c31af7Sopenharmony_ci
1198e5c31af7Sopenharmony_ci	virtual						~WriteSampleTestInstance	(void) {}
1199e5c31af7Sopenharmony_ci
1200e5c31af7Sopenharmony_ci	virtual tcu::TestStatus		iterate						(void);
1201e5c31af7Sopenharmony_ci
1202e5c31af7Sopenharmony_ciprivate:
1203e5c31af7Sopenharmony_ci	WriteSampleParams			m_params;
1204e5c31af7Sopenharmony_ci};
1205e5c31af7Sopenharmony_ci
1206e5c31af7Sopenharmony_civoid WriteSampleTest::checkSupport (Context& context) const
1207e5c31af7Sopenharmony_ci{
1208e5c31af7Sopenharmony_ci	const auto&	vki				= context.getInstanceInterface();
1209e5c31af7Sopenharmony_ci	const auto	physicalDevice	= context.getPhysicalDevice();
1210e5c31af7Sopenharmony_ci
1211e5c31af7Sopenharmony_ci	// Check multisample storage images support.
1212e5c31af7Sopenharmony_ci	const auto features = vk::getPhysicalDeviceFeatures(vki, physicalDevice);
1213e5c31af7Sopenharmony_ci	if (!features.shaderStorageImageMultisample)
1214e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Using multisample images as storage is not supported");
1215e5c31af7Sopenharmony_ci
1216e5c31af7Sopenharmony_ci	// Check the specific image format.
1217e5c31af7Sopenharmony_ci	const auto properties = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kImageFormat);
1218e5c31af7Sopenharmony_ci	if (!(properties.optimalTilingFeatures & kFeatureFlags))
1219e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format does not support the required features");
1220e5c31af7Sopenharmony_ci
1221e5c31af7Sopenharmony_ci	// Check the supported sample count.
1222e5c31af7Sopenharmony_ci	const auto imgProps = vk::getPhysicalDeviceImageFormatProperties(vki, physicalDevice, kImageFormat, vk::VK_IMAGE_TYPE_2D, vk::VK_IMAGE_TILING_OPTIMAL, kUsageFlags, 0u);
1223e5c31af7Sopenharmony_ci	if (!(imgProps.sampleCounts & m_params.sampleCount))
1224e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format does not support the required sample count");
1225e5c31af7Sopenharmony_ci
1226e5c31af7Sopenharmony_ci	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType);
1227e5c31af7Sopenharmony_ci}
1228e5c31af7Sopenharmony_ci
1229e5c31af7Sopenharmony_civoid WriteSampleTest::initPrograms (vk::SourceCollections& programCollection) const
1230e5c31af7Sopenharmony_ci{
1231e5c31af7Sopenharmony_ci	std::ostringstream writeColorDecl, goodColorDecl, badColorDecl, clearColorDecl, allColorDecl;
1232e5c31af7Sopenharmony_ci
1233e5c31af7Sopenharmony_ci	writeColorDecl	<< "        vec4  wcolor   = " << getShaderDecl(kWriteColor)	<< ";\n";
1234e5c31af7Sopenharmony_ci	goodColorDecl	<< "        vec4  bcolor   = " << getShaderDecl(kBadColor)		<< ";\n";
1235e5c31af7Sopenharmony_ci	badColorDecl	<< "        vec4  gcolor   = " << getShaderDecl(kGoodColor)		<< ";\n";
1236e5c31af7Sopenharmony_ci	clearColorDecl	<< "        vec4  ccolor   = " << getShaderDecl(kClearColor)	<< ";\n";
1237e5c31af7Sopenharmony_ci	allColorDecl	<< writeColorDecl.str() << goodColorDecl.str() << badColorDecl.str() << clearColorDecl.str();
1238e5c31af7Sopenharmony_ci
1239e5c31af7Sopenharmony_ci	std::ostringstream shaderWrite;
1240e5c31af7Sopenharmony_ci
1241e5c31af7Sopenharmony_ci	const auto bpc		= de::toString(bitsPerCoord(m_params.sampleCount));
1242e5c31af7Sopenharmony_ci	const auto count	= de::toString(m_params.sampleCount);
1243e5c31af7Sopenharmony_ci
1244e5c31af7Sopenharmony_ci	shaderWrite
1245e5c31af7Sopenharmony_ci		<< "#version 450\n"
1246e5c31af7Sopenharmony_ci		<< "\n"
1247e5c31af7Sopenharmony_ci		<< "layout (rgba8, set=0, binding=0) uniform image2DMS writeImg;\n"
1248e5c31af7Sopenharmony_ci		<< "layout (rgba8, set=0, binding=1) uniform image2D   verificationImg;\n"
1249e5c31af7Sopenharmony_ci		<< "\n"
1250e5c31af7Sopenharmony_ci		<< "void main()\n"
1251e5c31af7Sopenharmony_ci		<< "{\n"
1252e5c31af7Sopenharmony_ci		<< writeColorDecl.str()
1253e5c31af7Sopenharmony_ci		<< "        uvec2 ucoords  = uvec2(gl_GlobalInvocationID.xy);\n"
1254e5c31af7Sopenharmony_ci		<< "        ivec2 icoords  = ivec2(ucoords);\n"
1255e5c31af7Sopenharmony_ci		<< "        uint writeMask = ((ucoords.x << " << bpc << ") | ucoords.y);\n"
1256e5c31af7Sopenharmony_ci		<< "        for (uint i = 0; i < " << count << "; ++i)\n"
1257e5c31af7Sopenharmony_ci		<< "        {\n"
1258e5c31af7Sopenharmony_ci		<< "                if ((writeMask & (1 << i)) != 0)\n"
1259e5c31af7Sopenharmony_ci		<< "                        imageStore(writeImg, icoords, int(i), wcolor);\n"
1260e5c31af7Sopenharmony_ci		<< "        }\n"
1261e5c31af7Sopenharmony_ci		<< "}\n"
1262e5c31af7Sopenharmony_ci		;
1263e5c31af7Sopenharmony_ci
1264e5c31af7Sopenharmony_ci	std::ostringstream shaderVerify;
1265e5c31af7Sopenharmony_ci
1266e5c31af7Sopenharmony_ci	shaderVerify
1267e5c31af7Sopenharmony_ci		<< "#version 450\n"
1268e5c31af7Sopenharmony_ci		<< "\n"
1269e5c31af7Sopenharmony_ci		<< "layout (rgba8, set=0, binding=0) uniform image2DMS writeImg;\n"
1270e5c31af7Sopenharmony_ci		<< "layout (rgba8, set=0, binding=1) uniform image2D   verificationImg;\n"
1271e5c31af7Sopenharmony_ci		<< "\n"
1272e5c31af7Sopenharmony_ci		<< "void main()\n"
1273e5c31af7Sopenharmony_ci		<< "{\n"
1274e5c31af7Sopenharmony_ci		<< allColorDecl.str()
1275e5c31af7Sopenharmony_ci		<< "        uvec2 ucoords  = uvec2(gl_GlobalInvocationID.xy);\n"
1276e5c31af7Sopenharmony_ci		<< "        ivec2 icoords  = ivec2(ucoords);\n"
1277e5c31af7Sopenharmony_ci		<< "        uint writeMask = ((ucoords.x << " << bpc << ") | ucoords.y);\n"
1278e5c31af7Sopenharmony_ci		<< "        bool ok = true;\n"
1279e5c31af7Sopenharmony_ci		<< "        for (uint i = 0; i < " << count << "; ++i)\n"
1280e5c31af7Sopenharmony_ci		<< "        {\n"
1281e5c31af7Sopenharmony_ci		<< "                bool expectWrite = ((writeMask & (1 << i)) != 0);\n"
1282e5c31af7Sopenharmony_ci		<< "                vec4 sampleColor = imageLoad(writeImg, icoords, int(i));\n"
1283e5c31af7Sopenharmony_ci		<< "                vec4 wantedColor = (expectWrite ? wcolor : ccolor);\n"
1284e5c31af7Sopenharmony_ci		<< "                ok = ok && (sampleColor == wantedColor);\n"
1285e5c31af7Sopenharmony_ci		<< "        }\n"
1286e5c31af7Sopenharmony_ci		<< "        vec4 resultColor = (ok ? gcolor : bcolor);\n"
1287e5c31af7Sopenharmony_ci		<< "        imageStore(verificationImg, icoords, resultColor);\n"
1288e5c31af7Sopenharmony_ci		<< "}\n"
1289e5c31af7Sopenharmony_ci		;
1290e5c31af7Sopenharmony_ci
1291e5c31af7Sopenharmony_ci	programCollection.glslSources.add("write")	<< glu::ComputeSource(shaderWrite.str());
1292e5c31af7Sopenharmony_ci	programCollection.glslSources.add("verify")	<< glu::ComputeSource(shaderVerify.str());
1293e5c31af7Sopenharmony_ci}
1294e5c31af7Sopenharmony_ci
1295e5c31af7Sopenharmony_civkt::TestInstance* WriteSampleTest::createInstance (Context& context) const
1296e5c31af7Sopenharmony_ci{
1297e5c31af7Sopenharmony_ci	return new WriteSampleTestInstance{context, m_params};
1298e5c31af7Sopenharmony_ci}
1299e5c31af7Sopenharmony_ci
1300e5c31af7Sopenharmony_citcu::TestStatus WriteSampleTestInstance::iterate (void)
1301e5c31af7Sopenharmony_ci{
1302e5c31af7Sopenharmony_ci	const auto&	vkd			= m_context.getDeviceInterface();
1303e5c31af7Sopenharmony_ci	const auto	device		= m_context.getDevice();
1304e5c31af7Sopenharmony_ci	auto&		allocator	= m_context.getDefaultAllocator();
1305e5c31af7Sopenharmony_ci	const auto	queue		= m_context.getUniversalQueue();
1306e5c31af7Sopenharmony_ci	const auto	queueIndex	= m_context.getUniversalQueueFamilyIndex();
1307e5c31af7Sopenharmony_ci	const auto	extent3D	= getExtent3D(m_params.sampleCount);
1308e5c31af7Sopenharmony_ci
1309e5c31af7Sopenharmony_ci	// Create storage image and verification image.
1310e5c31af7Sopenharmony_ci	const vk::VkImageCreateInfo storageImageInfo =
1311e5c31af7Sopenharmony_ci	{
1312e5c31af7Sopenharmony_ci		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
1313e5c31af7Sopenharmony_ci		nullptr,									// const void*				pNext;
1314e5c31af7Sopenharmony_ci		0u,											// VkImageCreateFlags		flags;
1315e5c31af7Sopenharmony_ci		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
1316e5c31af7Sopenharmony_ci		WriteSampleTest::kImageFormat,				// VkFormat					format;
1317e5c31af7Sopenharmony_ci		extent3D,									// VkExtent3D				extent;
1318e5c31af7Sopenharmony_ci		1u,											// deUint32					mipLevels;
1319e5c31af7Sopenharmony_ci		1u,											// deUint32					arrayLayers;
1320e5c31af7Sopenharmony_ci		m_params.sampleCount,						// VkSampleCountFlagBits	samples;
1321e5c31af7Sopenharmony_ci		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
1322e5c31af7Sopenharmony_ci		WriteSampleTest::kUsageFlags,				// VkImageUsageFlags		usage;
1323e5c31af7Sopenharmony_ci		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
1324e5c31af7Sopenharmony_ci		1u,											// deUint32					queueFamilyIndexCount;
1325e5c31af7Sopenharmony_ci		&queueIndex,								// const deUint32*			pQueueFamilyIndices;
1326e5c31af7Sopenharmony_ci		vk::VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			initialLayout;
1327e5c31af7Sopenharmony_ci	};
1328e5c31af7Sopenharmony_ci
1329e5c31af7Sopenharmony_ci	const vk::VkImageCreateInfo verificationImageInfo =
1330e5c31af7Sopenharmony_ci	{
1331e5c31af7Sopenharmony_ci		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
1332e5c31af7Sopenharmony_ci		nullptr,									// const void*				pNext;
1333e5c31af7Sopenharmony_ci		0u,											// VkImageCreateFlags		flags;
1334e5c31af7Sopenharmony_ci		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
1335e5c31af7Sopenharmony_ci		WriteSampleTest::kImageFormat,				// VkFormat					format;
1336e5c31af7Sopenharmony_ci		extent3D,									// VkExtent3D				extent;
1337e5c31af7Sopenharmony_ci		1u,											// deUint32					mipLevels;
1338e5c31af7Sopenharmony_ci		1u,											// deUint32					arrayLayers;
1339e5c31af7Sopenharmony_ci		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
1340e5c31af7Sopenharmony_ci		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
1341e5c31af7Sopenharmony_ci		WriteSampleTest::kUsageFlags,				// VkImageUsageFlags		usage;
1342e5c31af7Sopenharmony_ci		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
1343e5c31af7Sopenharmony_ci		1u,											// deUint32					queueFamilyIndexCount;
1344e5c31af7Sopenharmony_ci		&queueIndex,								// const deUint32*			pQueueFamilyIndices;
1345e5c31af7Sopenharmony_ci		vk::VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			initialLayout;
1346e5c31af7Sopenharmony_ci	};
1347e5c31af7Sopenharmony_ci
1348e5c31af7Sopenharmony_ci	vk::ImageWithMemory storageImgPrt		{vkd, device, allocator, storageImageInfo, vk::MemoryRequirement::Any};
1349e5c31af7Sopenharmony_ci	vk::ImageWithMemory verificationImgPtr	{vkd, device, allocator, verificationImageInfo, vk::MemoryRequirement::Any};
1350e5c31af7Sopenharmony_ci
1351e5c31af7Sopenharmony_ci	const vk::VkImageSubresourceRange kSubresourceRange =
1352e5c31af7Sopenharmony_ci	{
1353e5c31af7Sopenharmony_ci		vk::VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
1354e5c31af7Sopenharmony_ci		0u,								// deUint32				baseMipLevel;
1355e5c31af7Sopenharmony_ci		1u,								// deUint32				levelCount;
1356e5c31af7Sopenharmony_ci		0u,								// deUint32				baseArrayLayer;
1357e5c31af7Sopenharmony_ci		1u,								// deUint32				layerCount;
1358e5c31af7Sopenharmony_ci	};
1359e5c31af7Sopenharmony_ci
1360e5c31af7Sopenharmony_ci	auto storageImgViewPtr		= vk::makeImageView(vkd, device, storageImgPrt.get(), vk::VK_IMAGE_VIEW_TYPE_2D, WriteSampleTest::kImageFormat, kSubresourceRange);
1361e5c31af7Sopenharmony_ci	auto verificationImgViewPtr	= vk::makeImageView(vkd, device, verificationImgPtr.get(), vk::VK_IMAGE_VIEW_TYPE_2D, WriteSampleTest::kImageFormat, kSubresourceRange);
1362e5c31af7Sopenharmony_ci
1363e5c31af7Sopenharmony_ci	// Prepare a staging buffer to check verification image.
1364e5c31af7Sopenharmony_ci	const auto				tcuFormat			= vk::mapVkFormat(WriteSampleTest::kImageFormat);
1365e5c31af7Sopenharmony_ci	const VkDeviceSize		bufferSize			= extent3D.width * extent3D.height * extent3D.depth * tcu::getPixelSize(tcuFormat);
1366e5c31af7Sopenharmony_ci	const auto				stagingBufferInfo	= vk::makeBufferCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1367e5c31af7Sopenharmony_ci	vk::BufferWithMemory	stagingBuffer		{vkd, device, allocator, stagingBufferInfo, MemoryRequirement::HostVisible};
1368e5c31af7Sopenharmony_ci
1369e5c31af7Sopenharmony_ci	// Descriptor set layout.
1370e5c31af7Sopenharmony_ci	vk::DescriptorSetLayoutBuilder layoutBuilder;
1371e5c31af7Sopenharmony_ci	layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
1372e5c31af7Sopenharmony_ci	layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
1373e5c31af7Sopenharmony_ci	auto descriptorSetLayout = layoutBuilder.build(vkd, device);
1374e5c31af7Sopenharmony_ci
1375e5c31af7Sopenharmony_ci	// Descriptor pool.
1376e5c31af7Sopenharmony_ci	vk::DescriptorPoolBuilder poolBuilder;
1377e5c31af7Sopenharmony_ci	poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2u);
1378e5c31af7Sopenharmony_ci	auto descriptorPool = poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1379e5c31af7Sopenharmony_ci
1380e5c31af7Sopenharmony_ci	// Descriptor set.
1381e5c31af7Sopenharmony_ci	const auto descriptorSet = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
1382e5c31af7Sopenharmony_ci
1383e5c31af7Sopenharmony_ci	// Update descriptor set using the images.
1384e5c31af7Sopenharmony_ci	const auto storageImgDescriptorInfo			= vk::makeDescriptorImageInfo(DE_NULL, storageImgViewPtr.get(), vk::VK_IMAGE_LAYOUT_GENERAL);
1385e5c31af7Sopenharmony_ci	const auto verificationImgDescriptorInfo	= vk::makeDescriptorImageInfo(DE_NULL, verificationImgViewPtr.get(), vk::VK_IMAGE_LAYOUT_GENERAL);
1386e5c31af7Sopenharmony_ci
1387e5c31af7Sopenharmony_ci	vk::DescriptorSetUpdateBuilder updateBuilder;
1388e5c31af7Sopenharmony_ci	updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &storageImgDescriptorInfo);
1389e5c31af7Sopenharmony_ci	updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &verificationImgDescriptorInfo);
1390e5c31af7Sopenharmony_ci	updateBuilder.update(vkd, device);
1391e5c31af7Sopenharmony_ci
1392e5c31af7Sopenharmony_ci	// Create write and verification compute pipelines.
1393e5c31af7Sopenharmony_ci	auto shaderWriteModule	= ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("write"), 0u);
1394e5c31af7Sopenharmony_ci	auto shaderVerifyModule	= ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("verify"), 0u);
1395e5c31af7Sopenharmony_ci	auto pipelineLayout		= vk::makePipelineLayout(vkd, device, descriptorSetLayout.get());
1396e5c31af7Sopenharmony_ci
1397e5c31af7Sopenharmony_ci	const vk::VkComputePipelineCreateInfo writePipelineCreateInfo =
1398e5c31af7Sopenharmony_ci	{
1399e5c31af7Sopenharmony_ci		vk::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1400e5c31af7Sopenharmony_ci		nullptr,
1401e5c31af7Sopenharmony_ci		0u,															// flags
1402e5c31af7Sopenharmony_ci		{															// compute shader
1403e5c31af7Sopenharmony_ci			vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
1404e5c31af7Sopenharmony_ci			nullptr,													// const void*							pNext;
1405e5c31af7Sopenharmony_ci			0u,															// VkPipelineShaderStageCreateFlags		flags;
1406e5c31af7Sopenharmony_ci			vk::VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits				stage;
1407e5c31af7Sopenharmony_ci			shaderWriteModule.getModule(),								// VkShaderModule						module;
1408e5c31af7Sopenharmony_ci			"main",														// const char*							pName;
1409e5c31af7Sopenharmony_ci			nullptr,													// const VkSpecializationInfo*			pSpecializationInfo;
1410e5c31af7Sopenharmony_ci		},
1411e5c31af7Sopenharmony_ci		pipelineLayout.get(),										// layout
1412e5c31af7Sopenharmony_ci		DE_NULL,													// basePipelineHandle
1413e5c31af7Sopenharmony_ci		0,															// basePipelineIndex
1414e5c31af7Sopenharmony_ci	};
1415e5c31af7Sopenharmony_ci
1416e5c31af7Sopenharmony_ci	auto verificationPipelineCreateInfo = writePipelineCreateInfo;
1417e5c31af7Sopenharmony_ci	verificationPipelineCreateInfo.stage.module = shaderVerifyModule.getModule();
1418e5c31af7Sopenharmony_ci
1419e5c31af7Sopenharmony_ci	auto writePipeline			= vk::createComputePipeline(vkd, device, DE_NULL, &writePipelineCreateInfo);
1420e5c31af7Sopenharmony_ci	auto verificationPipeline	= vk::createComputePipeline(vkd, device, DE_NULL, &verificationPipelineCreateInfo);
1421e5c31af7Sopenharmony_ci
1422e5c31af7Sopenharmony_ci	// Transition images to the correct layout and buffers at different stages.
1423e5c31af7Sopenharmony_ci	auto storageImgPreClearBarrier			= vk::makeImageMemoryBarrier(0, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, storageImgPrt.get(), kSubresourceRange);
1424e5c31af7Sopenharmony_ci	auto storageImgPreShaderBarrier			= vk::makeImageMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, vk::VK_IMAGE_LAYOUT_GENERAL, storageImgPrt.get(), kSubresourceRange);
1425e5c31af7Sopenharmony_ci	auto verificationImgPreShaderBarrier	= vk::makeImageMemoryBarrier(0, vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL, verificationImgPtr.get(), kSubresourceRange);
1426e5c31af7Sopenharmony_ci	auto storageImgPreVerificationBarrier	= vk::makeImageMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_SHADER_READ_BIT, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL, storageImgPrt.get(), kSubresourceRange);
1427e5c31af7Sopenharmony_ci	auto verificationImgPostBarrier			= vk::makeImageMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationImgPtr.get(), kSubresourceRange);
1428e5c31af7Sopenharmony_ci	auto bufferBarrier						= vk::makeBufferMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, stagingBuffer.get(), 0ull, bufferSize);
1429e5c31af7Sopenharmony_ci
1430e5c31af7Sopenharmony_ci	// Command buffer.
1431e5c31af7Sopenharmony_ci	auto cmdPool		= vk::makeCommandPool(vkd, device, queueIndex);
1432e5c31af7Sopenharmony_ci	auto cmdBufferPtr	= vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1433e5c31af7Sopenharmony_ci	auto cmdBuffer		= cmdBufferPtr.get();
1434e5c31af7Sopenharmony_ci
1435e5c31af7Sopenharmony_ci	// Clear color for the storage image.
1436e5c31af7Sopenharmony_ci	const auto clearColor = vk::makeClearValueColor(WriteSampleTest::kClearColor);
1437e5c31af7Sopenharmony_ci
1438e5c31af7Sopenharmony_ci	const vk::VkBufferImageCopy	copyRegion =
1439e5c31af7Sopenharmony_ci	{
1440e5c31af7Sopenharmony_ci		0ull,									// VkDeviceSize				bufferOffset;
1441e5c31af7Sopenharmony_ci		extent3D.width,							// deUint32					bufferRowLength;
1442e5c31af7Sopenharmony_ci		extent3D.height,						// deUint32					bufferImageHeight;
1443e5c31af7Sopenharmony_ci		{										// VkImageSubresourceLayers	imageSubresource;
1444e5c31af7Sopenharmony_ci			vk::VK_IMAGE_ASPECT_COLOR_BIT,			// VkImageAspectFlags	aspectMask;
1445e5c31af7Sopenharmony_ci			0u,										// deUint32				mipLevel;
1446e5c31af7Sopenharmony_ci			0u,										// deUint32				baseArrayLayer;
1447e5c31af7Sopenharmony_ci			1u,										// deUint32				layerCount;
1448e5c31af7Sopenharmony_ci		},
1449e5c31af7Sopenharmony_ci		{ 0, 0, 0 },							// VkOffset3D				imageOffset;
1450e5c31af7Sopenharmony_ci		extent3D,								// VkExtent3D				imageExtent;
1451e5c31af7Sopenharmony_ci	};
1452e5c31af7Sopenharmony_ci
1453e5c31af7Sopenharmony_ci	// Record and submit commands.
1454e5c31af7Sopenharmony_ci	vk::beginCommandBuffer(vkd, cmdBuffer);
1455e5c31af7Sopenharmony_ci		// Clear storage image.
1456e5c31af7Sopenharmony_ci		vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &storageImgPreClearBarrier);
1457e5c31af7Sopenharmony_ci		vkd.cmdClearColorImage(cmdBuffer, storageImgPrt.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor.color, 1u, &kSubresourceRange);
1458e5c31af7Sopenharmony_ci
1459e5c31af7Sopenharmony_ci		// Bind write pipeline and descriptor set.
1460e5c31af7Sopenharmony_ci		vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, writePipeline.get());
1461e5c31af7Sopenharmony_ci		vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout.get(), 0, 1u, &descriptorSet.get(), 0u, nullptr);
1462e5c31af7Sopenharmony_ci
1463e5c31af7Sopenharmony_ci		// Transition images to the appropriate layout before running the shader.
1464e5c31af7Sopenharmony_ci		vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &storageImgPreShaderBarrier);
1465e5c31af7Sopenharmony_ci		vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &verificationImgPreShaderBarrier);
1466e5c31af7Sopenharmony_ci
1467e5c31af7Sopenharmony_ci		// Run shader.
1468e5c31af7Sopenharmony_ci		vkd.cmdDispatch(cmdBuffer, extent3D.width, extent3D.height, extent3D.depth);
1469e5c31af7Sopenharmony_ci
1470e5c31af7Sopenharmony_ci		// Bind verification pipeline.
1471e5c31af7Sopenharmony_ci		vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, verificationPipeline.get());
1472e5c31af7Sopenharmony_ci
1473e5c31af7Sopenharmony_ci		// Make sure writes happen before reads in the second dispatch for the storage image.
1474e5c31af7Sopenharmony_ci		vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &storageImgPreVerificationBarrier);
1475e5c31af7Sopenharmony_ci
1476e5c31af7Sopenharmony_ci		// Run verification shader.
1477e5c31af7Sopenharmony_ci		vkd.cmdDispatch(cmdBuffer, extent3D.width, extent3D.height, extent3D.depth);
1478e5c31af7Sopenharmony_ci
1479e5c31af7Sopenharmony_ci		// Change verification image layout to prepare the transfer.
1480e5c31af7Sopenharmony_ci		vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &verificationImgPostBarrier);
1481e5c31af7Sopenharmony_ci
1482e5c31af7Sopenharmony_ci		// Copy verification image to staging buffer.
1483e5c31af7Sopenharmony_ci		vkd.cmdCopyImageToBuffer(cmdBuffer, verificationImgPtr.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingBuffer.get(), 1u, &copyRegion);
1484e5c31af7Sopenharmony_ci		vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0, 0u, nullptr, 1u, &bufferBarrier, 0u, nullptr);
1485e5c31af7Sopenharmony_ci
1486e5c31af7Sopenharmony_ci	vk::endCommandBuffer(vkd, cmdBuffer);
1487e5c31af7Sopenharmony_ci
1488e5c31af7Sopenharmony_ci	// Run shaders.
1489e5c31af7Sopenharmony_ci	vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1490e5c31af7Sopenharmony_ci
1491e5c31af7Sopenharmony_ci	// Read buffer pixels.
1492e5c31af7Sopenharmony_ci	const auto& bufferAlloc = stagingBuffer.getAllocation();
1493e5c31af7Sopenharmony_ci	vk::invalidateAlloc(vkd, device, bufferAlloc);
1494e5c31af7Sopenharmony_ci
1495e5c31af7Sopenharmony_ci	// Copy buffer data to texture level and verify all pixels have the proper color.
1496e5c31af7Sopenharmony_ci	tcu::TextureLevel texture {tcuFormat, static_cast<int>(extent3D.width), static_cast<int>(extent3D.height), static_cast<int>(extent3D.depth)};
1497e5c31af7Sopenharmony_ci	const auto access = texture.getAccess();
1498e5c31af7Sopenharmony_ci	deMemcpy(access.getDataPtr(), reinterpret_cast<char*>(bufferAlloc.getHostPtr()) + bufferAlloc.getOffset(), static_cast<size_t>(bufferSize));
1499e5c31af7Sopenharmony_ci
1500e5c31af7Sopenharmony_ci	for (int i = 0; i < access.getWidth(); ++i)
1501e5c31af7Sopenharmony_ci	for (int j = 0; j < access.getHeight(); ++j)
1502e5c31af7Sopenharmony_ci	for (int k = 0; k < access.getDepth(); ++k)
1503e5c31af7Sopenharmony_ci	{
1504e5c31af7Sopenharmony_ci		if (access.getPixel(i, j, k) != WriteSampleTest::kGoodColor)
1505e5c31af7Sopenharmony_ci		{
1506e5c31af7Sopenharmony_ci			std::ostringstream msg;
1507e5c31af7Sopenharmony_ci			msg << "Invalid result at pixel (" << i << ", " << j << ", " << k << "); check error mask for more details";
1508e5c31af7Sopenharmony_ci			m_context.getTestContext().getLog() << tcu::TestLog::Image("ErrorMask", "Indicates which pixels have unexpected values", access);
1509e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail(msg.str());
1510e5c31af7Sopenharmony_ci		}
1511e5c31af7Sopenharmony_ci	}
1512e5c31af7Sopenharmony_ci
1513e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("Pass");
1514e5c31af7Sopenharmony_ci}
1515e5c31af7Sopenharmony_ci
1516e5c31af7Sopenharmony_ciusing WriteSampleMaskParams = WriteSampleParams;
1517e5c31af7Sopenharmony_ci
1518e5c31af7Sopenharmony_ciclass WriteSampleMaskTestCase : public vkt::TestCase
1519e5c31af7Sopenharmony_ci{
1520e5c31af7Sopenharmony_cipublic:
1521e5c31af7Sopenharmony_ci							WriteSampleMaskTestCase		(tcu::TestContext& testCtx, const std::string& name, const WriteSampleMaskParams& params);
1522e5c31af7Sopenharmony_ci	virtual					~WriteSampleMaskTestCase	(void) {}
1523e5c31af7Sopenharmony_ci
1524e5c31af7Sopenharmony_ci	virtual void			checkSupport				(Context& context) const;
1525e5c31af7Sopenharmony_ci	virtual void			initPrograms				(vk::SourceCollections& programCollection) const;
1526e5c31af7Sopenharmony_ci	virtual TestInstance*	createInstance				(Context& context) const;
1527e5c31af7Sopenharmony_ci	static deUint32			getBufferElems				(deUint32 sampleCount);
1528e5c31af7Sopenharmony_ci
1529e5c31af7Sopenharmony_ci	static const tcu::Vec4						kClearColor;
1530e5c31af7Sopenharmony_ci	static const tcu::Vec4						kWriteColor;
1531e5c31af7Sopenharmony_ci
1532e5c31af7Sopenharmony_ci	static constexpr vk::VkFormat				kImageFormat	= vk::VK_FORMAT_R8G8B8A8_UNORM;
1533e5c31af7Sopenharmony_ci	static constexpr vk::VkImageUsageFlags		kUsageFlags		= (vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
1534e5c31af7Sopenharmony_ci	static constexpr vk::VkFormatFeatureFlags	kFeatureFlags	= (vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
1535e5c31af7Sopenharmony_ci
1536e5c31af7Sopenharmony_ciprivate:
1537e5c31af7Sopenharmony_ci	WriteSampleMaskParams	m_params;
1538e5c31af7Sopenharmony_ci};
1539e5c31af7Sopenharmony_ci
1540e5c31af7Sopenharmony_ciconst tcu::Vec4 WriteSampleMaskTestCase::kClearColor	{0.0f, 0.0f, 0.0f, 1.0f};
1541e5c31af7Sopenharmony_ciconst tcu::Vec4 WriteSampleMaskTestCase::kWriteColor	{0.0f, 0.0f, 1.0f, 1.0f};
1542e5c31af7Sopenharmony_ci
1543e5c31af7Sopenharmony_ciclass WriteSampleMaskTestInstance : public vkt::TestInstance
1544e5c31af7Sopenharmony_ci{
1545e5c31af7Sopenharmony_cipublic:
1546e5c31af7Sopenharmony_ci								WriteSampleMaskTestInstance		(Context& context, const WriteSampleMaskParams& params);
1547e5c31af7Sopenharmony_ci	virtual						~WriteSampleMaskTestInstance	(void) {}
1548e5c31af7Sopenharmony_ci
1549e5c31af7Sopenharmony_ci	virtual tcu::TestStatus		iterate							(void);
1550e5c31af7Sopenharmony_ci
1551e5c31af7Sopenharmony_ciprivate:
1552e5c31af7Sopenharmony_ci	WriteSampleMaskParams		m_params;
1553e5c31af7Sopenharmony_ci};
1554e5c31af7Sopenharmony_ci
1555e5c31af7Sopenharmony_ciWriteSampleMaskTestCase::WriteSampleMaskTestCase (tcu::TestContext& testCtx, const std::string& name, const WriteSampleMaskParams& params)
1556e5c31af7Sopenharmony_ci	: vkt::TestCase	(testCtx, name)
1557e5c31af7Sopenharmony_ci	, m_params		(params)
1558e5c31af7Sopenharmony_ci{}
1559e5c31af7Sopenharmony_ci
1560e5c31af7Sopenharmony_civoid WriteSampleMaskTestCase::checkSupport (Context& context) const
1561e5c31af7Sopenharmony_ci{
1562e5c31af7Sopenharmony_ci	const auto&	vki				= context.getInstanceInterface();
1563e5c31af7Sopenharmony_ci	const auto	physicalDevice	= context.getPhysicalDevice();
1564e5c31af7Sopenharmony_ci
1565e5c31af7Sopenharmony_ci	// Check if sampleRateShading is supported.
1566e5c31af7Sopenharmony_ci	if(!vk::getPhysicalDeviceFeatures(vki, physicalDevice).sampleRateShading)
1567e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Sample rate shading is not supported");
1568e5c31af7Sopenharmony_ci
1569e5c31af7Sopenharmony_ci	// Check the specific image format.
1570e5c31af7Sopenharmony_ci	const auto properties = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kImageFormat);
1571e5c31af7Sopenharmony_ci	if (!(properties.optimalTilingFeatures & kFeatureFlags))
1572e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format does not support the required features");
1573e5c31af7Sopenharmony_ci
1574e5c31af7Sopenharmony_ci	// Check the supported sample count.
1575e5c31af7Sopenharmony_ci	const auto imgProps = vk::getPhysicalDeviceImageFormatProperties(vki, physicalDevice, kImageFormat, vk::VK_IMAGE_TYPE_2D, vk::VK_IMAGE_TILING_OPTIMAL, kUsageFlags, 0u);
1576e5c31af7Sopenharmony_ci	if (!(imgProps.sampleCounts & m_params.sampleCount))
1577e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format does not support the required sample count");
1578e5c31af7Sopenharmony_ci
1579e5c31af7Sopenharmony_ci	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType);
1580e5c31af7Sopenharmony_ci}
1581e5c31af7Sopenharmony_ci
1582e5c31af7Sopenharmony_civoid WriteSampleMaskTestCase::initPrograms (vk::SourceCollections& programCollection) const
1583e5c31af7Sopenharmony_ci{
1584e5c31af7Sopenharmony_ci	const auto bpc			= de::toString(bitsPerCoord(m_params.sampleCount));
1585e5c31af7Sopenharmony_ci	const auto size			= imageSize(m_params.sampleCount);
1586e5c31af7Sopenharmony_ci	const auto bufferElems	= getBufferElems(m_params.sampleCount);
1587e5c31af7Sopenharmony_ci
1588e5c31af7Sopenharmony_ci	// Passthrough vertex shader.
1589e5c31af7Sopenharmony_ci	std::ostringstream vertShader;
1590e5c31af7Sopenharmony_ci
1591e5c31af7Sopenharmony_ci	vertShader
1592e5c31af7Sopenharmony_ci		<< "#version 450\n"
1593e5c31af7Sopenharmony_ci		<< "layout (location=0) in vec2 inPos;\n"
1594e5c31af7Sopenharmony_ci		<< "void main()\n"
1595e5c31af7Sopenharmony_ci		<< "{\n"
1596e5c31af7Sopenharmony_ci		<< "    gl_Position = vec4(inPos, 0.0, 1.0);\n"
1597e5c31af7Sopenharmony_ci		<< "}\n"
1598e5c31af7Sopenharmony_ci		;
1599e5c31af7Sopenharmony_ci
1600e5c31af7Sopenharmony_ci	// Fragment shader common header.
1601e5c31af7Sopenharmony_ci	std::ostringstream fragHeader;
1602e5c31af7Sopenharmony_ci
1603e5c31af7Sopenharmony_ci	fragHeader
1604e5c31af7Sopenharmony_ci		<< "#version 450\n"
1605e5c31af7Sopenharmony_ci		<< "\n"
1606e5c31af7Sopenharmony_ci		// The color attachment is useless for the second subpass but avoids having to use an empty subpass and verifying the sample
1607e5c31af7Sopenharmony_ci		// count is valid for it.
1608e5c31af7Sopenharmony_ci		<< "layout (location=0) out vec4 outColor;\n"
1609e5c31af7Sopenharmony_ci		<< "\n"
1610e5c31af7Sopenharmony_ci		<< "vec4 wcolor = " << getShaderDecl(kWriteColor) << ";\n"
1611e5c31af7Sopenharmony_ci		<< "vec4 ccolor = " << getShaderDecl(kClearColor) << ";\n"
1612e5c31af7Sopenharmony_ci		<< "\n"
1613e5c31af7Sopenharmony_ci		;
1614e5c31af7Sopenharmony_ci
1615e5c31af7Sopenharmony_ci	const auto fragHeaderStr = fragHeader.str();
1616e5c31af7Sopenharmony_ci
1617e5c31af7Sopenharmony_ci	// Fragment shader setting the sample mask and writing to the output color attachment. The sample mask will guarantee each image
1618e5c31af7Sopenharmony_ci	// pixel gets a different combination of sample bits set, allowing the fragment shader to write in that sample or not, from all
1619e5c31af7Sopenharmony_ci	// zeros in pixel (0, 0) to all ones in the opposite corner.
1620e5c31af7Sopenharmony_ci	std::ostringstream fragShaderWrite;
1621e5c31af7Sopenharmony_ci
1622e5c31af7Sopenharmony_ci	fragShaderWrite
1623e5c31af7Sopenharmony_ci		<< fragHeaderStr
1624e5c31af7Sopenharmony_ci		<< "void main()\n"
1625e5c31af7Sopenharmony_ci		<< "{\n"
1626e5c31af7Sopenharmony_ci		<< "    uvec2 ucoords    = uvec2(gl_FragCoord);\n"
1627e5c31af7Sopenharmony_ci		<< "    ivec2 icoords    = ivec2(ucoords);\n"
1628e5c31af7Sopenharmony_ci		<< "    gl_SampleMask[0] = int((ucoords.x << " << bpc << ") | ucoords.y);\n"
1629e5c31af7Sopenharmony_ci		<< "    outColor         = wcolor;\n"
1630e5c31af7Sopenharmony_ci		<< "}\n"
1631e5c31af7Sopenharmony_ci		;
1632e5c31af7Sopenharmony_ci
1633e5c31af7Sopenharmony_ci	// Fragment shader reading from the previous output color attachment and copying the state to an SSBO for verification.
1634e5c31af7Sopenharmony_ci	std::ostringstream fragShaderCheck;
1635e5c31af7Sopenharmony_ci
1636e5c31af7Sopenharmony_ci	const bool isMultiSample = (m_params.sampleCount != vk::VK_SAMPLE_COUNT_1_BIT);
1637e5c31af7Sopenharmony_ci	fragShaderCheck
1638e5c31af7Sopenharmony_ci		<< fragHeaderStr
1639e5c31af7Sopenharmony_ci		<< "layout(set=0, binding=0, input_attachment_index=0) uniform subpassInput" << (isMultiSample ? "MS" : "") << " inputAttachment;\n"
1640e5c31af7Sopenharmony_ci		<< "layout(set=0, binding=1, std430) buffer StorageBuffer {\n"
1641e5c31af7Sopenharmony_ci		<< "    int writeFlags[" << bufferElems << "];\n"
1642e5c31af7Sopenharmony_ci		<< "} sb;\n"
1643e5c31af7Sopenharmony_ci		<< "\n"
1644e5c31af7Sopenharmony_ci		<< "void main()\n"
1645e5c31af7Sopenharmony_ci		<< "{\n"
1646e5c31af7Sopenharmony_ci		<< "    uvec2 ucoords          = uvec2(gl_FragCoord);\n"
1647e5c31af7Sopenharmony_ci		<< "    ivec2 icoords          = ivec2(ucoords);\n"
1648e5c31af7Sopenharmony_ci		<< "    uint  bufferp          = ((ucoords.y * " << size.width << " + ucoords.x) * " << m_params.sampleCount << ") + uint(gl_SampleID);\n"
1649e5c31af7Sopenharmony_ci		<< "    vec4  storedc          = subpassLoad(inputAttachment" << (isMultiSample ? ", gl_SampleID" : "") << ");\n"
1650e5c31af7Sopenharmony_ci		<< "    sb.writeFlags[bufferp] = ((storedc == wcolor) ? 1 : ((storedc == ccolor) ? 0 : 2));\n"
1651e5c31af7Sopenharmony_ci		<< "    outColor               = storedc;\n"
1652e5c31af7Sopenharmony_ci		<< "}\n"
1653e5c31af7Sopenharmony_ci		;
1654e5c31af7Sopenharmony_ci
1655e5c31af7Sopenharmony_ci	programCollection.glslSources.add("vert")		<< glu::VertexSource(vertShader.str());
1656e5c31af7Sopenharmony_ci	programCollection.glslSources.add("frag_write")	<< glu::FragmentSource(fragShaderWrite.str());
1657e5c31af7Sopenharmony_ci	programCollection.glslSources.add("frag_check")	<< glu::FragmentSource(fragShaderCheck.str());
1658e5c31af7Sopenharmony_ci}
1659e5c31af7Sopenharmony_ci
1660e5c31af7Sopenharmony_ciTestInstance* WriteSampleMaskTestCase::createInstance (Context& context) const
1661e5c31af7Sopenharmony_ci{
1662e5c31af7Sopenharmony_ci	return new WriteSampleMaskTestInstance(context, m_params);
1663e5c31af7Sopenharmony_ci}
1664e5c31af7Sopenharmony_ci
1665e5c31af7Sopenharmony_cideUint32 WriteSampleMaskTestCase::getBufferElems (deUint32 sampleCount)
1666e5c31af7Sopenharmony_ci{
1667e5c31af7Sopenharmony_ci	const auto imgSize = imageSize(sampleCount);
1668e5c31af7Sopenharmony_ci	return (imgSize.width * imgSize.height * sampleCount);
1669e5c31af7Sopenharmony_ci}
1670e5c31af7Sopenharmony_ci
1671e5c31af7Sopenharmony_ciWriteSampleMaskTestInstance::WriteSampleMaskTestInstance (Context& context, const WriteSampleMaskParams& params)
1672e5c31af7Sopenharmony_ci	: vkt::TestInstance	(context)
1673e5c31af7Sopenharmony_ci	, m_params			(params)
1674e5c31af7Sopenharmony_ci{}
1675e5c31af7Sopenharmony_ci
1676e5c31af7Sopenharmony_citcu::TestStatus WriteSampleMaskTestInstance::iterate (void)
1677e5c31af7Sopenharmony_ci{
1678e5c31af7Sopenharmony_ci	const auto&		vki					= m_context.getInstanceInterface();
1679e5c31af7Sopenharmony_ci	const auto&		vkd					= m_context.getDeviceInterface();
1680e5c31af7Sopenharmony_ci	const auto		physicalDevice		= m_context.getPhysicalDevice();
1681e5c31af7Sopenharmony_ci	const auto		device				= m_context.getDevice();
1682e5c31af7Sopenharmony_ci	auto&			alloc				= m_context.getDefaultAllocator();
1683e5c31af7Sopenharmony_ci	const auto		queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1684e5c31af7Sopenharmony_ci	const auto		queue				= m_context.getUniversalQueue();
1685e5c31af7Sopenharmony_ci
1686e5c31af7Sopenharmony_ci	static constexpr auto	kImageFormat	= WriteSampleMaskTestCase::kImageFormat;
1687e5c31af7Sopenharmony_ci	static constexpr auto	kImageUsage		= WriteSampleMaskTestCase::kUsageFlags;
1688e5c31af7Sopenharmony_ci	const auto				kImageExtent	= getExtent3D(m_params.sampleCount);
1689e5c31af7Sopenharmony_ci	const auto				kBufferElems	= WriteSampleMaskTestCase::getBufferElems(m_params.sampleCount);
1690e5c31af7Sopenharmony_ci	const auto				kBufferSize		= static_cast<vk::VkDeviceSize>(kBufferElems * sizeof(deInt32));
1691e5c31af7Sopenharmony_ci
1692e5c31af7Sopenharmony_ci	// Create image.
1693e5c31af7Sopenharmony_ci	const vk::VkImageCreateInfo imageCreateInfo =
1694e5c31af7Sopenharmony_ci	{
1695e5c31af7Sopenharmony_ci		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
1696e5c31af7Sopenharmony_ci		nullptr,									//	const void*				pNext;
1697e5c31af7Sopenharmony_ci		0u,											//	VkImageCreateFlags		flags;
1698e5c31af7Sopenharmony_ci		vk::VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
1699e5c31af7Sopenharmony_ci		kImageFormat,								//	VkFormat				format;
1700e5c31af7Sopenharmony_ci		kImageExtent,								//	VkExtent3D				extent;
1701e5c31af7Sopenharmony_ci		1u,											//	deUint32				mipLevels;
1702e5c31af7Sopenharmony_ci		1u,											//	deUint32				arrayLayers;
1703e5c31af7Sopenharmony_ci		m_params.sampleCount,						//	VkSampleCountFlagBits	samples;
1704e5c31af7Sopenharmony_ci		vk::VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
1705e5c31af7Sopenharmony_ci		kImageUsage,								//	VkImageUsageFlags		usage;
1706e5c31af7Sopenharmony_ci		vk::VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
1707e5c31af7Sopenharmony_ci		0u,											//	deUint32				queueFamilyIndexCount;
1708e5c31af7Sopenharmony_ci		nullptr,									//	const deUint32*			pQueueFamilyIndices;
1709e5c31af7Sopenharmony_ci		vk::VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
1710e5c31af7Sopenharmony_ci	};
1711e5c31af7Sopenharmony_ci
1712e5c31af7Sopenharmony_ci	const vk::ImageWithMemory colorImage	(vkd, device, alloc, imageCreateInfo, vk::MemoryRequirement::Any);
1713e5c31af7Sopenharmony_ci	const vk::ImageWithMemory auxiliarImage	(vkd, device, alloc, imageCreateInfo, vk::MemoryRequirement::Any);	// For the second subpass.
1714e5c31af7Sopenharmony_ci
1715e5c31af7Sopenharmony_ci	// Image views.
1716e5c31af7Sopenharmony_ci	const auto subresourceRange		= vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1717e5c31af7Sopenharmony_ci	const auto colorImageView		= vk::makeImageView(vkd, device, colorImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, kImageFormat, subresourceRange);
1718e5c31af7Sopenharmony_ci	const auto auxiliarImageView	= vk::makeImageView(vkd, device, auxiliarImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, kImageFormat, subresourceRange);
1719e5c31af7Sopenharmony_ci
1720e5c31af7Sopenharmony_ci	// Create storage buffer used to verify results.
1721e5c31af7Sopenharmony_ci	const vk::BufferWithMemory storageBuffer(vkd, device, alloc, vk::makeBufferCreateInfo(kBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::HostVisible);
1722e5c31af7Sopenharmony_ci
1723e5c31af7Sopenharmony_ci	// Full-screen quad.
1724e5c31af7Sopenharmony_ci	const std::vector<tcu::Vec2> quadVertices =
1725e5c31af7Sopenharmony_ci	{
1726e5c31af7Sopenharmony_ci		tcu::Vec2(-1.0f,  1.0f),	// Lower left
1727e5c31af7Sopenharmony_ci		tcu::Vec2( 1.0f,  1.0f),	// Lower right
1728e5c31af7Sopenharmony_ci		tcu::Vec2( 1.0f, -1.0f),	// Top right.
1729e5c31af7Sopenharmony_ci		tcu::Vec2(-1.0f,  1.0f),	// Lower left
1730e5c31af7Sopenharmony_ci		tcu::Vec2( 1.0f, -1.0f),	// Top right.
1731e5c31af7Sopenharmony_ci		tcu::Vec2(-1.0f, -1.0f),	// Top left.
1732e5c31af7Sopenharmony_ci	};
1733e5c31af7Sopenharmony_ci
1734e5c31af7Sopenharmony_ci	// Vertex buffer.
1735e5c31af7Sopenharmony_ci	const auto					vertexBufferSize	= static_cast<vk::VkDeviceSize>(quadVertices.size() * sizeof(decltype(quadVertices)::value_type));
1736e5c31af7Sopenharmony_ci	const vk::BufferWithMemory	vertexBuffer		(vkd, device, alloc, vk::makeBufferCreateInfo(vertexBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), vk::MemoryRequirement::HostVisible);
1737e5c31af7Sopenharmony_ci	const auto&					vertexBufferAlloc	= vertexBuffer.getAllocation();
1738e5c31af7Sopenharmony_ci	void*						vertexBufferPtr		= vertexBufferAlloc.getHostPtr();
1739e5c31af7Sopenharmony_ci	const vk::VkDeviceSize		vertexBufferOffset	= 0;
1740e5c31af7Sopenharmony_ci	deMemcpy(vertexBufferPtr, quadVertices.data(), static_cast<size_t>(vertexBufferSize));
1741e5c31af7Sopenharmony_ci	vk::flushAlloc(vkd, device, vertexBufferAlloc);
1742e5c31af7Sopenharmony_ci
1743e5c31af7Sopenharmony_ci	// Descriptor set layout.
1744e5c31af7Sopenharmony_ci	vk::DescriptorSetLayoutBuilder setLayoutBuilder;
1745e5c31af7Sopenharmony_ci	setLayoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
1746e5c31af7Sopenharmony_ci	setLayoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
1747e5c31af7Sopenharmony_ci	const auto descriptorSetLayout = setLayoutBuilder.build(vkd, device);
1748e5c31af7Sopenharmony_ci
1749e5c31af7Sopenharmony_ci	// Descriptor pool and set.
1750e5c31af7Sopenharmony_ci	vk::DescriptorPoolBuilder poolBuilder;
1751e5c31af7Sopenharmony_ci	poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u);
1752e5c31af7Sopenharmony_ci	poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u);
1753e5c31af7Sopenharmony_ci	const auto descriptorPool	= poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1754e5c31af7Sopenharmony_ci	const auto descriptorSet	= vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
1755e5c31af7Sopenharmony_ci
1756e5c31af7Sopenharmony_ci	// Render pass.
1757e5c31af7Sopenharmony_ci	const std::vector<vk::VkAttachmentDescription> attachments =
1758e5c31af7Sopenharmony_ci	{
1759e5c31af7Sopenharmony_ci		// Main color attachment.
1760e5c31af7Sopenharmony_ci		{
1761e5c31af7Sopenharmony_ci			0u,												//	VkAttachmentDescriptionFlags	flags;
1762e5c31af7Sopenharmony_ci			kImageFormat,									//	VkFormat						format;
1763e5c31af7Sopenharmony_ci			m_params.sampleCount,							//	VkSampleCountFlagBits			samples;
1764e5c31af7Sopenharmony_ci			vk::VK_ATTACHMENT_LOAD_OP_CLEAR,				//	VkAttachmentLoadOp				loadOp;
1765e5c31af7Sopenharmony_ci			vk::VK_ATTACHMENT_STORE_OP_STORE,				//	VkAttachmentStoreOp				storeOp;
1766e5c31af7Sopenharmony_ci			vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//	VkAttachmentLoadOp				stencilLoadOp;
1767e5c31af7Sopenharmony_ci			vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			//	VkAttachmentStoreOp				stencilStoreOp;
1768e5c31af7Sopenharmony_ci			vk::VK_IMAGE_LAYOUT_UNDEFINED,					//	VkImageLayout					initialLayout;
1769e5c31af7Sopenharmony_ci			vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,	//	VkImageLayout					finalLayout;
1770e5c31af7Sopenharmony_ci		},
1771e5c31af7Sopenharmony_ci		// Auxiliar color attachment for the check pass.
1772e5c31af7Sopenharmony_ci		{
1773e5c31af7Sopenharmony_ci			0u,												//	VkAttachmentDescriptionFlags	flags;
1774e5c31af7Sopenharmony_ci			kImageFormat,									//	VkFormat						format;
1775e5c31af7Sopenharmony_ci			m_params.sampleCount,							//	VkSampleCountFlagBits			samples;
1776e5c31af7Sopenharmony_ci			vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//	VkAttachmentLoadOp				loadOp;
1777e5c31af7Sopenharmony_ci			vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			//	VkAttachmentStoreOp				storeOp;
1778e5c31af7Sopenharmony_ci			vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//	VkAttachmentLoadOp				stencilLoadOp;
1779e5c31af7Sopenharmony_ci			vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			//	VkAttachmentStoreOp				stencilStoreOp;
1780e5c31af7Sopenharmony_ci			vk::VK_IMAGE_LAYOUT_UNDEFINED,					//	VkImageLayout					initialLayout;
1781e5c31af7Sopenharmony_ci			vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout					finalLayout;
1782e5c31af7Sopenharmony_ci		},
1783e5c31af7Sopenharmony_ci	};
1784e5c31af7Sopenharmony_ci
1785e5c31af7Sopenharmony_ci	const vk::VkAttachmentReference colorAttachmentReference =
1786e5c31af7Sopenharmony_ci	{
1787e5c31af7Sopenharmony_ci		0u,												//	deUint32		attachment;
1788e5c31af7Sopenharmony_ci		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout	layout;
1789e5c31af7Sopenharmony_ci	};
1790e5c31af7Sopenharmony_ci
1791e5c31af7Sopenharmony_ci	const vk::VkAttachmentReference colorAsInputAttachment =
1792e5c31af7Sopenharmony_ci	{
1793e5c31af7Sopenharmony_ci		0u,												//	deUint32		attachment;
1794e5c31af7Sopenharmony_ci		vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,	//	VkImageLayout	layout;
1795e5c31af7Sopenharmony_ci	};
1796e5c31af7Sopenharmony_ci
1797e5c31af7Sopenharmony_ci	const vk::VkAttachmentReference auxiliarAttachmentReference =
1798e5c31af7Sopenharmony_ci	{
1799e5c31af7Sopenharmony_ci		1u,												//	deUint32		attachment;
1800e5c31af7Sopenharmony_ci		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout	layout;
1801e5c31af7Sopenharmony_ci	};
1802e5c31af7Sopenharmony_ci
1803e5c31af7Sopenharmony_ci	const std::vector<vk::VkSubpassDescription> subpasses =
1804e5c31af7Sopenharmony_ci	{
1805e5c31af7Sopenharmony_ci		// First subpass writing to the main attachment.
1806e5c31af7Sopenharmony_ci		{
1807e5c31af7Sopenharmony_ci			0u,										//	VkSubpassDescriptionFlags		flags;
1808e5c31af7Sopenharmony_ci			vk::VK_PIPELINE_BIND_POINT_GRAPHICS,	//	VkPipelineBindPoint				pipelineBindPoint;
1809e5c31af7Sopenharmony_ci			0u,										//	deUint32						inputAttachmentCount;
1810e5c31af7Sopenharmony_ci			nullptr,								//	const VkAttachmentReference*	pInputAttachments;
1811e5c31af7Sopenharmony_ci			1u,										//	deUint32						colorAttachmentCount;
1812e5c31af7Sopenharmony_ci			&colorAttachmentReference,				//	const VkAttachmentReference*	pColorAttachments;
1813e5c31af7Sopenharmony_ci			nullptr,								//	const VkAttachmentReference*	pResolveAttachments;
1814e5c31af7Sopenharmony_ci			nullptr,								//	const VkAttachmentReference*	pDepthStencilAttachment;
1815e5c31af7Sopenharmony_ci			0u,										//	deUint32						preserveAttachmentCount;
1816e5c31af7Sopenharmony_ci			nullptr,								//	const deUint32*					pPreserveAttachments;
1817e5c31af7Sopenharmony_ci		},
1818e5c31af7Sopenharmony_ci		// Second subpass writing to the auxiliar attachment.
1819e5c31af7Sopenharmony_ci		{
1820e5c31af7Sopenharmony_ci			0u,										//	VkSubpassDescriptionFlags		flags;
1821e5c31af7Sopenharmony_ci			vk::VK_PIPELINE_BIND_POINT_GRAPHICS,	//	VkPipelineBindPoint				pipelineBindPoint;
1822e5c31af7Sopenharmony_ci			1u,										//	deUint32						inputAttachmentCount;
1823e5c31af7Sopenharmony_ci			&colorAsInputAttachment,				//	const VkAttachmentReference*	pInputAttachments;
1824e5c31af7Sopenharmony_ci			1u,										//	deUint32						colorAttachmentCount;
1825e5c31af7Sopenharmony_ci			&auxiliarAttachmentReference,			//	const VkAttachmentReference*	pColorAttachments;
1826e5c31af7Sopenharmony_ci			nullptr,								//	const VkAttachmentReference*	pResolveAttachments;
1827e5c31af7Sopenharmony_ci			nullptr,								//	const VkAttachmentReference*	pDepthStencilAttachment;
1828e5c31af7Sopenharmony_ci			0u,										//	deUint32						preserveAttachmentCount;
1829e5c31af7Sopenharmony_ci			nullptr,								//	const deUint32*					pPreserveAttachments;
1830e5c31af7Sopenharmony_ci		},
1831e5c31af7Sopenharmony_ci	};
1832e5c31af7Sopenharmony_ci
1833e5c31af7Sopenharmony_ci	const std::vector<vk::VkSubpassDependency> subpassDependencies =
1834e5c31af7Sopenharmony_ci	{
1835e5c31af7Sopenharmony_ci		// First subpass writes to the color attachment and second subpass reads it as an input attachment.
1836e5c31af7Sopenharmony_ci		{
1837e5c31af7Sopenharmony_ci			0u,													//	deUint32				srcSubpass;
1838e5c31af7Sopenharmony_ci			1u,													//	deUint32				dstSubpass;
1839e5c31af7Sopenharmony_ci			vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,	//	VkPipelineStageFlags	srcStageMask;
1840e5c31af7Sopenharmony_ci			vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,			//	VkPipelineStageFlags	dstStageMask;
1841e5c31af7Sopenharmony_ci			vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			//	VkAccessFlags			srcAccessMask;
1842e5c31af7Sopenharmony_ci			vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,			//	VkAccessFlags			dstAccessMask;
1843e5c31af7Sopenharmony_ci			0u,													//	VkDependencyFlags		dependencyFlags;
1844e5c31af7Sopenharmony_ci		},
1845e5c31af7Sopenharmony_ci	};
1846e5c31af7Sopenharmony_ci
1847e5c31af7Sopenharmony_ci	const vk::VkRenderPassCreateInfo renderPassInfo =
1848e5c31af7Sopenharmony_ci	{
1849e5c31af7Sopenharmony_ci		vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,		//	VkStructureType					sType;
1850e5c31af7Sopenharmony_ci		nullptr,											//	const void*						pNext;
1851e5c31af7Sopenharmony_ci		0u,													//	VkRenderPassCreateFlags			flags;
1852e5c31af7Sopenharmony_ci		static_cast<deUint32>(attachments.size()),			//	deUint32						attachmentCount;
1853e5c31af7Sopenharmony_ci		attachments.data(),									//	const VkAttachmentDescription*	pAttachments;
1854e5c31af7Sopenharmony_ci		static_cast<deUint32>(subpasses.size()),			//	deUint32						subpassCount;
1855e5c31af7Sopenharmony_ci		subpasses.data(),									//	const VkSubpassDescription*		pSubpasses;
1856e5c31af7Sopenharmony_ci		static_cast<deUint32>(subpassDependencies.size()),	//	deUint32						dependencyCount;
1857e5c31af7Sopenharmony_ci		subpassDependencies.data(),							//	const VkSubpassDependency*		pDependencies;
1858e5c31af7Sopenharmony_ci	};
1859e5c31af7Sopenharmony_ci	RenderPassWrapper renderPass (m_params.pipelineConstructionType, vkd, device, &renderPassInfo);
1860e5c31af7Sopenharmony_ci
1861e5c31af7Sopenharmony_ci	// Framebuffer.
1862e5c31af7Sopenharmony_ci	const std::vector<vk::VkImage>		images		=
1863e5c31af7Sopenharmony_ci	{
1864e5c31af7Sopenharmony_ci		colorImage.get(),
1865e5c31af7Sopenharmony_ci		auxiliarImage.get(),
1866e5c31af7Sopenharmony_ci	};
1867e5c31af7Sopenharmony_ci	const std::vector<vk::VkImageView>	imageViews	=
1868e5c31af7Sopenharmony_ci	{
1869e5c31af7Sopenharmony_ci		colorImageView.get(),
1870e5c31af7Sopenharmony_ci		auxiliarImageView.get(),
1871e5c31af7Sopenharmony_ci	};
1872e5c31af7Sopenharmony_ci	renderPass.createFramebuffer(vkd, device, static_cast<deUint32>(imageViews.size()), images.data(), imageViews.data(), kImageExtent.width, kImageExtent.height);
1873e5c31af7Sopenharmony_ci
1874e5c31af7Sopenharmony_ci	// Empty pipeline layout for the first subpass.
1875e5c31af7Sopenharmony_ci	const PipelineLayoutWrapper emptyPipelineLayout (m_params.pipelineConstructionType, vkd, device);
1876e5c31af7Sopenharmony_ci
1877e5c31af7Sopenharmony_ci	// Pipeline layout for the second subpass.
1878e5c31af7Sopenharmony_ci	const PipelineLayoutWrapper checkPipelineLayout (m_params.pipelineConstructionType, vkd, device, descriptorSetLayout.get());
1879e5c31af7Sopenharmony_ci
1880e5c31af7Sopenharmony_ci	// Shader modules.
1881e5c31af7Sopenharmony_ci	const auto vertModule	= ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
1882e5c31af7Sopenharmony_ci	const auto writeModule	= ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag_write"), 0u);
1883e5c31af7Sopenharmony_ci	const auto checkModule	= ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag_check"), 0u);
1884e5c31af7Sopenharmony_ci
1885e5c31af7Sopenharmony_ci	const std::vector<vk::VkVertexInputBindingDescription> vertexBindings =
1886e5c31af7Sopenharmony_ci	{
1887e5c31af7Sopenharmony_ci		{
1888e5c31af7Sopenharmony_ci			0u,																	//	deUint32			binding;
1889e5c31af7Sopenharmony_ci			static_cast<deUint32>(sizeof(decltype(quadVertices)::value_type)),	//	deUint32			stride;
1890e5c31af7Sopenharmony_ci			vk::VK_VERTEX_INPUT_RATE_VERTEX,									//	VkVertexInputRate	inputRate;
1891e5c31af7Sopenharmony_ci		},
1892e5c31af7Sopenharmony_ci	};
1893e5c31af7Sopenharmony_ci
1894e5c31af7Sopenharmony_ci	const std::vector<vk::VkVertexInputAttributeDescription> vertexAttributes =
1895e5c31af7Sopenharmony_ci	{
1896e5c31af7Sopenharmony_ci		{
1897e5c31af7Sopenharmony_ci			0u,								//	deUint32	location;
1898e5c31af7Sopenharmony_ci			0u,								//	deUint32	binding;
1899e5c31af7Sopenharmony_ci			vk::VK_FORMAT_R32G32_SFLOAT,	//	VkFormat	format;
1900e5c31af7Sopenharmony_ci			0u,								//	deUint32	offset;
1901e5c31af7Sopenharmony_ci		},
1902e5c31af7Sopenharmony_ci	};
1903e5c31af7Sopenharmony_ci
1904e5c31af7Sopenharmony_ci	const vk::VkPipelineVertexInputStateCreateInfo vertexInputInfo =
1905e5c31af7Sopenharmony_ci	{
1906e5c31af7Sopenharmony_ci		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	//	VkStructureType								sType;
1907e5c31af7Sopenharmony_ci		nullptr,														//	const void*									pNext;
1908e5c31af7Sopenharmony_ci		0u,																//	VkPipelineVertexInputStateCreateFlags		flags;
1909e5c31af7Sopenharmony_ci		static_cast<deUint32>(vertexBindings.size()),					//	deUint32									vertexBindingDescriptionCount;
1910e5c31af7Sopenharmony_ci		vertexBindings.data(),											//	const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
1911e5c31af7Sopenharmony_ci		static_cast<deUint32>(vertexAttributes.size()),					//	deUint32									vertexAttributeDescriptionCount;
1912e5c31af7Sopenharmony_ci		vertexAttributes.data(),										//	const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1913e5c31af7Sopenharmony_ci	};
1914e5c31af7Sopenharmony_ci
1915e5c31af7Sopenharmony_ci	const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo =
1916e5c31af7Sopenharmony_ci	{
1917e5c31af7Sopenharmony_ci		vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	//	VkStructureType							sType;
1918e5c31af7Sopenharmony_ci		nullptr,															//	const void*								pNext;
1919e5c31af7Sopenharmony_ci		0u,																	//	VkPipelineInputAssemblyStateCreateFlags	flags;
1920e5c31af7Sopenharmony_ci		vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							//	VkPrimitiveTopology						topology;
1921e5c31af7Sopenharmony_ci		VK_FALSE,															//	VkBool32								primitiveRestartEnable;
1922e5c31af7Sopenharmony_ci	};
1923e5c31af7Sopenharmony_ci
1924e5c31af7Sopenharmony_ci	const std::vector<VkViewport>	viewport	{ vk::makeViewport(kImageExtent) };
1925e5c31af7Sopenharmony_ci	const std::vector<VkRect2D>		scissor		{ vk::makeRect2D(kImageExtent) };
1926e5c31af7Sopenharmony_ci
1927e5c31af7Sopenharmony_ci	const vk::VkPipelineMultisampleStateCreateInfo multisampleInfo =
1928e5c31af7Sopenharmony_ci	{
1929e5c31af7Sopenharmony_ci		vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	//	VkStructureType							sType;
1930e5c31af7Sopenharmony_ci		nullptr,														//	const void*								pNext;
1931e5c31af7Sopenharmony_ci		0u,																//	VkPipelineMultisampleStateCreateFlags	flags;
1932e5c31af7Sopenharmony_ci		m_params.sampleCount,											//	VkSampleCountFlagBits					rasterizationSamples;
1933e5c31af7Sopenharmony_ci		VK_FALSE,														//	VkBool32								sampleShadingEnable;
1934e5c31af7Sopenharmony_ci		1.0f,															//	float									minSampleShading;
1935e5c31af7Sopenharmony_ci		nullptr,														//	const VkSampleMask*						pSampleMask;
1936e5c31af7Sopenharmony_ci		VK_FALSE,														//	VkBool32								alphaToCoverageEnable;
1937e5c31af7Sopenharmony_ci		VK_FALSE,														//	VkBool32								alphaToOneEnable;
1938e5c31af7Sopenharmony_ci	};
1939e5c31af7Sopenharmony_ci
1940e5c31af7Sopenharmony_ci	const auto stencilState = vk::makeStencilOpState(vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0xFFu, 0xFFu, 0u);
1941e5c31af7Sopenharmony_ci
1942e5c31af7Sopenharmony_ci	const vk::VkPipelineDepthStencilStateCreateInfo depthStencilInfo =
1943e5c31af7Sopenharmony_ci	{
1944e5c31af7Sopenharmony_ci		vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	//	VkStructureType							sType;
1945e5c31af7Sopenharmony_ci		nullptr,														//	const void*								pNext;
1946e5c31af7Sopenharmony_ci		0u,																//	VkPipelineDepthStencilStateCreateFlags	flags;
1947e5c31af7Sopenharmony_ci		VK_FALSE,														//	VkBool32								depthTestEnable;
1948e5c31af7Sopenharmony_ci		VK_FALSE,														//	VkBool32								depthWriteEnable;
1949e5c31af7Sopenharmony_ci		vk::VK_COMPARE_OP_ALWAYS,										//	VkCompareOp								depthCompareOp;
1950e5c31af7Sopenharmony_ci		VK_FALSE,														//	VkBool32								depthBoundsTestEnable;
1951e5c31af7Sopenharmony_ci		VK_FALSE,														//	VkBool32								stencilTestEnable;
1952e5c31af7Sopenharmony_ci		stencilState,													//	VkStencilOpState						front;
1953e5c31af7Sopenharmony_ci		stencilState,													//	VkStencilOpState						back;
1954e5c31af7Sopenharmony_ci		0.0f,															//	float									minDepthBounds;
1955e5c31af7Sopenharmony_ci		1.0f,															//	float									maxDepthBounds;
1956e5c31af7Sopenharmony_ci	};
1957e5c31af7Sopenharmony_ci
1958e5c31af7Sopenharmony_ci	const vk::VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
1959e5c31af7Sopenharmony_ci	{
1960e5c31af7Sopenharmony_ci		VK_FALSE,					//	VkBool32				blendEnable;
1961e5c31af7Sopenharmony_ci		vk::VK_BLEND_FACTOR_ZERO,	//	VkBlendFactor			srcColorBlendFactor;
1962e5c31af7Sopenharmony_ci		vk::VK_BLEND_FACTOR_ZERO,	//	VkBlendFactor			dstColorBlendFactor;
1963e5c31af7Sopenharmony_ci		vk::VK_BLEND_OP_ADD,		//	VkBlendOp				colorBlendOp;
1964e5c31af7Sopenharmony_ci		vk::VK_BLEND_FACTOR_ZERO,	//	VkBlendFactor			srcAlphaBlendFactor;
1965e5c31af7Sopenharmony_ci		vk::VK_BLEND_FACTOR_ZERO,	//	VkBlendFactor			dstAlphaBlendFactor;
1966e5c31af7Sopenharmony_ci		vk::VK_BLEND_OP_ADD,		//	VkBlendOp				alphaBlendOp;
1967e5c31af7Sopenharmony_ci		(							//	VkColorComponentFlags	colorWriteMask;
1968e5c31af7Sopenharmony_ci			vk::VK_COLOR_COMPONENT_R_BIT	|
1969e5c31af7Sopenharmony_ci			vk::VK_COLOR_COMPONENT_G_BIT	|
1970e5c31af7Sopenharmony_ci			vk::VK_COLOR_COMPONENT_B_BIT	|
1971e5c31af7Sopenharmony_ci			vk::VK_COLOR_COMPONENT_A_BIT	),
1972e5c31af7Sopenharmony_ci	};
1973e5c31af7Sopenharmony_ci
1974e5c31af7Sopenharmony_ci	const vk::VkPipelineColorBlendStateCreateInfo colorBlendInfo =
1975e5c31af7Sopenharmony_ci	{
1976e5c31af7Sopenharmony_ci		vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	//	VkStructureType								sType;
1977e5c31af7Sopenharmony_ci		nullptr,														//	const void*									pNext;
1978e5c31af7Sopenharmony_ci		0u,																//	VkPipelineColorBlendStateCreateFlags		flags;
1979e5c31af7Sopenharmony_ci		VK_FALSE,														//	VkBool32									logicOpEnable;
1980e5c31af7Sopenharmony_ci		vk::VK_LOGIC_OP_NO_OP,											//	VkLogicOp									logicOp;
1981e5c31af7Sopenharmony_ci		1u,																//	deUint32									attachmentCount;
1982e5c31af7Sopenharmony_ci		&colorBlendAttachmentState,										//	const VkPipelineColorBlendAttachmentState*	pAttachments;
1983e5c31af7Sopenharmony_ci		{ .0f, .0f, .0f, .0f },											//	float										blendConstants[4];
1984e5c31af7Sopenharmony_ci	};
1985e5c31af7Sopenharmony_ci
1986e5c31af7Sopenharmony_ci	const vk::VkPipelineDynamicStateCreateInfo dynamicStateInfo =
1987e5c31af7Sopenharmony_ci	{
1988e5c31af7Sopenharmony_ci		vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	//	VkStructureType						sType;
1989e5c31af7Sopenharmony_ci		nullptr,													//	const void*							pNext;
1990e5c31af7Sopenharmony_ci		0u,															//	VkPipelineDynamicStateCreateFlags	flags;
1991e5c31af7Sopenharmony_ci		0u,															//	deUint32							dynamicStateCount;
1992e5c31af7Sopenharmony_ci		nullptr,													//	const VkDynamicState*				pDynamicStates;
1993e5c31af7Sopenharmony_ci	};
1994e5c31af7Sopenharmony_ci
1995e5c31af7Sopenharmony_ci	// Pipeline for the first subpass.
1996e5c31af7Sopenharmony_ci	vk::GraphicsPipelineWrapper firstSubpassPipeline(vki, vkd, physicalDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType);
1997e5c31af7Sopenharmony_ci	firstSubpassPipeline.setDynamicState(&dynamicStateInfo)
1998e5c31af7Sopenharmony_ci						.setDefaultRasterizationState()
1999e5c31af7Sopenharmony_ci						.setupVertexInputState(&vertexInputInfo, &inputAssemblyInfo)
2000e5c31af7Sopenharmony_ci						.setupPreRasterizationShaderState(viewport, scissor, emptyPipelineLayout, *renderPass, 0u, vertModule)
2001e5c31af7Sopenharmony_ci						.setupFragmentShaderState(emptyPipelineLayout, *renderPass, 0u, writeModule, &depthStencilInfo, &multisampleInfo)
2002e5c31af7Sopenharmony_ci						.setupFragmentOutputState(*renderPass, 0u, &colorBlendInfo, &multisampleInfo)
2003e5c31af7Sopenharmony_ci						.setMonolithicPipelineLayout(emptyPipelineLayout)
2004e5c31af7Sopenharmony_ci						.buildPipeline();
2005e5c31af7Sopenharmony_ci
2006e5c31af7Sopenharmony_ci	// Pipeline for the second subpass.
2007e5c31af7Sopenharmony_ci	vk::GraphicsPipelineWrapper secondSubpassPipeline(vki, vkd, physicalDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType);
2008e5c31af7Sopenharmony_ci	secondSubpassPipeline.setDynamicState(&dynamicStateInfo)
2009e5c31af7Sopenharmony_ci						.setDefaultRasterizationState()
2010e5c31af7Sopenharmony_ci						.setupVertexInputState(&vertexInputInfo, &inputAssemblyInfo)
2011e5c31af7Sopenharmony_ci						.setupPreRasterizationShaderState(viewport, scissor, checkPipelineLayout, *renderPass, 1u, vertModule)
2012e5c31af7Sopenharmony_ci						.setupFragmentShaderState(checkPipelineLayout, *renderPass, 1u, checkModule, &depthStencilInfo, &multisampleInfo)
2013e5c31af7Sopenharmony_ci						.setupFragmentOutputState(*renderPass, 1u, &colorBlendInfo, &multisampleInfo)
2014e5c31af7Sopenharmony_ci						.setMonolithicPipelineLayout(checkPipelineLayout)
2015e5c31af7Sopenharmony_ci						.buildPipeline();
2016e5c31af7Sopenharmony_ci
2017e5c31af7Sopenharmony_ci	// Command pool and command buffer.
2018e5c31af7Sopenharmony_ci	const auto cmdPool		= vk::makeCommandPool(vkd, device, queueFamilyIndex);
2019e5c31af7Sopenharmony_ci	const auto cmdBufferPtr	= vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2020e5c31af7Sopenharmony_ci	const auto cmdBuffer	= cmdBufferPtr.get();
2021e5c31af7Sopenharmony_ci
2022e5c31af7Sopenharmony_ci	// Update descriptor set.
2023e5c31af7Sopenharmony_ci	vk::DescriptorSetUpdateBuilder updateBuilder;
2024e5c31af7Sopenharmony_ci	const auto imageInfo	= vk::makeDescriptorImageInfo(DE_NULL, colorImageView.get(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2025e5c31af7Sopenharmony_ci	const auto bufferInfo	= vk::makeDescriptorBufferInfo(storageBuffer.get(), 0u, VK_WHOLE_SIZE);
2026e5c31af7Sopenharmony_ci	updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &imageInfo);
2027e5c31af7Sopenharmony_ci	updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo);
2028e5c31af7Sopenharmony_ci	updateBuilder.update(vkd, device);
2029e5c31af7Sopenharmony_ci
2030e5c31af7Sopenharmony_ci	// Output buffer pipeline barrier.
2031e5c31af7Sopenharmony_ci	const auto bufferBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, storageBuffer.get(), 0ull, VK_WHOLE_SIZE);
2032e5c31af7Sopenharmony_ci
2033e5c31af7Sopenharmony_ci	// Run pipelines.
2034e5c31af7Sopenharmony_ci	vk::beginCommandBuffer(vkd, cmdBuffer);
2035e5c31af7Sopenharmony_ci
2036e5c31af7Sopenharmony_ci	renderPass.begin(vkd, cmdBuffer, vk::makeRect2D(kImageExtent), WriteSampleMaskTestCase::kClearColor);
2037e5c31af7Sopenharmony_ci	vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
2038e5c31af7Sopenharmony_ci	firstSubpassPipeline.bind(cmdBuffer);
2039e5c31af7Sopenharmony_ci	vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(quadVertices.size()), 1u, 0u, 0u);
2040e5c31af7Sopenharmony_ci
2041e5c31af7Sopenharmony_ci	renderPass.nextSubpass(vkd, cmdBuffer, vk::VK_SUBPASS_CONTENTS_INLINE);
2042e5c31af7Sopenharmony_ci	secondSubpassPipeline.bind(cmdBuffer);
2043e5c31af7Sopenharmony_ci	vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, checkPipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
2044e5c31af7Sopenharmony_ci	vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(quadVertices.size()), 1u, 0u, 0u);
2045e5c31af7Sopenharmony_ci
2046e5c31af7Sopenharmony_ci	renderPass.end(vkd, cmdBuffer);
2047e5c31af7Sopenharmony_ci	vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, nullptr, 1u, &bufferBarrier, 0u, nullptr);
2048e5c31af7Sopenharmony_ci	vk::endCommandBuffer(vkd, cmdBuffer);
2049e5c31af7Sopenharmony_ci
2050e5c31af7Sopenharmony_ci	vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
2051e5c31af7Sopenharmony_ci
2052e5c31af7Sopenharmony_ci	// Check buffer contents.
2053e5c31af7Sopenharmony_ci	auto&					bufferAlloc		= storageBuffer.getAllocation();
2054e5c31af7Sopenharmony_ci	const void*				bufferPtr		= bufferAlloc.getHostPtr();
2055e5c31af7Sopenharmony_ci	std::vector<deInt32>	bufferContents	(kBufferElems, 0);
2056e5c31af7Sopenharmony_ci
2057e5c31af7Sopenharmony_ci	vk::invalidateAlloc(vkd, device, bufferAlloc);
2058e5c31af7Sopenharmony_ci	deMemcpy(bufferContents.data(), bufferPtr, static_cast<size_t>(kBufferSize));
2059e5c31af7Sopenharmony_ci
2060e5c31af7Sopenharmony_ci	const auto sampleCount	= static_cast<deUint32>(m_params.sampleCount);
2061e5c31af7Sopenharmony_ci	const auto bpc			= bitsPerCoord(sampleCount);
2062e5c31af7Sopenharmony_ci
2063e5c31af7Sopenharmony_ci	for (deUint32 x = 0; x < kImageExtent.width; ++x)
2064e5c31af7Sopenharmony_ci	for (deUint32 y = 0; y < kImageExtent.height; ++y)
2065e5c31af7Sopenharmony_ci	{
2066e5c31af7Sopenharmony_ci		// Samples on which we expect writes.
2067e5c31af7Sopenharmony_ci		const deUint32 sampleMask = ((x << bpc) | y);
2068e5c31af7Sopenharmony_ci
2069e5c31af7Sopenharmony_ci		// Starting location for the pixel sample values in the buffer.
2070e5c31af7Sopenharmony_ci		const deUint32 pixelOffset = (y * kImageExtent.width + x) * sampleCount;
2071e5c31af7Sopenharmony_ci
2072e5c31af7Sopenharmony_ci		for (deUint32 s = 0; s < sampleCount; ++s)
2073e5c31af7Sopenharmony_ci		{
2074e5c31af7Sopenharmony_ci			const deUint32 sampleIndex	= pixelOffset + s;
2075e5c31af7Sopenharmony_ci			const deInt32& value		= bufferContents[sampleIndex];
2076e5c31af7Sopenharmony_ci
2077e5c31af7Sopenharmony_ci			if (value != 0 && value != 1)
2078e5c31af7Sopenharmony_ci			{
2079e5c31af7Sopenharmony_ci				// Garbage!
2080e5c31af7Sopenharmony_ci				std::ostringstream msg;
2081e5c31af7Sopenharmony_ci				msg << "Found garbage value " << value << " in buffer position " << sampleIndex << " (x=" << x << ", y=" << y << ", sample=" << s << ")";
2082e5c31af7Sopenharmony_ci				return tcu::TestStatus::fail(msg.str());
2083e5c31af7Sopenharmony_ci			}
2084e5c31af7Sopenharmony_ci
2085e5c31af7Sopenharmony_ci			const deInt32 expected = (((sampleMask & (1u << s)) != 0u) ? 1 : 0);
2086e5c31af7Sopenharmony_ci			if (value != expected)
2087e5c31af7Sopenharmony_ci			{
2088e5c31af7Sopenharmony_ci				std::ostringstream msg;
2089e5c31af7Sopenharmony_ci				msg << "Read " << value << " while expecting " << expected << " in buffer position " << sampleIndex << " (x=" << x << ", y=" << y << ", sample=" << s << ")";
2090e5c31af7Sopenharmony_ci				return tcu::TestStatus::fail(msg.str());
2091e5c31af7Sopenharmony_ci			}
2092e5c31af7Sopenharmony_ci		}
2093e5c31af7Sopenharmony_ci	}
2094e5c31af7Sopenharmony_ci
2095e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("Pass");
2096e5c31af7Sopenharmony_ci}
2097e5c31af7Sopenharmony_ci
2098e5c31af7Sopenharmony_ci} // multisample
2099e5c31af7Sopenharmony_ci
2100e5c31af7Sopenharmony_citcu::TestCaseGroup* createMultisampleShaderBuiltInTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)
2101e5c31af7Sopenharmony_ci{
2102e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "multisample_shader_builtin"));
2103e5c31af7Sopenharmony_ci
2104e5c31af7Sopenharmony_ci	const tcu::UVec3 imageSizes[] =
2105e5c31af7Sopenharmony_ci	{
2106e5c31af7Sopenharmony_ci		tcu::UVec3(128u, 128u, 1u),
2107e5c31af7Sopenharmony_ci		tcu::UVec3(137u, 191u, 1u),
2108e5c31af7Sopenharmony_ci	};
2109e5c31af7Sopenharmony_ci
2110e5c31af7Sopenharmony_ci	const deUint32 sizesElemCount = static_cast<deUint32>(sizeof(imageSizes) / sizeof(tcu::UVec3));
2111e5c31af7Sopenharmony_ci
2112e5c31af7Sopenharmony_ci	const vk::VkSampleCountFlagBits samplesSetFull[] =
2113e5c31af7Sopenharmony_ci	{
2114e5c31af7Sopenharmony_ci		vk::VK_SAMPLE_COUNT_2_BIT,
2115e5c31af7Sopenharmony_ci		vk::VK_SAMPLE_COUNT_4_BIT,
2116e5c31af7Sopenharmony_ci		vk::VK_SAMPLE_COUNT_8_BIT,
2117e5c31af7Sopenharmony_ci		vk::VK_SAMPLE_COUNT_16_BIT,
2118e5c31af7Sopenharmony_ci		vk::VK_SAMPLE_COUNT_32_BIT,
2119e5c31af7Sopenharmony_ci		vk::VK_SAMPLE_COUNT_64_BIT,
2120e5c31af7Sopenharmony_ci	};
2121e5c31af7Sopenharmony_ci
2122e5c31af7Sopenharmony_ci	const deUint32 samplesSetFullCount = static_cast<deUint32>(sizeof(samplesSetFull) / sizeof(vk::VkSampleCountFlagBits));
2123e5c31af7Sopenharmony_ci
2124e5c31af7Sopenharmony_ci	testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleID> >(testCtx, "sample_id", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount));
2125e5c31af7Sopenharmony_ci
2126e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> samplePositionGroup(new tcu::TestCaseGroup(testCtx, "sample_position"));
2127e5c31af7Sopenharmony_ci
2128e5c31af7Sopenharmony_ci	samplePositionGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSamplePosDistribution> >(testCtx, "distribution", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount));
2129e5c31af7Sopenharmony_ci	samplePositionGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSamplePosCorrectness> > (testCtx, "correctness", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount));
2130e5c31af7Sopenharmony_ci
2131e5c31af7Sopenharmony_ci	testGroup->addChild(samplePositionGroup.release());
2132e5c31af7Sopenharmony_ci
2133e5c31af7Sopenharmony_ci	const vk::VkSampleCountFlagBits samplesSetReduced[] =
2134e5c31af7Sopenharmony_ci	{
2135e5c31af7Sopenharmony_ci		vk::VK_SAMPLE_COUNT_2_BIT,
2136e5c31af7Sopenharmony_ci		vk::VK_SAMPLE_COUNT_4_BIT,
2137e5c31af7Sopenharmony_ci		vk::VK_SAMPLE_COUNT_8_BIT,
2138e5c31af7Sopenharmony_ci		vk::VK_SAMPLE_COUNT_16_BIT,
2139e5c31af7Sopenharmony_ci		vk::VK_SAMPLE_COUNT_32_BIT,
2140e5c31af7Sopenharmony_ci	};
2141e5c31af7Sopenharmony_ci
2142e5c31af7Sopenharmony_ci	const deUint32 samplesSetReducedCount = static_cast<deUint32>(DE_LENGTH_OF_ARRAY(samplesSetReduced));
2143e5c31af7Sopenharmony_ci
2144e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> sampleMaskGroup(new tcu::TestCaseGroup(testCtx, "sample_mask"));
2145e5c31af7Sopenharmony_ci
2146e5c31af7Sopenharmony_ci	sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskPattern> >	(testCtx, "pattern",		pipelineConstructionType, imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
2147e5c31af7Sopenharmony_ci	sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskBitCount> >	(testCtx, "bit_count",		pipelineConstructionType, imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
2148e5c31af7Sopenharmony_ci	sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskBitCount> >	(testCtx, "bit_count_0_5",	pipelineConstructionType, imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount, multisample::ComponentData{}, 0.5f));
2149e5c31af7Sopenharmony_ci	sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskCorrectBit> >(testCtx, "correct_bit",	pipelineConstructionType, imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
2150e5c31af7Sopenharmony_ci	sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskWrite> >		(testCtx, "write",			pipelineConstructionType, imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
2151e5c31af7Sopenharmony_ci
2152e5c31af7Sopenharmony_ci	testGroup->addChild(sampleMaskGroup.release());
2153e5c31af7Sopenharmony_ci
2154e5c31af7Sopenharmony_ci	// Write image sample tests using a storage images (tests construct only compute pipeline).
2155e5c31af7Sopenharmony_ci	if (pipelineConstructionType == vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
2156e5c31af7Sopenharmony_ci	{
2157e5c31af7Sopenharmony_ci		// Test OpImageWrite with a sample ID
2158e5c31af7Sopenharmony_ci		de::MovePtr<tcu::TestCaseGroup> imageWriteSampleGroup(new tcu::TestCaseGroup(testCtx, "image_write_sample"));
2159e5c31af7Sopenharmony_ci
2160e5c31af7Sopenharmony_ci		for (auto count : multisample::kValidSquareSampleCounts)
2161e5c31af7Sopenharmony_ci		{
2162e5c31af7Sopenharmony_ci			if (count == vk::VK_SAMPLE_COUNT_1_BIT)
2163e5c31af7Sopenharmony_ci				continue;
2164e5c31af7Sopenharmony_ci
2165e5c31af7Sopenharmony_ci			multisample::WriteSampleParams params { pipelineConstructionType, static_cast<vk::VkSampleCountFlagBits>(count) };
2166e5c31af7Sopenharmony_ci			const auto countStr = de::toString(count);
2167e5c31af7Sopenharmony_ci			imageWriteSampleGroup->addChild(new multisample::WriteSampleTest(testCtx, countStr + "_samples", params));
2168e5c31af7Sopenharmony_ci		}
2169e5c31af7Sopenharmony_ci
2170e5c31af7Sopenharmony_ci		testGroup->addChild(imageWriteSampleGroup.release());
2171e5c31af7Sopenharmony_ci	}
2172e5c31af7Sopenharmony_ci
2173e5c31af7Sopenharmony_ci	// Write to gl_SampleMask from the fragment shader.
2174e5c31af7Sopenharmony_ci	{
2175e5c31af7Sopenharmony_ci		de::MovePtr<tcu::TestCaseGroup> writeSampleMaskGroup(new tcu::TestCaseGroup(testCtx, "write_sample_mask"));
2176e5c31af7Sopenharmony_ci
2177e5c31af7Sopenharmony_ci		for (auto count : multisample::kValidSquareSampleCounts)
2178e5c31af7Sopenharmony_ci		{
2179e5c31af7Sopenharmony_ci			multisample::WriteSampleMaskParams params { pipelineConstructionType, static_cast<vk::VkSampleCountFlagBits>(count) };
2180e5c31af7Sopenharmony_ci			const auto countStr = de::toString(count);
2181e5c31af7Sopenharmony_ci			writeSampleMaskGroup->addChild(new multisample::WriteSampleMaskTestCase(testCtx, countStr + "_samples", params));
2182e5c31af7Sopenharmony_ci		}
2183e5c31af7Sopenharmony_ci
2184e5c31af7Sopenharmony_ci		testGroup->addChild(writeSampleMaskGroup.release());
2185e5c31af7Sopenharmony_ci	}
2186e5c31af7Sopenharmony_ci
2187e5c31af7Sopenharmony_ci	return testGroup.release();
2188e5c31af7Sopenharmony_ci}
2189e5c31af7Sopenharmony_ci
2190e5c31af7Sopenharmony_ci} // pipeline
2191e5c31af7Sopenharmony_ci} // vkt
2192