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