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