1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2023 LunarG, Inc.
7 * Copyright (c) 2023 Nintendo
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*
22 * \file vktPipelineMultisampleShaderBuiltInTests.cpp
23 * \brief Multisample Shader BuiltIn Tests
24 *//*--------------------------------------------------------------------*/
25 
26 #include "vktPipelineMultisampleShaderBuiltInTests.hpp"
27 #include "vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp"
28 #include "vktPipelineMakeUtil.hpp"
29 
30 #include "vkBuilderUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkImageWithMemory.hpp"
34 #include "vkBufferWithMemory.hpp"
35 #include "vkBarrierUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 
39 #include "tcuVectorUtil.hpp"
40 #include "tcuTestLog.hpp"
41 
42 #include <set>
43 #include <cmath>
44 
45 using std::set;
46 
47 namespace vkt
48 {
49 namespace pipeline
50 {
51 namespace multisample
52 {
53 
54 using namespace vk;
55 
56 struct VertexDataNdc
57 {
VertexDataNdcvkt::pipeline::multisample::VertexDataNdc58 	VertexDataNdc (const tcu::Vec4& posNdc) : positionNdc(posNdc) {}
59 
60 	tcu::Vec4 positionNdc;
61 };
62 
getVertexDataDescriptonNdc(void)63 MultisampleInstanceBase::VertexDataDesc getVertexDataDescriptonNdc (void)
64 {
65 	MultisampleInstanceBase::VertexDataDesc vertexDataDesc;
66 
67 	vertexDataDesc.verticesCount	 = 4u;
68 	vertexDataDesc.dataStride		 = sizeof(VertexDataNdc);
69 	vertexDataDesc.dataSize			 = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
70 	vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
71 
72 	const VkVertexInputAttributeDescription vertexAttribPositionNdc =
73 	{
74 		0u,											// deUint32	location;
75 		0u,											// deUint32	binding;
76 		VK_FORMAT_R32G32B32A32_SFLOAT,				// VkFormat	format;
77 		DE_OFFSET_OF(VertexDataNdc, positionNdc),	// deUint32	offset;
78 	};
79 
80 	vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
81 
82 	return vertexDataDesc;
83 }
84 
uploadVertexDataNdc(const Allocation& vertexBufferAllocation, const MultisampleInstanceBase::VertexDataDesc& vertexDataDescripton)85 void uploadVertexDataNdc (const Allocation& vertexBufferAllocation, const MultisampleInstanceBase::VertexDataDesc& vertexDataDescripton)
86 {
87 	std::vector<VertexDataNdc> vertices;
88 
89 	vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f)));
90 	vertices.push_back(VertexDataNdc(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f)));
91 	vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f)));
92 	vertices.push_back(VertexDataNdc(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f)));
93 
94 	deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
95 }
96 
97 struct VertexDataNdcScreen
98 {
VertexDataNdcScreenvkt::pipeline::multisample::VertexDataNdcScreen99 	VertexDataNdcScreen (const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {}
100 
101 	tcu::Vec4 positionNdc;
102 	tcu::Vec2 positionScreen;
103 };
104 
getVertexDataDescriptonNdcScreen(void)105 MultisampleInstanceBase::VertexDataDesc getVertexDataDescriptonNdcScreen (void)
106 {
107 	MultisampleInstanceBase::VertexDataDesc vertexDataDesc;
108 
109 	vertexDataDesc.verticesCount	 = 4u;
110 	vertexDataDesc.dataStride		 = sizeof(VertexDataNdcScreen);
111 	vertexDataDesc.dataSize			 = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
112 	vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
113 
114 	const VkVertexInputAttributeDescription vertexAttribPositionNdc =
115 	{
116 		0u,													// deUint32	location;
117 		0u,													// deUint32	binding;
118 		VK_FORMAT_R32G32B32A32_SFLOAT,						// VkFormat	format;
119 		DE_OFFSET_OF(VertexDataNdcScreen, positionNdc),		// deUint32	offset;
120 	};
121 
122 	vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
123 
124 	const VkVertexInputAttributeDescription vertexAttribPositionScreen =
125 	{
126 		1u,													// deUint32	location;
127 		0u,													// deUint32	binding;
128 		VK_FORMAT_R32G32_SFLOAT,							// VkFormat	format;
129 		DE_OFFSET_OF(VertexDataNdcScreen, positionScreen),	// deUint32	offset;
130 	};
131 
132 	vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen);
133 
134 	return vertexDataDesc;
135 }
136 
uploadVertexDataNdcScreen(const Allocation& vertexBufferAllocation, const MultisampleInstanceBase::VertexDataDesc& vertexDataDescripton, const tcu::Vec2& screenSize)137 void uploadVertexDataNdcScreen (const Allocation& vertexBufferAllocation, const MultisampleInstanceBase::VertexDataDesc& vertexDataDescripton, const tcu::Vec2& screenSize)
138 {
139 	std::vector<VertexDataNdcScreen> vertices;
140 
141 	vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, 0.0f)));
142 	vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(screenSize.x(), 0.0f)));
143 	vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, screenSize.y())));
144 	vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f), tcu::Vec2(screenSize.x(), screenSize.y())));
145 
146 	deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
147 }
148 
checkForErrorMS(const vk::VkImageCreateInfo& imageMSInfo, const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, const deUint32 errorCompNdx)149 bool checkForErrorMS (const vk::VkImageCreateInfo& imageMSInfo, const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, const deUint32 errorCompNdx)
150 {
151 	const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
152 
153 	for (deUint32 z = 0u; z < imageMSInfo.extent.depth;  ++z)
154 	for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
155 	for (deUint32 x = 0u; x < imageMSInfo.extent.width;  ++x)
156 	{
157 		for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
158 		{
159 			const deUint32 errorComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z)[errorCompNdx];
160 
161 			if (errorComponent > 0)
162 				return true;
163 		}
164 	}
165 
166 	return false;
167 }
168 
checkForErrorRS(const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS, const deUint32 errorCompNdx)169 bool checkForErrorRS (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS, const deUint32 errorCompNdx)
170 {
171 	for (deUint32 z = 0u; z < imageRSInfo.extent.depth;  ++z)
172 	for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
173 	for (deUint32 x = 0u; x < imageRSInfo.extent.width;  ++x)
174 	{
175 		const deUint32 errorComponent = dataRS.getPixelUint(x, y, z)[errorCompNdx];
176 
177 		if (errorComponent > 0)
178 			return true;
179 	}
180 
181 	return false;
182 }
183 
184 template <typename CaseClassName>
185 class MSCase : public MSCaseBaseResolveAndPerSampleFetch
186 {
187 public:
MSCase(tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)188 								MSCase			(tcu::TestContext&		testCtx,
189 												 const std::string&		name,
190 												 const ImageMSParams&	imageMSParams)
191 								: MSCaseBaseResolveAndPerSampleFetch(testCtx, name, imageMSParams) {}
192 
193 	virtual void				checkSupport	(Context& context) const;
194 	void						init			(void);
195 	void						initPrograms	(vk::SourceCollections& programCollection) const;
196 	TestInstance*				createInstance	(Context&				context) const;
197 	static MultisampleCaseBase*	createCase		(tcu::TestContext&		testCtx,
198 												 const std::string&		name,
199 												 const ImageMSParams&	imageMSParams);
200 };
201 #ifndef CTS_USES_VULKANSC
202 template <typename CaseClassName>
checkSupport(Context& context) const203 void MSCase<CaseClassName>::checkSupport(Context& context) const
204 {
205 	checkGraphicsPipelineLibrarySupport(context);
206 }
207 #endif // CTS_USES_VULKANSC
208 
209 template <typename CaseClassName>
createCase(tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)210 MultisampleCaseBase* MSCase<CaseClassName>::createCase (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
211 {
212 	return new MSCase<CaseClassName>(testCtx, name, imageMSParams);
213 }
214 
215 template <typename InstanceClassName>
216 class MSInstance : public MSInstanceBaseResolveAndPerSampleFetch
217 {
218 public:
MSInstance(Context& context, const ImageMSParams& imageMSParams)219 													MSInstance				(Context&											context,
220 																			 const ImageMSParams&								imageMSParams)
221 													: MSInstanceBaseResolveAndPerSampleFetch(context, imageMSParams) {}
222 
223 	VertexDataDesc									getVertexDataDescripton	(void) const;
224 	void											uploadVertexData		(const Allocation&									vertexBufferAllocation,
225 																			 const VertexDataDesc&								vertexDataDescripton) const;
226 
227 	tcu::TestStatus									verifyImageData			(const vk::VkImageCreateInfo&						imageMSInfo,
228 																			 const vk::VkImageCreateInfo&						imageRSInfo,
229 																			 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
230 																			 const tcu::ConstPixelBufferAccess&					dataRS) const;
231 
getMSStateCreateInfo(const ImageMSParams& imageMSParams) const232 	virtual VkPipelineMultisampleStateCreateInfo	getMSStateCreateInfo	(const ImageMSParams&								imageMSParams) const
233 	{
234 		return MSInstanceBaseResolveAndPerSampleFetch::getMSStateCreateInfo(imageMSParams);
235 	}
236 };
237 
238 class MSInstanceSampleID;
239 
getVertexDataDescripton(void) const240 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleID>::getVertexDataDescripton (void) const
241 {
242 	return getVertexDataDescriptonNdc();
243 }
244 
uploadVertexData(const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const245 template<> void MSInstance<MSInstanceSampleID>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
246 {
247 	uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
248 }
249 
verifyImageData(const vk::VkImageCreateInfo& imageMSInfo, const vk::VkImageCreateInfo& imageRSInfo, const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, const tcu::ConstPixelBufferAccess& dataRS) const250 template<> tcu::TestStatus MSInstance<MSInstanceSampleID>::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
251 																			 const vk::VkImageCreateInfo&						imageRSInfo,
252 																			 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
253 																			 const tcu::ConstPixelBufferAccess&					dataRS) const
254 {
255 	DE_UNREF(imageRSInfo);
256 	DE_UNREF(dataRS);
257 
258 	const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
259 
260 	for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
261 	{
262 		for (deUint32 z = 0u; z < imageMSInfo.extent.depth;  ++z)
263 		for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
264 		for (deUint32 x = 0u; x < imageMSInfo.extent.width;  ++x)
265 		{
266 			const deUint32 sampleID = dataPerSample[sampleNdx].getPixelUint(x, y, z).x();
267 
268 			if (sampleID != sampleNdx)
269 				return tcu::TestStatus::fail("gl_SampleID does not have correct value");
270 		}
271 	}
272 
273 	return tcu::TestStatus::pass("Passed");
274 }
275 
276 class MSCaseSampleID;
277 
checkSupport(Context& context) const278 template<> void MSCase<MSCaseSampleID>::checkSupport (Context& context) const
279 {
280 	checkGraphicsPipelineLibrarySupport(context);
281 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
282 }
283 
init(void)284 template<> void MSCase<MSCaseSampleID>::init (void)
285 {
286 	m_testCtx.getLog()
287 		<< tcu::TestLog::Message
288 		<< "Writing gl_SampleID to the red channel of the texture and verifying texture values.\n"
289 		<< "Expecting value N at sample index N of a multisample texture.\n"
290 		<< tcu::TestLog::EndMessage;
291 
292 	MultisampleCaseBase::init();
293 }
294 
initPrograms(vk::SourceCollections& programCollection) const295 template<> void MSCase<MSCaseSampleID>::initPrograms (vk::SourceCollections& programCollection) const
296 {
297 	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
298 
299 	// Create vertex shader
300 	std::ostringstream vs;
301 
302 	vs << "#version 440\n"
303 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
304 		<< "\n"
305 		<< "out gl_PerVertex {\n"
306 		<< "	vec4  gl_Position;\n"
307 		<< "};\n"
308 		<< "void main (void)\n"
309 		<< "{\n"
310 		<< "	gl_Position	= vs_in_position_ndc;\n"
311 		<< "}\n";
312 
313 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
314 
315 	// Create fragment shader
316 	std::ostringstream fs;
317 
318 	fs << "#version 440\n"
319 		<< "\n"
320 		<< "layout(location = 0) out vec4 fs_out_color;\n"
321 		<< "\n"
322 		<< "void main (void)\n"
323 		<< "{\n"
324 		<< "	fs_out_color = vec4(float(gl_SampleID) / float(255), 0.0, 0.0, 1.0);\n"
325 		<< "}\n";
326 
327 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
328 }
329 
createInstance(Context& context) const330 template<> TestInstance* MSCase<MSCaseSampleID>::createInstance (Context& context) const
331 {
332 	return new MSInstance<MSInstanceSampleID>(context, m_imageMSParams);
333 }
334 
335 class MSInstanceSamplePosDistribution;
336 
getVertexDataDescripton(void) const337 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSamplePosDistribution>::getVertexDataDescripton (void) const
338 {
339 	return getVertexDataDescriptonNdc();
340 }
341 
uploadVertexData(const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const342 template<> void MSInstance<MSInstanceSamplePosDistribution>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
343 {
344 	uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
345 }
346 
verifyImageData(const vk::VkImageCreateInfo& imageMSInfo, const vk::VkImageCreateInfo& imageRSInfo, const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, const tcu::ConstPixelBufferAccess& dataRS) const347 template<> tcu::TestStatus MSInstance<MSInstanceSamplePosDistribution>::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
348 																						 const vk::VkImageCreateInfo&						imageRSInfo,
349 																						 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
350 																						 const tcu::ConstPixelBufferAccess&					dataRS) const
351 {
352 	const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
353 
354 	// approximate Bates distribution as normal
355 	const float variance = (1.0f / (12.0f * (float)numSamples));
356 	const float standardDeviation = deFloatSqrt(variance);
357 
358 	// 95% of means of sample positions are within 2 standard deviations if
359 	// they were randomly assigned. Sample patterns are expected to be more
360 	// uniform than a random pattern.
361 	const float distanceThreshold = 2.0f * standardDeviation;
362 
363 	for (deUint32 z = 0u; z < imageRSInfo.extent.depth;  ++z)
364 	for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
365 	for (deUint32 x = 0u; x < imageRSInfo.extent.width;  ++x)
366 	{
367 		const deUint32 errorComponent = dataRS.getPixelUint(x, y, z).z();
368 
369 		if (errorComponent > 0)
370 			return tcu::TestStatus::fail("gl_SamplePosition is not within interval [0,1]");
371 
372 		if (numSamples >= VK_SAMPLE_COUNT_4_BIT)
373 		{
374 			const tcu::Vec2 averageSamplePos	= tcu::Vec2((float)dataRS.getPixelUint(x, y, z).x() / 255.0f, (float)dataRS.getPixelUint(x, y, z).y() / 255.0f);
375 			const tcu::Vec2	distanceFromCenter	= tcu::abs(averageSamplePos - tcu::Vec2(0.5f, 0.5f));
376 
377 			if (distanceFromCenter.x() > distanceThreshold || distanceFromCenter.y() > distanceThreshold)
378 				return tcu::TestStatus::fail("Sample positions are not uniformly distributed within the pixel");
379 		}
380 	}
381 
382 	for (deUint32 z = 0u; z < imageMSInfo.extent.depth;  ++z)
383 	for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
384 	for (deUint32 x = 0u; x < imageMSInfo.extent.width;  ++x)
385 	{
386 		std::vector<tcu::Vec2> samplePositions(numSamples);
387 
388 		for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
389 		{
390 			const deUint32 errorComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z).z();
391 
392 			if (errorComponent > 0)
393 				return tcu::TestStatus::fail("gl_SamplePosition is not within interval [0,1]");
394 
395 			samplePositions[sampleNdx] = tcu::Vec2( (float)dataPerSample[sampleNdx].getPixelUint(x, y, z).x() / 255.0f,
396 													(float)dataPerSample[sampleNdx].getPixelUint(x, y, z).y() / 255.0f);
397 		}
398 
399 		for (deUint32 sampleNdxA = 0u;				sampleNdxA < numSamples; ++sampleNdxA)
400 		for (deUint32 sampleNdxB = sampleNdxA + 1u; sampleNdxB < numSamples; ++sampleNdxB)
401 		{
402 			if (samplePositions[sampleNdxA] == samplePositions[sampleNdxB])
403 				return tcu::TestStatus::fail("Two samples have the same position");
404 		}
405 
406 		if (numSamples >= VK_SAMPLE_COUNT_4_BIT)
407 		{
408 			tcu::Vec2 averageSamplePos(0.0f, 0.0f);
409 
410 			for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
411 			{
412 				averageSamplePos.x() += samplePositions[sampleNdx].x();
413 				averageSamplePos.y() += samplePositions[sampleNdx].y();
414 			}
415 
416 			averageSamplePos.x() /= (float)numSamples;
417 			averageSamplePos.y() /= (float)numSamples;
418 
419 			const tcu::Vec2	distanceFromCenter = tcu::abs(averageSamplePos - tcu::Vec2(0.5f, 0.5f));
420 
421 			if (distanceFromCenter.x() > distanceThreshold || distanceFromCenter.y() > distanceThreshold)
422 				return tcu::TestStatus::fail("Sample positions are not uniformly distributed within the pixel");
423 		}
424 	}
425 
426 	return tcu::TestStatus::pass("Passed");
427 }
428 
429 class MSCaseSamplePosDistribution;
430 
checkSupport(Context& context) const431 template<> void MSCase<MSCaseSamplePosDistribution>::checkSupport (Context& context) const
432 {
433 	checkGraphicsPipelineLibrarySupport(context);
434 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
435 }
436 
init(void)437 template<> void MSCase<MSCaseSamplePosDistribution>::init (void)
438 {
439 	m_testCtx.getLog()
440 		<< tcu::TestLog::Message
441 		<< "Verifying gl_SamplePosition value with multisample targets:\n"
442 		<< "	a) Expect legal sample position.\n"
443 		<< "	b) Sample position is unique within the set of all sample positions of a pixel.\n"
444 		<< "	c) Sample position distribution is uniform or almost uniform.\n"
445 		<< tcu::TestLog::EndMessage;
446 
447 	MultisampleCaseBase::init();
448 }
449 
initPrograms(vk::SourceCollections& programCollection) const450 template<> void MSCase<MSCaseSamplePosDistribution>::initPrograms (vk::SourceCollections& programCollection) const
451 {
452 	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
453 
454 	// Create vertex shader
455 	std::ostringstream vs;
456 
457 	vs << "#version 440\n"
458 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\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 		<< "}\n";
467 
468 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
469 
470 	// Create fragment shader
471 	std::ostringstream fs;
472 
473 	fs << "#version 440\n"
474 		<< "\n"
475 		<< "layout(location = 0) out vec4 fs_out_color;\n"
476 		<< "\n"
477 		<< "void main (void)\n"
478 		<< "{\n"
479 		<< "	if (gl_SamplePosition.x < 0.0 || gl_SamplePosition.x > 1.0 || gl_SamplePosition.y < 0.0 || gl_SamplePosition.y > 1.0)\n"
480 		"		fs_out_color = vec4(0.0, 0.0, 1.0, 1.0);\n"
481 		"	else\n"
482 		"		fs_out_color = vec4(gl_SamplePosition.x, gl_SamplePosition.y, 0.0, 1.0);\n"
483 		"}\n";
484 
485 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
486 }
487 
createInstance(Context& context) const488 template<> TestInstance* MSCase<MSCaseSamplePosDistribution>::createInstance (Context& context) const
489 {
490 	return new MSInstance<MSInstanceSamplePosDistribution>(context, m_imageMSParams);
491 }
492 
493 class MSInstanceSamplePosCorrectness;
494 
getVertexDataDescripton(void) const495 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSamplePosCorrectness>::getVertexDataDescripton (void) const
496 {
497 	return getVertexDataDescriptonNdcScreen();
498 }
499 
uploadVertexData(const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const500 template<> void MSInstance<MSInstanceSamplePosCorrectness>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
501 {
502 	const tcu::UVec3 layerSize = getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize);
503 
504 	uploadVertexDataNdcScreen(vertexBufferAllocation, vertexDataDescripton, tcu::Vec2(static_cast<float>(layerSize.x()), static_cast<float>(layerSize.y())));
505 }
506 
verifyImageData(const vk::VkImageCreateInfo& imageMSInfo, const vk::VkImageCreateInfo& imageRSInfo, const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, const tcu::ConstPixelBufferAccess& dataRS) const507 template<> tcu::TestStatus MSInstance<MSInstanceSamplePosCorrectness>::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
508 																						 const vk::VkImageCreateInfo&						imageRSInfo,
509 																						 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
510 																						 const tcu::ConstPixelBufferAccess&					dataRS) const
511 {
512 	if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
513 		return tcu::TestStatus::fail("Varying values are not sampled at gl_SamplePosition");
514 
515 	if (checkForErrorRS(imageRSInfo, dataRS, 0))
516 		return tcu::TestStatus::fail("Varying values are not sampled at gl_SamplePosition");
517 
518 	return tcu::TestStatus::pass("Passed");
519 }
520 
521 class MSCaseSamplePosCorrectness;
522 
checkSupport(Context& context) const523 template<> void MSCase<MSCaseSamplePosCorrectness>::checkSupport (Context& context) const
524 {
525 	checkGraphicsPipelineLibrarySupport(context);
526 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
527 }
528 
init(void)529 template<> void MSCase<MSCaseSamplePosCorrectness>::init (void)
530 {
531 	m_testCtx.getLog()
532 		<< tcu::TestLog::Message
533 		<< "Verifying gl_SamplePosition correctness:\n"
534 		<< "	1) Varying values should be sampled at the sample position.\n"
535 		<< "		=> fract(position_screen) == gl_SamplePosition\n"
536 		<< tcu::TestLog::EndMessage;
537 
538 	MultisampleCaseBase::init();
539 }
540 
initPrograms(vk::SourceCollections& programCollection) const541 template<> void MSCase<MSCaseSamplePosCorrectness>::initPrograms (vk::SourceCollections& programCollection) const
542 {
543 	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
544 
545 	// Create vertex shaders
546 	std::ostringstream vs;
547 
548 	vs	<< "#version 440\n"
549 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
550 		<< "layout(location = 1) in vec2 vs_in_position_screen;\n"
551 		<< "\n"
552 		<< "layout(location = 0) sample out vec2 vs_out_position_screen;\n"
553 		<< "\n"
554 		<< "out gl_PerVertex {\n"
555 		<< "	vec4  gl_Position;\n"
556 		<< "};\n"
557 		<< "void main (void)\n"
558 		<< "{\n"
559 		<< "	gl_Position				= vs_in_position_ndc;\n"
560 		<< "	vs_out_position_screen	= vs_in_position_screen;\n"
561 		<< "}\n";
562 
563 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
564 
565 	// Create fragment shader
566 	std::ostringstream fs;
567 
568 	fs	<< "#version 440\n"
569 		<< "layout(location = 0) sample in vec2 fs_in_position_screen;\n"
570 		<< "\n"
571 		<< "layout(location = 0) out vec4 fs_out_color;\n"
572 		<< "\n"
573 		<< "void main (void)\n"
574 		<< "{\n"
575 		<< "	const float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n"
576 		<< "	const ivec2 nearby_pixel = ivec2(floor(fs_in_position_screen));\n"
577 		<< "	bool ok	= false;\n"
578 		<< "\n"
579 		<< "	// sample at edge + inaccuaries may cause us to round to any neighboring pixel\n"
580 		<< "	// check all neighbors for any match\n"
581 		<< "	for (int dy = -1; dy <= 1; ++dy)\n"
582 		<< "	for (int dx = -1; dx <= 1; ++dx)\n"
583 		<< "	{\n"
584 		<< "		ivec2 current_pixel			= nearby_pixel + ivec2(dx, dy);\n"
585 		<< "		vec2 position_inside_pixel	= vec2(current_pixel) + gl_SamplePosition;\n"
586 		<< "		vec2 position_diff			= abs(position_inside_pixel - fs_in_position_screen);\n"
587 		<< "\n"
588 		<< "		if (all(lessThan(position_diff, vec2(threshold))))\n"
589 		<< "			ok = true;\n"
590 		<< "	}\n"
591 		<< "\n"
592 		<< "	if (ok)\n"
593 		<< "		fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
594 		<< "	else\n"
595 		<< "		fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
596 		<< "}\n";
597 
598 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
599 }
600 
createInstance(Context& context) const601 template<> TestInstance* MSCase<MSCaseSamplePosCorrectness>::createInstance (Context& context) const
602 {
603 	return new MSInstance<MSInstanceSamplePosCorrectness>(context, m_imageMSParams);
604 }
605 
606 class MSInstanceSampleMaskPattern : public MSInstanceBaseResolveAndPerSampleFetch
607 {
608 public:
609 											MSInstanceSampleMaskPattern	(Context&											context,
610 																		 const ImageMSParams&								imageMSParams);
611 
612 	VkPipelineMultisampleStateCreateInfo	getMSStateCreateInfo		(const ImageMSParams&								imageMSParams) const;
613 
614 	const VkDescriptorSetLayout*			createMSPassDescSetLayout	(const ImageMSParams&								imageMSParams);
615 
616 	const VkDescriptorSet*					createMSPassDescSet			(const ImageMSParams&								imageMSParams,
617 																		 const VkDescriptorSetLayout*						descSetLayout);
618 
619 	VertexDataDesc							getVertexDataDescripton		(void) const;
620 
621 	void									uploadVertexData			(const Allocation&									vertexBufferAllocation,
622 																		 const VertexDataDesc&								vertexDataDescripton) const;
623 
624 	tcu::TestStatus							verifyImageData				(const vk::VkImageCreateInfo&						imageMSInfo,
625 																		 const vk::VkImageCreateInfo&						imageRSInfo,
626 																		 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
627 																		 const tcu::ConstPixelBufferAccess&					dataRS) const;
628 protected:
629 
630 	VkSampleMask					m_sampleMask;
631 	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
632 	Move<VkDescriptorPool>			m_descriptorPool;
633 	Move<VkDescriptorSet>			m_descriptorSet;
634 	de::MovePtr<BufferWithMemory>	m_buffer;
635 };
636 
MSInstanceSampleMaskPattern(Context& context, const ImageMSParams& imageMSParams)637 MSInstanceSampleMaskPattern::MSInstanceSampleMaskPattern (Context& context, const ImageMSParams& imageMSParams) : MSInstanceBaseResolveAndPerSampleFetch(context, imageMSParams)
638 {
639 	m_sampleMask = 0xAAAAAAAAu & ((1u << imageMSParams.numSamples) - 1u);
640 }
641 
getMSStateCreateInfo(const ImageMSParams& imageMSParams) const642 VkPipelineMultisampleStateCreateInfo MSInstanceSampleMaskPattern::getMSStateCreateInfo (const ImageMSParams& imageMSParams) const
643 {
644 	const VkPipelineMultisampleStateCreateInfo multisampleStateInfo =
645 	{
646 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
647 		DE_NULL,														// const void*								pNext;
648 		(VkPipelineMultisampleStateCreateFlags)0u,						// VkPipelineMultisampleStateCreateFlags	flags;
649 		imageMSParams.numSamples,										// VkSampleCountFlagBits					rasterizationSamples;
650 		VK_FALSE,														// VkBool32									sampleShadingEnable;
651 		imageMSParams.shadingRate,										// float									minSampleShading;
652 		&m_sampleMask,													// const VkSampleMask*						pSampleMask;
653 		VK_FALSE,														// VkBool32									alphaToCoverageEnable;
654 		VK_FALSE,														// VkBool32									alphaToOneEnable;
655 	};
656 
657 	return multisampleStateInfo;
658 }
659 
createMSPassDescSetLayout(const ImageMSParams& imageMSParams)660 const VkDescriptorSetLayout* MSInstanceSampleMaskPattern::createMSPassDescSetLayout (const ImageMSParams& imageMSParams)
661 {
662 	DE_UNREF(imageMSParams);
663 
664 	const DeviceInterface&		deviceInterface = m_context.getDeviceInterface();
665 	const VkDevice				device			= m_context.getDevice();
666 
667 	// Create descriptor set layout
668 	m_descriptorSetLayout = DescriptorSetLayoutBuilder()
669 		.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
670 		.build(deviceInterface, device);
671 
672 	return &m_descriptorSetLayout.get();
673 }
674 
createMSPassDescSet(const ImageMSParams& imageMSParams, const VkDescriptorSetLayout* descSetLayout)675 const VkDescriptorSet* MSInstanceSampleMaskPattern::createMSPassDescSet (const ImageMSParams& imageMSParams, const VkDescriptorSetLayout* descSetLayout)
676 {
677 	DE_UNREF(imageMSParams);
678 
679 	const DeviceInterface&		deviceInterface = m_context.getDeviceInterface();
680 	const VkDevice				device			= m_context.getDevice();
681 	Allocator&					allocator		= m_context.getDefaultAllocator();
682 
683 	// Create descriptor pool
684 	m_descriptorPool = DescriptorPoolBuilder()
685 		.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u)
686 		.build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
687 
688 	// Create descriptor set
689 	m_descriptorSet = makeDescriptorSet(deviceInterface, device, *m_descriptorPool, *descSetLayout);
690 
691 	const VkBufferCreateInfo bufferSampleMaskInfo = makeBufferCreateInfo(sizeof(VkSampleMask), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
692 
693 	m_buffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(deviceInterface, device, allocator, bufferSampleMaskInfo, MemoryRequirement::HostVisible));
694 
695 	deMemcpy(m_buffer->getAllocation().getHostPtr(), &m_sampleMask, sizeof(VkSampleMask));
696 
697 	flushAlloc(deviceInterface, device, m_buffer->getAllocation());
698 
699 	const VkDescriptorBufferInfo descBufferInfo = makeDescriptorBufferInfo(**m_buffer, 0u, sizeof(VkSampleMask));
700 
701 	DescriptorSetUpdateBuilder()
702 		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descBufferInfo)
703 		.update(deviceInterface, device);
704 
705 	return &m_descriptorSet.get();
706 }
707 
getVertexDataDescripton(void) const708 MultisampleInstanceBase::VertexDataDesc MSInstanceSampleMaskPattern::getVertexDataDescripton (void) const
709 {
710 	return getVertexDataDescriptonNdc();
711 }
712 
uploadVertexData(const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const713 void MSInstanceSampleMaskPattern::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
714 {
715 	uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
716 }
717 
verifyImageData(const vk::VkImageCreateInfo& imageMSInfo, const vk::VkImageCreateInfo& imageRSInfo, const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, const tcu::ConstPixelBufferAccess& dataRS) const718 tcu::TestStatus	MSInstanceSampleMaskPattern::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
719 																 const vk::VkImageCreateInfo&						imageRSInfo,
720 																 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
721 																 const tcu::ConstPixelBufferAccess&					dataRS) const
722 {
723 	DE_UNREF(imageRSInfo);
724 	DE_UNREF(dataRS);
725 
726 	if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
727 		return tcu::TestStatus::fail("gl_SampleMaskIn bits have not been killed by pSampleMask state");
728 
729 	return tcu::TestStatus::pass("Passed");
730 }
731 
732 class MSCaseSampleMaskPattern;
733 
init(void)734 template<> void MSCase<MSCaseSampleMaskPattern>::init (void)
735 {
736 	m_testCtx.getLog()
737 		<< tcu::TestLog::Message
738 		<< "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"
739 		<< "Expected result: gl_SampleMaskIn AND ~(pSampleMask) should be zero.\n"
740 		<< tcu::TestLog::EndMessage;
741 
742 	MultisampleCaseBase::init();
743 }
744 
initPrograms(vk::SourceCollections& programCollection) const745 template<> void MSCase<MSCaseSampleMaskPattern>::initPrograms (vk::SourceCollections& programCollection) const
746 {
747 	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
748 
749 	// Create vertex shader
750 	std::ostringstream vs;
751 
752 	vs << "#version 440\n"
753 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
754 		<< "\n"
755 		<< "out gl_PerVertex {\n"
756 		<< "	vec4  gl_Position;\n"
757 		<< "};\n"
758 		<< "void main (void)\n"
759 		<< "{\n"
760 		<< "	gl_Position	= vs_in_position_ndc;\n"
761 		<< "}\n";
762 
763 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
764 
765 	// Create fragment shader
766 	std::ostringstream fs;
767 
768 	fs << "#version 440\n"
769 		<< "\n"
770 		<< "layout(location = 0) out vec4 fs_out_color;\n"
771 		<< "\n"
772 		<< "layout(set = 0, binding = 0, std140) uniform SampleMaskBlock\n"
773 		<< "{\n"
774 		<< "	int sampleMaskPattern;\n"
775 		<< "};"
776 		<< "\n"
777 		<< "void main (void)\n"
778 		<< "{\n"
779 		<< "	if ((gl_SampleMaskIn[0] & ~sampleMaskPattern) != 0)\n"
780 		<< "		fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
781 		<< "	else\n"
782 		<< "		fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
783 		<< "}\n";
784 
785 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
786 }
787 
createInstance(Context& context) const788 template<> TestInstance* MSCase<MSCaseSampleMaskPattern>::createInstance (Context& context) const
789 {
790 	return new MSInstanceSampleMaskPattern(context, m_imageMSParams);
791 }
792 
793 class MSInstanceSampleMaskBitCount;
794 
getVertexDataDescripton(void) const795 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskBitCount>::getVertexDataDescripton (void) const
796 {
797 	return getVertexDataDescriptonNdc();
798 }
799 
uploadVertexData(const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const800 template<> void MSInstance<MSInstanceSampleMaskBitCount>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
801 {
802 	uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
803 }
804 
verifyImageData(const vk::VkImageCreateInfo& imageMSInfo, const vk::VkImageCreateInfo& imageRSInfo, const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, const tcu::ConstPixelBufferAccess& dataRS) const805 template<> tcu::TestStatus MSInstance<MSInstanceSampleMaskBitCount>::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
806 																						 const vk::VkImageCreateInfo&						imageRSInfo,
807 																						 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
808 																						 const tcu::ConstPixelBufferAccess&					dataRS) const
809 {
810 	DE_UNREF(imageRSInfo);
811 	DE_UNREF(dataRS);
812 
813 	if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
814 		return tcu::TestStatus::fail("gl_SampleMaskIn has an illegal number of bits for some shader invocations");
815 
816 	return tcu::TestStatus::pass("Passed");
817 }
818 
819 class MSCaseSampleMaskBitCount;
820 
checkSupport(Context& context) const821 template<> void MSCase<MSCaseSampleMaskBitCount>::checkSupport (Context& context) const
822 {
823 	checkGraphicsPipelineLibrarySupport(context);
824 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
825 }
826 
init(void)827 template<> void MSCase<MSCaseSampleMaskBitCount>::init (void)
828 {
829 	m_testCtx.getLog()
830 		<< tcu::TestLog::Message
831 		<< "Verifying gl_SampleMaskIn.\n"
832 		<< "	Fragment shader will be invoked numSamples times.\n"
833 		<< "	=> gl_SampleMaskIn should have a number of bits that depends on the shading rate.\n"
834 		<< tcu::TestLog::EndMessage;
835 
836 	MultisampleCaseBase::init();
837 }
838 
initPrograms(vk::SourceCollections& programCollection) const839 template<> void MSCase<MSCaseSampleMaskBitCount>::initPrograms (vk::SourceCollections& programCollection) const
840 {
841 	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
842 
843 	// Create vertex shader
844 	std::ostringstream vs;
845 
846 	vs << "#version 440\n"
847 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
848 		<< "\n"
849 		<< "out gl_PerVertex {\n"
850 		<< "	vec4  gl_Position;\n"
851 		<< "};\n"
852 		<< "void main (void)\n"
853 		<< "{\n"
854 		<< "	gl_Position	= vs_in_position_ndc;\n"
855 		<< "}\n";
856 
857 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
858 
859 	// Create fragment shader
860 	std::ostringstream fs;
861 
862 	// The worst case scenario would be all invocations except one covering a single sample, and then one invocation covering the rest.
863 	const int minInvocations	= static_cast<int>(std::ceil(static_cast<float>(m_imageMSParams.numSamples) * m_imageMSParams.shadingRate));
864 	const int minCount			= 1;
865 	const int maxCount			= m_imageMSParams.numSamples - (minInvocations - 1);
866 
867 	fs << "#version 440\n"
868 		<< "\n"
869 		<< "layout(location = 0) out vec4 fs_out_color;\n"
870 		<< "\n"
871 		<< "void main (void)\n"
872 		<< "{\n"
873 		<< "	const int maskBitCount = bitCount(gl_SampleMaskIn[0]);\n"
874 		<< "\n"
875 		<< "	if (maskBitCount < " << minCount << " || maskBitCount > " << maxCount << ")\n"
876 		<< "		fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
877 		<< "	else\n"
878 		<< "		fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
879 		<< "}\n";
880 
881 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
882 }
883 
createInstance(Context& context) const884 template<> TestInstance* MSCase<MSCaseSampleMaskBitCount>::createInstance (Context& context) const
885 {
886 	return new MSInstance<MSInstanceSampleMaskBitCount>(context, m_imageMSParams);
887 }
888 
889 class MSInstanceSampleMaskCorrectBit;
890 
getVertexDataDescripton(void) const891 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskCorrectBit>::getVertexDataDescripton (void) const
892 {
893 	return getVertexDataDescriptonNdc();
894 }
895 
uploadVertexData(const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const896 template<> void MSInstance<MSInstanceSampleMaskCorrectBit>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
897 {
898 	uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
899 }
900 
verifyImageData(const vk::VkImageCreateInfo& imageMSInfo, const vk::VkImageCreateInfo& imageRSInfo, const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, const tcu::ConstPixelBufferAccess& dataRS) const901 template<> tcu::TestStatus MSInstance<MSInstanceSampleMaskCorrectBit>::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
902 																						 const vk::VkImageCreateInfo&						imageRSInfo,
903 																						 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
904 																						 const tcu::ConstPixelBufferAccess&					dataRS) const
905 {
906 	DE_UNREF(imageRSInfo);
907 	DE_UNREF(dataRS);
908 
909 	if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
910 		return tcu::TestStatus::fail("The bit corresponsing to current gl_SampleID is not set in gl_SampleMaskIn");
911 
912 	return tcu::TestStatus::pass("Passed");
913 }
914 
915 class MSCaseSampleMaskCorrectBit;
916 
checkSupport(Context& context) const917 template<> void MSCase<MSCaseSampleMaskCorrectBit>::checkSupport (Context& context) const
918 {
919 	checkGraphicsPipelineLibrarySupport(context);
920 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
921 }
922 
init(void)923 template<> void MSCase<MSCaseSampleMaskCorrectBit>::init (void)
924 {
925 	m_testCtx.getLog()
926 		<< tcu::TestLog::Message
927 		<< "Verifying gl_SampleMaskIn.\n"
928 		<< "	Fragment shader will be invoked numSamples times.\n"
929 		<< "	=> In each invocation gl_SampleMaskIn should have the bit set that corresponds to gl_SampleID.\n"
930 		<< tcu::TestLog::EndMessage;
931 
932 	MultisampleCaseBase::init();
933 }
934 
initPrograms(vk::SourceCollections& programCollection) const935 template<> void MSCase<MSCaseSampleMaskCorrectBit>::initPrograms (vk::SourceCollections& programCollection) const
936 {
937 	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
938 
939 	// Create vertex shader
940 	std::ostringstream vs;
941 
942 	vs << "#version 440\n"
943 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
944 		<< "\n"
945 		<< "out gl_PerVertex {\n"
946 		<< "	vec4  gl_Position;\n"
947 		<< "};\n"
948 		<< "void main (void)\n"
949 		<< "{\n"
950 		<< "	gl_Position	= vs_in_position_ndc;\n"
951 		<< "}\n";
952 
953 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
954 
955 	// Create fragment shader
956 	std::ostringstream fs;
957 
958 	fs << "#version 440\n"
959 		<< "\n"
960 		<< "layout(location = 0) out vec4 fs_out_color;\n"
961 		<< "\n"
962 		<< "void main (void)\n"
963 		<< "{\n"
964 		<< "	if (((gl_SampleMaskIn[0] >> gl_SampleID) & 0x01) == 0x01)\n"
965 		<< "		fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
966 		<< "	else\n"
967 		<< "		fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
968 		<< "}\n";
969 
970 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
971 }
972 
createInstance(Context& context) const973 template<> TestInstance* MSCase<MSCaseSampleMaskCorrectBit>::createInstance (Context& context) const
974 {
975 	return new MSInstance<MSInstanceSampleMaskCorrectBit>(context, m_imageMSParams);
976 }
977 
978 class MSInstanceSampleMaskWrite;
979 
getVertexDataDescripton(void) const980 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskWrite>::getVertexDataDescripton (void) const
981 {
982 	return getVertexDataDescriptonNdc();
983 }
984 
uploadVertexData(const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const985 template<> void MSInstance<MSInstanceSampleMaskWrite>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
986 {
987 	uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
988 }
989 
990 //! Creates VkPipelineMultisampleStateCreateInfo with sample shading disabled.
getMSStateCreateInfo(const ImageMSParams& imageMSParams) const991 template<> VkPipelineMultisampleStateCreateInfo MSInstance<MSInstanceSampleMaskWrite>::getMSStateCreateInfo (const ImageMSParams& imageMSParams) const
992 {
993 	const VkPipelineMultisampleStateCreateInfo multisampleStateInfo =
994 	{
995 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
996 		DE_NULL,													// const void*								pNext;
997 		(VkPipelineMultisampleStateCreateFlags)0u,					// VkPipelineMultisampleStateCreateFlags	flags;
998 		imageMSParams.numSamples,									// VkSampleCountFlagBits					rasterizationSamples;
999 		VK_FALSE,													// VkBool32									sampleShadingEnable;
1000 		imageMSParams.shadingRate,									// float									minSampleShading;
1001 		DE_NULL,													// const VkSampleMask*						pSampleMask;
1002 		VK_FALSE,													// VkBool32									alphaToCoverageEnable;
1003 		VK_FALSE,													// VkBool32									alphaToOneEnable;
1004 	};
1005 
1006 	return multisampleStateInfo;
1007 }
1008 
verifyImageData(const vk::VkImageCreateInfo& imageMSInfo, const vk::VkImageCreateInfo& imageRSInfo, const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, const tcu::ConstPixelBufferAccess& dataRS) const1009 template<> tcu::TestStatus MSInstance<MSInstanceSampleMaskWrite>::verifyImageData	(const vk::VkImageCreateInfo&						imageMSInfo,
1010 																					 const vk::VkImageCreateInfo&						imageRSInfo,
1011 																					 const std::vector<tcu::ConstPixelBufferAccess>&	dataPerSample,
1012 																					 const tcu::ConstPixelBufferAccess&					dataRS) const
1013 {
1014 	const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
1015 
1016 	for (deUint32 z = 0u; z < imageMSInfo.extent.depth;  ++z)
1017 	for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
1018 	for (deUint32 x = 0u; x < imageMSInfo.extent.width;  ++x)
1019 	{
1020 		for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
1021 		{
1022 			const deUint32 firstComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z)[0];
1023 
1024 			if (firstComponent != 0u && firstComponent != 255u)
1025 				return tcu::TestStatus::fail("Expected color to be zero or saturated on the first channel");
1026 		}
1027 	}
1028 
1029 	for (deUint32 z = 0u; z < imageRSInfo.extent.depth;  ++z)
1030 	for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
1031 	for (deUint32 x = 0u; x < imageRSInfo.extent.width;  ++x)
1032 	{
1033 		const float firstComponent = dataRS.getPixel(x, y, z)[0];
1034 
1035 		if (deFloatAbs(firstComponent - 0.5f) > 0.02f)
1036 			return tcu::TestStatus::fail("Expected resolve color to be half intensity on the first channel");
1037 	}
1038 
1039 	return tcu::TestStatus::pass("Passed");
1040 }
1041 
1042 class MSCaseSampleMaskWrite;
1043 
init(void)1044 template<> void MSCase<MSCaseSampleMaskWrite>::init (void)
1045 {
1046 	m_testCtx.getLog()
1047 		<< tcu::TestLog::Message
1048 		<< "Discarding half of the samples using gl_SampleMask."
1049 		<< "Expecting half intensity on multisample targets (numSamples > 1)\n"
1050 		<< tcu::TestLog::EndMessage;
1051 
1052 	MultisampleCaseBase::init();
1053 }
1054 
initPrograms(vk::SourceCollections& programCollection) const1055 template<> void MSCase<MSCaseSampleMaskWrite>::initPrograms (vk::SourceCollections& programCollection) const
1056 {
1057 	MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
1058 
1059 	// Create vertex shader
1060 	std::ostringstream vs;
1061 
1062 	vs << "#version 440\n"
1063 		<< "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1064 		<< "\n"
1065 		<< "out gl_PerVertex {\n"
1066 		<< "	vec4  gl_Position;\n"
1067 		<< "};\n"
1068 		<< "void main (void)\n"
1069 		<< "{\n"
1070 		<< "	gl_Position	= vs_in_position_ndc;\n"
1071 		<< "}\n";
1072 
1073 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1074 
1075 	// Create fragment shader
1076 	std::ostringstream fs;
1077 
1078 	fs << "#version 440\n"
1079 		<< "\n"
1080 		<< "layout(location = 0) out vec4 fs_out_color;\n"
1081 		<< "\n"
1082 		<< "void main (void)\n"
1083 		<< "{\n"
1084 		<< "	gl_SampleMask[0] = 0xAAAAAAAA;\n"
1085 		<< "\n"
1086 		<< "	fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1087 		<< "}\n";
1088 
1089 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1090 }
1091 
createInstance(Context& context) const1092 template<> TestInstance* MSCase<MSCaseSampleMaskWrite>::createInstance (Context& context) const
1093 {
1094 	return new MSInstance<MSInstanceSampleMaskWrite>(context, m_imageMSParams);
1095 }
1096 
1097 const set<deUint32> kValidSquareSampleCounts =
1098 {
1099 	vk::VK_SAMPLE_COUNT_1_BIT,
1100 	vk::VK_SAMPLE_COUNT_2_BIT,
1101 	vk::VK_SAMPLE_COUNT_4_BIT,
1102 	vk::VK_SAMPLE_COUNT_8_BIT,
1103 	vk::VK_SAMPLE_COUNT_16_BIT,
1104 };
1105 
assertSquareSampleCount(deUint32 sampleCount)1106 void assertSquareSampleCount (deUint32 sampleCount)
1107 {
1108 	DE_ASSERT(kValidSquareSampleCounts.find(sampleCount) != kValidSquareSampleCounts.end());
1109 	DE_UNREF(sampleCount); // for release builds.
1110 }
1111 
1112 // When dealing with N samples, each coordinate (x, y) will be used to decide which samples will be written to, using N/2 bits for
1113 // each of the X and Y values. Take into account this returns 0 for 1 sample.
bitsPerCoord(deUint32 numSamples)1114 deUint32 bitsPerCoord (deUint32 numSamples)
1115 {
1116 	assertSquareSampleCount(numSamples);
1117 	return (numSamples / 2u);
1118 }
1119 
1120 // These tests will try to verify all write or mask bit combinations for the given sample count, and will verify one combination per
1121 // image pixel. This means the following image sizes need to be used:
1122 //		- 2 samples: 2x2
1123 //		- 4 samples: 4x4
1124 //		- 8 samples: 16x16
1125 //		- 16 samples: 256x256
1126 // In other words, images will be square with 2^(samples-1) pixels on each side.
imageSize(deUint32 sampleCount)1127 vk::VkExtent2D imageSize (deUint32 sampleCount)
1128 {
1129 	assertSquareSampleCount(sampleCount);
1130 
1131 	// Special case: 2x1 image (not actually square).
1132 	if (sampleCount == vk::VK_SAMPLE_COUNT_1_BIT)
1133 		return vk::VkExtent2D{2u, 1u};
1134 
1135 	// Other cases: square image as described above.
1136 	const auto dim = (1u<<(sampleCount>>1u));
1137 	return vk::VkExtent2D{dim, dim};
1138 }
1139 
getExtent3D(deUint32 sampleCount)1140 vk::VkExtent3D getExtent3D (deUint32 sampleCount)
1141 {
1142 	const auto size = imageSize(sampleCount);
1143 	return vk::VkExtent3D{size.width, size.height, 1u};
1144 }
1145 
getShaderDecl(const tcu::Vec4& color)1146 std::string getShaderDecl (const tcu::Vec4& color)
1147 {
1148 	std::ostringstream declaration;
1149 	declaration << "vec4(" << color.x() << ", " << color.y() << ", " << color.z() << ", " << color.w() << ")";
1150 	return declaration.str();
1151 }
1152 
1153 struct WriteSampleParams
1154 {
1155 	vk::PipelineConstructionType	pipelineConstructionType;
1156 	vk::VkSampleCountFlagBits		sampleCount;
1157 };
1158 
1159 class WriteSampleTest : public vkt::TestCase
1160 {
1161 public:
WriteSampleTest(tcu::TestContext& testCtx, const std::string& name, const WriteSampleParams& params)1162 									WriteSampleTest		(tcu::TestContext& testCtx, const std::string& name, const WriteSampleParams& params)
1163 										: vkt::TestCase(testCtx, name), m_params(params)
1164 										{}
~WriteSampleTest(void)1165 	virtual							~WriteSampleTest	(void) {}
1166 
1167 	virtual void					initPrograms		(vk::SourceCollections& programCollection) const;
1168 	virtual vkt::TestInstance*		createInstance		(Context& context) const;
1169 	virtual void					checkSupport		(Context& context) const;
1170 
1171 	static const tcu::Vec4			kClearColor;
1172 	static const tcu::Vec4			kBadColor;
1173 	static const tcu::Vec4			kGoodColor;
1174 	static const tcu::Vec4			kWriteColor;
1175 
1176 	static constexpr vk::VkFormat	kImageFormat		= vk::VK_FORMAT_R8G8B8A8_UNORM;
1177 
1178 	// Keep these two in sync.
1179 	static constexpr vk::VkImageUsageFlags		kUsageFlags		= (vk::VK_IMAGE_USAGE_STORAGE_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
1180 	static constexpr vk::VkFormatFeatureFlags	kFeatureFlags	= (vk::VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_DST_BIT);
1181 
1182 private:
1183 	WriteSampleParams		m_params;
1184 };
1185 
1186 const tcu::Vec4 WriteSampleTest::kClearColor	{0.0f, 0.0f, 0.0f, 1.0f};
1187 const tcu::Vec4 WriteSampleTest::kBadColor		{1.0f, 0.0f, 0.0f, 1.0f};
1188 const tcu::Vec4 WriteSampleTest::kGoodColor		{0.0f, 1.0f, 0.0f, 1.0f};
1189 const tcu::Vec4 WriteSampleTest::kWriteColor	{0.0f, 0.0f, 1.0f, 1.0f};
1190 
1191 class WriteSampleTestInstance : public vkt::TestInstance
1192 {
1193 public:
WriteSampleTestInstance(vkt::Context& context, const WriteSampleParams& params)1194 								WriteSampleTestInstance		(vkt::Context& context, const WriteSampleParams& params)
1195 									: vkt::TestInstance(context), m_params(params)
1196 									{}
1197 
~WriteSampleTestInstance(void)1198 	virtual						~WriteSampleTestInstance	(void) {}
1199 
1200 	virtual tcu::TestStatus		iterate						(void);
1201 
1202 private:
1203 	WriteSampleParams			m_params;
1204 };
1205 
checkSupport(Context& context) const1206 void WriteSampleTest::checkSupport (Context& context) const
1207 {
1208 	const auto&	vki				= context.getInstanceInterface();
1209 	const auto	physicalDevice	= context.getPhysicalDevice();
1210 
1211 	// Check multisample storage images support.
1212 	const auto features = vk::getPhysicalDeviceFeatures(vki, physicalDevice);
1213 	if (!features.shaderStorageImageMultisample)
1214 		TCU_THROW(NotSupportedError, "Using multisample images as storage is not supported");
1215 
1216 	// Check the specific image format.
1217 	const auto properties = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kImageFormat);
1218 	if (!(properties.optimalTilingFeatures & kFeatureFlags))
1219 		TCU_THROW(NotSupportedError, "Format does not support the required features");
1220 
1221 	// Check the supported sample count.
1222 	const auto imgProps = vk::getPhysicalDeviceImageFormatProperties(vki, physicalDevice, kImageFormat, vk::VK_IMAGE_TYPE_2D, vk::VK_IMAGE_TILING_OPTIMAL, kUsageFlags, 0u);
1223 	if (!(imgProps.sampleCounts & m_params.sampleCount))
1224 		TCU_THROW(NotSupportedError, "Format does not support the required sample count");
1225 
1226 	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType);
1227 }
1228 
initPrograms(vk::SourceCollections& programCollection) const1229 void WriteSampleTest::initPrograms (vk::SourceCollections& programCollection) const
1230 {
1231 	std::ostringstream writeColorDecl, goodColorDecl, badColorDecl, clearColorDecl, allColorDecl;
1232 
1233 	writeColorDecl	<< "        vec4  wcolor   = " << getShaderDecl(kWriteColor)	<< ";\n";
1234 	goodColorDecl	<< "        vec4  bcolor   = " << getShaderDecl(kBadColor)		<< ";\n";
1235 	badColorDecl	<< "        vec4  gcolor   = " << getShaderDecl(kGoodColor)		<< ";\n";
1236 	clearColorDecl	<< "        vec4  ccolor   = " << getShaderDecl(kClearColor)	<< ";\n";
1237 	allColorDecl	<< writeColorDecl.str() << goodColorDecl.str() << badColorDecl.str() << clearColorDecl.str();
1238 
1239 	std::ostringstream shaderWrite;
1240 
1241 	const auto bpc		= de::toString(bitsPerCoord(m_params.sampleCount));
1242 	const auto count	= de::toString(m_params.sampleCount);
1243 
1244 	shaderWrite
1245 		<< "#version 450\n"
1246 		<< "\n"
1247 		<< "layout (rgba8, set=0, binding=0) uniform image2DMS writeImg;\n"
1248 		<< "layout (rgba8, set=0, binding=1) uniform image2D   verificationImg;\n"
1249 		<< "\n"
1250 		<< "void main()\n"
1251 		<< "{\n"
1252 		<< writeColorDecl.str()
1253 		<< "        uvec2 ucoords  = uvec2(gl_GlobalInvocationID.xy);\n"
1254 		<< "        ivec2 icoords  = ivec2(ucoords);\n"
1255 		<< "        uint writeMask = ((ucoords.x << " << bpc << ") | ucoords.y);\n"
1256 		<< "        for (uint i = 0; i < " << count << "; ++i)\n"
1257 		<< "        {\n"
1258 		<< "                if ((writeMask & (1 << i)) != 0)\n"
1259 		<< "                        imageStore(writeImg, icoords, int(i), wcolor);\n"
1260 		<< "        }\n"
1261 		<< "}\n"
1262 		;
1263 
1264 	std::ostringstream shaderVerify;
1265 
1266 	shaderVerify
1267 		<< "#version 450\n"
1268 		<< "\n"
1269 		<< "layout (rgba8, set=0, binding=0) uniform image2DMS writeImg;\n"
1270 		<< "layout (rgba8, set=0, binding=1) uniform image2D   verificationImg;\n"
1271 		<< "\n"
1272 		<< "void main()\n"
1273 		<< "{\n"
1274 		<< allColorDecl.str()
1275 		<< "        uvec2 ucoords  = uvec2(gl_GlobalInvocationID.xy);\n"
1276 		<< "        ivec2 icoords  = ivec2(ucoords);\n"
1277 		<< "        uint writeMask = ((ucoords.x << " << bpc << ") | ucoords.y);\n"
1278 		<< "        bool ok = true;\n"
1279 		<< "        for (uint i = 0; i < " << count << "; ++i)\n"
1280 		<< "        {\n"
1281 		<< "                bool expectWrite = ((writeMask & (1 << i)) != 0);\n"
1282 		<< "                vec4 sampleColor = imageLoad(writeImg, icoords, int(i));\n"
1283 		<< "                vec4 wantedColor = (expectWrite ? wcolor : ccolor);\n"
1284 		<< "                ok = ok && (sampleColor == wantedColor);\n"
1285 		<< "        }\n"
1286 		<< "        vec4 resultColor = (ok ? gcolor : bcolor);\n"
1287 		<< "        imageStore(verificationImg, icoords, resultColor);\n"
1288 		<< "}\n"
1289 		;
1290 
1291 	programCollection.glslSources.add("write")	<< glu::ComputeSource(shaderWrite.str());
1292 	programCollection.glslSources.add("verify")	<< glu::ComputeSource(shaderVerify.str());
1293 }
1294 
createInstance(Context& context) const1295 vkt::TestInstance* WriteSampleTest::createInstance (Context& context) const
1296 {
1297 	return new WriteSampleTestInstance{context, m_params};
1298 }
1299 
iterate(void)1300 tcu::TestStatus WriteSampleTestInstance::iterate (void)
1301 {
1302 	const auto&	vkd			= m_context.getDeviceInterface();
1303 	const auto	device		= m_context.getDevice();
1304 	auto&		allocator	= m_context.getDefaultAllocator();
1305 	const auto	queue		= m_context.getUniversalQueue();
1306 	const auto	queueIndex	= m_context.getUniversalQueueFamilyIndex();
1307 	const auto	extent3D	= getExtent3D(m_params.sampleCount);
1308 
1309 	// Create storage image and verification image.
1310 	const vk::VkImageCreateInfo storageImageInfo =
1311 	{
1312 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
1313 		nullptr,									// const void*				pNext;
1314 		0u,											// VkImageCreateFlags		flags;
1315 		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
1316 		WriteSampleTest::kImageFormat,				// VkFormat					format;
1317 		extent3D,									// VkExtent3D				extent;
1318 		1u,											// deUint32					mipLevels;
1319 		1u,											// deUint32					arrayLayers;
1320 		m_params.sampleCount,						// VkSampleCountFlagBits	samples;
1321 		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
1322 		WriteSampleTest::kUsageFlags,				// VkImageUsageFlags		usage;
1323 		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
1324 		1u,											// deUint32					queueFamilyIndexCount;
1325 		&queueIndex,								// const deUint32*			pQueueFamilyIndices;
1326 		vk::VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			initialLayout;
1327 	};
1328 
1329 	const vk::VkImageCreateInfo verificationImageInfo =
1330 	{
1331 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
1332 		nullptr,									// const void*				pNext;
1333 		0u,											// VkImageCreateFlags		flags;
1334 		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
1335 		WriteSampleTest::kImageFormat,				// VkFormat					format;
1336 		extent3D,									// VkExtent3D				extent;
1337 		1u,											// deUint32					mipLevels;
1338 		1u,											// deUint32					arrayLayers;
1339 		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
1340 		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
1341 		WriteSampleTest::kUsageFlags,				// VkImageUsageFlags		usage;
1342 		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
1343 		1u,											// deUint32					queueFamilyIndexCount;
1344 		&queueIndex,								// const deUint32*			pQueueFamilyIndices;
1345 		vk::VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			initialLayout;
1346 	};
1347 
1348 	vk::ImageWithMemory storageImgPrt		{vkd, device, allocator, storageImageInfo, vk::MemoryRequirement::Any};
1349 	vk::ImageWithMemory verificationImgPtr	{vkd, device, allocator, verificationImageInfo, vk::MemoryRequirement::Any};
1350 
1351 	const vk::VkImageSubresourceRange kSubresourceRange =
1352 	{
1353 		vk::VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
1354 		0u,								// deUint32				baseMipLevel;
1355 		1u,								// deUint32				levelCount;
1356 		0u,								// deUint32				baseArrayLayer;
1357 		1u,								// deUint32				layerCount;
1358 	};
1359 
1360 	auto storageImgViewPtr		= vk::makeImageView(vkd, device, storageImgPrt.get(), vk::VK_IMAGE_VIEW_TYPE_2D, WriteSampleTest::kImageFormat, kSubresourceRange);
1361 	auto verificationImgViewPtr	= vk::makeImageView(vkd, device, verificationImgPtr.get(), vk::VK_IMAGE_VIEW_TYPE_2D, WriteSampleTest::kImageFormat, kSubresourceRange);
1362 
1363 	// Prepare a staging buffer to check verification image.
1364 	const auto				tcuFormat			= vk::mapVkFormat(WriteSampleTest::kImageFormat);
1365 	const VkDeviceSize		bufferSize			= extent3D.width * extent3D.height * extent3D.depth * tcu::getPixelSize(tcuFormat);
1366 	const auto				stagingBufferInfo	= vk::makeBufferCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1367 	vk::BufferWithMemory	stagingBuffer		{vkd, device, allocator, stagingBufferInfo, MemoryRequirement::HostVisible};
1368 
1369 	// Descriptor set layout.
1370 	vk::DescriptorSetLayoutBuilder layoutBuilder;
1371 	layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
1372 	layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
1373 	auto descriptorSetLayout = layoutBuilder.build(vkd, device);
1374 
1375 	// Descriptor pool.
1376 	vk::DescriptorPoolBuilder poolBuilder;
1377 	poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2u);
1378 	auto descriptorPool = poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1379 
1380 	// Descriptor set.
1381 	const auto descriptorSet = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
1382 
1383 	// Update descriptor set using the images.
1384 	const auto storageImgDescriptorInfo			= vk::makeDescriptorImageInfo(DE_NULL, storageImgViewPtr.get(), vk::VK_IMAGE_LAYOUT_GENERAL);
1385 	const auto verificationImgDescriptorInfo	= vk::makeDescriptorImageInfo(DE_NULL, verificationImgViewPtr.get(), vk::VK_IMAGE_LAYOUT_GENERAL);
1386 
1387 	vk::DescriptorSetUpdateBuilder updateBuilder;
1388 	updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &storageImgDescriptorInfo);
1389 	updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &verificationImgDescriptorInfo);
1390 	updateBuilder.update(vkd, device);
1391 
1392 	// Create write and verification compute pipelines.
1393 	auto shaderWriteModule	= ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("write"), 0u);
1394 	auto shaderVerifyModule	= ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("verify"), 0u);
1395 	auto pipelineLayout		= vk::makePipelineLayout(vkd, device, descriptorSetLayout.get());
1396 
1397 	const vk::VkComputePipelineCreateInfo writePipelineCreateInfo =
1398 	{
1399 		vk::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1400 		nullptr,
1401 		0u,															// flags
1402 		{															// compute shader
1403 			vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
1404 			nullptr,													// const void*							pNext;
1405 			0u,															// VkPipelineShaderStageCreateFlags		flags;
1406 			vk::VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits				stage;
1407 			shaderWriteModule.getModule(),								// VkShaderModule						module;
1408 			"main",														// const char*							pName;
1409 			nullptr,													// const VkSpecializationInfo*			pSpecializationInfo;
1410 		},
1411 		pipelineLayout.get(),										// layout
1412 		DE_NULL,													// basePipelineHandle
1413 		0,															// basePipelineIndex
1414 	};
1415 
1416 	auto verificationPipelineCreateInfo = writePipelineCreateInfo;
1417 	verificationPipelineCreateInfo.stage.module = shaderVerifyModule.getModule();
1418 
1419 	auto writePipeline			= vk::createComputePipeline(vkd, device, DE_NULL, &writePipelineCreateInfo);
1420 	auto verificationPipeline	= vk::createComputePipeline(vkd, device, DE_NULL, &verificationPipelineCreateInfo);
1421 
1422 	// Transition images to the correct layout and buffers at different stages.
1423 	auto storageImgPreClearBarrier			= vk::makeImageMemoryBarrier(0, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, storageImgPrt.get(), kSubresourceRange);
1424 	auto storageImgPreShaderBarrier			= vk::makeImageMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, vk::VK_IMAGE_LAYOUT_GENERAL, storageImgPrt.get(), kSubresourceRange);
1425 	auto verificationImgPreShaderBarrier	= vk::makeImageMemoryBarrier(0, vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL, verificationImgPtr.get(), kSubresourceRange);
1426 	auto storageImgPreVerificationBarrier	= vk::makeImageMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_SHADER_READ_BIT, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL, storageImgPrt.get(), kSubresourceRange);
1427 	auto verificationImgPostBarrier			= vk::makeImageMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationImgPtr.get(), kSubresourceRange);
1428 	auto bufferBarrier						= vk::makeBufferMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, stagingBuffer.get(), 0ull, bufferSize);
1429 
1430 	// Command buffer.
1431 	auto cmdPool		= vk::makeCommandPool(vkd, device, queueIndex);
1432 	auto cmdBufferPtr	= vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1433 	auto cmdBuffer		= cmdBufferPtr.get();
1434 
1435 	// Clear color for the storage image.
1436 	const auto clearColor = vk::makeClearValueColor(WriteSampleTest::kClearColor);
1437 
1438 	const vk::VkBufferImageCopy	copyRegion =
1439 	{
1440 		0ull,									// VkDeviceSize				bufferOffset;
1441 		extent3D.width,							// deUint32					bufferRowLength;
1442 		extent3D.height,						// deUint32					bufferImageHeight;
1443 		{										// VkImageSubresourceLayers	imageSubresource;
1444 			vk::VK_IMAGE_ASPECT_COLOR_BIT,			// VkImageAspectFlags	aspectMask;
1445 			0u,										// deUint32				mipLevel;
1446 			0u,										// deUint32				baseArrayLayer;
1447 			1u,										// deUint32				layerCount;
1448 		},
1449 		{ 0, 0, 0 },							// VkOffset3D				imageOffset;
1450 		extent3D,								// VkExtent3D				imageExtent;
1451 	};
1452 
1453 	// Record and submit commands.
1454 	vk::beginCommandBuffer(vkd, cmdBuffer);
1455 		// Clear storage image.
1456 		vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &storageImgPreClearBarrier);
1457 		vkd.cmdClearColorImage(cmdBuffer, storageImgPrt.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor.color, 1u, &kSubresourceRange);
1458 
1459 		// Bind write pipeline and descriptor set.
1460 		vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, writePipeline.get());
1461 		vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout.get(), 0, 1u, &descriptorSet.get(), 0u, nullptr);
1462 
1463 		// Transition images to the appropriate layout before running the shader.
1464 		vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &storageImgPreShaderBarrier);
1465 		vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &verificationImgPreShaderBarrier);
1466 
1467 		// Run shader.
1468 		vkd.cmdDispatch(cmdBuffer, extent3D.width, extent3D.height, extent3D.depth);
1469 
1470 		// Bind verification pipeline.
1471 		vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, verificationPipeline.get());
1472 
1473 		// Make sure writes happen before reads in the second dispatch for the storage image.
1474 		vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &storageImgPreVerificationBarrier);
1475 
1476 		// Run verification shader.
1477 		vkd.cmdDispatch(cmdBuffer, extent3D.width, extent3D.height, extent3D.depth);
1478 
1479 		// Change verification image layout to prepare the transfer.
1480 		vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &verificationImgPostBarrier);
1481 
1482 		// Copy verification image to staging buffer.
1483 		vkd.cmdCopyImageToBuffer(cmdBuffer, verificationImgPtr.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingBuffer.get(), 1u, &copyRegion);
1484 		vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0, 0u, nullptr, 1u, &bufferBarrier, 0u, nullptr);
1485 
1486 	vk::endCommandBuffer(vkd, cmdBuffer);
1487 
1488 	// Run shaders.
1489 	vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1490 
1491 	// Read buffer pixels.
1492 	const auto& bufferAlloc = stagingBuffer.getAllocation();
1493 	vk::invalidateAlloc(vkd, device, bufferAlloc);
1494 
1495 	// Copy buffer data to texture level and verify all pixels have the proper color.
1496 	tcu::TextureLevel texture {tcuFormat, static_cast<int>(extent3D.width), static_cast<int>(extent3D.height), static_cast<int>(extent3D.depth)};
1497 	const auto access = texture.getAccess();
1498 	deMemcpy(access.getDataPtr(), reinterpret_cast<char*>(bufferAlloc.getHostPtr()) + bufferAlloc.getOffset(), static_cast<size_t>(bufferSize));
1499 
1500 	for (int i = 0; i < access.getWidth(); ++i)
1501 	for (int j = 0; j < access.getHeight(); ++j)
1502 	for (int k = 0; k < access.getDepth(); ++k)
1503 	{
1504 		if (access.getPixel(i, j, k) != WriteSampleTest::kGoodColor)
1505 		{
1506 			std::ostringstream msg;
1507 			msg << "Invalid result at pixel (" << i << ", " << j << ", " << k << "); check error mask for more details";
1508 			m_context.getTestContext().getLog() << tcu::TestLog::Image("ErrorMask", "Indicates which pixels have unexpected values", access);
1509 			return tcu::TestStatus::fail(msg.str());
1510 		}
1511 	}
1512 
1513 	return tcu::TestStatus::pass("Pass");
1514 }
1515 
1516 using WriteSampleMaskParams = WriteSampleParams;
1517 
1518 class WriteSampleMaskTestCase : public vkt::TestCase
1519 {
1520 public:
1521 							WriteSampleMaskTestCase		(tcu::TestContext& testCtx, const std::string& name, const WriteSampleMaskParams& params);
~WriteSampleMaskTestCase(void)1522 	virtual					~WriteSampleMaskTestCase	(void) {}
1523 
1524 	virtual void			checkSupport				(Context& context) const;
1525 	virtual void			initPrograms				(vk::SourceCollections& programCollection) const;
1526 	virtual TestInstance*	createInstance				(Context& context) const;
1527 	static deUint32			getBufferElems				(deUint32 sampleCount);
1528 
1529 	static const tcu::Vec4						kClearColor;
1530 	static const tcu::Vec4						kWriteColor;
1531 
1532 	static constexpr vk::VkFormat				kImageFormat	= vk::VK_FORMAT_R8G8B8A8_UNORM;
1533 	static constexpr vk::VkImageUsageFlags		kUsageFlags		= (vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
1534 	static constexpr vk::VkFormatFeatureFlags	kFeatureFlags	= (vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
1535 
1536 private:
1537 	WriteSampleMaskParams	m_params;
1538 };
1539 
1540 const tcu::Vec4 WriteSampleMaskTestCase::kClearColor	{0.0f, 0.0f, 0.0f, 1.0f};
1541 const tcu::Vec4 WriteSampleMaskTestCase::kWriteColor	{0.0f, 0.0f, 1.0f, 1.0f};
1542 
1543 class WriteSampleMaskTestInstance : public vkt::TestInstance
1544 {
1545 public:
1546 								WriteSampleMaskTestInstance		(Context& context, const WriteSampleMaskParams& params);
~WriteSampleMaskTestInstance(void)1547 	virtual						~WriteSampleMaskTestInstance	(void) {}
1548 
1549 	virtual tcu::TestStatus		iterate							(void);
1550 
1551 private:
1552 	WriteSampleMaskParams		m_params;
1553 };
1554 
WriteSampleMaskTestCase(tcu::TestContext& testCtx, const std::string& name, const WriteSampleMaskParams& params)1555 WriteSampleMaskTestCase::WriteSampleMaskTestCase (tcu::TestContext& testCtx, const std::string& name, const WriteSampleMaskParams& params)
1556 	: vkt::TestCase	(testCtx, name)
1557 	, m_params		(params)
1558 {}
1559 
checkSupport(Context& context) const1560 void WriteSampleMaskTestCase::checkSupport (Context& context) const
1561 {
1562 	const auto&	vki				= context.getInstanceInterface();
1563 	const auto	physicalDevice	= context.getPhysicalDevice();
1564 
1565 	// Check if sampleRateShading is supported.
1566 	if(!vk::getPhysicalDeviceFeatures(vki, physicalDevice).sampleRateShading)
1567 		TCU_THROW(NotSupportedError, "Sample rate shading is not supported");
1568 
1569 	// Check the specific image format.
1570 	const auto properties = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kImageFormat);
1571 	if (!(properties.optimalTilingFeatures & kFeatureFlags))
1572 		TCU_THROW(NotSupportedError, "Format does not support the required features");
1573 
1574 	// Check the supported sample count.
1575 	const auto imgProps = vk::getPhysicalDeviceImageFormatProperties(vki, physicalDevice, kImageFormat, vk::VK_IMAGE_TYPE_2D, vk::VK_IMAGE_TILING_OPTIMAL, kUsageFlags, 0u);
1576 	if (!(imgProps.sampleCounts & m_params.sampleCount))
1577 		TCU_THROW(NotSupportedError, "Format does not support the required sample count");
1578 
1579 	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType);
1580 }
1581 
initPrograms(vk::SourceCollections& programCollection) const1582 void WriteSampleMaskTestCase::initPrograms (vk::SourceCollections& programCollection) const
1583 {
1584 	const auto bpc			= de::toString(bitsPerCoord(m_params.sampleCount));
1585 	const auto size			= imageSize(m_params.sampleCount);
1586 	const auto bufferElems	= getBufferElems(m_params.sampleCount);
1587 
1588 	// Passthrough vertex shader.
1589 	std::ostringstream vertShader;
1590 
1591 	vertShader
1592 		<< "#version 450\n"
1593 		<< "layout (location=0) in vec2 inPos;\n"
1594 		<< "void main()\n"
1595 		<< "{\n"
1596 		<< "    gl_Position = vec4(inPos, 0.0, 1.0);\n"
1597 		<< "}\n"
1598 		;
1599 
1600 	// Fragment shader common header.
1601 	std::ostringstream fragHeader;
1602 
1603 	fragHeader
1604 		<< "#version 450\n"
1605 		<< "\n"
1606 		// The color attachment is useless for the second subpass but avoids having to use an empty subpass and verifying the sample
1607 		// count is valid for it.
1608 		<< "layout (location=0) out vec4 outColor;\n"
1609 		<< "\n"
1610 		<< "vec4 wcolor = " << getShaderDecl(kWriteColor) << ";\n"
1611 		<< "vec4 ccolor = " << getShaderDecl(kClearColor) << ";\n"
1612 		<< "\n"
1613 		;
1614 
1615 	const auto fragHeaderStr = fragHeader.str();
1616 
1617 	// Fragment shader setting the sample mask and writing to the output color attachment. The sample mask will guarantee each image
1618 	// pixel gets a different combination of sample bits set, allowing the fragment shader to write in that sample or not, from all
1619 	// zeros in pixel (0, 0) to all ones in the opposite corner.
1620 	std::ostringstream fragShaderWrite;
1621 
1622 	fragShaderWrite
1623 		<< fragHeaderStr
1624 		<< "void main()\n"
1625 		<< "{\n"
1626 		<< "    uvec2 ucoords    = uvec2(gl_FragCoord);\n"
1627 		<< "    ivec2 icoords    = ivec2(ucoords);\n"
1628 		<< "    gl_SampleMask[0] = int((ucoords.x << " << bpc << ") | ucoords.y);\n"
1629 		<< "    outColor         = wcolor;\n"
1630 		<< "}\n"
1631 		;
1632 
1633 	// Fragment shader reading from the previous output color attachment and copying the state to an SSBO for verification.
1634 	std::ostringstream fragShaderCheck;
1635 
1636 	const bool isMultiSample = (m_params.sampleCount != vk::VK_SAMPLE_COUNT_1_BIT);
1637 	fragShaderCheck
1638 		<< fragHeaderStr
1639 		<< "layout(set=0, binding=0, input_attachment_index=0) uniform subpassInput" << (isMultiSample ? "MS" : "") << " inputAttachment;\n"
1640 		<< "layout(set=0, binding=1, std430) buffer StorageBuffer {\n"
1641 		<< "    int writeFlags[" << bufferElems << "];\n"
1642 		<< "} sb;\n"
1643 		<< "\n"
1644 		<< "void main()\n"
1645 		<< "{\n"
1646 		<< "    uvec2 ucoords          = uvec2(gl_FragCoord);\n"
1647 		<< "    ivec2 icoords          = ivec2(ucoords);\n"
1648 		<< "    uint  bufferp          = ((ucoords.y * " << size.width << " + ucoords.x) * " << m_params.sampleCount << ") + uint(gl_SampleID);\n"
1649 		<< "    vec4  storedc          = subpassLoad(inputAttachment" << (isMultiSample ? ", gl_SampleID" : "") << ");\n"
1650 		<< "    sb.writeFlags[bufferp] = ((storedc == wcolor) ? 1 : ((storedc == ccolor) ? 0 : 2));\n"
1651 		<< "    outColor               = storedc;\n"
1652 		<< "}\n"
1653 		;
1654 
1655 	programCollection.glslSources.add("vert")		<< glu::VertexSource(vertShader.str());
1656 	programCollection.glslSources.add("frag_write")	<< glu::FragmentSource(fragShaderWrite.str());
1657 	programCollection.glslSources.add("frag_check")	<< glu::FragmentSource(fragShaderCheck.str());
1658 }
1659 
createInstance(Context& context) const1660 TestInstance* WriteSampleMaskTestCase::createInstance (Context& context) const
1661 {
1662 	return new WriteSampleMaskTestInstance(context, m_params);
1663 }
1664 
getBufferElems(deUint32 sampleCount)1665 deUint32 WriteSampleMaskTestCase::getBufferElems (deUint32 sampleCount)
1666 {
1667 	const auto imgSize = imageSize(sampleCount);
1668 	return (imgSize.width * imgSize.height * sampleCount);
1669 }
1670 
WriteSampleMaskTestInstance(Context& context, const WriteSampleMaskParams& params)1671 WriteSampleMaskTestInstance::WriteSampleMaskTestInstance (Context& context, const WriteSampleMaskParams& params)
1672 	: vkt::TestInstance	(context)
1673 	, m_params			(params)
1674 {}
1675 
iterate(void)1676 tcu::TestStatus WriteSampleMaskTestInstance::iterate (void)
1677 {
1678 	const auto&		vki					= m_context.getInstanceInterface();
1679 	const auto&		vkd					= m_context.getDeviceInterface();
1680 	const auto		physicalDevice		= m_context.getPhysicalDevice();
1681 	const auto		device				= m_context.getDevice();
1682 	auto&			alloc				= m_context.getDefaultAllocator();
1683 	const auto		queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1684 	const auto		queue				= m_context.getUniversalQueue();
1685 
1686 	static constexpr auto	kImageFormat	= WriteSampleMaskTestCase::kImageFormat;
1687 	static constexpr auto	kImageUsage		= WriteSampleMaskTestCase::kUsageFlags;
1688 	const auto				kImageExtent	= getExtent3D(m_params.sampleCount);
1689 	const auto				kBufferElems	= WriteSampleMaskTestCase::getBufferElems(m_params.sampleCount);
1690 	const auto				kBufferSize		= static_cast<vk::VkDeviceSize>(kBufferElems * sizeof(deInt32));
1691 
1692 	// Create image.
1693 	const vk::VkImageCreateInfo imageCreateInfo =
1694 	{
1695 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
1696 		nullptr,									//	const void*				pNext;
1697 		0u,											//	VkImageCreateFlags		flags;
1698 		vk::VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
1699 		kImageFormat,								//	VkFormat				format;
1700 		kImageExtent,								//	VkExtent3D				extent;
1701 		1u,											//	deUint32				mipLevels;
1702 		1u,											//	deUint32				arrayLayers;
1703 		m_params.sampleCount,						//	VkSampleCountFlagBits	samples;
1704 		vk::VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
1705 		kImageUsage,								//	VkImageUsageFlags		usage;
1706 		vk::VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
1707 		0u,											//	deUint32				queueFamilyIndexCount;
1708 		nullptr,									//	const deUint32*			pQueueFamilyIndices;
1709 		vk::VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
1710 	};
1711 
1712 	const vk::ImageWithMemory colorImage	(vkd, device, alloc, imageCreateInfo, vk::MemoryRequirement::Any);
1713 	const vk::ImageWithMemory auxiliarImage	(vkd, device, alloc, imageCreateInfo, vk::MemoryRequirement::Any);	// For the second subpass.
1714 
1715 	// Image views.
1716 	const auto subresourceRange		= vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1717 	const auto colorImageView		= vk::makeImageView(vkd, device, colorImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, kImageFormat, subresourceRange);
1718 	const auto auxiliarImageView	= vk::makeImageView(vkd, device, auxiliarImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, kImageFormat, subresourceRange);
1719 
1720 	// Create storage buffer used to verify results.
1721 	const vk::BufferWithMemory storageBuffer(vkd, device, alloc, vk::makeBufferCreateInfo(kBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::HostVisible);
1722 
1723 	// Full-screen quad.
1724 	const std::vector<tcu::Vec2> quadVertices =
1725 	{
1726 		tcu::Vec2(-1.0f,  1.0f),	// Lower left
1727 		tcu::Vec2( 1.0f,  1.0f),	// Lower right
1728 		tcu::Vec2( 1.0f, -1.0f),	// Top right.
1729 		tcu::Vec2(-1.0f,  1.0f),	// Lower left
1730 		tcu::Vec2( 1.0f, -1.0f),	// Top right.
1731 		tcu::Vec2(-1.0f, -1.0f),	// Top left.
1732 	};
1733 
1734 	// Vertex buffer.
1735 	const auto					vertexBufferSize	= static_cast<vk::VkDeviceSize>(quadVertices.size() * sizeof(decltype(quadVertices)::value_type));
1736 	const vk::BufferWithMemory	vertexBuffer		(vkd, device, alloc, vk::makeBufferCreateInfo(vertexBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), vk::MemoryRequirement::HostVisible);
1737 	const auto&					vertexBufferAlloc	= vertexBuffer.getAllocation();
1738 	void*						vertexBufferPtr		= vertexBufferAlloc.getHostPtr();
1739 	const vk::VkDeviceSize		vertexBufferOffset	= 0;
1740 	deMemcpy(vertexBufferPtr, quadVertices.data(), static_cast<size_t>(vertexBufferSize));
1741 	vk::flushAlloc(vkd, device, vertexBufferAlloc);
1742 
1743 	// Descriptor set layout.
1744 	vk::DescriptorSetLayoutBuilder setLayoutBuilder;
1745 	setLayoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
1746 	setLayoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
1747 	const auto descriptorSetLayout = setLayoutBuilder.build(vkd, device);
1748 
1749 	// Descriptor pool and set.
1750 	vk::DescriptorPoolBuilder poolBuilder;
1751 	poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u);
1752 	poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u);
1753 	const auto descriptorPool	= poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1754 	const auto descriptorSet	= vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
1755 
1756 	// Render pass.
1757 	const std::vector<vk::VkAttachmentDescription> attachments =
1758 	{
1759 		// Main color attachment.
1760 		{
1761 			0u,												//	VkAttachmentDescriptionFlags	flags;
1762 			kImageFormat,									//	VkFormat						format;
1763 			m_params.sampleCount,							//	VkSampleCountFlagBits			samples;
1764 			vk::VK_ATTACHMENT_LOAD_OP_CLEAR,				//	VkAttachmentLoadOp				loadOp;
1765 			vk::VK_ATTACHMENT_STORE_OP_STORE,				//	VkAttachmentStoreOp				storeOp;
1766 			vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//	VkAttachmentLoadOp				stencilLoadOp;
1767 			vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			//	VkAttachmentStoreOp				stencilStoreOp;
1768 			vk::VK_IMAGE_LAYOUT_UNDEFINED,					//	VkImageLayout					initialLayout;
1769 			vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,	//	VkImageLayout					finalLayout;
1770 		},
1771 		// Auxiliar color attachment for the check pass.
1772 		{
1773 			0u,												//	VkAttachmentDescriptionFlags	flags;
1774 			kImageFormat,									//	VkFormat						format;
1775 			m_params.sampleCount,							//	VkSampleCountFlagBits			samples;
1776 			vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//	VkAttachmentLoadOp				loadOp;
1777 			vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			//	VkAttachmentStoreOp				storeOp;
1778 			vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//	VkAttachmentLoadOp				stencilLoadOp;
1779 			vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			//	VkAttachmentStoreOp				stencilStoreOp;
1780 			vk::VK_IMAGE_LAYOUT_UNDEFINED,					//	VkImageLayout					initialLayout;
1781 			vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout					finalLayout;
1782 		},
1783 	};
1784 
1785 	const vk::VkAttachmentReference colorAttachmentReference =
1786 	{
1787 		0u,												//	deUint32		attachment;
1788 		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout	layout;
1789 	};
1790 
1791 	const vk::VkAttachmentReference colorAsInputAttachment =
1792 	{
1793 		0u,												//	deUint32		attachment;
1794 		vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,	//	VkImageLayout	layout;
1795 	};
1796 
1797 	const vk::VkAttachmentReference auxiliarAttachmentReference =
1798 	{
1799 		1u,												//	deUint32		attachment;
1800 		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout	layout;
1801 	};
1802 
1803 	const std::vector<vk::VkSubpassDescription> subpasses =
1804 	{
1805 		// First subpass writing to the main attachment.
1806 		{
1807 			0u,										//	VkSubpassDescriptionFlags		flags;
1808 			vk::VK_PIPELINE_BIND_POINT_GRAPHICS,	//	VkPipelineBindPoint				pipelineBindPoint;
1809 			0u,										//	deUint32						inputAttachmentCount;
1810 			nullptr,								//	const VkAttachmentReference*	pInputAttachments;
1811 			1u,										//	deUint32						colorAttachmentCount;
1812 			&colorAttachmentReference,				//	const VkAttachmentReference*	pColorAttachments;
1813 			nullptr,								//	const VkAttachmentReference*	pResolveAttachments;
1814 			nullptr,								//	const VkAttachmentReference*	pDepthStencilAttachment;
1815 			0u,										//	deUint32						preserveAttachmentCount;
1816 			nullptr,								//	const deUint32*					pPreserveAttachments;
1817 		},
1818 		// Second subpass writing to the auxiliar attachment.
1819 		{
1820 			0u,										//	VkSubpassDescriptionFlags		flags;
1821 			vk::VK_PIPELINE_BIND_POINT_GRAPHICS,	//	VkPipelineBindPoint				pipelineBindPoint;
1822 			1u,										//	deUint32						inputAttachmentCount;
1823 			&colorAsInputAttachment,				//	const VkAttachmentReference*	pInputAttachments;
1824 			1u,										//	deUint32						colorAttachmentCount;
1825 			&auxiliarAttachmentReference,			//	const VkAttachmentReference*	pColorAttachments;
1826 			nullptr,								//	const VkAttachmentReference*	pResolveAttachments;
1827 			nullptr,								//	const VkAttachmentReference*	pDepthStencilAttachment;
1828 			0u,										//	deUint32						preserveAttachmentCount;
1829 			nullptr,								//	const deUint32*					pPreserveAttachments;
1830 		},
1831 	};
1832 
1833 	const std::vector<vk::VkSubpassDependency> subpassDependencies =
1834 	{
1835 		// First subpass writes to the color attachment and second subpass reads it as an input attachment.
1836 		{
1837 			0u,													//	deUint32				srcSubpass;
1838 			1u,													//	deUint32				dstSubpass;
1839 			vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,	//	VkPipelineStageFlags	srcStageMask;
1840 			vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,			//	VkPipelineStageFlags	dstStageMask;
1841 			vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			//	VkAccessFlags			srcAccessMask;
1842 			vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,			//	VkAccessFlags			dstAccessMask;
1843 			0u,													//	VkDependencyFlags		dependencyFlags;
1844 		},
1845 	};
1846 
1847 	const vk::VkRenderPassCreateInfo renderPassInfo =
1848 	{
1849 		vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,		//	VkStructureType					sType;
1850 		nullptr,											//	const void*						pNext;
1851 		0u,													//	VkRenderPassCreateFlags			flags;
1852 		static_cast<deUint32>(attachments.size()),			//	deUint32						attachmentCount;
1853 		attachments.data(),									//	const VkAttachmentDescription*	pAttachments;
1854 		static_cast<deUint32>(subpasses.size()),			//	deUint32						subpassCount;
1855 		subpasses.data(),									//	const VkSubpassDescription*		pSubpasses;
1856 		static_cast<deUint32>(subpassDependencies.size()),	//	deUint32						dependencyCount;
1857 		subpassDependencies.data(),							//	const VkSubpassDependency*		pDependencies;
1858 	};
1859 	RenderPassWrapper renderPass (m_params.pipelineConstructionType, vkd, device, &renderPassInfo);
1860 
1861 	// Framebuffer.
1862 	const std::vector<vk::VkImage>		images		=
1863 	{
1864 		colorImage.get(),
1865 		auxiliarImage.get(),
1866 	};
1867 	const std::vector<vk::VkImageView>	imageViews	=
1868 	{
1869 		colorImageView.get(),
1870 		auxiliarImageView.get(),
1871 	};
1872 	renderPass.createFramebuffer(vkd, device, static_cast<deUint32>(imageViews.size()), images.data(), imageViews.data(), kImageExtent.width, kImageExtent.height);
1873 
1874 	// Empty pipeline layout for the first subpass.
1875 	const PipelineLayoutWrapper emptyPipelineLayout (m_params.pipelineConstructionType, vkd, device);
1876 
1877 	// Pipeline layout for the second subpass.
1878 	const PipelineLayoutWrapper checkPipelineLayout (m_params.pipelineConstructionType, vkd, device, descriptorSetLayout.get());
1879 
1880 	// Shader modules.
1881 	const auto vertModule	= ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
1882 	const auto writeModule	= ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag_write"), 0u);
1883 	const auto checkModule	= ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag_check"), 0u);
1884 
1885 	const std::vector<vk::VkVertexInputBindingDescription> vertexBindings =
1886 	{
1887 		{
1888 			0u,																	//	deUint32			binding;
1889 			static_cast<deUint32>(sizeof(decltype(quadVertices)::value_type)),	//	deUint32			stride;
1890 			vk::VK_VERTEX_INPUT_RATE_VERTEX,									//	VkVertexInputRate	inputRate;
1891 		},
1892 	};
1893 
1894 	const std::vector<vk::VkVertexInputAttributeDescription> vertexAttributes =
1895 	{
1896 		{
1897 			0u,								//	deUint32	location;
1898 			0u,								//	deUint32	binding;
1899 			vk::VK_FORMAT_R32G32_SFLOAT,	//	VkFormat	format;
1900 			0u,								//	deUint32	offset;
1901 		},
1902 	};
1903 
1904 	const vk::VkPipelineVertexInputStateCreateInfo vertexInputInfo =
1905 	{
1906 		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	//	VkStructureType								sType;
1907 		nullptr,														//	const void*									pNext;
1908 		0u,																//	VkPipelineVertexInputStateCreateFlags		flags;
1909 		static_cast<deUint32>(vertexBindings.size()),					//	deUint32									vertexBindingDescriptionCount;
1910 		vertexBindings.data(),											//	const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
1911 		static_cast<deUint32>(vertexAttributes.size()),					//	deUint32									vertexAttributeDescriptionCount;
1912 		vertexAttributes.data(),										//	const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1913 	};
1914 
1915 	const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo =
1916 	{
1917 		vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	//	VkStructureType							sType;
1918 		nullptr,															//	const void*								pNext;
1919 		0u,																	//	VkPipelineInputAssemblyStateCreateFlags	flags;
1920 		vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							//	VkPrimitiveTopology						topology;
1921 		VK_FALSE,															//	VkBool32								primitiveRestartEnable;
1922 	};
1923 
1924 	const std::vector<VkViewport>	viewport	{ vk::makeViewport(kImageExtent) };
1925 	const std::vector<VkRect2D>		scissor		{ vk::makeRect2D(kImageExtent) };
1926 
1927 	const vk::VkPipelineMultisampleStateCreateInfo multisampleInfo =
1928 	{
1929 		vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	//	VkStructureType							sType;
1930 		nullptr,														//	const void*								pNext;
1931 		0u,																//	VkPipelineMultisampleStateCreateFlags	flags;
1932 		m_params.sampleCount,											//	VkSampleCountFlagBits					rasterizationSamples;
1933 		VK_FALSE,														//	VkBool32								sampleShadingEnable;
1934 		1.0f,															//	float									minSampleShading;
1935 		nullptr,														//	const VkSampleMask*						pSampleMask;
1936 		VK_FALSE,														//	VkBool32								alphaToCoverageEnable;
1937 		VK_FALSE,														//	VkBool32								alphaToOneEnable;
1938 	};
1939 
1940 	const auto stencilState = vk::makeStencilOpState(vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0xFFu, 0xFFu, 0u);
1941 
1942 	const vk::VkPipelineDepthStencilStateCreateInfo depthStencilInfo =
1943 	{
1944 		vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	//	VkStructureType							sType;
1945 		nullptr,														//	const void*								pNext;
1946 		0u,																//	VkPipelineDepthStencilStateCreateFlags	flags;
1947 		VK_FALSE,														//	VkBool32								depthTestEnable;
1948 		VK_FALSE,														//	VkBool32								depthWriteEnable;
1949 		vk::VK_COMPARE_OP_ALWAYS,										//	VkCompareOp								depthCompareOp;
1950 		VK_FALSE,														//	VkBool32								depthBoundsTestEnable;
1951 		VK_FALSE,														//	VkBool32								stencilTestEnable;
1952 		stencilState,													//	VkStencilOpState						front;
1953 		stencilState,													//	VkStencilOpState						back;
1954 		0.0f,															//	float									minDepthBounds;
1955 		1.0f,															//	float									maxDepthBounds;
1956 	};
1957 
1958 	const vk::VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
1959 	{
1960 		VK_FALSE,					//	VkBool32				blendEnable;
1961 		vk::VK_BLEND_FACTOR_ZERO,	//	VkBlendFactor			srcColorBlendFactor;
1962 		vk::VK_BLEND_FACTOR_ZERO,	//	VkBlendFactor			dstColorBlendFactor;
1963 		vk::VK_BLEND_OP_ADD,		//	VkBlendOp				colorBlendOp;
1964 		vk::VK_BLEND_FACTOR_ZERO,	//	VkBlendFactor			srcAlphaBlendFactor;
1965 		vk::VK_BLEND_FACTOR_ZERO,	//	VkBlendFactor			dstAlphaBlendFactor;
1966 		vk::VK_BLEND_OP_ADD,		//	VkBlendOp				alphaBlendOp;
1967 		(							//	VkColorComponentFlags	colorWriteMask;
1968 			vk::VK_COLOR_COMPONENT_R_BIT	|
1969 			vk::VK_COLOR_COMPONENT_G_BIT	|
1970 			vk::VK_COLOR_COMPONENT_B_BIT	|
1971 			vk::VK_COLOR_COMPONENT_A_BIT	),
1972 	};
1973 
1974 	const vk::VkPipelineColorBlendStateCreateInfo colorBlendInfo =
1975 	{
1976 		vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	//	VkStructureType								sType;
1977 		nullptr,														//	const void*									pNext;
1978 		0u,																//	VkPipelineColorBlendStateCreateFlags		flags;
1979 		VK_FALSE,														//	VkBool32									logicOpEnable;
1980 		vk::VK_LOGIC_OP_NO_OP,											//	VkLogicOp									logicOp;
1981 		1u,																//	deUint32									attachmentCount;
1982 		&colorBlendAttachmentState,										//	const VkPipelineColorBlendAttachmentState*	pAttachments;
1983 		{ .0f, .0f, .0f, .0f },											//	float										blendConstants[4];
1984 	};
1985 
1986 	const vk::VkPipelineDynamicStateCreateInfo dynamicStateInfo =
1987 	{
1988 		vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	//	VkStructureType						sType;
1989 		nullptr,													//	const void*							pNext;
1990 		0u,															//	VkPipelineDynamicStateCreateFlags	flags;
1991 		0u,															//	deUint32							dynamicStateCount;
1992 		nullptr,													//	const VkDynamicState*				pDynamicStates;
1993 	};
1994 
1995 	// Pipeline for the first subpass.
1996 	vk::GraphicsPipelineWrapper firstSubpassPipeline(vki, vkd, physicalDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType);
1997 	firstSubpassPipeline.setDynamicState(&dynamicStateInfo)
1998 						.setDefaultRasterizationState()
1999 						.setupVertexInputState(&vertexInputInfo, &inputAssemblyInfo)
2000 						.setupPreRasterizationShaderState(viewport, scissor, emptyPipelineLayout, *renderPass, 0u, vertModule)
2001 						.setupFragmentShaderState(emptyPipelineLayout, *renderPass, 0u, writeModule, &depthStencilInfo, &multisampleInfo)
2002 						.setupFragmentOutputState(*renderPass, 0u, &colorBlendInfo, &multisampleInfo)
2003 						.setMonolithicPipelineLayout(emptyPipelineLayout)
2004 						.buildPipeline();
2005 
2006 	// Pipeline for the second subpass.
2007 	vk::GraphicsPipelineWrapper secondSubpassPipeline(vki, vkd, physicalDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType);
2008 	secondSubpassPipeline.setDynamicState(&dynamicStateInfo)
2009 						.setDefaultRasterizationState()
2010 						.setupVertexInputState(&vertexInputInfo, &inputAssemblyInfo)
2011 						.setupPreRasterizationShaderState(viewport, scissor, checkPipelineLayout, *renderPass, 1u, vertModule)
2012 						.setupFragmentShaderState(checkPipelineLayout, *renderPass, 1u, checkModule, &depthStencilInfo, &multisampleInfo)
2013 						.setupFragmentOutputState(*renderPass, 1u, &colorBlendInfo, &multisampleInfo)
2014 						.setMonolithicPipelineLayout(checkPipelineLayout)
2015 						.buildPipeline();
2016 
2017 	// Command pool and command buffer.
2018 	const auto cmdPool		= vk::makeCommandPool(vkd, device, queueFamilyIndex);
2019 	const auto cmdBufferPtr	= vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2020 	const auto cmdBuffer	= cmdBufferPtr.get();
2021 
2022 	// Update descriptor set.
2023 	vk::DescriptorSetUpdateBuilder updateBuilder;
2024 	const auto imageInfo	= vk::makeDescriptorImageInfo(DE_NULL, colorImageView.get(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2025 	const auto bufferInfo	= vk::makeDescriptorBufferInfo(storageBuffer.get(), 0u, VK_WHOLE_SIZE);
2026 	updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &imageInfo);
2027 	updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo);
2028 	updateBuilder.update(vkd, device);
2029 
2030 	// Output buffer pipeline barrier.
2031 	const auto bufferBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, storageBuffer.get(), 0ull, VK_WHOLE_SIZE);
2032 
2033 	// Run pipelines.
2034 	vk::beginCommandBuffer(vkd, cmdBuffer);
2035 
2036 	renderPass.begin(vkd, cmdBuffer, vk::makeRect2D(kImageExtent), WriteSampleMaskTestCase::kClearColor);
2037 	vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
2038 	firstSubpassPipeline.bind(cmdBuffer);
2039 	vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(quadVertices.size()), 1u, 0u, 0u);
2040 
2041 	renderPass.nextSubpass(vkd, cmdBuffer, vk::VK_SUBPASS_CONTENTS_INLINE);
2042 	secondSubpassPipeline.bind(cmdBuffer);
2043 	vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, checkPipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
2044 	vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(quadVertices.size()), 1u, 0u, 0u);
2045 
2046 	renderPass.end(vkd, cmdBuffer);
2047 	vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, nullptr, 1u, &bufferBarrier, 0u, nullptr);
2048 	vk::endCommandBuffer(vkd, cmdBuffer);
2049 
2050 	vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
2051 
2052 	// Check buffer contents.
2053 	auto&					bufferAlloc		= storageBuffer.getAllocation();
2054 	const void*				bufferPtr		= bufferAlloc.getHostPtr();
2055 	std::vector<deInt32>	bufferContents	(kBufferElems, 0);
2056 
2057 	vk::invalidateAlloc(vkd, device, bufferAlloc);
2058 	deMemcpy(bufferContents.data(), bufferPtr, static_cast<size_t>(kBufferSize));
2059 
2060 	const auto sampleCount	= static_cast<deUint32>(m_params.sampleCount);
2061 	const auto bpc			= bitsPerCoord(sampleCount);
2062 
2063 	for (deUint32 x = 0; x < kImageExtent.width; ++x)
2064 	for (deUint32 y = 0; y < kImageExtent.height; ++y)
2065 	{
2066 		// Samples on which we expect writes.
2067 		const deUint32 sampleMask = ((x << bpc) | y);
2068 
2069 		// Starting location for the pixel sample values in the buffer.
2070 		const deUint32 pixelOffset = (y * kImageExtent.width + x) * sampleCount;
2071 
2072 		for (deUint32 s = 0; s < sampleCount; ++s)
2073 		{
2074 			const deUint32 sampleIndex	= pixelOffset + s;
2075 			const deInt32& value		= bufferContents[sampleIndex];
2076 
2077 			if (value != 0 && value != 1)
2078 			{
2079 				// Garbage!
2080 				std::ostringstream msg;
2081 				msg << "Found garbage value " << value << " in buffer position " << sampleIndex << " (x=" << x << ", y=" << y << ", sample=" << s << ")";
2082 				return tcu::TestStatus::fail(msg.str());
2083 			}
2084 
2085 			const deInt32 expected = (((sampleMask & (1u << s)) != 0u) ? 1 : 0);
2086 			if (value != expected)
2087 			{
2088 				std::ostringstream msg;
2089 				msg << "Read " << value << " while expecting " << expected << " in buffer position " << sampleIndex << " (x=" << x << ", y=" << y << ", sample=" << s << ")";
2090 				return tcu::TestStatus::fail(msg.str());
2091 			}
2092 		}
2093 	}
2094 
2095 	return tcu::TestStatus::pass("Pass");
2096 }
2097 
2098 } // multisample
2099 
createMultisampleShaderBuiltInTests(tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)2100 tcu::TestCaseGroup* createMultisampleShaderBuiltInTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)
2101 {
2102 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "multisample_shader_builtin"));
2103 
2104 	const tcu::UVec3 imageSizes[] =
2105 	{
2106 		tcu::UVec3(128u, 128u, 1u),
2107 		tcu::UVec3(137u, 191u, 1u),
2108 	};
2109 
2110 	const deUint32 sizesElemCount = static_cast<deUint32>(sizeof(imageSizes) / sizeof(tcu::UVec3));
2111 
2112 	const vk::VkSampleCountFlagBits samplesSetFull[] =
2113 	{
2114 		vk::VK_SAMPLE_COUNT_2_BIT,
2115 		vk::VK_SAMPLE_COUNT_4_BIT,
2116 		vk::VK_SAMPLE_COUNT_8_BIT,
2117 		vk::VK_SAMPLE_COUNT_16_BIT,
2118 		vk::VK_SAMPLE_COUNT_32_BIT,
2119 		vk::VK_SAMPLE_COUNT_64_BIT,
2120 	};
2121 
2122 	const deUint32 samplesSetFullCount = static_cast<deUint32>(sizeof(samplesSetFull) / sizeof(vk::VkSampleCountFlagBits));
2123 
2124 	testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleID> >(testCtx, "sample_id", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount));
2125 
2126 	de::MovePtr<tcu::TestCaseGroup> samplePositionGroup(new tcu::TestCaseGroup(testCtx, "sample_position"));
2127 
2128 	samplePositionGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSamplePosDistribution> >(testCtx, "distribution", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount));
2129 	samplePositionGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSamplePosCorrectness> > (testCtx, "correctness", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount));
2130 
2131 	testGroup->addChild(samplePositionGroup.release());
2132 
2133 	const vk::VkSampleCountFlagBits samplesSetReduced[] =
2134 	{
2135 		vk::VK_SAMPLE_COUNT_2_BIT,
2136 		vk::VK_SAMPLE_COUNT_4_BIT,
2137 		vk::VK_SAMPLE_COUNT_8_BIT,
2138 		vk::VK_SAMPLE_COUNT_16_BIT,
2139 		vk::VK_SAMPLE_COUNT_32_BIT,
2140 	};
2141 
2142 	const deUint32 samplesSetReducedCount = static_cast<deUint32>(DE_LENGTH_OF_ARRAY(samplesSetReduced));
2143 
2144 	de::MovePtr<tcu::TestCaseGroup> sampleMaskGroup(new tcu::TestCaseGroup(testCtx, "sample_mask"));
2145 
2146 	sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskPattern> >	(testCtx, "pattern",		pipelineConstructionType, imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
2147 	sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskBitCount> >	(testCtx, "bit_count",		pipelineConstructionType, imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
2148 	sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskBitCount> >	(testCtx, "bit_count_0_5",	pipelineConstructionType, imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount, multisample::ComponentData{}, 0.5f));
2149 	sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskCorrectBit> >(testCtx, "correct_bit",	pipelineConstructionType, imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
2150 	sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskWrite> >		(testCtx, "write",			pipelineConstructionType, imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
2151 
2152 	testGroup->addChild(sampleMaskGroup.release());
2153 
2154 	// Write image sample tests using a storage images (tests construct only compute pipeline).
2155 	if (pipelineConstructionType == vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
2156 	{
2157 		// Test OpImageWrite with a sample ID
2158 		de::MovePtr<tcu::TestCaseGroup> imageWriteSampleGroup(new tcu::TestCaseGroup(testCtx, "image_write_sample"));
2159 
2160 		for (auto count : multisample::kValidSquareSampleCounts)
2161 		{
2162 			if (count == vk::VK_SAMPLE_COUNT_1_BIT)
2163 				continue;
2164 
2165 			multisample::WriteSampleParams params { pipelineConstructionType, static_cast<vk::VkSampleCountFlagBits>(count) };
2166 			const auto countStr = de::toString(count);
2167 			imageWriteSampleGroup->addChild(new multisample::WriteSampleTest(testCtx, countStr + "_samples", params));
2168 		}
2169 
2170 		testGroup->addChild(imageWriteSampleGroup.release());
2171 	}
2172 
2173 	// Write to gl_SampleMask from the fragment shader.
2174 	{
2175 		de::MovePtr<tcu::TestCaseGroup> writeSampleMaskGroup(new tcu::TestCaseGroup(testCtx, "write_sample_mask"));
2176 
2177 		for (auto count : multisample::kValidSquareSampleCounts)
2178 		{
2179 			multisample::WriteSampleMaskParams params { pipelineConstructionType, static_cast<vk::VkSampleCountFlagBits>(count) };
2180 			const auto countStr = de::toString(count);
2181 			writeSampleMaskGroup->addChild(new multisample::WriteSampleMaskTestCase(testCtx, countStr + "_samples", params));
2182 		}
2183 
2184 		testGroup->addChild(writeSampleMaskGroup.release());
2185 	}
2186 
2187 	return testGroup.release();
2188 }
2189 
2190 } // pipeline
2191 } // vkt
2192