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