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