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 vktPipelineMultisampleInterpolationTests.cpp
23e5c31af7Sopenharmony_ci* \brief Multisample Interpolation Tests
24e5c31af7Sopenharmony_ci*//*--------------------------------------------------------------------*/
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ci#include "vktPipelineMultisampleInterpolationTests.hpp"
27e5c31af7Sopenharmony_ci#include "vktPipelineMultisampleBaseResolve.hpp"
28e5c31af7Sopenharmony_ci#include "vktPipelineMultisampleTestsUtil.hpp"
29e5c31af7Sopenharmony_ci#include "vktPipelineMakeUtil.hpp"
30e5c31af7Sopenharmony_ci#include "vktAmberTestCase.hpp"
31e5c31af7Sopenharmony_ci#include "vkQueryUtil.hpp"
32e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
33e5c31af7Sopenharmony_ci#include <vector>
34e5c31af7Sopenharmony_ci
35e5c31af7Sopenharmony_cinamespace vkt
36e5c31af7Sopenharmony_ci{
37e5c31af7Sopenharmony_cinamespace pipeline
38e5c31af7Sopenharmony_ci{
39e5c31af7Sopenharmony_cinamespace multisample
40e5c31af7Sopenharmony_ci{
41e5c31af7Sopenharmony_ci
42e5c31af7Sopenharmony_ciusing namespace vk;
43e5c31af7Sopenharmony_ci
44e5c31af7Sopenharmony_cistruct VertexDataNdc
45e5c31af7Sopenharmony_ci{
46e5c31af7Sopenharmony_ci	VertexDataNdc (const tcu::Vec4& posNdc) : positionNdc(posNdc) {}
47e5c31af7Sopenharmony_ci
48e5c31af7Sopenharmony_ci	tcu::Vec4 positionNdc;
49e5c31af7Sopenharmony_ci};
50e5c31af7Sopenharmony_ci
51e5c31af7Sopenharmony_cistruct VertexDataNdcScreen
52e5c31af7Sopenharmony_ci{
53e5c31af7Sopenharmony_ci	VertexDataNdcScreen (const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {}
54e5c31af7Sopenharmony_ci
55e5c31af7Sopenharmony_ci	tcu::Vec4 positionNdc;
56e5c31af7Sopenharmony_ci	tcu::Vec2 positionScreen;
57e5c31af7Sopenharmony_ci};
58e5c31af7Sopenharmony_ci
59e5c31af7Sopenharmony_cistruct VertexDataNdcBarycentric
60e5c31af7Sopenharmony_ci{
61e5c31af7Sopenharmony_ci	VertexDataNdcBarycentric (const tcu::Vec4& posNdc, const tcu::Vec3& barCoord) : positionNdc(posNdc), barycentricCoord(barCoord) {}
62e5c31af7Sopenharmony_ci
63e5c31af7Sopenharmony_ci	tcu::Vec4 positionNdc;
64e5c31af7Sopenharmony_ci	tcu::Vec3 barycentricCoord;
65e5c31af7Sopenharmony_ci};
66e5c31af7Sopenharmony_ci
67e5c31af7Sopenharmony_cibool checkForError (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS, const deUint32 errorCompNdx)
68e5c31af7Sopenharmony_ci{
69e5c31af7Sopenharmony_ci	for (deUint32 z = 0u; z < imageRSInfo.extent.depth;  ++z)
70e5c31af7Sopenharmony_ci	for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
71e5c31af7Sopenharmony_ci	for (deUint32 x = 0u; x < imageRSInfo.extent.width;  ++x)
72e5c31af7Sopenharmony_ci	{
73e5c31af7Sopenharmony_ci		const deUint32 errorComponent = dataRS.getPixelUint(x, y, z)[errorCompNdx];
74e5c31af7Sopenharmony_ci
75e5c31af7Sopenharmony_ci		if (errorComponent > 0)
76e5c31af7Sopenharmony_ci			return true;
77e5c31af7Sopenharmony_ci	}
78e5c31af7Sopenharmony_ci
79e5c31af7Sopenharmony_ci	return false;
80e5c31af7Sopenharmony_ci}
81e5c31af7Sopenharmony_ci
82e5c31af7Sopenharmony_citemplate <typename CaseClassName>
83e5c31af7Sopenharmony_ciclass MSCase : public MultisampleCaseBase
84e5c31af7Sopenharmony_ci{
85e5c31af7Sopenharmony_cipublic:
86e5c31af7Sopenharmony_ci								MSCase			(tcu::TestContext&		testCtx,
87e5c31af7Sopenharmony_ci												 const std::string&		name,
88e5c31af7Sopenharmony_ci												 const ImageMSParams&	imageMSParams)
89e5c31af7Sopenharmony_ci								: MultisampleCaseBase(testCtx, name, imageMSParams) {}
90e5c31af7Sopenharmony_ci
91e5c31af7Sopenharmony_ci	void						init			(void);
92e5c31af7Sopenharmony_ci	void						initPrograms	(vk::SourceCollections& programCollection) const;
93e5c31af7Sopenharmony_ci	void						checkSupport	(Context&				context) const;
94e5c31af7Sopenharmony_ci	TestInstance*				createInstance	(Context&				context) const;
95e5c31af7Sopenharmony_ci	static MultisampleCaseBase*	createCase		(tcu::TestContext&		testCtx,
96e5c31af7Sopenharmony_ci												 const std::string&		name,
97e5c31af7Sopenharmony_ci												 const ImageMSParams&	imageMSParams);
98e5c31af7Sopenharmony_ci};
99e5c31af7Sopenharmony_ci
100e5c31af7Sopenharmony_citemplate <typename CaseClassName>
101e5c31af7Sopenharmony_civoid MSCase<CaseClassName>::checkSupport (Context& context) const
102e5c31af7Sopenharmony_ci{
103e5c31af7Sopenharmony_ci	checkGraphicsPipelineLibrarySupport(context);
104e5c31af7Sopenharmony_ci
105e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
106e5c31af7Sopenharmony_ci	if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
107e5c31af7Sopenharmony_ci		!context.getPortabilitySubsetFeatures().shaderSampleRateInterpolationFunctions)
108e5c31af7Sopenharmony_ci	{
109e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Shader sample rate interpolation functions are not supported by this implementation");
110e5c31af7Sopenharmony_ci	}
111e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
112e5c31af7Sopenharmony_ci
113e5c31af7Sopenharmony_ci	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
114e5c31af7Sopenharmony_ci}
115e5c31af7Sopenharmony_ci
116e5c31af7Sopenharmony_citemplate <typename CaseClassName>
117e5c31af7Sopenharmony_ciMultisampleCaseBase* MSCase<CaseClassName>::createCase (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
118e5c31af7Sopenharmony_ci{
119e5c31af7Sopenharmony_ci	return new MSCase<CaseClassName>(testCtx, name, imageMSParams);
120e5c31af7Sopenharmony_ci}
121e5c31af7Sopenharmony_ci
122e5c31af7Sopenharmony_citemplate <typename InstanceClassName>
123e5c31af7Sopenharmony_ciclass MSInstance : public MSInstanceBaseResolve
124e5c31af7Sopenharmony_ci{
125e5c31af7Sopenharmony_cipublic:
126e5c31af7Sopenharmony_ci					MSInstance				(Context&							context,
127e5c31af7Sopenharmony_ci											 const ImageMSParams&				imageMSParams)
128e5c31af7Sopenharmony_ci					: MSInstanceBaseResolve(context, imageMSParams) {}
129e5c31af7Sopenharmony_ci
130e5c31af7Sopenharmony_ci	VertexDataDesc	getVertexDataDescripton	(void) const;
131e5c31af7Sopenharmony_ci	void			uploadVertexData		(const Allocation&					vertexBufferAllocation,
132e5c31af7Sopenharmony_ci											 const VertexDataDesc&				vertexDataDescripton) const;
133e5c31af7Sopenharmony_ci	tcu::TestStatus	verifyImageData			(const vk::VkImageCreateInfo&		imageRSInfo,
134e5c31af7Sopenharmony_ci											 const tcu::ConstPixelBufferAccess& dataRS) const;
135e5c31af7Sopenharmony_ci};
136e5c31af7Sopenharmony_ci
137e5c31af7Sopenharmony_ciclass MSInstanceDistinctValues;
138e5c31af7Sopenharmony_ci
139e5c31af7Sopenharmony_citemplate<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceDistinctValues>::getVertexDataDescripton (void) const
140e5c31af7Sopenharmony_ci{
141e5c31af7Sopenharmony_ci	VertexDataDesc vertexDataDesc;
142e5c31af7Sopenharmony_ci
143e5c31af7Sopenharmony_ci	vertexDataDesc.verticesCount		= 3u;
144e5c31af7Sopenharmony_ci	vertexDataDesc.dataStride			= sizeof(VertexDataNdc);
145e5c31af7Sopenharmony_ci	vertexDataDesc.dataSize				= vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
146e5c31af7Sopenharmony_ci	vertexDataDesc.primitiveTopology	= VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
147e5c31af7Sopenharmony_ci
148e5c31af7Sopenharmony_ci	const VkVertexInputAttributeDescription vertexAttribPositionNdc =
149e5c31af7Sopenharmony_ci	{
150e5c31af7Sopenharmony_ci		0u,										// deUint32	location;
151e5c31af7Sopenharmony_ci		0u,										// deUint32	binding;
152e5c31af7Sopenharmony_ci		VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat	format;
153e5c31af7Sopenharmony_ci		DE_OFFSET_OF(VertexDataNdc, positionNdc),	// deUint32	offset;
154e5c31af7Sopenharmony_ci	};
155e5c31af7Sopenharmony_ci
156e5c31af7Sopenharmony_ci	vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
157e5c31af7Sopenharmony_ci
158e5c31af7Sopenharmony_ci	return vertexDataDesc;
159e5c31af7Sopenharmony_ci}
160e5c31af7Sopenharmony_ci
161e5c31af7Sopenharmony_citemplate<> void MSInstance<MSInstanceDistinctValues>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
162e5c31af7Sopenharmony_ci{
163e5c31af7Sopenharmony_ci	std::vector<VertexDataNdc> vertices;
164e5c31af7Sopenharmony_ci
165e5c31af7Sopenharmony_ci	vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f)));
166e5c31af7Sopenharmony_ci	vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f,  4.0f, 0.0f, 1.0f)));
167e5c31af7Sopenharmony_ci	vertices.push_back(VertexDataNdc(tcu::Vec4( 4.0f, -1.0f, 0.0f, 1.0f)));
168e5c31af7Sopenharmony_ci
169e5c31af7Sopenharmony_ci	deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
170e5c31af7Sopenharmony_ci}
171e5c31af7Sopenharmony_ci
172e5c31af7Sopenharmony_citemplate<> tcu::TestStatus MSInstance<MSInstanceDistinctValues>::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const
173e5c31af7Sopenharmony_ci{
174e5c31af7Sopenharmony_ci	const deUint32 distinctValuesExpected = static_cast<deUint32>(m_imageMSParams.numSamples) + 1u;
175e5c31af7Sopenharmony_ci
176e5c31af7Sopenharmony_ci	std::vector<tcu::IVec4> distinctValues;
177e5c31af7Sopenharmony_ci
178e5c31af7Sopenharmony_ci	for (deUint32 z = 0u; z < imageRSInfo.extent.depth;	 ++z)
179e5c31af7Sopenharmony_ci	for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
180e5c31af7Sopenharmony_ci	for (deUint32 x = 0u; x < imageRSInfo.extent.width;	 ++x)
181e5c31af7Sopenharmony_ci	{
182e5c31af7Sopenharmony_ci		const tcu::IVec4 pixel = dataRS.getPixelInt(x, y, z);
183e5c31af7Sopenharmony_ci
184e5c31af7Sopenharmony_ci		if (std::find(distinctValues.begin(), distinctValues.end(), pixel) == distinctValues.end())
185e5c31af7Sopenharmony_ci			distinctValues.push_back(pixel);
186e5c31af7Sopenharmony_ci	}
187e5c31af7Sopenharmony_ci
188e5c31af7Sopenharmony_ci	if (distinctValues.size() >= distinctValuesExpected)
189e5c31af7Sopenharmony_ci		return tcu::TestStatus::pass("Passed");
190e5c31af7Sopenharmony_ci	else
191e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("Expected numSamples+1 different colors in the output image");
192e5c31af7Sopenharmony_ci}
193e5c31af7Sopenharmony_ci
194e5c31af7Sopenharmony_ciclass MSCaseSampleQualifierDistinctValues;
195e5c31af7Sopenharmony_ci
196e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleQualifierDistinctValues>::init (void)
197e5c31af7Sopenharmony_ci{
198e5c31af7Sopenharmony_ci	m_testCtx.getLog()
199e5c31af7Sopenharmony_ci		<< tcu::TestLog::Message
200e5c31af7Sopenharmony_ci		<< "Verifying that a sample qualified varying is given different values for different samples.\n"
201e5c31af7Sopenharmony_ci		<< "	Render full screen traingle with quadratic function defining red/green color pattern division.\n"
202e5c31af7Sopenharmony_ci		<< "	=> Resulting image should contain n+1 different colors, where n = sample count.\n"
203e5c31af7Sopenharmony_ci		<< tcu::TestLog::EndMessage;
204e5c31af7Sopenharmony_ci
205e5c31af7Sopenharmony_ci	MultisampleCaseBase::init();
206e5c31af7Sopenharmony_ci}
207e5c31af7Sopenharmony_ci
208e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleQualifierDistinctValues>::initPrograms (vk::SourceCollections& programCollection) const
209e5c31af7Sopenharmony_ci{
210e5c31af7Sopenharmony_ci	// Create vertex shader
211e5c31af7Sopenharmony_ci	std::ostringstream vs;
212e5c31af7Sopenharmony_ci
213e5c31af7Sopenharmony_ci	vs << "#version 440\n"
214e5c31af7Sopenharmony_ci		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
215e5c31af7Sopenharmony_ci		<< "\n"
216e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec4 vs_out_position_ndc;\n"
217e5c31af7Sopenharmony_ci		<< "\n"
218e5c31af7Sopenharmony_ci		<< "out gl_PerVertex {\n"
219e5c31af7Sopenharmony_ci		<< "	vec4  gl_Position;\n"
220e5c31af7Sopenharmony_ci		<< "};\n"
221e5c31af7Sopenharmony_ci		<< "void main (void)\n"
222e5c31af7Sopenharmony_ci		<< "{\n"
223e5c31af7Sopenharmony_ci		<< "	gl_Position			= vs_in_position_ndc;\n"
224e5c31af7Sopenharmony_ci		<< "	vs_out_position_ndc = vs_in_position_ndc;\n"
225e5c31af7Sopenharmony_ci		<< "}\n";
226e5c31af7Sopenharmony_ci
227e5c31af7Sopenharmony_ci	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
228e5c31af7Sopenharmony_ci
229e5c31af7Sopenharmony_ci	// Create fragment shader
230e5c31af7Sopenharmony_ci	std::ostringstream fs;
231e5c31af7Sopenharmony_ci
232e5c31af7Sopenharmony_ci	fs << "#version 440\n"
233e5c31af7Sopenharmony_ci		<< "layout(location = 0) sample in vec4 fs_in_position_ndc;\n"
234e5c31af7Sopenharmony_ci		<< "\n"
235e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec4 fs_out_color;\n"
236e5c31af7Sopenharmony_ci		<< "\n"
237e5c31af7Sopenharmony_ci		<< "void main (void)\n"
238e5c31af7Sopenharmony_ci		<< "{\n"
239e5c31af7Sopenharmony_ci		<< "	if(fs_in_position_ndc.y < -2.0*pow(0.5*(fs_in_position_ndc.x + 1.0), 2.0) + 1.0)\n"
240e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
241e5c31af7Sopenharmony_ci		<< "	else\n"
242e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
243e5c31af7Sopenharmony_ci		<< "}\n";
244e5c31af7Sopenharmony_ci
245e5c31af7Sopenharmony_ci	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
246e5c31af7Sopenharmony_ci}
247e5c31af7Sopenharmony_ci
248e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseSampleQualifierDistinctValues>::checkSupport (Context& context) const
249e5c31af7Sopenharmony_ci{
250e5c31af7Sopenharmony_ci	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_imageMSParams.pipelineConstructionType);
251e5c31af7Sopenharmony_ci
252e5c31af7Sopenharmony_ci	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
253e5c31af7Sopenharmony_ci}
254e5c31af7Sopenharmony_ci
255e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseSampleQualifierDistinctValues>::createInstance (Context& context) const
256e5c31af7Sopenharmony_ci{
257e5c31af7Sopenharmony_ci	return new MSInstance<MSInstanceDistinctValues>(context, m_imageMSParams);
258e5c31af7Sopenharmony_ci}
259e5c31af7Sopenharmony_ci
260e5c31af7Sopenharmony_ciclass MSCaseInterpolateAtSampleDistinctValues;
261e5c31af7Sopenharmony_ci
262e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseInterpolateAtSampleDistinctValues>::init (void)
263e5c31af7Sopenharmony_ci{
264e5c31af7Sopenharmony_ci	m_testCtx.getLog()
265e5c31af7Sopenharmony_ci		<< tcu::TestLog::Message
266e5c31af7Sopenharmony_ci		<< "Verifying that a interpolateAtSample returns different values for different samples.\n"
267e5c31af7Sopenharmony_ci		<< "	Render full screen traingle with quadratic function defining red/green color pattern division.\n"
268e5c31af7Sopenharmony_ci		<< "	=> Resulting image should contain n+1 different colors, where n = sample count.\n"
269e5c31af7Sopenharmony_ci		<< tcu::TestLog::EndMessage;
270e5c31af7Sopenharmony_ci
271e5c31af7Sopenharmony_ci	MultisampleCaseBase::init();
272e5c31af7Sopenharmony_ci}
273e5c31af7Sopenharmony_ci
274e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseInterpolateAtSampleDistinctValues>::initPrograms (vk::SourceCollections& programCollection) const
275e5c31af7Sopenharmony_ci{
276e5c31af7Sopenharmony_ci	// Create vertex shader
277e5c31af7Sopenharmony_ci	std::ostringstream vs;
278e5c31af7Sopenharmony_ci
279e5c31af7Sopenharmony_ci	vs << "#version 440\n"
280e5c31af7Sopenharmony_ci		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
281e5c31af7Sopenharmony_ci		<< "\n"
282e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec4 vs_out_position_ndc;\n"
283e5c31af7Sopenharmony_ci		<< "\n"
284e5c31af7Sopenharmony_ci		<< "out gl_PerVertex {\n"
285e5c31af7Sopenharmony_ci		<< "	vec4  gl_Position;\n"
286e5c31af7Sopenharmony_ci		<< "};\n"
287e5c31af7Sopenharmony_ci		<< "void main (void)\n"
288e5c31af7Sopenharmony_ci		<< "{\n"
289e5c31af7Sopenharmony_ci		<< "	gl_Position			= vs_in_position_ndc;\n"
290e5c31af7Sopenharmony_ci		<< "	vs_out_position_ndc = vs_in_position_ndc;\n"
291e5c31af7Sopenharmony_ci		<< "}\n";
292e5c31af7Sopenharmony_ci
293e5c31af7Sopenharmony_ci	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
294e5c31af7Sopenharmony_ci
295e5c31af7Sopenharmony_ci	// Create fragment shader
296e5c31af7Sopenharmony_ci	std::ostringstream fs;
297e5c31af7Sopenharmony_ci
298e5c31af7Sopenharmony_ci	fs << "#version 440\n"
299e5c31af7Sopenharmony_ci		<< "layout(location = 0) in vec4 fs_in_position_ndc;\n"
300e5c31af7Sopenharmony_ci		<< "\n"
301e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec4 fs_out_color;\n"
302e5c31af7Sopenharmony_ci		<< "\n"
303e5c31af7Sopenharmony_ci		<< "void main (void)\n"
304e5c31af7Sopenharmony_ci		<< "{\n"
305e5c31af7Sopenharmony_ci		<< "	const vec4 position_ndc_at_sample = interpolateAtSample(fs_in_position_ndc, gl_SampleID);\n"
306e5c31af7Sopenharmony_ci		<< "	if(position_ndc_at_sample.y < -2.0*pow(0.5*(position_ndc_at_sample.x + 1.0), 2.0) + 1.0)\n"
307e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
308e5c31af7Sopenharmony_ci		<< "	else\n"
309e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
310e5c31af7Sopenharmony_ci		<< "}\n";
311e5c31af7Sopenharmony_ci
312e5c31af7Sopenharmony_ci	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
313e5c31af7Sopenharmony_ci}
314e5c31af7Sopenharmony_ci
315e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseInterpolateAtSampleDistinctValues>::createInstance (Context& context) const
316e5c31af7Sopenharmony_ci{
317e5c31af7Sopenharmony_ci	return new MSInstance<MSInstanceDistinctValues>(context, m_imageMSParams);
318e5c31af7Sopenharmony_ci}
319e5c31af7Sopenharmony_ci
320e5c31af7Sopenharmony_ciclass MSInstanceInterpolateScreenPosition;
321e5c31af7Sopenharmony_ci
322e5c31af7Sopenharmony_citemplate<> MSInstanceBaseResolve::VertexDataDesc MSInstance<MSInstanceInterpolateScreenPosition>::getVertexDataDescripton (void) const
323e5c31af7Sopenharmony_ci{
324e5c31af7Sopenharmony_ci	VertexDataDesc vertexDataDesc;
325e5c31af7Sopenharmony_ci
326e5c31af7Sopenharmony_ci	vertexDataDesc.verticesCount		= 4u;
327e5c31af7Sopenharmony_ci	vertexDataDesc.dataStride			= sizeof(VertexDataNdcScreen);
328e5c31af7Sopenharmony_ci	vertexDataDesc.dataSize				= vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
329e5c31af7Sopenharmony_ci	vertexDataDesc.primitiveTopology	= VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
330e5c31af7Sopenharmony_ci
331e5c31af7Sopenharmony_ci	const VkVertexInputAttributeDescription vertexAttribPositionNdc =
332e5c31af7Sopenharmony_ci	{
333e5c31af7Sopenharmony_ci		0u,												// deUint32	location;
334e5c31af7Sopenharmony_ci		0u,												// deUint32	binding;
335e5c31af7Sopenharmony_ci		VK_FORMAT_R32G32B32A32_SFLOAT,					// VkFormat	format;
336e5c31af7Sopenharmony_ci		DE_OFFSET_OF(VertexDataNdcScreen, positionNdc),	// deUint32	offset;
337e5c31af7Sopenharmony_ci	};
338e5c31af7Sopenharmony_ci
339e5c31af7Sopenharmony_ci	vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
340e5c31af7Sopenharmony_ci
341e5c31af7Sopenharmony_ci	const VkVertexInputAttributeDescription vertexAttribPositionScreen =
342e5c31af7Sopenharmony_ci	{
343e5c31af7Sopenharmony_ci		1u,											// deUint32	location;
344e5c31af7Sopenharmony_ci		0u,											// deUint32	binding;
345e5c31af7Sopenharmony_ci		VK_FORMAT_R32G32_SFLOAT,					// VkFormat	format;
346e5c31af7Sopenharmony_ci		DE_OFFSET_OF(VertexDataNdcScreen, positionScreen),	// deUint32	offset;
347e5c31af7Sopenharmony_ci	};
348e5c31af7Sopenharmony_ci
349e5c31af7Sopenharmony_ci	vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen);
350e5c31af7Sopenharmony_ci
351e5c31af7Sopenharmony_ci	return vertexDataDesc;
352e5c31af7Sopenharmony_ci}
353e5c31af7Sopenharmony_ci
354e5c31af7Sopenharmony_citemplate<> void MSInstance<MSInstanceInterpolateScreenPosition>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
355e5c31af7Sopenharmony_ci{
356e5c31af7Sopenharmony_ci	const tcu::UVec3 layerSize		= getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize);
357e5c31af7Sopenharmony_ci	const float		 screenSizeX	= static_cast<float>(layerSize.x());
358e5c31af7Sopenharmony_ci	const float		 screenSizeY	= static_cast<float>(layerSize.y());
359e5c31af7Sopenharmony_ci
360e5c31af7Sopenharmony_ci	std::vector<VertexDataNdcScreen> vertices;
361e5c31af7Sopenharmony_ci
362e5c31af7Sopenharmony_ci	vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, 0.0f)));
363e5c31af7Sopenharmony_ci	vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, 0.0f)));
364e5c31af7Sopenharmony_ci	vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, screenSizeY)));
365e5c31af7Sopenharmony_ci	vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, screenSizeY)));
366e5c31af7Sopenharmony_ci
367e5c31af7Sopenharmony_ci	deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
368e5c31af7Sopenharmony_ci}
369e5c31af7Sopenharmony_ci
370e5c31af7Sopenharmony_citemplate<> tcu::TestStatus MSInstance<MSInstanceInterpolateScreenPosition>::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const
371e5c31af7Sopenharmony_ci{
372e5c31af7Sopenharmony_ci	if (checkForError(imageRSInfo, dataRS, 0))
373e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("Failed");
374e5c31af7Sopenharmony_ci
375e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("Passed");
376e5c31af7Sopenharmony_ci}
377e5c31af7Sopenharmony_ci
378e5c31af7Sopenharmony_ciclass MSCaseInterpolateAtSampleSingleSample;
379e5c31af7Sopenharmony_ci
380e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseInterpolateAtSampleSingleSample>::init (void)
381e5c31af7Sopenharmony_ci{
382e5c31af7Sopenharmony_ci	m_testCtx.getLog()
383e5c31af7Sopenharmony_ci		<< tcu::TestLog::Message
384e5c31af7Sopenharmony_ci		<< "Verifying that using interpolateAtSample with multisample buffers not available returns sample evaluated at the center of the pixel.\n"
385e5c31af7Sopenharmony_ci		<< "	Interpolate varying containing screen space location.\n"
386e5c31af7Sopenharmony_ci		<< "	=> fract(screen space location) should be (about) (0.5, 0.5)\n"
387e5c31af7Sopenharmony_ci		<< tcu::TestLog::EndMessage;
388e5c31af7Sopenharmony_ci
389e5c31af7Sopenharmony_ci	MultisampleCaseBase::init();
390e5c31af7Sopenharmony_ci}
391e5c31af7Sopenharmony_ci
392e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseInterpolateAtSampleSingleSample>::initPrograms (vk::SourceCollections& programCollection) const
393e5c31af7Sopenharmony_ci{
394e5c31af7Sopenharmony_ci	// Create vertex shader
395e5c31af7Sopenharmony_ci	std::ostringstream vs;
396e5c31af7Sopenharmony_ci
397e5c31af7Sopenharmony_ci	vs << "#version 440\n"
398e5c31af7Sopenharmony_ci		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
399e5c31af7Sopenharmony_ci		<< "layout(location = 1) in vec2 vs_in_position_screen;\n"
400e5c31af7Sopenharmony_ci		<< "\n"
401e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec2 vs_out_position_screen;\n"
402e5c31af7Sopenharmony_ci		<< "\n"
403e5c31af7Sopenharmony_ci		<< "out gl_PerVertex {\n"
404e5c31af7Sopenharmony_ci		<< "	vec4  gl_Position;\n"
405e5c31af7Sopenharmony_ci		<< "};\n"
406e5c31af7Sopenharmony_ci		<< "void main (void)\n"
407e5c31af7Sopenharmony_ci		<< "{\n"
408e5c31af7Sopenharmony_ci		<< "	gl_Position				= vs_in_position_ndc;\n"
409e5c31af7Sopenharmony_ci		<< "	vs_out_position_screen	= vs_in_position_screen;\n"
410e5c31af7Sopenharmony_ci		<< "}\n";
411e5c31af7Sopenharmony_ci
412e5c31af7Sopenharmony_ci	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
413e5c31af7Sopenharmony_ci
414e5c31af7Sopenharmony_ci	// Create fragment shader
415e5c31af7Sopenharmony_ci	std::ostringstream fs;
416e5c31af7Sopenharmony_ci
417e5c31af7Sopenharmony_ci	fs << "#version 440\n"
418e5c31af7Sopenharmony_ci		<< "layout(location = 0) in vec2 fs_in_position_screen;\n"
419e5c31af7Sopenharmony_ci		<< "\n"
420e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec4 fs_out_color;\n"
421e5c31af7Sopenharmony_ci		<< "\n"
422e5c31af7Sopenharmony_ci		<< "void main (void)\n"
423e5c31af7Sopenharmony_ci		<< "{\n"
424e5c31af7Sopenharmony_ci		<< "	const float threshold					= 0.15625;\n"
425e5c31af7Sopenharmony_ci		<< "	const vec2  position_screen_at_sample	= interpolateAtSample(fs_in_position_screen, 0);\n"
426e5c31af7Sopenharmony_ci		<< "	const vec2  position_inside_pixel		= fract(position_screen_at_sample);\n"
427e5c31af7Sopenharmony_ci		<< "\n"
428e5c31af7Sopenharmony_ci		<< "	if (abs(position_inside_pixel.x - 0.5) <= threshold && abs(position_inside_pixel.y - 0.5) <= threshold)\n"
429e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
430e5c31af7Sopenharmony_ci		<< "	else\n"
431e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
432e5c31af7Sopenharmony_ci		<< "}\n";
433e5c31af7Sopenharmony_ci
434e5c31af7Sopenharmony_ci	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
435e5c31af7Sopenharmony_ci}
436e5c31af7Sopenharmony_ci
437e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseInterpolateAtSampleSingleSample>::createInstance (Context& context) const
438e5c31af7Sopenharmony_ci{
439e5c31af7Sopenharmony_ci	return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
440e5c31af7Sopenharmony_ci}
441e5c31af7Sopenharmony_ci
442e5c31af7Sopenharmony_ciclass MSCaseInterpolateAtSampleIgnoresCentroid;
443e5c31af7Sopenharmony_ci
444e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::init (void)
445e5c31af7Sopenharmony_ci{
446e5c31af7Sopenharmony_ci	m_testCtx.getLog()
447e5c31af7Sopenharmony_ci		<< tcu::TestLog::Message
448e5c31af7Sopenharmony_ci		<< "Verifying that interpolateAtSample ignores centroid qualifier.\n"
449e5c31af7Sopenharmony_ci		<< "	Interpolate varying containing screen space location with centroid and sample qualifiers.\n"
450e5c31af7Sopenharmony_ci		<< "	=> interpolateAtSample(screenSample, n) ~= interpolateAtSample(screenCentroid, n)\n"
451e5c31af7Sopenharmony_ci		<< tcu::TestLog::EndMessage;
452e5c31af7Sopenharmony_ci
453e5c31af7Sopenharmony_ci	MultisampleCaseBase::init();
454e5c31af7Sopenharmony_ci}
455e5c31af7Sopenharmony_ci
456e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::initPrograms (vk::SourceCollections& programCollection) const
457e5c31af7Sopenharmony_ci{
458e5c31af7Sopenharmony_ci	// Create vertex shader
459e5c31af7Sopenharmony_ci	std::ostringstream vs;
460e5c31af7Sopenharmony_ci
461e5c31af7Sopenharmony_ci	vs << "#version 440\n"
462e5c31af7Sopenharmony_ci		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
463e5c31af7Sopenharmony_ci		<< "layout(location = 1) in vec2 vs_in_position_screen;\n"
464e5c31af7Sopenharmony_ci		<< "\n"
465e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec2 vs_out_pos_screen_centroid;\n"
466e5c31af7Sopenharmony_ci		<< "layout(location = 1) out vec2 vs_out_pos_screen_fragment;\n"
467e5c31af7Sopenharmony_ci		<< "\n"
468e5c31af7Sopenharmony_ci		<< "out gl_PerVertex {\n"
469e5c31af7Sopenharmony_ci		<< "	vec4  gl_Position;\n"
470e5c31af7Sopenharmony_ci		<< "};\n"
471e5c31af7Sopenharmony_ci		<< "void main (void)\n"
472e5c31af7Sopenharmony_ci		<< "{\n"
473e5c31af7Sopenharmony_ci		<< "	gl_Position					= vs_in_position_ndc;\n"
474e5c31af7Sopenharmony_ci		<< "	vs_out_pos_screen_centroid	= vs_in_position_screen;\n"
475e5c31af7Sopenharmony_ci		<< "	vs_out_pos_screen_fragment	= vs_in_position_screen;\n"
476e5c31af7Sopenharmony_ci		<< "}\n";
477e5c31af7Sopenharmony_ci
478e5c31af7Sopenharmony_ci	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
479e5c31af7Sopenharmony_ci
480e5c31af7Sopenharmony_ci	// Create fragment shader
481e5c31af7Sopenharmony_ci	std::ostringstream fs;
482e5c31af7Sopenharmony_ci
483e5c31af7Sopenharmony_ci	fs << "#version 440\n"
484e5c31af7Sopenharmony_ci		<< "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n"
485e5c31af7Sopenharmony_ci		<< "layout(location = 1)		  in vec2 fs_in_pos_screen_fragment;\n"
486e5c31af7Sopenharmony_ci		<< "\n"
487e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec4 fs_out_color;\n"
488e5c31af7Sopenharmony_ci		<< "\n"
489e5c31af7Sopenharmony_ci		<< "void main (void)\n"
490e5c31af7Sopenharmony_ci		<< "{\n"
491e5c31af7Sopenharmony_ci		<< "	const float threshold = 0.0005;\n"
492e5c31af7Sopenharmony_ci		<< "\n"
493e5c31af7Sopenharmony_ci		<< "	const vec2 position_a  = interpolateAtSample(fs_in_pos_screen_centroid, gl_SampleID);\n"
494e5c31af7Sopenharmony_ci		<< "	const vec2 position_b  = interpolateAtSample(fs_in_pos_screen_fragment, gl_SampleID);\n"
495e5c31af7Sopenharmony_ci		<< "	const bool valuesEqual = all(lessThan(abs(position_a - position_b), vec2(threshold)));\n"
496e5c31af7Sopenharmony_ci		<< "\n"
497e5c31af7Sopenharmony_ci		<< "	if (valuesEqual)\n"
498e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
499e5c31af7Sopenharmony_ci		<< "	else\n"
500e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
501e5c31af7Sopenharmony_ci		<< "}\n";
502e5c31af7Sopenharmony_ci
503e5c31af7Sopenharmony_ci	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
504e5c31af7Sopenharmony_ci}
505e5c31af7Sopenharmony_ci
506e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::createInstance (Context& context) const
507e5c31af7Sopenharmony_ci{
508e5c31af7Sopenharmony_ci	return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
509e5c31af7Sopenharmony_ci}
510e5c31af7Sopenharmony_ci
511e5c31af7Sopenharmony_ciclass MSCaseInterpolateAtSampleConsistency;
512e5c31af7Sopenharmony_ci
513e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseInterpolateAtSampleConsistency>::init (void)
514e5c31af7Sopenharmony_ci{
515e5c31af7Sopenharmony_ci	const std::string	indexStr = de::toString(m_imageMSParams.componentData.index);
516e5c31af7Sopenharmony_ci	std::string			componentMsg;
517e5c31af7Sopenharmony_ci
518e5c31af7Sopenharmony_ci	switch (m_imageMSParams.componentData.source)
519e5c31af7Sopenharmony_ci	{
520e5c31af7Sopenharmony_ci	case multisample::ComponentSource::CONSTANT:		componentMsg = "Using single constant component " + indexStr;			break;
521e5c31af7Sopenharmony_ci	case multisample::ComponentSource::PUSH_CONSTANT:	componentMsg = "Using single component via push constant " + indexStr;	break;
522e5c31af7Sopenharmony_ci	default: break;
523e5c31af7Sopenharmony_ci	}
524e5c31af7Sopenharmony_ci
525e5c31af7Sopenharmony_ci	m_testCtx.getLog()
526e5c31af7Sopenharmony_ci		<< tcu::TestLog::Message
527e5c31af7Sopenharmony_ci		<< "Verifying that interpolateAtSample with the sample set to the current sampleID returns consistent values.\n"
528e5c31af7Sopenharmony_ci		<< (componentMsg.empty() ? std::string() : componentMsg + "\n")
529e5c31af7Sopenharmony_ci		<< "	Interpolate varying containing screen space location with centroid and sample qualifiers.\n"
530e5c31af7Sopenharmony_ci		<< "	=> interpolateAtSample(screenCentroid, sampleID) = screenSample\n"
531e5c31af7Sopenharmony_ci		<< tcu::TestLog::EndMessage;
532e5c31af7Sopenharmony_ci
533e5c31af7Sopenharmony_ci	MultisampleCaseBase::init();
534e5c31af7Sopenharmony_ci}
535e5c31af7Sopenharmony_ci
536e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseInterpolateAtSampleConsistency>::initPrograms (vk::SourceCollections& programCollection) const
537e5c31af7Sopenharmony_ci{
538e5c31af7Sopenharmony_ci	// Create vertex shader
539e5c31af7Sopenharmony_ci	std::ostringstream vs;
540e5c31af7Sopenharmony_ci
541e5c31af7Sopenharmony_ci	vs << "#version 440\n"
542e5c31af7Sopenharmony_ci		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
543e5c31af7Sopenharmony_ci		<< "layout(location = 1) in vec2 vs_in_position_screen;\n"
544e5c31af7Sopenharmony_ci		<< "\n"
545e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec2 vs_out_pos_screen_centroid;\n"
546e5c31af7Sopenharmony_ci		<< "layout(location = 1) out vec2 vs_out_pos_screen_sample;\n"
547e5c31af7Sopenharmony_ci		<< "\n"
548e5c31af7Sopenharmony_ci		<< "out gl_PerVertex {\n"
549e5c31af7Sopenharmony_ci		<< "	vec4  gl_Position;\n"
550e5c31af7Sopenharmony_ci		<< "};\n"
551e5c31af7Sopenharmony_ci		<< "void main (void)\n"
552e5c31af7Sopenharmony_ci		<< "{\n"
553e5c31af7Sopenharmony_ci		<< "	gl_Position					= vs_in_position_ndc;\n"
554e5c31af7Sopenharmony_ci		<< "	vs_out_pos_screen_centroid	= vs_in_position_screen;\n"
555e5c31af7Sopenharmony_ci		<< "	vs_out_pos_screen_sample	= vs_in_position_screen;\n"
556e5c31af7Sopenharmony_ci		<< "}\n";
557e5c31af7Sopenharmony_ci
558e5c31af7Sopenharmony_ci	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
559e5c31af7Sopenharmony_ci
560e5c31af7Sopenharmony_ci	// Create fragment shader
561e5c31af7Sopenharmony_ci	std::ostringstream fs;
562e5c31af7Sopenharmony_ci
563e5c31af7Sopenharmony_ci	fs	<< "#version 440\n"
564e5c31af7Sopenharmony_ci		<< "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n"
565e5c31af7Sopenharmony_ci		<< "layout(location = 1) sample   in vec2 fs_in_pos_screen_sample;\n"
566e5c31af7Sopenharmony_ci		<< "\n"
567e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec4 fs_out_color;\n"
568e5c31af7Sopenharmony_ci		<< "\n";
569e5c31af7Sopenharmony_ci
570e5c31af7Sopenharmony_ci	if (m_imageMSParams.componentData.source == multisample::ComponentSource::PUSH_CONSTANT)
571e5c31af7Sopenharmony_ci	{
572e5c31af7Sopenharmony_ci		fs	<< "layout(push_constant) uniform PushConstants {\n"
573e5c31af7Sopenharmony_ci			<< "   uint component;\n"
574e5c31af7Sopenharmony_ci			<< "};\n"
575e5c31af7Sopenharmony_ci			<< "\n";
576e5c31af7Sopenharmony_ci	}
577e5c31af7Sopenharmony_ci
578e5c31af7Sopenharmony_ci	fs	<< "void main (void)\n"
579e5c31af7Sopenharmony_ci		<< "{\n"
580e5c31af7Sopenharmony_ci		<< "	const float threshold = 0.15625;\n"
581e5c31af7Sopenharmony_ci		<< "\n";
582e5c31af7Sopenharmony_ci
583e5c31af7Sopenharmony_ci	if (m_imageMSParams.componentData.source == multisample::ComponentSource::NONE)
584e5c31af7Sopenharmony_ci	{
585e5c31af7Sopenharmony_ci		fs	<< "	const vec2  pos_interpolated_at_sample = interpolateAtSample(fs_in_pos_screen_centroid, gl_SampleID);\n"
586e5c31af7Sopenharmony_ci			<< "	const bool  valuesEqual                = all(lessThan(abs(pos_interpolated_at_sample - fs_in_pos_screen_sample), vec2(threshold)));\n";
587e5c31af7Sopenharmony_ci	}
588e5c31af7Sopenharmony_ci	else if (m_imageMSParams.componentData.source == multisample::ComponentSource::CONSTANT)
589e5c31af7Sopenharmony_ci	{
590e5c31af7Sopenharmony_ci		const auto& index = m_imageMSParams.componentData.index;
591e5c31af7Sopenharmony_ci		fs	<< "	const float pos_interpolated_at_sample = interpolateAtSample(fs_in_pos_screen_centroid[" << index << "], gl_SampleID);\n"
592e5c31af7Sopenharmony_ci			<< "	const bool  valuesEqual                = (abs(pos_interpolated_at_sample - fs_in_pos_screen_sample[" << index << "]) < threshold);\n";
593e5c31af7Sopenharmony_ci	}
594e5c31af7Sopenharmony_ci	else // multisample::ComponentSource::PUSH_CONSTANT
595e5c31af7Sopenharmony_ci	{
596e5c31af7Sopenharmony_ci		fs	<< "	const float pos_interpolated_at_sample = interpolateAtSample(fs_in_pos_screen_centroid[component], gl_SampleID);\n"
597e5c31af7Sopenharmony_ci			<< "	const bool  valuesEqual                = (abs(pos_interpolated_at_sample - fs_in_pos_screen_sample[component]) < threshold);\n";
598e5c31af7Sopenharmony_ci	}
599e5c31af7Sopenharmony_ci
600e5c31af7Sopenharmony_ci	fs	<< "\n"
601e5c31af7Sopenharmony_ci		<< "	if (valuesEqual)\n"
602e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
603e5c31af7Sopenharmony_ci		<< "	else\n"
604e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
605e5c31af7Sopenharmony_ci		<< "}\n";
606e5c31af7Sopenharmony_ci
607e5c31af7Sopenharmony_ci	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
608e5c31af7Sopenharmony_ci}
609e5c31af7Sopenharmony_ci
610e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseInterpolateAtSampleConsistency>::createInstance (Context& context) const
611e5c31af7Sopenharmony_ci{
612e5c31af7Sopenharmony_ci	return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
613e5c31af7Sopenharmony_ci}
614e5c31af7Sopenharmony_ci
615e5c31af7Sopenharmony_ciclass MSCaseInterpolateAtCentroidConsistency;
616e5c31af7Sopenharmony_ci
617e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseInterpolateAtCentroidConsistency>::init (void)
618e5c31af7Sopenharmony_ci{
619e5c31af7Sopenharmony_ci	const std::string	indexStr = de::toString(m_imageMSParams.componentData.index);
620e5c31af7Sopenharmony_ci	std::string			componentMsg;
621e5c31af7Sopenharmony_ci
622e5c31af7Sopenharmony_ci	switch (m_imageMSParams.componentData.source)
623e5c31af7Sopenharmony_ci	{
624e5c31af7Sopenharmony_ci	case multisample::ComponentSource::CONSTANT:		componentMsg = "Using single constant component " + indexStr;			break;
625e5c31af7Sopenharmony_ci	case multisample::ComponentSource::PUSH_CONSTANT:	componentMsg = "Using single component via push constant " + indexStr;	break;
626e5c31af7Sopenharmony_ci	default: break;
627e5c31af7Sopenharmony_ci	}
628e5c31af7Sopenharmony_ci
629e5c31af7Sopenharmony_ci	m_testCtx.getLog()
630e5c31af7Sopenharmony_ci		<< tcu::TestLog::Message
631e5c31af7Sopenharmony_ci		<< "Verifying that interpolateAtCentroid does not return different values than a corresponding centroid qualified varying.\n"
632e5c31af7Sopenharmony_ci		<< (componentMsg.empty() ? std::string() : componentMsg + "\n")
633e5c31af7Sopenharmony_ci		<< "	Interpolate varying containing screen space location with sample and centroid qualifiers.\n"
634e5c31af7Sopenharmony_ci		<< "	=> interpolateAtCentroid(screenSample) = screenCentroid\n"
635e5c31af7Sopenharmony_ci		<< tcu::TestLog::EndMessage;
636e5c31af7Sopenharmony_ci
637e5c31af7Sopenharmony_ci	MultisampleCaseBase::init();
638e5c31af7Sopenharmony_ci}
639e5c31af7Sopenharmony_ci
640e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseInterpolateAtCentroidConsistency>::initPrograms (vk::SourceCollections& programCollection) const
641e5c31af7Sopenharmony_ci{
642e5c31af7Sopenharmony_ci	// Create vertex shader
643e5c31af7Sopenharmony_ci	std::ostringstream vs;
644e5c31af7Sopenharmony_ci
645e5c31af7Sopenharmony_ci	vs << "#version 440\n"
646e5c31af7Sopenharmony_ci		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
647e5c31af7Sopenharmony_ci		<< "layout(location = 1) in vec2 vs_in_position_screen;\n"
648e5c31af7Sopenharmony_ci		<< "\n"
649e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec2 vs_out_pos_screen_sample[2];\n"
650e5c31af7Sopenharmony_ci		<< "layout(location = 2) out vec2 vs_out_pos_screen_centroid[2];\n"
651e5c31af7Sopenharmony_ci		<< "\n"
652e5c31af7Sopenharmony_ci		<< "out gl_PerVertex {\n"
653e5c31af7Sopenharmony_ci		<< "	vec4  gl_Position;\n"
654e5c31af7Sopenharmony_ci		<< "};\n"
655e5c31af7Sopenharmony_ci		<< "void main (void)\n"
656e5c31af7Sopenharmony_ci		<< "{\n"
657e5c31af7Sopenharmony_ci		<< "	gl_Position				      = vs_in_position_ndc;\n"
658e5c31af7Sopenharmony_ci		// Index 0 is never read, so we'll populate them with bad values
659e5c31af7Sopenharmony_ci		<< "	vs_out_pos_screen_sample[0]	  = vec2(-70.3, 42.1);\n"
660e5c31af7Sopenharmony_ci		<< "	vs_out_pos_screen_centroid[0] = vec2(7.7, -3.2);\n"
661e5c31af7Sopenharmony_ci		// Actual coordinates in index 1:
662e5c31af7Sopenharmony_ci		<< "	vs_out_pos_screen_sample[1]	  = vs_in_position_screen;\n"
663e5c31af7Sopenharmony_ci		<< "	vs_out_pos_screen_centroid[1] = vs_in_position_screen;\n"
664e5c31af7Sopenharmony_ci		<< "}\n";
665e5c31af7Sopenharmony_ci
666e5c31af7Sopenharmony_ci	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
667e5c31af7Sopenharmony_ci
668e5c31af7Sopenharmony_ci	// Create fragment shader
669e5c31af7Sopenharmony_ci	std::ostringstream fs;
670e5c31af7Sopenharmony_ci
671e5c31af7Sopenharmony_ci	fs	<< "#version 440\n"
672e5c31af7Sopenharmony_ci		<< "layout(location = 0) sample   in vec2 fs_in_pos_screen_sample[2];\n"
673e5c31af7Sopenharmony_ci		<< "layout(location = 2) centroid in vec2 fs_in_pos_screen_centroid[2];\n"
674e5c31af7Sopenharmony_ci		<< "\n"
675e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec4 fs_out_color;\n"
676e5c31af7Sopenharmony_ci		<< "\n";
677e5c31af7Sopenharmony_ci
678e5c31af7Sopenharmony_ci	if (m_imageMSParams.componentData.source == multisample::ComponentSource::PUSH_CONSTANT)
679e5c31af7Sopenharmony_ci	{
680e5c31af7Sopenharmony_ci		fs	<< "layout(push_constant) uniform PushConstants {\n"
681e5c31af7Sopenharmony_ci			<< "   uint component;\n"
682e5c31af7Sopenharmony_ci			<< "};\n"
683e5c31af7Sopenharmony_ci			<< "\n";
684e5c31af7Sopenharmony_ci	}
685e5c31af7Sopenharmony_ci
686e5c31af7Sopenharmony_ci	fs	<< "void main (void)\n"
687e5c31af7Sopenharmony_ci		<< "{\n"
688e5c31af7Sopenharmony_ci		<< "	const float threshold = 0.0005;\n"
689e5c31af7Sopenharmony_ci		<< "\n";
690e5c31af7Sopenharmony_ci
691e5c31af7Sopenharmony_ci	if (m_imageMSParams.componentData.source == multisample::ComponentSource::NONE)
692e5c31af7Sopenharmony_ci	{
693e5c31af7Sopenharmony_ci		fs	<< "	const vec2 pos_interpolated_at_centroid = interpolateAtCentroid(fs_in_pos_screen_sample[1]);\n"
694e5c31af7Sopenharmony_ci			<< "	const bool valuesEqual                  = all(lessThan(abs(pos_interpolated_at_centroid - fs_in_pos_screen_centroid[1]), vec2(threshold)));\n";
695e5c31af7Sopenharmony_ci	}
696e5c31af7Sopenharmony_ci	else if (m_imageMSParams.componentData.source == multisample::ComponentSource::CONSTANT)
697e5c31af7Sopenharmony_ci	{
698e5c31af7Sopenharmony_ci		const auto& index = m_imageMSParams.componentData.index;
699e5c31af7Sopenharmony_ci		fs	<< "	const float pos_interpolated_at_centroid = interpolateAtCentroid(fs_in_pos_screen_sample[1][" << index << "]);\n"
700e5c31af7Sopenharmony_ci			<< "	const bool  valuesEqual                  = (abs(pos_interpolated_at_centroid - fs_in_pos_screen_centroid[1][" << index << "]) < threshold);\n";
701e5c31af7Sopenharmony_ci	}
702e5c31af7Sopenharmony_ci	else // multisample::ComponentSource::PUSH_CONSTANT
703e5c31af7Sopenharmony_ci	{
704e5c31af7Sopenharmony_ci		fs	<< "	const float pos_interpolated_at_centroid = interpolateAtCentroid(fs_in_pos_screen_sample[1][component]);\n"
705e5c31af7Sopenharmony_ci			<< "	const bool  valuesEqual                  = (abs(pos_interpolated_at_centroid - fs_in_pos_screen_centroid[1][component]) < threshold);\n";
706e5c31af7Sopenharmony_ci	}
707e5c31af7Sopenharmony_ci
708e5c31af7Sopenharmony_ci	fs	<< "\n"
709e5c31af7Sopenharmony_ci		<< "	if (valuesEqual)\n"
710e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
711e5c31af7Sopenharmony_ci		<< "	else\n"
712e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
713e5c31af7Sopenharmony_ci		<< "}\n";
714e5c31af7Sopenharmony_ci
715e5c31af7Sopenharmony_ci	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
716e5c31af7Sopenharmony_ci}
717e5c31af7Sopenharmony_ci
718e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseInterpolateAtCentroidConsistency>::createInstance (Context& context) const
719e5c31af7Sopenharmony_ci{
720e5c31af7Sopenharmony_ci	return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
721e5c31af7Sopenharmony_ci}
722e5c31af7Sopenharmony_ci
723e5c31af7Sopenharmony_ciclass MSCaseInterpolateAtOffsetPixelCenter;
724e5c31af7Sopenharmony_ci
725e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseInterpolateAtOffsetPixelCenter>::init (void)
726e5c31af7Sopenharmony_ci{
727e5c31af7Sopenharmony_ci	m_testCtx.getLog()
728e5c31af7Sopenharmony_ci		<< tcu::TestLog::Message
729e5c31af7Sopenharmony_ci		<< "Verifying that interpolateAtOffset returns value sampled at an offset from the center of the pixel.\n"
730e5c31af7Sopenharmony_ci		<< "	Interpolate varying containing screen space location.\n"
731e5c31af7Sopenharmony_ci		<< "	=> interpolateAtOffset(screen, offset) should be \"varying value at the pixel center\" + offset"
732e5c31af7Sopenharmony_ci		<< tcu::TestLog::EndMessage;
733e5c31af7Sopenharmony_ci
734e5c31af7Sopenharmony_ci	MultisampleCaseBase::init();
735e5c31af7Sopenharmony_ci}
736e5c31af7Sopenharmony_ci
737e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseInterpolateAtOffsetPixelCenter>::initPrograms (vk::SourceCollections& programCollection) const
738e5c31af7Sopenharmony_ci{
739e5c31af7Sopenharmony_ci	// Create vertex shader
740e5c31af7Sopenharmony_ci	std::ostringstream vs;
741e5c31af7Sopenharmony_ci
742e5c31af7Sopenharmony_ci	vs << "#version 440\n"
743e5c31af7Sopenharmony_ci		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
744e5c31af7Sopenharmony_ci		<< "layout(location = 1) in vec2 vs_in_position_screen;\n"
745e5c31af7Sopenharmony_ci		<< "\n"
746e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec2 vs_out_pos_screen;\n"
747e5c31af7Sopenharmony_ci		<< "layout(location = 1) out vec2 vs_out_offset;\n"
748e5c31af7Sopenharmony_ci		<< "\n"
749e5c31af7Sopenharmony_ci		<< "out gl_PerVertex {\n"
750e5c31af7Sopenharmony_ci		<< "	vec4  gl_Position;\n"
751e5c31af7Sopenharmony_ci		<< "};\n"
752e5c31af7Sopenharmony_ci		<< "void main (void)\n"
753e5c31af7Sopenharmony_ci		<< "{\n"
754e5c31af7Sopenharmony_ci		<< "	gl_Position			= vs_in_position_ndc;\n"
755e5c31af7Sopenharmony_ci		<< "	vs_out_pos_screen	= vs_in_position_screen;\n"
756e5c31af7Sopenharmony_ci		<< "	vs_out_offset		= vs_in_position_ndc.xy * 0.5;\n"
757e5c31af7Sopenharmony_ci		<< "}\n";
758e5c31af7Sopenharmony_ci
759e5c31af7Sopenharmony_ci	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
760e5c31af7Sopenharmony_ci
761e5c31af7Sopenharmony_ci	// Create fragment shader
762e5c31af7Sopenharmony_ci	std::ostringstream fs;
763e5c31af7Sopenharmony_ci
764e5c31af7Sopenharmony_ci	fs << "#version 440\n"
765e5c31af7Sopenharmony_ci		<< "layout(location = 0) in  vec2 fs_in_pos_screen;\n"
766e5c31af7Sopenharmony_ci		<< "layout(location = 1) in  vec2 fs_in_offset;\n"
767e5c31af7Sopenharmony_ci		<< "\n"
768e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec4 fs_out_color;\n"
769e5c31af7Sopenharmony_ci		<< "\n"
770e5c31af7Sopenharmony_ci		<< "void main (void)\n"
771e5c31af7Sopenharmony_ci		<< "{\n"
772e5c31af7Sopenharmony_ci		<< "    const vec2  frag_center = interpolateAtOffset(fs_in_pos_screen, vec2(0.0));\n"
773e5c31af7Sopenharmony_ci		<< "    const vec2  center_diff = abs(frag_center - fs_in_pos_screen);\n"
774e5c31af7Sopenharmony_ci		<< "    const float threshold   = 0.125;\n"
775e5c31af7Sopenharmony_ci		<< "    bool        valuesEqual = false;\n"
776e5c31af7Sopenharmony_ci		<< "\n"
777e5c31af7Sopenharmony_ci		<< "    if (all(lessThan(center_diff, vec2(0.5 + threshold)))) {\n"
778e5c31af7Sopenharmony_ci		<< "        const vec2 pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen, fs_in_offset);\n"
779e5c31af7Sopenharmony_ci		<< "        const vec2 reference_value            = frag_center + fs_in_offset;\n"
780e5c31af7Sopenharmony_ci		<< "\n"
781e5c31af7Sopenharmony_ci		<< "        valuesEqual = all(lessThan(abs(pos_interpolated_at_offset - reference_value), vec2(threshold)));\n"
782e5c31af7Sopenharmony_ci		<< "    }\n"
783e5c31af7Sopenharmony_ci		<< "\n"
784e5c31af7Sopenharmony_ci		<< "    if (valuesEqual)\n"
785e5c31af7Sopenharmony_ci		<< "        fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
786e5c31af7Sopenharmony_ci		<< "    else\n"
787e5c31af7Sopenharmony_ci		<< "        fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
788e5c31af7Sopenharmony_ci		<< "}\n";
789e5c31af7Sopenharmony_ci
790e5c31af7Sopenharmony_ci	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
791e5c31af7Sopenharmony_ci}
792e5c31af7Sopenharmony_ci
793e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseInterpolateAtOffsetPixelCenter>::createInstance (Context& context) const
794e5c31af7Sopenharmony_ci{
795e5c31af7Sopenharmony_ci	return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
796e5c31af7Sopenharmony_ci}
797e5c31af7Sopenharmony_ci
798e5c31af7Sopenharmony_ciclass MSCaseInterpolateAtOffsetSamplePosition;
799e5c31af7Sopenharmony_ci
800e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseInterpolateAtOffsetSamplePosition>::init (void)
801e5c31af7Sopenharmony_ci{
802e5c31af7Sopenharmony_ci	const std::string	indexStr = de::toString(m_imageMSParams.componentData.index);
803e5c31af7Sopenharmony_ci	std::string			componentMsg;
804e5c31af7Sopenharmony_ci
805e5c31af7Sopenharmony_ci	switch (m_imageMSParams.componentData.source)
806e5c31af7Sopenharmony_ci	{
807e5c31af7Sopenharmony_ci	case multisample::ComponentSource::CONSTANT:		componentMsg = "Using single constant component " + indexStr;			break;
808e5c31af7Sopenharmony_ci	case multisample::ComponentSource::PUSH_CONSTANT:	componentMsg = "Using single component via push constant " + indexStr;	break;
809e5c31af7Sopenharmony_ci	default: break;
810e5c31af7Sopenharmony_ci	}
811e5c31af7Sopenharmony_ci
812e5c31af7Sopenharmony_ci	m_testCtx.getLog()
813e5c31af7Sopenharmony_ci		<< tcu::TestLog::Message
814e5c31af7Sopenharmony_ci		<< "Verifying that interpolateAtOffset of screen position with the offset of current sample position returns value "
815e5c31af7Sopenharmony_ci		<< "similar to screen position interpolated at sample.\n"
816e5c31af7Sopenharmony_ci		<< (componentMsg.empty() ? std::string() : componentMsg + "\n")
817e5c31af7Sopenharmony_ci		<< "	Interpolate varying containing screen space location with and without sample qualifier.\n"
818e5c31af7Sopenharmony_ci		<< "	=> interpolateAtOffset(screenFragment, samplePosition - (0.5,0.5)) = screenSample"
819e5c31af7Sopenharmony_ci		<< tcu::TestLog::EndMessage;
820e5c31af7Sopenharmony_ci
821e5c31af7Sopenharmony_ci	MultisampleCaseBase::init();
822e5c31af7Sopenharmony_ci}
823e5c31af7Sopenharmony_ci
824e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseInterpolateAtOffsetSamplePosition>::initPrograms (vk::SourceCollections& programCollection) const
825e5c31af7Sopenharmony_ci{
826e5c31af7Sopenharmony_ci	// Create vertex shader
827e5c31af7Sopenharmony_ci	std::ostringstream vs;
828e5c31af7Sopenharmony_ci
829e5c31af7Sopenharmony_ci	vs << "#version 440\n"
830e5c31af7Sopenharmony_ci		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
831e5c31af7Sopenharmony_ci		<< "layout(location = 1) in vec2 vs_in_position_screen;\n"
832e5c31af7Sopenharmony_ci		<< "\n"
833e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec2 vs_out_pos_screen_fragment;\n"
834e5c31af7Sopenharmony_ci		<< "layout(location = 1) out vec2 vs_out_pos_screen_sample;\n"
835e5c31af7Sopenharmony_ci		<< "\n"
836e5c31af7Sopenharmony_ci		<< "out gl_PerVertex {\n"
837e5c31af7Sopenharmony_ci		<< "	vec4  gl_Position;\n"
838e5c31af7Sopenharmony_ci		<< "};\n"
839e5c31af7Sopenharmony_ci		<< "void main (void)\n"
840e5c31af7Sopenharmony_ci		<< "{\n"
841e5c31af7Sopenharmony_ci		<< "	gl_Position					= vs_in_position_ndc;\n"
842e5c31af7Sopenharmony_ci		<< "	vs_out_pos_screen_fragment	= vs_in_position_screen;\n"
843e5c31af7Sopenharmony_ci		<< "	vs_out_pos_screen_sample	= vs_in_position_screen;\n"
844e5c31af7Sopenharmony_ci		<< "}\n";
845e5c31af7Sopenharmony_ci
846e5c31af7Sopenharmony_ci	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
847e5c31af7Sopenharmony_ci
848e5c31af7Sopenharmony_ci	// Create fragment shader
849e5c31af7Sopenharmony_ci	std::ostringstream fs;
850e5c31af7Sopenharmony_ci
851e5c31af7Sopenharmony_ci	fs	<< "#version 440\n"
852e5c31af7Sopenharmony_ci		<< "layout(location = 0)		in vec2 fs_in_pos_screen_fragment;\n"
853e5c31af7Sopenharmony_ci		<< "layout(location = 1) sample in vec2 fs_in_pos_screen_sample;\n"
854e5c31af7Sopenharmony_ci		<< "\n"
855e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec4 fs_out_color;\n"
856e5c31af7Sopenharmony_ci		<< "\n";
857e5c31af7Sopenharmony_ci
858e5c31af7Sopenharmony_ci	if (m_imageMSParams.componentData.source == multisample::ComponentSource::PUSH_CONSTANT)
859e5c31af7Sopenharmony_ci	{
860e5c31af7Sopenharmony_ci		fs	<< "layout(push_constant) uniform PushConstants {\n"
861e5c31af7Sopenharmony_ci			<< "   uint component;\n"
862e5c31af7Sopenharmony_ci			<< "};\n"
863e5c31af7Sopenharmony_ci			<< "\n";
864e5c31af7Sopenharmony_ci	}
865e5c31af7Sopenharmony_ci
866e5c31af7Sopenharmony_ci	fs	<< "void main (void)\n"
867e5c31af7Sopenharmony_ci		<< "{\n"
868e5c31af7Sopenharmony_ci		<< "	const float threshold = 0.15625;\n"
869e5c31af7Sopenharmony_ci		<< "\n"
870e5c31af7Sopenharmony_ci		<< "	const vec2 offset                     = gl_SamplePosition - vec2(0.5, 0.5);\n";
871e5c31af7Sopenharmony_ci
872e5c31af7Sopenharmony_ci	if (m_imageMSParams.componentData.source == multisample::ComponentSource::NONE)
873e5c31af7Sopenharmony_ci	{
874e5c31af7Sopenharmony_ci		fs	<< "	const vec2 pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen_fragment, offset);\n"
875e5c31af7Sopenharmony_ci			<< "	const bool valuesEqual                = all(lessThan(abs(pos_interpolated_at_offset - fs_in_pos_screen_sample), vec2(threshold)));\n";
876e5c31af7Sopenharmony_ci	}
877e5c31af7Sopenharmony_ci	else if (m_imageMSParams.componentData.source == multisample::ComponentSource::CONSTANT)
878e5c31af7Sopenharmony_ci	{
879e5c31af7Sopenharmony_ci		const auto& index = m_imageMSParams.componentData.index;
880e5c31af7Sopenharmony_ci		fs	<< "	const float pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen_fragment[" << index << "], offset);\n"
881e5c31af7Sopenharmony_ci			<< "	const bool valuesEqual                 = (abs(pos_interpolated_at_offset - fs_in_pos_screen_sample[" << index << "]) < threshold);\n";
882e5c31af7Sopenharmony_ci	}
883e5c31af7Sopenharmony_ci	else // multisample::ComponentSource::PUSH_CONSTANT
884e5c31af7Sopenharmony_ci	{
885e5c31af7Sopenharmony_ci		fs	<< "	const float pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen_fragment[component], offset);\n"
886e5c31af7Sopenharmony_ci			<< "	const bool valuesEqual                 = (abs(pos_interpolated_at_offset - fs_in_pos_screen_sample[component]) < threshold);\n";
887e5c31af7Sopenharmony_ci	}
888e5c31af7Sopenharmony_ci
889e5c31af7Sopenharmony_ci	fs	<< "\n"
890e5c31af7Sopenharmony_ci		<< "	if (valuesEqual)\n"
891e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
892e5c31af7Sopenharmony_ci		<< "	else\n"
893e5c31af7Sopenharmony_ci		<< "		fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
894e5c31af7Sopenharmony_ci		<< "}\n";
895e5c31af7Sopenharmony_ci
896e5c31af7Sopenharmony_ci	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
897e5c31af7Sopenharmony_ci}
898e5c31af7Sopenharmony_ci
899e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseInterpolateAtOffsetSamplePosition>::createInstance (Context& context) const
900e5c31af7Sopenharmony_ci{
901e5c31af7Sopenharmony_ci	return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
902e5c31af7Sopenharmony_ci}
903e5c31af7Sopenharmony_ci
904e5c31af7Sopenharmony_ciclass MSInstanceInterpolateBarycentricCoordinates;
905e5c31af7Sopenharmony_ci
906e5c31af7Sopenharmony_citemplate<> MSInstanceBaseResolve::VertexDataDesc MSInstance<MSInstanceInterpolateBarycentricCoordinates>::getVertexDataDescripton (void) const
907e5c31af7Sopenharmony_ci{
908e5c31af7Sopenharmony_ci	VertexDataDesc vertexDataDesc;
909e5c31af7Sopenharmony_ci
910e5c31af7Sopenharmony_ci	vertexDataDesc.verticesCount		= 3u;
911e5c31af7Sopenharmony_ci	vertexDataDesc.dataStride			= sizeof(VertexDataNdcBarycentric);
912e5c31af7Sopenharmony_ci	vertexDataDesc.dataSize				= vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
913e5c31af7Sopenharmony_ci	vertexDataDesc.primitiveTopology	= VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
914e5c31af7Sopenharmony_ci
915e5c31af7Sopenharmony_ci	const VkVertexInputAttributeDescription vertexAttribPositionNdc =
916e5c31af7Sopenharmony_ci	{
917e5c31af7Sopenharmony_ci		0u,															// deUint32	location;
918e5c31af7Sopenharmony_ci		0u,															// deUint32	binding;
919e5c31af7Sopenharmony_ci		VK_FORMAT_R32G32B32A32_SFLOAT,								// VkFormat	format;
920e5c31af7Sopenharmony_ci		DE_OFFSET_OF(VertexDataNdcBarycentric, positionNdc),		// deUint32	offset;
921e5c31af7Sopenharmony_ci	};
922e5c31af7Sopenharmony_ci
923e5c31af7Sopenharmony_ci	vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
924e5c31af7Sopenharmony_ci
925e5c31af7Sopenharmony_ci	const VkVertexInputAttributeDescription vertexAttrBarCoord =
926e5c31af7Sopenharmony_ci	{
927e5c31af7Sopenharmony_ci		1u,															// deUint32	location;
928e5c31af7Sopenharmony_ci		0u,															// deUint32	binding;
929e5c31af7Sopenharmony_ci		VK_FORMAT_R32G32B32_SFLOAT,									// VkFormat	format;
930e5c31af7Sopenharmony_ci		DE_OFFSET_OF(VertexDataNdcBarycentric, barycentricCoord),	// deUint32	offset;
931e5c31af7Sopenharmony_ci	};
932e5c31af7Sopenharmony_ci
933e5c31af7Sopenharmony_ci	vertexDataDesc.vertexAttribDescVec.push_back(vertexAttrBarCoord);
934e5c31af7Sopenharmony_ci
935e5c31af7Sopenharmony_ci	return vertexDataDesc;
936e5c31af7Sopenharmony_ci}
937e5c31af7Sopenharmony_ci
938e5c31af7Sopenharmony_citemplate<> void MSInstance<MSInstanceInterpolateBarycentricCoordinates>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
939e5c31af7Sopenharmony_ci{
940e5c31af7Sopenharmony_ci	// Create buffer storing vertex data
941e5c31af7Sopenharmony_ci	std::vector<VertexDataNdcBarycentric> vertices;
942e5c31af7Sopenharmony_ci
943e5c31af7Sopenharmony_ci	vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 0.0f, 1.0f)));
944e5c31af7Sopenharmony_ci	vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f), tcu::Vec3(1.0f, 0.0f, 0.0f)));
945e5c31af7Sopenharmony_ci	vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 1.0f, 0.0f)));
946e5c31af7Sopenharmony_ci
947e5c31af7Sopenharmony_ci	deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
948e5c31af7Sopenharmony_ci}
949e5c31af7Sopenharmony_ci
950e5c31af7Sopenharmony_citemplate<> tcu::TestStatus MSInstance<MSInstanceInterpolateBarycentricCoordinates>::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const
951e5c31af7Sopenharmony_ci{
952e5c31af7Sopenharmony_ci	if (checkForError(imageRSInfo, dataRS, 0))
953e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("Failed");
954e5c31af7Sopenharmony_ci
955e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("Passed");
956e5c31af7Sopenharmony_ci}
957e5c31af7Sopenharmony_ci
958e5c31af7Sopenharmony_ciclass MSCaseCentroidQualifierInsidePrimitive;
959e5c31af7Sopenharmony_ci
960e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseCentroidQualifierInsidePrimitive>::init (void)
961e5c31af7Sopenharmony_ci{
962e5c31af7Sopenharmony_ci	m_testCtx.getLog()
963e5c31af7Sopenharmony_ci		<< tcu::TestLog::Message
964e5c31af7Sopenharmony_ci		<< "Verifying that varying qualified with centroid is interpolated at location inside both the pixel and the primitive being processed.\n"
965e5c31af7Sopenharmony_ci		<< "	Interpolate triangle's barycentric coordinates with centroid qualifier.\n"
966e5c31af7Sopenharmony_ci		<< "	=> After interpolation we expect barycentric.xyz >= 0.0 && barycentric.xyz <= 1.0\n"
967e5c31af7Sopenharmony_ci		<< tcu::TestLog::EndMessage;
968e5c31af7Sopenharmony_ci
969e5c31af7Sopenharmony_ci	MultisampleCaseBase::init();
970e5c31af7Sopenharmony_ci}
971e5c31af7Sopenharmony_ci
972e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseCentroidQualifierInsidePrimitive>::initPrograms (vk::SourceCollections& programCollection) const
973e5c31af7Sopenharmony_ci{
974e5c31af7Sopenharmony_ci	// Create vertex shader
975e5c31af7Sopenharmony_ci	std::ostringstream vs;
976e5c31af7Sopenharmony_ci
977e5c31af7Sopenharmony_ci	vs << "#version 440\n"
978e5c31af7Sopenharmony_ci		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
979e5c31af7Sopenharmony_ci		<< "layout(location = 1) in vec3 vs_in_barCoord;\n"
980e5c31af7Sopenharmony_ci		<< "\n"
981e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec3 vs_out_barCoord;\n"
982e5c31af7Sopenharmony_ci		<< "\n"
983e5c31af7Sopenharmony_ci		<< "out gl_PerVertex {\n"
984e5c31af7Sopenharmony_ci		<< "	vec4  gl_Position;\n"
985e5c31af7Sopenharmony_ci		<< "};\n"
986e5c31af7Sopenharmony_ci		<< "void main (void)\n"
987e5c31af7Sopenharmony_ci		<< "{\n"
988e5c31af7Sopenharmony_ci		<< "	gl_Position		= vs_in_position_ndc;\n"
989e5c31af7Sopenharmony_ci		<< "	vs_out_barCoord = vs_in_barCoord;\n"
990e5c31af7Sopenharmony_ci		<< "}\n";
991e5c31af7Sopenharmony_ci
992e5c31af7Sopenharmony_ci	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
993e5c31af7Sopenharmony_ci
994e5c31af7Sopenharmony_ci	// Create fragment shader
995e5c31af7Sopenharmony_ci	std::ostringstream fs;
996e5c31af7Sopenharmony_ci
997e5c31af7Sopenharmony_ci	fs << "#version 440\n"
998e5c31af7Sopenharmony_ci		<< "layout(location = 0) centroid in vec3 fs_in_barCoord;\n"
999e5c31af7Sopenharmony_ci		<< "\n"
1000e5c31af7Sopenharmony_ci		<< "layout(location = 0) out vec4 fs_out_color;\n"
1001e5c31af7Sopenharmony_ci		<< "\n"
1002e5c31af7Sopenharmony_ci		<< "void main (void)\n"
1003e5c31af7Sopenharmony_ci		<< "{\n"
1004e5c31af7Sopenharmony_ci		<< "	if( all(greaterThanEqual(fs_in_barCoord, vec3(0.0))) && all(lessThanEqual(fs_in_barCoord, vec3(1.0))) )\n"
1005e5c31af7Sopenharmony_ci		<< "			fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
1006e5c31af7Sopenharmony_ci		<< "	else\n"
1007e5c31af7Sopenharmony_ci		<< "			fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1008e5c31af7Sopenharmony_ci		<< "}\n";
1009e5c31af7Sopenharmony_ci
1010e5c31af7Sopenharmony_ci	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1011e5c31af7Sopenharmony_ci}
1012e5c31af7Sopenharmony_ci
1013e5c31af7Sopenharmony_citemplate<> void MSCase<MSCaseCentroidQualifierInsidePrimitive>::checkSupport (Context& context) const
1014e5c31af7Sopenharmony_ci{
1015e5c31af7Sopenharmony_ci	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_imageMSParams.pipelineConstructionType);
1016e5c31af7Sopenharmony_ci}
1017e5c31af7Sopenharmony_ci
1018e5c31af7Sopenharmony_citemplate<> TestInstance* MSCase<MSCaseCentroidQualifierInsidePrimitive>::createInstance (Context& context) const
1019e5c31af7Sopenharmony_ci{
1020e5c31af7Sopenharmony_ci	return new MSInstance<MSInstanceInterpolateBarycentricCoordinates>(context, m_imageMSParams);
1021e5c31af7Sopenharmony_ci}
1022e5c31af7Sopenharmony_ci
1023e5c31af7Sopenharmony_ci} // multisample
1024e5c31af7Sopenharmony_ci
1025e5c31af7Sopenharmony_citcu::TestCaseGroup* createMultisampleInterpolationTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)
1026e5c31af7Sopenharmony_ci{
1027e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "multisample_interpolation"));
1028e5c31af7Sopenharmony_ci
1029e5c31af7Sopenharmony_ci	const tcu::UVec3 imageSizes[] =
1030e5c31af7Sopenharmony_ci	{
1031e5c31af7Sopenharmony_ci		tcu::UVec3(128u, 128u, 1u),
1032e5c31af7Sopenharmony_ci		tcu::UVec3(137u, 191u, 1u),
1033e5c31af7Sopenharmony_ci	};
1034e5c31af7Sopenharmony_ci
1035e5c31af7Sopenharmony_ci	const deUint32 sizesElemCount = static_cast<deUint32>(sizeof(imageSizes) / sizeof(tcu::UVec3));
1036e5c31af7Sopenharmony_ci
1037e5c31af7Sopenharmony_ci	const vk::VkSampleCountFlagBits imageSamples[] =
1038e5c31af7Sopenharmony_ci	{
1039e5c31af7Sopenharmony_ci		vk::VK_SAMPLE_COUNT_2_BIT,
1040e5c31af7Sopenharmony_ci		vk::VK_SAMPLE_COUNT_4_BIT,
1041e5c31af7Sopenharmony_ci		vk::VK_SAMPLE_COUNT_8_BIT,
1042e5c31af7Sopenharmony_ci		vk::VK_SAMPLE_COUNT_16_BIT,
1043e5c31af7Sopenharmony_ci		vk::VK_SAMPLE_COUNT_32_BIT,
1044e5c31af7Sopenharmony_ci		vk::VK_SAMPLE_COUNT_64_BIT,
1045e5c31af7Sopenharmony_ci	};
1046e5c31af7Sopenharmony_ci
1047e5c31af7Sopenharmony_ci	const deUint32 samplesElemCount = static_cast<deUint32>(sizeof(imageSamples) / sizeof(vk::VkSampleCountFlagBits));
1048e5c31af7Sopenharmony_ci
1049e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> caseGroup(new tcu::TestCaseGroup(testCtx, "sample_interpolate_at_single_sample"));
1050e5c31af7Sopenharmony_ci
1051e5c31af7Sopenharmony_ci	for (deUint32 imageSizeNdx = 0u; imageSizeNdx < sizesElemCount; ++imageSizeNdx)
1052e5c31af7Sopenharmony_ci	{
1053e5c31af7Sopenharmony_ci		const tcu::UVec3	imageSize = imageSizes[imageSizeNdx];
1054e5c31af7Sopenharmony_ci		std::ostringstream	imageSizeStream;
1055e5c31af7Sopenharmony_ci
1056e5c31af7Sopenharmony_ci		imageSizeStream << imageSize.x() << "_" << imageSize.y() << "_" << imageSize.z();
1057e5c31af7Sopenharmony_ci
1058e5c31af7Sopenharmony_ci		de::MovePtr<tcu::TestCaseGroup> sizeGroup(new tcu::TestCaseGroup(testCtx, imageSizeStream.str().c_str()));
1059e5c31af7Sopenharmony_ci
1060e5c31af7Sopenharmony_ci		multisample::ImageMSParams imageParams
1061e5c31af7Sopenharmony_ci		{
1062e5c31af7Sopenharmony_ci			pipelineConstructionType,
1063e5c31af7Sopenharmony_ci			vk::VK_SAMPLE_COUNT_1_BIT,
1064e5c31af7Sopenharmony_ci			imageSize,
1065e5c31af7Sopenharmony_ci			multisample::ComponentData{},
1066e5c31af7Sopenharmony_ci			1.0f,
1067e5c31af7Sopenharmony_ci		};
1068e5c31af7Sopenharmony_ci		sizeGroup->addChild(multisample::MSCase<multisample::MSCaseInterpolateAtSampleSingleSample>::createCase(testCtx, "samples_" + de::toString(1), imageParams));
1069e5c31af7Sopenharmony_ci
1070e5c31af7Sopenharmony_ci		caseGroup->addChild(sizeGroup.release());
1071e5c31af7Sopenharmony_ci	}
1072e5c31af7Sopenharmony_ci
1073e5c31af7Sopenharmony_ci	testGroup->addChild(caseGroup.release());
1074e5c31af7Sopenharmony_ci
1075e5c31af7Sopenharmony_ci	testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleDistinctValues> >	(testCtx, "sample_interpolate_at_distinct_values", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1076e5c31af7Sopenharmony_ci	testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleIgnoresCentroid> >(testCtx, "sample_interpolate_at_ignores_centroid", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1077e5c31af7Sopenharmony_ci
1078e5c31af7Sopenharmony_ci	// Test consistency in sample interpolation function
1079e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> sampleGroup(new tcu::TestCaseGroup(testCtx, "sample_interpolation_consistency"));
1080e5c31af7Sopenharmony_ci	sampleGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency> >	(testCtx, "all_components",		pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1081e5c31af7Sopenharmony_ci	sampleGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency> >	(testCtx, "component_0",		pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::CONSTANT, 0u}));
1082e5c31af7Sopenharmony_ci	sampleGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency> >	(testCtx, "component_1",		pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::CONSTANT, 1u}));
1083e5c31af7Sopenharmony_ci	sampleGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency> >	(testCtx, "pushc_component_0",	pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 0u}));
1084e5c31af7Sopenharmony_ci	sampleGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency> >	(testCtx, "pushc_component_1",	pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 1u}));
1085e5c31af7Sopenharmony_ci	testGroup->addChild(sampleGroup.release());
1086e5c31af7Sopenharmony_ci
1087e5c31af7Sopenharmony_ci	testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleQualifierDistinctValues> >		(testCtx, "sample_qualifier_distinct_values", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1088e5c31af7Sopenharmony_ci
1089e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> centroidGroup(new tcu::TestCaseGroup(testCtx, "centroid_interpolation_consistency", "Test consistency in centroid interpolation function"));
1090e5c31af7Sopenharmony_ci	centroidGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency> >	(testCtx, "all_components",		pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1091e5c31af7Sopenharmony_ci	centroidGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency> >	(testCtx, "component_0",		pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::CONSTANT, 0u}));
1092e5c31af7Sopenharmony_ci	centroidGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency> >	(testCtx, "component_1",		pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::CONSTANT, 1u}));
1093e5c31af7Sopenharmony_ci	centroidGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency> >	(testCtx, "pushc_component_0",	pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 0u}));
1094e5c31af7Sopenharmony_ci	centroidGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency> >	(testCtx, "pushc_component_1",	pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 1u}));
1095e5c31af7Sopenharmony_ci	testGroup->addChild(centroidGroup.release());
1096e5c31af7Sopenharmony_ci
1097e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
1098e5c31af7Sopenharmony_ci	// there is no support for pipelineConstructionType in amber
1099e5c31af7Sopenharmony_ci	if (pipelineConstructionType == vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
1100e5c31af7Sopenharmony_ci	{
1101e5c31af7Sopenharmony_ci		de::MovePtr<tcu::TestCaseGroup> reInterpolationGroup(new tcu::TestCaseGroup(testCtx, "reinterpolation_consistency", "Test consistency in reinterpolation"));
1102e5c31af7Sopenharmony_ci		std::vector<std::string> requirements;
1103e5c31af7Sopenharmony_ci		requirements.push_back("Features.sampleRateShading");
1104e5c31af7Sopenharmony_ci		reInterpolationGroup->addChild(cts_amber::createAmberTestCase(testCtx, "interpolate_at_centroid", "", "pipeline", "reinterpolate_at_centroid.amber", requirements));
1105e5c31af7Sopenharmony_ci		reInterpolationGroup->addChild(cts_amber::createAmberTestCase(testCtx, "interpolate_at_sample", "", "pipeline", "reinterpolate_at_sample.amber", requirements));
1106e5c31af7Sopenharmony_ci		testGroup->addChild(reInterpolationGroup.release());
1107e5c31af7Sopenharmony_ci
1108e5c31af7Sopenharmony_ci		de::MovePtr<tcu::TestCaseGroup> nonuniformInterpolantIndexingGroup(new tcu::TestCaseGroup(testCtx, "nonuniform_interpolant_indexing", "Test nonuniform interpolant indexing"));
1109e5c31af7Sopenharmony_ci		std::vector<std::string> requirementsNonuniformIntepolantIndexing;
1110e5c31af7Sopenharmony_ci		requirementsNonuniformIntepolantIndexing.push_back("Features.sampleRateShading");
1111e5c31af7Sopenharmony_ci		nonuniformInterpolantIndexingGroup->addChild(cts_amber::createAmberTestCase(testCtx, "centroid",  "pipeline/nonuniform_interpolant_indexing", "centroid.amber", requirementsNonuniformIntepolantIndexing));
1112e5c31af7Sopenharmony_ci		nonuniformInterpolantIndexingGroup->addChild(cts_amber::createAmberTestCase(testCtx, "sample",  "pipeline/nonuniform_interpolant_indexing", "sample.amber", requirementsNonuniformIntepolantIndexing));
1113e5c31af7Sopenharmony_ci		nonuniformInterpolantIndexingGroup->addChild(cts_amber::createAmberTestCase(testCtx, "offset",  "pipeline/nonuniform_interpolant_indexing", "offset.amber", requirementsNonuniformIntepolantIndexing));
1114e5c31af7Sopenharmony_ci		testGroup->addChild(nonuniformInterpolantIndexingGroup.release());
1115e5c31af7Sopenharmony_ci	}
1116e5c31af7Sopenharmony_ci
1117e5c31af7Sopenharmony_ci	testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseCentroidQualifierInsidePrimitive> >	(testCtx, "centroid_qualifier_inside_primitive",	pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1118e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
1119e5c31af7Sopenharmony_ci	testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetPixelCenter> >	(testCtx, "offset_interpolate_at_pixel_center",		pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1120e5c31af7Sopenharmony_ci
1121e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> offsetGroup(new tcu::TestCaseGroup(testCtx, "offset_interpolation_at_sample_position", "Test interpolation at offset function works for sample positions"));
1122e5c31af7Sopenharmony_ci	offsetGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition> >	(testCtx, "all_components",		pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1123e5c31af7Sopenharmony_ci	offsetGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition> >	(testCtx, "component_0",		pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::CONSTANT, 0u}));
1124e5c31af7Sopenharmony_ci	offsetGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition> >	(testCtx, "component_1",		pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::CONSTANT, 1u}));
1125e5c31af7Sopenharmony_ci	offsetGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition> >	(testCtx, "pushc_component_0",	pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 0u}));
1126e5c31af7Sopenharmony_ci	offsetGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition> >	(testCtx, "pushc_component_1",	pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 1u}));
1127e5c31af7Sopenharmony_ci	testGroup->addChild(offsetGroup.release());
1128e5c31af7Sopenharmony_ci
1129e5c31af7Sopenharmony_ci	return testGroup.release();
1130e5c31af7Sopenharmony_ci}
1131e5c31af7Sopenharmony_ci
1132e5c31af7Sopenharmony_ci} // pipeline
1133e5c31af7Sopenharmony_ci} // vkt
1134