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 vktPipelineMultisampleShaderBuiltInTests.cpp
21 * \brief Multisample Shader BuiltIn Tests
22 *//*--------------------------------------------------------------------*/
23 
24 #include "vktPipelineMultisampleShaderBuiltInTests.hpp"
25 #include "vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp"
26 #include "vktPipelineMakeUtil.hpp"
27 #include "vkBuilderUtil.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "tcuVectorUtil.hpp"
30 #include "tcuTestLog.hpp"
31 
32 namespace vkt
33 {
34 namespace pipeline
35 {
36 namespace multisample
37 {
38 
39 using namespace vk;
40 
41 struct VertexDataNdc
42 {
VertexDataNdcvkt::pipeline::multisample::VertexDataNdc43 	VertexDataNdc (const tcu::Vec4& posNdc) : positionNdc(posNdc) {}
44 
45 	tcu::Vec4 positionNdc;
46 };
47 
getVertexDataDescriptonNdc(void)48 MultisampleInstanceBase::VertexDataDesc getVertexDataDescriptonNdc (void)
49 {
50 	MultisampleInstanceBase::VertexDataDesc vertexDataDesc;
51 
52 	vertexDataDesc.verticesCount	 = 4u;
53 	vertexDataDesc.dataStride		 = sizeof(VertexDataNdc);
54 	vertexDataDesc.dataSize			 = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
55 	vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
56 
57 	const VkVertexInputAttributeDescription vertexAttribPositionNdc =
58 	{
59 		0u,											// deUint32	location;
60 		0u,											// deUint32	binding;
61 		VK_FORMAT_R32G32B32A32_SFLOAT,				// VkFormat	format;
62 		DE_OFFSET_OF(VertexDataNdc, positionNdc),	// deUint32	offset;
63 	};
64 
65 	vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
66 
67 	return vertexDataDesc;
68 }
69 
uploadVertexDataNdc(const Allocation & vertexBufferAllocation,const MultisampleInstanceBase::VertexDataDesc & vertexDataDescripton)70 void uploadVertexDataNdc (const Allocation& vertexBufferAllocation, const MultisampleInstanceBase::VertexDataDesc& vertexDataDescripton)
71 {
72 	std::vector<VertexDataNdc> vertices;
73 
74 	vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f)));
75 	vertices.push_back(VertexDataNdc(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f)));
76 	vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f)));
77 	vertices.push_back(VertexDataNdc(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f)));
78 
79 	deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
80 }
81 
82 struct VertexDataNdcScreen
83 {
VertexDataNdcScreenvkt::pipeline::multisample::VertexDataNdcScreen84 	VertexDataNdcScreen (const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {}
85 
86 	tcu::Vec4 positionNdc;
87 	tcu::Vec2 positionScreen;
88 };
89 
getVertexDataDescriptonNdcScreen(void)90 MultisampleInstanceBase::VertexDataDesc getVertexDataDescriptonNdcScreen (void)
91 {
92 	MultisampleInstanceBase::VertexDataDesc vertexDataDesc;
93 
94 	vertexDataDesc.verticesCount	 = 4u;
95 	vertexDataDesc.dataStride		 = sizeof(VertexDataNdcScreen);
96 	vertexDataDesc.dataSize			 = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
97 	vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
98 
99 	const VkVertexInputAttributeDescription vertexAttribPositionNdc =
100 	{
101 		0u,													// deUint32	location;
102 		0u,													// deUint32	binding;
103 		VK_FORMAT_R32G32B32A32_SFLOAT,						// VkFormat	format;
104 		DE_OFFSET_OF(VertexDataNdcScreen, positionNdc),		// deUint32	offset;
105 	};
106 
107 	vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
108 
109 	const VkVertexInputAttributeDescription vertexAttribPositionScreen =
110 	{
111 		1u,													// deUint32	location;
112 		0u,													// deUint32	binding;
113 		VK_FORMAT_R32G32_SFLOAT,							// VkFormat	format;
114 		DE_OFFSET_OF(VertexDataNdcScreen, positionScreen),	// deUint32	offset;
115 	};
116 
117 	vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen);
118 
119 	return vertexDataDesc;
120 }
121 
uploadVertexDataNdcScreen(const Allocation & vertexBufferAllocation,const MultisampleInstanceBase::VertexDataDesc & vertexDataDescripton,const tcu::Vec2 & screenSize)122 void uploadVertexDataNdcScreen (const Allocation& vertexBufferAllocation, const MultisampleInstanceBase::VertexDataDesc& vertexDataDescripton, const tcu::Vec2& screenSize)
123 {
124 	std::vector<VertexDataNdcScreen> vertices;
125 
126 	vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, 0.0f)));
127 	vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(screenSize.x(), 0.0f)));
128 	vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, screenSize.y())));
129 	vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f), tcu::Vec2(screenSize.x(), screenSize.y())));
130 
131 	deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
132 }
133 
checkForErrorMS(const vk::VkImageCreateInfo & imageMSInfo,const std::vector<tcu::ConstPixelBufferAccess> & dataPerSample,const deUint32 errorCompNdx)134 bool checkForErrorMS (const vk::VkImageCreateInfo& imageMSInfo, const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, const deUint32 errorCompNdx)
135 {
136 	const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
137 
138 	for (deUint32 z = 0u; z < imageMSInfo.extent.depth;  ++z)
139 	for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
140 	for (deUint32 x = 0u; x < imageMSInfo.extent.width;  ++x)
141 	{
142 		for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
143 		{
144 			const deUint32 errorComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z)[errorCompNdx];
145 
146 			if (errorComponent > 0)
147 				return true;
148 		}
149 	}
150 
151 	return false;
152 }
153 
checkForErrorRS(const vk::VkImageCreateInfo & imageRSInfo,const tcu::ConstPixelBufferAccess & dataRS,const deUint32 errorCompNdx)154 bool checkForErrorRS (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS, const deUint32 errorCompNdx)
155 {
156 	for (deUint32 z = 0u; z < imageRSInfo.extent.depth;  ++z)
157 	for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
158 	for (deUint32 x = 0u; x < imageRSInfo.extent.width;  ++x)
159 	{
160 		const deUint32 errorComponent = dataRS.getPixelUint(x, y, z)[errorCompNdx];
161 
162 		if (errorComponent > 0)
163 			return true;
164 	}
165 
166 	return false;
167 }
168 
169 template <typename CaseClassName>
170 class MSCase : public MSCaseBaseResolveAndPerSampleFetch
171 {
172 public:
MSCase(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)173 								MSCase			(tcu::TestContext&		testCtx,
174 												 const std::string&		name,
175 												 const ImageMSParams&	imageMSParams)
176 								: MSCaseBaseResolveAndPerSampleFetch(testCtx, name, imageMSParams) {}
177 
checkSupport(Context &) const178 	virtual void				checkSupport	(Context&) const {}
179 	void						init			(void);
180 	void						initPrograms	(vk::SourceCollections& programCollection) const;
181 	TestInstance*				createInstance	(Context&				context) const;
182 	static MultisampleCaseBase*	createCase		(tcu::TestContext&		testCtx,
183 												 const std::string&		name,
184 												 const ImageMSParams&	imageMSParams);
185 };
186 
187 template <typename CaseClassName>
createCase(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)188 MultisampleCaseBase* MSCase<CaseClassName>::createCase (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
189 {
190 	return new MSCase<CaseClassName>(testCtx, name, imageMSParams);
191 }
192 
193 template <typename InstanceClassName>
194 class MSInstance : public MSInstanceBaseResolveAndPerSampleFetch
195 {
196 public:
MSInstance(Context & context,const ImageMSParams & imageMSParams)197 					MSInstance				(Context&											context,
198 											 const ImageMSParams&								imageMSParams)
199 					: MSInstanceBaseResolveAndPerSampleFetch(context, imageMSParams) {}
200 
201 	VertexDataDesc	getVertexDataDescripton	(void) const;
202 	void			uploadVertexData		(const Allocation&									vertexBufferAllocation,
203 											 const VertexDataDesc&								vertexDataDescripton) const;
204 
205 	tcu::TestStatus	verifyImageData			(const vk::VkImageCreateInfo&						imageMSInfo,
206 											 const vk::VkImageCreateInfo&						imageRSInfo,
207 											 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
208 											 const tcu::ConstPixelBufferAccess&					dataRS) const;
209 };
210 
211 class MSInstanceSampleID;
212 
getVertexDataDescripton(void) const213 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleID>::getVertexDataDescripton (void) const
214 {
215 	return getVertexDataDescriptonNdc();
216 }
217 
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const218 template<> void MSInstance<MSInstanceSampleID>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
219 {
220 	uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
221 }
222 
verifyImageData(const vk::VkImageCreateInfo & imageMSInfo,const vk::VkImageCreateInfo & imageRSInfo,const std::vector<tcu::ConstPixelBufferAccess> & dataPerSample,const tcu::ConstPixelBufferAccess & dataRS) const223 template<> tcu::TestStatus MSInstance<MSInstanceSampleID>::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
224 																			 const vk::VkImageCreateInfo&						imageRSInfo,
225 																			 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
226 																			 const tcu::ConstPixelBufferAccess&					dataRS) const
227 {
228 	DE_UNREF(imageRSInfo);
229 	DE_UNREF(dataRS);
230 
231 	const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
232 
233 	for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
234 	{
235 		for (deUint32 z = 0u; z < imageMSInfo.extent.depth;  ++z)
236 		for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
237 		for (deUint32 x = 0u; x < imageMSInfo.extent.width;  ++x)
238 		{
239 			const deUint32 sampleID = dataPerSample[sampleNdx].getPixelUint(x, y, z).x();
240 
241 			if (sampleID != sampleNdx)
242 				return tcu::TestStatus::fail("gl_SampleID does not have correct value");
243 		}
244 	}
245 
246 	return tcu::TestStatus::pass("Passed");
247 }
248 
249 class MSCaseSampleID;
250 
checkSupport(Context & context) const251 template<> void MSCase<MSCaseSampleID>::checkSupport (Context& context) const
252 {
253 	if (!context.getDeviceFeatures().sampleRateShading)
254 		TCU_THROW(NotSupportedError, "sampleRateShading not supported");
255 }
256 
init(void)257 template<> void MSCase<MSCaseSampleID>::init (void)
258 {
259 	m_testCtx.getLog()
260 		<< tcu::TestLog::Message
261 		<< "Writing gl_SampleID to the red channel of the texture and verifying texture values.\n"
262 		<< "Expecting value N at sample index N of a multisample texture.\n"
263 		<< tcu::TestLog::EndMessage;
264 
265 	MultisampleCaseBase::init();
266 }
267 
initPrograms(vk::SourceCollections & programCollection) const268 template<> void MSCase<MSCaseSampleID>::initPrograms (vk::SourceCollections& programCollection) const
269 {
270 	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
271 
272 	// Create vertex shader
273 	std::ostringstream vs;
274 
275 	vs << "#version 440\n"
276 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
277 		<< "\n"
278 		<< "out gl_PerVertex {\n"
279 		<< "	vec4  gl_Position;\n"
280 		<< "};\n"
281 		<< "void main (void)\n"
282 		<< "{\n"
283 		<< "	gl_Position	= vs_in_position_ndc;\n"
284 		<< "}\n";
285 
286 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
287 
288 	// Create fragment shader
289 	std::ostringstream fs;
290 
291 	fs << "#version 440\n"
292 		<< "\n"
293 		<< "layout(location = 0) out vec4 fs_out_color;\n"
294 		<< "\n"
295 		<< "void main (void)\n"
296 		<< "{\n"
297 		<< "	fs_out_color = vec4(float(gl_SampleID) / float(255), 0.0, 0.0, 1.0);\n"
298 		<< "}\n";
299 
300 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
301 }
302 
createInstance(Context & context) const303 template<> TestInstance* MSCase<MSCaseSampleID>::createInstance (Context& context) const
304 {
305 	return new MSInstance<MSInstanceSampleID>(context, m_imageMSParams);
306 }
307 
308 class MSInstanceSamplePosDistribution;
309 
getVertexDataDescripton(void) const310 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSamplePosDistribution>::getVertexDataDescripton (void) const
311 {
312 	return getVertexDataDescriptonNdc();
313 }
314 
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const315 template<> void MSInstance<MSInstanceSamplePosDistribution>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
316 {
317 	uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
318 }
319 
verifyImageData(const vk::VkImageCreateInfo & imageMSInfo,const vk::VkImageCreateInfo & imageRSInfo,const std::vector<tcu::ConstPixelBufferAccess> & dataPerSample,const tcu::ConstPixelBufferAccess & dataRS) const320 template<> tcu::TestStatus MSInstance<MSInstanceSamplePosDistribution>::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
321 																						 const vk::VkImageCreateInfo&						imageRSInfo,
322 																						 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
323 																						 const tcu::ConstPixelBufferAccess&					dataRS) const
324 {
325 	const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
326 
327 	// approximate Bates distribution as normal
328 	const float variance = (1.0f / (12.0f * (float)numSamples));
329 	const float standardDeviation = deFloatSqrt(variance);
330 
331 	// 95% of means of sample positions are within 2 standard deviations if
332 	// they were randomly assigned. Sample patterns are expected to be more
333 	// uniform than a random pattern.
334 	const float distanceThreshold = 2.0f * standardDeviation;
335 
336 	for (deUint32 z = 0u; z < imageRSInfo.extent.depth;  ++z)
337 	for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
338 	for (deUint32 x = 0u; x < imageRSInfo.extent.width;  ++x)
339 	{
340 		const deUint32 errorComponent = dataRS.getPixelUint(x, y, z).z();
341 
342 		if (errorComponent > 0)
343 			return tcu::TestStatus::fail("gl_SamplePosition is not within interval [0,1]");
344 
345 		if (numSamples >= VK_SAMPLE_COUNT_4_BIT)
346 		{
347 			const tcu::Vec2 averageSamplePos	= tcu::Vec2((float)dataRS.getPixelUint(x, y, z).x() / 255.0f, (float)dataRS.getPixelUint(x, y, z).y() / 255.0f);
348 			const tcu::Vec2	distanceFromCenter	= tcu::abs(averageSamplePos - tcu::Vec2(0.5f, 0.5f));
349 
350 			if (distanceFromCenter.x() > distanceThreshold || distanceFromCenter.y() > distanceThreshold)
351 				return tcu::TestStatus::fail("Sample positions are not uniformly distributed within the pixel");
352 		}
353 	}
354 
355 	for (deUint32 z = 0u; z < imageMSInfo.extent.depth;  ++z)
356 	for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
357 	for (deUint32 x = 0u; x < imageMSInfo.extent.width;  ++x)
358 	{
359 		std::vector<tcu::Vec2> samplePositions(numSamples);
360 
361 		for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
362 		{
363 			const deUint32 errorComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z).z();
364 
365 			if (errorComponent > 0)
366 				return tcu::TestStatus::fail("gl_SamplePosition is not within interval [0,1]");
367 
368 			samplePositions[sampleNdx] = tcu::Vec2( (float)dataPerSample[sampleNdx].getPixelUint(x, y, z).x() / 255.0f,
369 													(float)dataPerSample[sampleNdx].getPixelUint(x, y, z).y() / 255.0f);
370 		}
371 
372 		for (deUint32 sampleNdxA = 0u;				sampleNdxA < numSamples; ++sampleNdxA)
373 		for (deUint32 sampleNdxB = sampleNdxA + 1u; sampleNdxB < numSamples; ++sampleNdxB)
374 		{
375 			if (samplePositions[sampleNdxA] == samplePositions[sampleNdxB])
376 				return tcu::TestStatus::fail("Two samples have the same position");
377 		}
378 
379 		if (numSamples >= VK_SAMPLE_COUNT_4_BIT)
380 		{
381 			tcu::Vec2 averageSamplePos(0.0f, 0.0f);
382 
383 			for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
384 			{
385 				averageSamplePos.x() += samplePositions[sampleNdx].x();
386 				averageSamplePos.y() += samplePositions[sampleNdx].y();
387 			}
388 
389 			averageSamplePos.x() /= (float)numSamples;
390 			averageSamplePos.y() /= (float)numSamples;
391 
392 			const tcu::Vec2	distanceFromCenter = tcu::abs(averageSamplePos - tcu::Vec2(0.5f, 0.5f));
393 
394 			if (distanceFromCenter.x() > distanceThreshold || distanceFromCenter.y() > distanceThreshold)
395 				return tcu::TestStatus::fail("Sample positions are not uniformly distributed within the pixel");
396 		}
397 	}
398 
399 	return tcu::TestStatus::pass("Passed");
400 }
401 
402 class MSCaseSamplePosDistribution;
403 
checkSupport(Context & context) const404 template<> void MSCase<MSCaseSamplePosDistribution>::checkSupport (Context& context) const
405 {
406 	if (!context.getDeviceFeatures().sampleRateShading)
407 		TCU_THROW(NotSupportedError, "sampleRateShading not supported");
408 }
409 
init(void)410 template<> void MSCase<MSCaseSamplePosDistribution>::init (void)
411 {
412 	m_testCtx.getLog()
413 		<< tcu::TestLog::Message
414 		<< "Verifying gl_SamplePosition value with multisample targets:\n"
415 		<< "	a) Expect legal sample position.\n"
416 		<< "	b) Sample position is unique within the set of all sample positions of a pixel.\n"
417 		<< "	c) Sample position distribution is uniform or almost uniform.\n"
418 		<< tcu::TestLog::EndMessage;
419 
420 	MultisampleCaseBase::init();
421 }
422 
initPrograms(vk::SourceCollections & programCollection) const423 template<> void MSCase<MSCaseSamplePosDistribution>::initPrograms (vk::SourceCollections& programCollection) const
424 {
425 	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
426 
427 	// Create vertex shader
428 	std::ostringstream vs;
429 
430 	vs << "#version 440\n"
431 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
432 		<< "\n"
433 		<< "out gl_PerVertex {\n"
434 		<< "	vec4  gl_Position;\n"
435 		<< "};\n"
436 		<< "void main (void)\n"
437 		<< "{\n"
438 		<< "	gl_Position	= vs_in_position_ndc;\n"
439 		<< "}\n";
440 
441 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
442 
443 	// Create fragment shader
444 	std::ostringstream fs;
445 
446 	fs << "#version 440\n"
447 		<< "\n"
448 		<< "layout(location = 0) out vec4 fs_out_color;\n"
449 		<< "\n"
450 		<< "void main (void)\n"
451 		<< "{\n"
452 		<< "	if (gl_SamplePosition.x < 0.0 || gl_SamplePosition.x > 1.0 || gl_SamplePosition.y < 0.0 || gl_SamplePosition.y > 1.0)\n"
453 		"		fs_out_color = vec4(0.0, 0.0, 1.0, 1.0);\n"
454 		"	else\n"
455 		"		fs_out_color = vec4(gl_SamplePosition.x, gl_SamplePosition.y, 0.0, 1.0);\n"
456 		"}\n";
457 
458 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
459 }
460 
createInstance(Context & context) const461 template<> TestInstance* MSCase<MSCaseSamplePosDistribution>::createInstance (Context& context) const
462 {
463 	return new MSInstance<MSInstanceSamplePosDistribution>(context, m_imageMSParams);
464 }
465 
466 class MSInstanceSamplePosCorrectness;
467 
getVertexDataDescripton(void) const468 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSamplePosCorrectness>::getVertexDataDescripton (void) const
469 {
470 	return getVertexDataDescriptonNdcScreen();
471 }
472 
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const473 template<> void MSInstance<MSInstanceSamplePosCorrectness>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
474 {
475 	const tcu::UVec3 layerSize = getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize);
476 
477 	uploadVertexDataNdcScreen(vertexBufferAllocation, vertexDataDescripton, tcu::Vec2(static_cast<float>(layerSize.x()), static_cast<float>(layerSize.y())));
478 }
479 
verifyImageData(const vk::VkImageCreateInfo & imageMSInfo,const vk::VkImageCreateInfo & imageRSInfo,const std::vector<tcu::ConstPixelBufferAccess> & dataPerSample,const tcu::ConstPixelBufferAccess & dataRS) const480 template<> tcu::TestStatus MSInstance<MSInstanceSamplePosCorrectness>::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
481 																						 const vk::VkImageCreateInfo&						imageRSInfo,
482 																						 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
483 																						 const tcu::ConstPixelBufferAccess&					dataRS) const
484 {
485 	if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
486 		return tcu::TestStatus::fail("Varying values are not sampled at gl_SamplePosition");
487 
488 	if (checkForErrorRS(imageRSInfo, dataRS, 0))
489 		return tcu::TestStatus::fail("Varying values are not sampled at gl_SamplePosition");
490 
491 	return tcu::TestStatus::pass("Passed");
492 }
493 
494 class MSCaseSamplePosCorrectness;
495 
checkSupport(Context & context) const496 template<> void MSCase<MSCaseSamplePosCorrectness>::checkSupport (Context& context) const
497 {
498 	if (!context.getDeviceFeatures().sampleRateShading)
499 		TCU_THROW(NotSupportedError, "sampleRateShading not supported");
500 }
501 
init(void)502 template<> void MSCase<MSCaseSamplePosCorrectness>::init (void)
503 {
504 	m_testCtx.getLog()
505 		<< tcu::TestLog::Message
506 		<< "Verifying gl_SamplePosition correctness:\n"
507 		<< "	1) Varying values should be sampled at the sample position.\n"
508 		<< "		=> fract(position_screen) == gl_SamplePosition\n"
509 		<< tcu::TestLog::EndMessage;
510 
511 	MultisampleCaseBase::init();
512 }
513 
initPrograms(vk::SourceCollections & programCollection) const514 template<> void MSCase<MSCaseSamplePosCorrectness>::initPrograms (vk::SourceCollections& programCollection) const
515 {
516 	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
517 
518 	// Create vertex shaders
519 	std::ostringstream vs;
520 
521 	vs	<< "#version 440\n"
522 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
523 		<< "layout(location = 1) in vec2 vs_in_position_screen;\n"
524 		<< "\n"
525 		<< "layout(location = 0) sample out vec2 vs_out_position_screen;\n"
526 		<< "\n"
527 		<< "out gl_PerVertex {\n"
528 		<< "	vec4  gl_Position;\n"
529 		<< "};\n"
530 		<< "void main (void)\n"
531 		<< "{\n"
532 		<< "	gl_Position				= vs_in_position_ndc;\n"
533 		<< "	vs_out_position_screen	= vs_in_position_screen;\n"
534 		<< "}\n";
535 
536 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
537 
538 	// Create fragment shader
539 	std::ostringstream fs;
540 
541 	fs	<< "#version 440\n"
542 		<< "layout(location = 0) sample in vec2 fs_in_position_screen;\n"
543 		<< "\n"
544 		<< "layout(location = 0) out vec4 fs_out_color;\n"
545 		<< "\n"
546 		<< "void main (void)\n"
547 		<< "{\n"
548 		<< "	const float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n"
549 		<< "	const ivec2 nearby_pixel = ivec2(floor(fs_in_position_screen));\n"
550 		<< "	bool ok	= false;\n"
551 		<< "\n"
552 		<< "	// sample at edge + inaccuaries may cause us to round to any neighboring pixel\n"
553 		<< "	// check all neighbors for any match\n"
554 		<< "	for (int dy = -1; dy <= 1; ++dy)\n"
555 		<< "	for (int dx = -1; dx <= 1; ++dx)\n"
556 		<< "	{\n"
557 		<< "		ivec2 current_pixel			= nearby_pixel + ivec2(dx, dy);\n"
558 		<< "		vec2 position_inside_pixel	= vec2(current_pixel) + gl_SamplePosition;\n"
559 		<< "		vec2 position_diff			= abs(position_inside_pixel - fs_in_position_screen);\n"
560 		<< "\n"
561 		<< "		if (all(lessThan(position_diff, vec2(threshold))))\n"
562 		<< "			ok = true;\n"
563 		<< "	}\n"
564 		<< "\n"
565 		<< "	if (ok)\n"
566 		<< "		fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
567 		<< "	else\n"
568 		<< "		fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
569 		<< "}\n";
570 
571 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
572 }
573 
createInstance(Context & context) const574 template<> TestInstance* MSCase<MSCaseSamplePosCorrectness>::createInstance (Context& context) const
575 {
576 	return new MSInstance<MSInstanceSamplePosCorrectness>(context, m_imageMSParams);
577 }
578 
579 class MSInstanceSampleMaskPattern : public MSInstanceBaseResolveAndPerSampleFetch
580 {
581 public:
582 											MSInstanceSampleMaskPattern	(Context&											context,
583 																		 const ImageMSParams&								imageMSParams);
584 
585 	VkPipelineMultisampleStateCreateInfo	getMSStateCreateInfo		(const ImageMSParams&								imageMSParams) const;
586 
587 	const VkDescriptorSetLayout*			createMSPassDescSetLayout	(const ImageMSParams&								imageMSParams);
588 
589 	const VkDescriptorSet*					createMSPassDescSet			(const ImageMSParams&								imageMSParams,
590 																		 const VkDescriptorSetLayout*						descSetLayout);
591 
592 	VertexDataDesc							getVertexDataDescripton		(void) const;
593 
594 	void									uploadVertexData			(const Allocation&									vertexBufferAllocation,
595 																		 const VertexDataDesc&								vertexDataDescripton) const;
596 
597 	tcu::TestStatus							verifyImageData				(const vk::VkImageCreateInfo&						imageMSInfo,
598 																		 const vk::VkImageCreateInfo&						imageRSInfo,
599 																		 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
600 																		 const tcu::ConstPixelBufferAccess&					dataRS) const;
601 protected:
602 
603 	VkSampleMask				m_sampleMask;
604 	Move<VkDescriptorSetLayout>	m_descriptorSetLayout;
605 	Move<VkDescriptorPool>		m_descriptorPool;
606 	Move<VkDescriptorSet>		m_descriptorSet;
607 	de::MovePtr<Buffer>			m_buffer;
608 };
609 
MSInstanceSampleMaskPattern(Context & context,const ImageMSParams & imageMSParams)610 MSInstanceSampleMaskPattern::MSInstanceSampleMaskPattern (Context& context, const ImageMSParams& imageMSParams) : MSInstanceBaseResolveAndPerSampleFetch(context, imageMSParams)
611 {
612 	m_sampleMask = 0xAAAAAAAAu & ((1u << imageMSParams.numSamples) - 1u);
613 }
614 
getMSStateCreateInfo(const ImageMSParams & imageMSParams) const615 VkPipelineMultisampleStateCreateInfo MSInstanceSampleMaskPattern::getMSStateCreateInfo (const ImageMSParams& imageMSParams) const
616 {
617 	const VkPipelineMultisampleStateCreateInfo multisampleStateInfo =
618 	{
619 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
620 		DE_NULL,														// const void*								pNext;
621 		(VkPipelineMultisampleStateCreateFlags)0u,						// VkPipelineMultisampleStateCreateFlags	flags;
622 		imageMSParams.numSamples,										// VkSampleCountFlagBits					rasterizationSamples;
623 		VK_FALSE,														// VkBool32									sampleShadingEnable;
624 		1.0f,															// float									minSampleShading;
625 		&m_sampleMask,													// const VkSampleMask*						pSampleMask;
626 		VK_FALSE,														// VkBool32									alphaToCoverageEnable;
627 		VK_FALSE,														// VkBool32									alphaToOneEnable;
628 	};
629 
630 	return multisampleStateInfo;
631 }
632 
createMSPassDescSetLayout(const ImageMSParams & imageMSParams)633 const VkDescriptorSetLayout* MSInstanceSampleMaskPattern::createMSPassDescSetLayout (const ImageMSParams& imageMSParams)
634 {
635 	DE_UNREF(imageMSParams);
636 
637 	const DeviceInterface&		deviceInterface = m_context.getDeviceInterface();
638 	const VkDevice				device			= m_context.getDevice();
639 
640 	// Create descriptor set layout
641 	m_descriptorSetLayout = DescriptorSetLayoutBuilder()
642 		.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
643 		.build(deviceInterface, device);
644 
645 	return &m_descriptorSetLayout.get();
646 }
647 
createMSPassDescSet(const ImageMSParams & imageMSParams,const VkDescriptorSetLayout * descSetLayout)648 const VkDescriptorSet* MSInstanceSampleMaskPattern::createMSPassDescSet (const ImageMSParams& imageMSParams, const VkDescriptorSetLayout* descSetLayout)
649 {
650 	DE_UNREF(imageMSParams);
651 
652 	const DeviceInterface&		deviceInterface = m_context.getDeviceInterface();
653 	const VkDevice				device			= m_context.getDevice();
654 	Allocator&					allocator		= m_context.getDefaultAllocator();
655 
656 	// Create descriptor pool
657 	m_descriptorPool = DescriptorPoolBuilder()
658 		.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u)
659 		.build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
660 
661 	// Create descriptor set
662 	m_descriptorSet = makeDescriptorSet(deviceInterface, device, *m_descriptorPool, *descSetLayout);
663 
664 	const VkBufferCreateInfo bufferSampleMaskInfo = makeBufferCreateInfo(sizeof(VkSampleMask), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
665 
666 	m_buffer = de::MovePtr<Buffer>(new Buffer(deviceInterface, device, allocator, bufferSampleMaskInfo, MemoryRequirement::HostVisible));
667 
668 	deMemcpy(m_buffer->getAllocation().getHostPtr(), &m_sampleMask, sizeof(VkSampleMask));
669 
670 	flushAlloc(deviceInterface, device, m_buffer->getAllocation());
671 
672 	const VkDescriptorBufferInfo descBufferInfo = makeDescriptorBufferInfo(**m_buffer, 0u, sizeof(VkSampleMask));
673 
674 	DescriptorSetUpdateBuilder()
675 		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descBufferInfo)
676 		.update(deviceInterface, device);
677 
678 	return &m_descriptorSet.get();
679 }
680 
getVertexDataDescripton(void) const681 MultisampleInstanceBase::VertexDataDesc MSInstanceSampleMaskPattern::getVertexDataDescripton (void) const
682 {
683 	return getVertexDataDescriptonNdc();
684 }
685 
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const686 void MSInstanceSampleMaskPattern::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
687 {
688 	uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
689 }
690 
verifyImageData(const vk::VkImageCreateInfo & imageMSInfo,const vk::VkImageCreateInfo & imageRSInfo,const std::vector<tcu::ConstPixelBufferAccess> & dataPerSample,const tcu::ConstPixelBufferAccess & dataRS) const691 tcu::TestStatus	MSInstanceSampleMaskPattern::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
692 																 const vk::VkImageCreateInfo&						imageRSInfo,
693 																 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
694 																 const tcu::ConstPixelBufferAccess&					dataRS) const
695 {
696 	DE_UNREF(imageRSInfo);
697 	DE_UNREF(dataRS);
698 
699 	if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
700 		return tcu::TestStatus::fail("gl_SampleMaskIn bits have not been killed by pSampleMask state");
701 
702 	return tcu::TestStatus::pass("Passed");
703 }
704 
705 class MSCaseSampleMaskPattern;
706 
init(void)707 template<> void MSCase<MSCaseSampleMaskPattern>::init (void)
708 {
709 	m_testCtx.getLog()
710 		<< tcu::TestLog::Message
711 		<< "Verifying gl_SampleMaskIn value with pSampleMask state. gl_SampleMaskIn does not contain any bits set that are have been killed by pSampleMask state. Expecting:\n"
712 		<< "Expected result: gl_SampleMaskIn AND ~(pSampleMask) should be zero.\n"
713 		<< tcu::TestLog::EndMessage;
714 
715 	MultisampleCaseBase::init();
716 }
717 
initPrograms(vk::SourceCollections & programCollection) const718 template<> void MSCase<MSCaseSampleMaskPattern>::initPrograms (vk::SourceCollections& programCollection) const
719 {
720 	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
721 
722 	// Create vertex shader
723 	std::ostringstream vs;
724 
725 	vs << "#version 440\n"
726 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
727 		<< "\n"
728 		<< "out gl_PerVertex {\n"
729 		<< "	vec4  gl_Position;\n"
730 		<< "};\n"
731 		<< "void main (void)\n"
732 		<< "{\n"
733 		<< "	gl_Position	= vs_in_position_ndc;\n"
734 		<< "}\n";
735 
736 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
737 
738 	// Create fragment shader
739 	std::ostringstream fs;
740 
741 	fs << "#version 440\n"
742 		<< "\n"
743 		<< "layout(location = 0) out vec4 fs_out_color;\n"
744 		<< "\n"
745 		<< "layout(set = 0, binding = 0, std140) uniform SampleMaskBlock\n"
746 		<< "{\n"
747 		<< "	int sampleMaskPattern;\n"
748 		<< "};"
749 		<< "\n"
750 		<< "void main (void)\n"
751 		<< "{\n"
752 		<< "	if ((gl_SampleMaskIn[0] & ~sampleMaskPattern) != 0)\n"
753 		<< "		fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
754 		<< "	else\n"
755 		<< "		fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
756 		<< "}\n";
757 
758 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
759 }
760 
createInstance(Context & context) const761 template<> TestInstance* MSCase<MSCaseSampleMaskPattern>::createInstance (Context& context) const
762 {
763 	return new MSInstanceSampleMaskPattern(context, m_imageMSParams);
764 }
765 
766 class MSInstanceSampleMaskBitCount;
767 
getVertexDataDescripton(void) const768 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskBitCount>::getVertexDataDescripton (void) const
769 {
770 	return getVertexDataDescriptonNdc();
771 }
772 
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const773 template<> void MSInstance<MSInstanceSampleMaskBitCount>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
774 {
775 	uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
776 }
777 
verifyImageData(const vk::VkImageCreateInfo & imageMSInfo,const vk::VkImageCreateInfo & imageRSInfo,const std::vector<tcu::ConstPixelBufferAccess> & dataPerSample,const tcu::ConstPixelBufferAccess & dataRS) const778 template<> tcu::TestStatus MSInstance<MSInstanceSampleMaskBitCount>::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
779 																						 const vk::VkImageCreateInfo&						imageRSInfo,
780 																						 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
781 																						 const tcu::ConstPixelBufferAccess&					dataRS) const
782 {
783 	DE_UNREF(imageRSInfo);
784 	DE_UNREF(dataRS);
785 
786 	if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
787 		return tcu::TestStatus::fail("gl_SampleMaskIn has more than one bit set for some shader invocations");
788 
789 	return tcu::TestStatus::pass("Passed");
790 }
791 
792 class MSCaseSampleMaskBitCount;
793 
checkSupport(Context & context) const794 template<> void MSCase<MSCaseSampleMaskBitCount>::checkSupport (Context& context) const
795 {
796 	if (!context.getDeviceFeatures().sampleRateShading)
797 		TCU_THROW(NotSupportedError, "sampleRateShading not supported");
798 }
799 
init(void)800 template<> void MSCase<MSCaseSampleMaskBitCount>::init (void)
801 {
802 	m_testCtx.getLog()
803 		<< tcu::TestLog::Message
804 		<< "Verifying gl_SampleMaskIn.\n"
805 		<< "	Fragment shader will be invoked numSamples times.\n"
806 		<< "	=> gl_SampleMaskIn should have only one bit set for each shader invocation.\n"
807 		<< tcu::TestLog::EndMessage;
808 
809 	MultisampleCaseBase::init();
810 }
811 
initPrograms(vk::SourceCollections & programCollection) const812 template<> void MSCase<MSCaseSampleMaskBitCount>::initPrograms (vk::SourceCollections& programCollection) const
813 {
814 	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
815 
816 	// Create vertex shader
817 	std::ostringstream vs;
818 
819 	vs << "#version 440\n"
820 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
821 		<< "\n"
822 		<< "out gl_PerVertex {\n"
823 		<< "	vec4  gl_Position;\n"
824 		<< "};\n"
825 		<< "void main (void)\n"
826 		<< "{\n"
827 		<< "	gl_Position	= vs_in_position_ndc;\n"
828 		<< "}\n";
829 
830 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
831 
832 	// Create fragment shader
833 	std::ostringstream fs;
834 
835 	fs << "#version 440\n"
836 		<< "\n"
837 		<< "layout(location = 0) out vec4 fs_out_color;\n"
838 		<< "\n"
839 		<< "void main (void)\n"
840 		<< "{\n"
841 		<< "	uint maskBitCount = 0u;\n"
842 		<< "\n"
843 		<< "	for (int i = 0; i < 32; ++i)\n"
844 		<< "		if (((gl_SampleMaskIn[0] >> i) & 0x01) == 0x01)\n"
845 		<< "			++maskBitCount;\n"
846 		<< "\n"
847 		<< "	if (maskBitCount != 1u)\n"
848 		<< "		fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
849 		<< "	else\n"
850 		<< "		fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
851 		<< "}\n";
852 
853 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
854 }
855 
createInstance(Context & context) const856 template<> TestInstance* MSCase<MSCaseSampleMaskBitCount>::createInstance (Context& context) const
857 {
858 	return new MSInstance<MSInstanceSampleMaskBitCount>(context, m_imageMSParams);
859 }
860 
861 class MSInstanceSampleMaskCorrectBit;
862 
getVertexDataDescripton(void) const863 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskCorrectBit>::getVertexDataDescripton (void) const
864 {
865 	return getVertexDataDescriptonNdc();
866 }
867 
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const868 template<> void MSInstance<MSInstanceSampleMaskCorrectBit>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
869 {
870 	uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
871 }
872 
verifyImageData(const vk::VkImageCreateInfo & imageMSInfo,const vk::VkImageCreateInfo & imageRSInfo,const std::vector<tcu::ConstPixelBufferAccess> & dataPerSample,const tcu::ConstPixelBufferAccess & dataRS) const873 template<> tcu::TestStatus MSInstance<MSInstanceSampleMaskCorrectBit>::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
874 																						 const vk::VkImageCreateInfo&						imageRSInfo,
875 																						 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
876 																						 const tcu::ConstPixelBufferAccess&					dataRS) const
877 {
878 	DE_UNREF(imageRSInfo);
879 	DE_UNREF(dataRS);
880 
881 	if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
882 		return tcu::TestStatus::fail("The bit corresponsing to current gl_SampleID is not set in gl_SampleMaskIn");
883 
884 	return tcu::TestStatus::pass("Passed");
885 }
886 
887 class MSCaseSampleMaskCorrectBit;
888 
checkSupport(Context & context) const889 template<> void MSCase<MSCaseSampleMaskCorrectBit>::checkSupport (Context& context) const
890 {
891 	if (!context.getDeviceFeatures().sampleRateShading)
892 		TCU_THROW(NotSupportedError, "sampleRateShading not supported");
893 }
894 
init(void)895 template<> void MSCase<MSCaseSampleMaskCorrectBit>::init (void)
896 {
897 	m_testCtx.getLog()
898 		<< tcu::TestLog::Message
899 		<< "Verifying gl_SampleMaskIn.\n"
900 		<< "	Fragment shader will be invoked numSamples times.\n"
901 		<< "	=> In each invocation gl_SampleMaskIn should have the bit set that corresponds to gl_SampleID.\n"
902 		<< tcu::TestLog::EndMessage;
903 
904 	MultisampleCaseBase::init();
905 }
906 
initPrograms(vk::SourceCollections & programCollection) const907 template<> void MSCase<MSCaseSampleMaskCorrectBit>::initPrograms (vk::SourceCollections& programCollection) const
908 {
909 	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
910 
911 	// Create vertex shader
912 	std::ostringstream vs;
913 
914 	vs << "#version 440\n"
915 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
916 		<< "\n"
917 		<< "out gl_PerVertex {\n"
918 		<< "	vec4  gl_Position;\n"
919 		<< "};\n"
920 		<< "void main (void)\n"
921 		<< "{\n"
922 		<< "	gl_Position	= vs_in_position_ndc;\n"
923 		<< "}\n";
924 
925 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
926 
927 	// Create fragment shader
928 	std::ostringstream fs;
929 
930 	fs << "#version 440\n"
931 		<< "\n"
932 		<< "layout(location = 0) out vec4 fs_out_color;\n"
933 		<< "\n"
934 		<< "void main (void)\n"
935 		<< "{\n"
936 		<< "	if (((gl_SampleMaskIn[0] >> gl_SampleID) & 0x01) == 0x01)\n"
937 		<< "		fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
938 		<< "	else\n"
939 		<< "		fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
940 		<< "}\n";
941 
942 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
943 }
944 
createInstance(Context & context) const945 template<> TestInstance* MSCase<MSCaseSampleMaskCorrectBit>::createInstance (Context& context) const
946 {
947 	return new MSInstance<MSInstanceSampleMaskCorrectBit>(context, m_imageMSParams);
948 }
949 
950 class MSInstanceSampleMaskWrite;
951 
getVertexDataDescripton(void) const952 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskWrite>::getVertexDataDescripton (void) const
953 {
954 	return getVertexDataDescriptonNdc();
955 }
956 
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const957 template<> void MSInstance<MSInstanceSampleMaskWrite>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
958 {
959 	uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
960 }
961 
verifyImageData(const vk::VkImageCreateInfo & imageMSInfo,const vk::VkImageCreateInfo & imageRSInfo,const std::vector<tcu::ConstPixelBufferAccess> & dataPerSample,const tcu::ConstPixelBufferAccess & dataRS) const962 template<> tcu::TestStatus MSInstance<MSInstanceSampleMaskWrite>::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
963 																					 const vk::VkImageCreateInfo&						imageRSInfo,
964 																					 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
965 																					 const tcu::ConstPixelBufferAccess&					dataRS) const
966 {
967 	const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
968 
969 	for (deUint32 z = 0u; z < imageMSInfo.extent.depth;  ++z)
970 	for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
971 	for (deUint32 x = 0u; x < imageMSInfo.extent.width;  ++x)
972 	{
973 		for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
974 		{
975 			const deUint32 firstComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z)[0];
976 
977 			if (firstComponent != 0u && firstComponent != 255u)
978 				return tcu::TestStatus::fail("Expected color to be zero or saturated on the first channel");
979 		}
980 	}
981 
982 	for (deUint32 z = 0u; z < imageRSInfo.extent.depth;  ++z)
983 	for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
984 	for (deUint32 x = 0u; x < imageRSInfo.extent.width;  ++x)
985 	{
986 		const float firstComponent = dataRS.getPixel(x, y, z)[0];
987 
988 		if (deFloatAbs(firstComponent - 0.5f) > 0.02f)
989 			return tcu::TestStatus::fail("Expected resolve color to be half intensity on the first channel");
990 	}
991 
992 	return tcu::TestStatus::pass("Passed");
993 }
994 
995 class MSCaseSampleMaskWrite;
996 
checkSupport(Context & context) const997 template<> void MSCase<MSCaseSampleMaskWrite>::checkSupport (Context& context) const
998 {
999 	if (!context.getDeviceFeatures().sampleRateShading)
1000 		TCU_THROW(NotSupportedError, "sampleRateShading not supported");
1001 }
1002 
init(void)1003 template<> void MSCase<MSCaseSampleMaskWrite>::init (void)
1004 {
1005 	m_testCtx.getLog()
1006 		<< tcu::TestLog::Message
1007 		<< "Discarding half of the samples using gl_SampleMask."
1008 		<< "Expecting half intensity on multisample targets (numSamples > 1)\n"
1009 		<< tcu::TestLog::EndMessage;
1010 
1011 	MultisampleCaseBase::init();
1012 }
1013 
initPrograms(vk::SourceCollections & programCollection) const1014 template<> void MSCase<MSCaseSampleMaskWrite>::initPrograms (vk::SourceCollections& programCollection) const
1015 {
1016 	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
1017 
1018 	// Create vertex shader
1019 	std::ostringstream vs;
1020 
1021 	vs << "#version 440\n"
1022 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1023 		<< "\n"
1024 		<< "out gl_PerVertex {\n"
1025 		<< "	vec4  gl_Position;\n"
1026 		<< "};\n"
1027 		<< "void main (void)\n"
1028 		<< "{\n"
1029 		<< "	gl_Position	= vs_in_position_ndc;\n"
1030 		<< "}\n";
1031 
1032 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1033 
1034 	// Create fragment shader
1035 	std::ostringstream fs;
1036 
1037 	fs << "#version 440\n"
1038 		<< "\n"
1039 		<< "layout(location = 0) out vec4 fs_out_color;\n"
1040 		<< "\n"
1041 		<< "void main (void)\n"
1042 		<< "{\n"
1043 		<< "	gl_SampleMask[0] = 0xAAAAAAAA;\n"
1044 		<< "\n"
1045 		<< "	fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1046 		<< "}\n";
1047 
1048 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1049 }
1050 
createInstance(Context & context) const1051 template<> TestInstance* MSCase<MSCaseSampleMaskWrite>::createInstance (Context& context) const
1052 {
1053 	return new MSInstance<MSInstanceSampleMaskWrite>(context, m_imageMSParams);
1054 }
1055 
1056 } // multisample
1057 
createMultisampleShaderBuiltInTests(tcu::TestContext & testCtx)1058 tcu::TestCaseGroup* createMultisampleShaderBuiltInTests (tcu::TestContext& testCtx)
1059 {
1060 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "multisample_shader_builtin", "Multisample Shader BuiltIn Tests"));
1061 
1062 	const tcu::UVec3 imageSizes[] =
1063 	{
1064 		tcu::UVec3(128u, 128u, 1u),
1065 		tcu::UVec3(137u, 191u, 1u),
1066 	};
1067 
1068 	const deUint32 sizesElemCount = static_cast<deUint32>(sizeof(imageSizes) / sizeof(tcu::UVec3));
1069 
1070 	const vk::VkSampleCountFlagBits samplesSetFull[] =
1071 	{
1072 		vk::VK_SAMPLE_COUNT_2_BIT,
1073 		vk::VK_SAMPLE_COUNT_4_BIT,
1074 		vk::VK_SAMPLE_COUNT_8_BIT,
1075 		vk::VK_SAMPLE_COUNT_16_BIT,
1076 		vk::VK_SAMPLE_COUNT_32_BIT,
1077 		vk::VK_SAMPLE_COUNT_64_BIT,
1078 	};
1079 
1080 	const deUint32 samplesSetFullCount = static_cast<deUint32>(sizeof(samplesSetFull) / sizeof(vk::VkSampleCountFlagBits));
1081 
1082 	testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleID> >(testCtx, "sample_id", imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount));
1083 
1084 	de::MovePtr<tcu::TestCaseGroup> samplePositionGroup(new tcu::TestCaseGroup(testCtx, "sample_position", "Sample Position Tests"));
1085 
1086 	samplePositionGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSamplePosDistribution> >(testCtx, "distribution", imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount));
1087 	samplePositionGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSamplePosCorrectness> > (testCtx, "correctness",  imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount));
1088 
1089 	testGroup->addChild(samplePositionGroup.release());
1090 
1091 	const vk::VkSampleCountFlagBits samplesSetReduced[] =
1092 	{
1093 		vk::VK_SAMPLE_COUNT_2_BIT,
1094 		vk::VK_SAMPLE_COUNT_4_BIT,
1095 		vk::VK_SAMPLE_COUNT_8_BIT,
1096 		vk::VK_SAMPLE_COUNT_16_BIT,
1097 		vk::VK_SAMPLE_COUNT_32_BIT,
1098 	};
1099 
1100 	const deUint32 samplesSetReducedCount = static_cast<deUint32>(sizeof(samplesSetReduced) / sizeof(vk::VkSampleCountFlagBits));
1101 
1102 	de::MovePtr<tcu::TestCaseGroup> sampleMaskGroup(new tcu::TestCaseGroup(testCtx, "sample_mask", "Sample Mask Tests"));
1103 
1104 	sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskPattern> >	(testCtx, "pattern",	imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
1105 	sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskBitCount> >	(testCtx, "bit_count",	imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
1106 	sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskCorrectBit> >(testCtx, "correct_bit",imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
1107 	sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskWrite> >		(testCtx, "write",		imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
1108 
1109 	testGroup->addChild(sampleMaskGroup.release());
1110 
1111 	return testGroup.release();
1112 }
1113 
1114 } // pipeline
1115 } // vkt
1116