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