1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Imagination Technologies Ltd.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Multisample Tests
23 *//*--------------------------------------------------------------------*/
24
25#include "vktPipelineMultisampleTests.hpp"
26#include "vktPipelineClearUtil.hpp"
27#include "vktPipelineImageUtil.hpp"
28#include "vktPipelineVertexUtil.hpp"
29#include "vktPipelineReferenceRenderer.hpp"
30#include "vktTestCase.hpp"
31#include "vktTestCaseUtil.hpp"
32#include "vkImageUtil.hpp"
33#include "vkMemUtil.hpp"
34#include "vkPrograms.hpp"
35#include "vkQueryUtil.hpp"
36#include "vkRef.hpp"
37#include "vkRefUtil.hpp"
38#include "tcuImageCompare.hpp"
39#include "deUniquePtr.hpp"
40#include "deStringUtil.hpp"
41#include "deMemory.h"
42
43#include <sstream>
44#include <vector>
45#include <map>
46
47namespace vkt
48{
49namespace pipeline
50{
51
52using namespace vk;
53
54namespace
55{
56enum GeometryType
57{
58	GEOMETRY_TYPE_OPAQUE_TRIANGLE,
59	GEOMETRY_TYPE_OPAQUE_LINE,
60	GEOMETRY_TYPE_OPAQUE_POINT,
61	GEOMETRY_TYPE_OPAQUE_QUAD,
62	GEOMETRY_TYPE_TRANSLUCENT_QUAD,
63	GEOMETRY_TYPE_INVISIBLE_QUAD,
64	GEOMETRY_TYPE_GRADIENT_QUAD
65};
66
67
68bool									isSupportedSampleCount				(const InstanceInterface& instanceInterface, VkPhysicalDevice physicalDevice, VkSampleCountFlagBits rasterizationSamples);
69VkPipelineColorBlendAttachmentState		getDefaultColorBlendAttachmentState	(void);
70deUint32								getUniqueColorsCount				(const tcu::ConstPixelBufferAccess& image);
71void									initMultisamplePrograms				(SourceCollections& sources, GeometryType geometryType);
72
73class MultisampleTest : public vkt::TestCase
74{
75public:
76
77												MultisampleTest						(tcu::TestContext&								testContext,
78																					 const std::string&								name,
79																					 const std::string&								description,
80																					 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
81																					 const VkPipelineColorBlendAttachmentState&		blendState,
82																					 GeometryType									geometryType);
83	virtual										~MultisampleTest					(void);
84
85	virtual void								initPrograms						(SourceCollections& programCollection) const;
86	virtual TestInstance*						createInstance						(Context& context) const;
87
88protected:
89	virtual TestInstance*						createMultisampleTestInstance		(Context&										context,
90																					 VkPrimitiveTopology							topology,
91																					 const std::vector<Vertex4RGBA>&				vertices,
92																					 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
93																					 const VkPipelineColorBlendAttachmentState&		colorBlendState) const = 0;
94	VkPipelineMultisampleStateCreateInfo		m_multisampleStateParams;
95	const VkPipelineColorBlendAttachmentState	m_colorBlendState;
96	const GeometryType							m_geometryType;
97	std::vector<VkSampleMask>					m_sampleMask;
98};
99
100class RasterizationSamplesTest : public MultisampleTest
101{
102public:
103												RasterizationSamplesTest			(tcu::TestContext&		testContext,
104																					 const std::string&		name,
105																					 const std::string&		description,
106																					 VkSampleCountFlagBits	rasterizationSamples,
107																					 GeometryType			geometryType);
108	virtual										~RasterizationSamplesTest			(void) {}
109
110protected:
111	virtual TestInstance*						createMultisampleTestInstance		(Context&										context,
112																					 VkPrimitiveTopology							topology,
113																					 const std::vector<Vertex4RGBA>&				vertices,
114																					 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
115																					 const VkPipelineColorBlendAttachmentState&		colorBlendState) const;
116
117	static VkPipelineMultisampleStateCreateInfo	getRasterizationSamplesStateParams	(VkSampleCountFlagBits rasterizationSamples);
118};
119
120class MinSampleShadingTest : public MultisampleTest
121{
122public:
123												MinSampleShadingTest				(tcu::TestContext&		testContext,
124																					 const std::string&		name,
125																					 const std::string&		description,
126																					 VkSampleCountFlagBits	rasterizationSamples,
127																					 float					minSampleShading,
128																					 GeometryType			geometryType);
129	virtual										~MinSampleShadingTest				(void) {}
130
131protected:
132	virtual TestInstance*						createMultisampleTestInstance		(Context&										context,
133																					 VkPrimitiveTopology							topology,
134																					 const std::vector<Vertex4RGBA>&				vertices,
135																					 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
136																					 const VkPipelineColorBlendAttachmentState&		colorBlendState) const;
137
138	static VkPipelineMultisampleStateCreateInfo	getMinSampleShadingStateParams		(VkSampleCountFlagBits rasterizationSamples, float minSampleShading);
139};
140
141class SampleMaskTest : public MultisampleTest
142{
143public:
144												SampleMaskTest						(tcu::TestContext&					testContext,
145																					 const std::string&					name,
146																					 const std::string&					description,
147																					 VkSampleCountFlagBits				rasterizationSamples,
148																					 const std::vector<VkSampleMask>&	sampleMask,
149																					 GeometryType						geometryType);
150
151	virtual										~SampleMaskTest						(void) {}
152
153protected:
154	virtual TestInstance*						createMultisampleTestInstance		(Context&										context,
155																					 VkPrimitiveTopology							topology,
156																					 const std::vector<Vertex4RGBA>&				vertices,
157																					 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
158																					 const VkPipelineColorBlendAttachmentState&		colorBlendState) const;
159
160	static VkPipelineMultisampleStateCreateInfo	getSampleMaskStateParams			(VkSampleCountFlagBits rasterizationSamples, const std::vector<VkSampleMask>& sampleMask);
161};
162
163class AlphaToOneTest : public MultisampleTest
164{
165public:
166												AlphaToOneTest					(tcu::TestContext&					testContext,
167																				 const std::string&					name,
168																				 const std::string&					description,
169																				 VkSampleCountFlagBits				rasterizationSamples);
170
171	virtual										~AlphaToOneTest					(void) {}
172
173protected:
174	virtual TestInstance*						createMultisampleTestInstance	(Context&										context,
175																				 VkPrimitiveTopology							topology,
176																				 const std::vector<Vertex4RGBA>&				vertices,
177																				 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
178																				 const VkPipelineColorBlendAttachmentState&		colorBlendState) const;
179
180	static VkPipelineMultisampleStateCreateInfo	getAlphaToOneStateParams		(VkSampleCountFlagBits rasterizationSamples);
181	static VkPipelineColorBlendAttachmentState	getAlphaToOneBlendState			(void);
182};
183
184class AlphaToCoverageTest : public MultisampleTest
185{
186public:
187												AlphaToCoverageTest				(tcu::TestContext&		testContext,
188																				 const std::string&		name,
189																				 const std::string&		description,
190																				 VkSampleCountFlagBits	rasterizationSamples,
191																				 GeometryType			geometryType);
192
193	virtual										~AlphaToCoverageTest			(void) {}
194
195protected:
196	virtual TestInstance*						createMultisampleTestInstance	(Context&										context,
197																				 VkPrimitiveTopology							topology,
198																				 const std::vector<Vertex4RGBA>&				vertices,
199																				 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
200																				 const VkPipelineColorBlendAttachmentState&		colorBlendState) const;
201
202	static VkPipelineMultisampleStateCreateInfo	getAlphaToCoverageStateParams	(VkSampleCountFlagBits rasterizationSamples);
203
204	GeometryType								m_geometryType;
205};
206
207class MultisampleRenderer
208{
209public:
210												MultisampleRenderer			(Context&										context,
211																			 VkFormat										colorFormat,
212																			 const tcu::IVec2&								renderSize,
213																			 VkPrimitiveTopology							topology,
214																			 const std::vector<Vertex4RGBA>&				vertices,
215																			 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
216																			 const VkPipelineColorBlendAttachmentState&		blendState);
217
218	virtual										~MultisampleRenderer		(void);
219
220	de::MovePtr<tcu::TextureLevel>				render						(void);
221
222protected:
223	Context&									m_context;
224
225	const VkFormat								m_colorFormat;
226	tcu::IVec2									m_renderSize;
227
228	const VkPipelineMultisampleStateCreateInfo	m_multisampleStateParams;
229	const VkPipelineColorBlendAttachmentState	m_colorBlendState;
230
231	Move<VkImage>								m_colorImage;
232	de::MovePtr<Allocation>						m_colorImageAlloc;
233	Move<VkImageView>							m_colorAttachmentView;
234
235	Move<VkImage>								m_resolveImage;
236	de::MovePtr<Allocation>						m_resolveImageAlloc;
237	Move<VkImageView>							m_resolveAttachmentView;
238
239	Move<VkRenderPass>							m_renderPass;
240	Move<VkFramebuffer>							m_framebuffer;
241
242	Move<VkShaderModule>						m_vertexShaderModule;
243	Move<VkShaderModule>						m_fragmentShaderModule;
244
245	Move<VkBuffer>								m_vertexBuffer;
246	de::MovePtr<Allocation>						m_vertexBufferAlloc;
247
248	Move<VkPipelineLayout>						m_pipelineLayout;
249	Move<VkPipeline>							m_graphicsPipeline;
250
251	Move<VkCommandPool>							m_cmdPool;
252	Move<VkCommandBuffer>						m_cmdBuffer;
253
254	Move<VkFence>								m_fence;
255};
256
257class RasterizationSamplesInstance : public vkt::TestInstance
258{
259public:
260									RasterizationSamplesInstance	(Context&										context,
261																	 VkPrimitiveTopology							topology,
262																	 const std::vector<Vertex4RGBA>&				vertices,
263																	 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
264																	 const VkPipelineColorBlendAttachmentState&		blendState);
265	virtual							~RasterizationSamplesInstance	(void) {}
266
267	virtual tcu::TestStatus			iterate							(void);
268
269protected:
270	virtual tcu::TestStatus			verifyImage						(const tcu::ConstPixelBufferAccess& result);
271
272	const VkFormat					m_colorFormat;
273	const tcu::IVec2				m_renderSize;
274	const VkPrimitiveTopology		m_primitiveTopology;
275	const std::vector<Vertex4RGBA>	m_vertices;
276	MultisampleRenderer				m_multisampleRenderer;
277};
278
279class MinSampleShadingInstance : public vkt::TestInstance
280{
281public:
282												MinSampleShadingInstance	(Context&										context,
283																			 VkPrimitiveTopology							topology,
284																			 const std::vector<Vertex4RGBA>&				vertices,
285																			 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
286																			 const VkPipelineColorBlendAttachmentState&		blendState);
287	virtual										~MinSampleShadingInstance	(void) {}
288
289	virtual tcu::TestStatus						iterate						(void);
290
291protected:
292	virtual tcu::TestStatus						verifyImage					(const tcu::ConstPixelBufferAccess& testShadingImage,
293																			 const tcu::ConstPixelBufferAccess& minShadingImage,
294																			 const tcu::ConstPixelBufferAccess& maxShadingImage);
295	const VkFormat								m_colorFormat;
296	const tcu::IVec2							m_renderSize;
297	const VkPrimitiveTopology					m_primitiveTopology;
298	const std::vector<Vertex4RGBA>				m_vertices;
299	const VkPipelineMultisampleStateCreateInfo	m_multisampleStateParams;
300	const VkPipelineColorBlendAttachmentState	m_colorBlendState;
301};
302
303class SampleMaskInstance : public vkt::TestInstance
304{
305public:
306												SampleMaskInstance			(Context&										context,
307																			 VkPrimitiveTopology							topology,
308																			 const std::vector<Vertex4RGBA>&				vertices,
309																			 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
310																			 const VkPipelineColorBlendAttachmentState&		blendState);
311	virtual										~SampleMaskInstance			(void) {}
312
313	virtual tcu::TestStatus						iterate						(void);
314
315protected:
316	virtual tcu::TestStatus						verifyImage					(const tcu::ConstPixelBufferAccess& testShadingImage,
317																			 const tcu::ConstPixelBufferAccess& minShadingImage,
318																			 const tcu::ConstPixelBufferAccess& maxShadingImage);
319	const VkFormat								m_colorFormat;
320	const tcu::IVec2							m_renderSize;
321	const VkPrimitiveTopology					m_primitiveTopology;
322	const std::vector<Vertex4RGBA>				m_vertices;
323	const VkPipelineMultisampleStateCreateInfo	m_multisampleStateParams;
324	const VkPipelineColorBlendAttachmentState	m_colorBlendState;
325};
326
327class AlphaToOneInstance : public vkt::TestInstance
328{
329public:
330												AlphaToOneInstance			(Context&										context,
331																			 VkPrimitiveTopology							topology,
332																			 const std::vector<Vertex4RGBA>&				vertices,
333																			 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
334																			 const VkPipelineColorBlendAttachmentState&		blendState);
335	virtual										~AlphaToOneInstance			(void) {}
336
337	virtual tcu::TestStatus						iterate						(void);
338
339protected:
340	virtual tcu::TestStatus						verifyImage					(const tcu::ConstPixelBufferAccess& alphaOneImage,
341																			 const tcu::ConstPixelBufferAccess& noAlphaOneImage);
342	const VkFormat								m_colorFormat;
343	const tcu::IVec2							m_renderSize;
344	const VkPrimitiveTopology					m_primitiveTopology;
345	const std::vector<Vertex4RGBA>				m_vertices;
346	const VkPipelineMultisampleStateCreateInfo	m_multisampleStateParams;
347	const VkPipelineColorBlendAttachmentState	m_colorBlendState;
348};
349
350class AlphaToCoverageInstance : public vkt::TestInstance
351{
352public:
353												AlphaToCoverageInstance		(Context&										context,
354																			 VkPrimitiveTopology							topology,
355																			 const std::vector<Vertex4RGBA>&				vertices,
356																			 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
357																			 const VkPipelineColorBlendAttachmentState&		blendState,
358																			 GeometryType									geometryType);
359	virtual										~AlphaToCoverageInstance	(void) {}
360
361	virtual tcu::TestStatus						iterate						(void);
362
363protected:
364	virtual tcu::TestStatus						verifyImage					(const tcu::ConstPixelBufferAccess& result);
365	const VkFormat								m_colorFormat;
366	const tcu::IVec2							m_renderSize;
367	const VkPrimitiveTopology					m_primitiveTopology;
368	const std::vector<Vertex4RGBA>				m_vertices;
369	const VkPipelineMultisampleStateCreateInfo	m_multisampleStateParams;
370	const VkPipelineColorBlendAttachmentState	m_colorBlendState;
371	const GeometryType							m_geometryType;
372};
373
374
375// Helper functions
376
377void initMultisamplePrograms (SourceCollections& sources, GeometryType geometryType)
378{
379	std::ostringstream vertexSource;
380
381	vertexSource <<
382		"#version 310 es\n"
383		"layout(location = 0) in vec4 position;\n"
384		"layout(location = 1) in vec4 color;\n"
385		"layout(location = 0) out highp vec4 vtxColor;\n"
386		"void main (void)\n"
387		"{\n"
388		"	gl_Position = position;\n"
389		"	vtxColor = color;\n"
390		<< (geometryType == GEOMETRY_TYPE_OPAQUE_POINT ? "	gl_PointSize = 3.0f;\n"
391														 : "" )
392		<< "}\n";
393
394	static const char* fragmentSource =
395		"#version 310 es\n"
396		"layout(location = 0) in highp vec4 vtxColor;\n"
397		"layout(location = 0) out highp vec4 fragColor;\n"
398		"void main (void)\n"
399		"{\n"
400		"	fragColor = vtxColor;\n"
401		"}\n";
402
403	sources.glslSources.add("color_vert") << glu::VertexSource(vertexSource.str());
404	sources.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource);
405}
406
407bool isSupportedSampleCount (const InstanceInterface& instanceInterface, VkPhysicalDevice physicalDevice, VkSampleCountFlagBits rasterizationSamples)
408{
409	VkPhysicalDeviceProperties deviceProperties;
410
411	instanceInterface.getPhysicalDeviceProperties(physicalDevice, &deviceProperties);
412
413	return !!(deviceProperties.limits.framebufferColorSampleCounts & rasterizationSamples);
414}
415
416VkPipelineColorBlendAttachmentState getDefaultColorBlendAttachmentState (void)
417{
418	const VkPipelineColorBlendAttachmentState colorBlendState =
419	{
420		false,														// VkBool32					blendEnable;
421		VK_BLEND_FACTOR_ONE,										// VkBlendFactor			srcColorBlendFactor;
422		VK_BLEND_FACTOR_ZERO,										// VkBlendFactor			dstColorBlendFactor;
423		VK_BLEND_OP_ADD,											// VkBlendOp				colorBlendOp;
424		VK_BLEND_FACTOR_ONE,										// VkBlendFactor			srcAlphaBlendFactor;
425		VK_BLEND_FACTOR_ZERO,										// VkBlendFactor			dstAlphaBlendFactor;
426		VK_BLEND_OP_ADD,											// VkBlendOp				alphaBlendOp;
427		VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |		// VkColorComponentFlags	colorWriteMask;
428			VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
429	};
430
431	return colorBlendState;
432}
433
434deUint32 getUniqueColorsCount (const tcu::ConstPixelBufferAccess& image)
435{
436	DE_ASSERT(image.getFormat().getPixelSize() == 4);
437
438	std::map<deUint32, deUint32>	histogram; // map<pixel value, number of occurrences>
439	const deUint32					pixelCount	= image.getWidth() * image.getHeight() * image.getDepth();
440
441	for (deUint32 pixelNdx = 0; pixelNdx < pixelCount; pixelNdx++)
442	{
443		const deUint32 pixelValue = *((const deUint32*)image.getDataPtr() + pixelNdx);
444
445		if (histogram.find(pixelValue) != histogram.end())
446			histogram[pixelValue]++;
447		else
448			histogram[pixelValue] = 1;
449	}
450
451	return (deUint32)histogram.size();
452}
453
454
455// MultisampleTest
456
457MultisampleTest::MultisampleTest (tcu::TestContext&								testContext,
458								  const std::string&							name,
459								  const std::string&							description,
460								  const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
461								  const VkPipelineColorBlendAttachmentState&	blendState,
462								  GeometryType									geometryType)
463	: vkt::TestCase				(testContext, name, description)
464	, m_multisampleStateParams	(multisampleStateParams)
465	, m_colorBlendState			(blendState)
466	, m_geometryType			(geometryType)
467{
468	if (m_multisampleStateParams.pSampleMask)
469	{
470		// Copy pSampleMask to avoid dependencies with other classes
471
472		const deUint32 maskCount = deCeilFloatToInt32(float(m_multisampleStateParams.rasterizationSamples) / 32);
473
474		for (deUint32 maskNdx = 0; maskNdx < maskCount; maskNdx++)
475			m_sampleMask.push_back(m_multisampleStateParams.pSampleMask[maskNdx]);
476
477		m_multisampleStateParams.pSampleMask = m_sampleMask.data();
478	}
479}
480
481MultisampleTest::~MultisampleTest (void)
482{
483}
484
485void MultisampleTest::initPrograms (SourceCollections& programCollection) const
486{
487	initMultisamplePrograms(programCollection, m_geometryType);
488}
489
490TestInstance* MultisampleTest::createInstance (Context& context) const
491{
492	VkPrimitiveTopology			topology;
493	std::vector<Vertex4RGBA>	vertices;
494
495	switch (m_geometryType)
496	{
497		case GEOMETRY_TYPE_OPAQUE_TRIANGLE:
498		{
499			topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
500			const Vertex4RGBA vertexData[3] =
501			{
502				{
503					tcu::Vec4(-0.75f, 0.0f, 0.0f, 1.0f),
504					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
505				},
506				{
507					tcu::Vec4(0.75f, 0.125f, 0.0f, 1.0f),
508					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
509				},
510				{
511					tcu::Vec4(0.75f, -0.125f, 0.0f, 1.0f),
512					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
513				}
514			};
515
516			vertices = std::vector<Vertex4RGBA>(vertexData, vertexData + 3);
517			break;
518		}
519
520		case GEOMETRY_TYPE_OPAQUE_LINE:
521		{
522			topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
523
524			const Vertex4RGBA vertexData[2] =
525			{
526				{
527					tcu::Vec4(-0.75f, 0.25f, 0.0f, 1.0f),
528					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
529				},
530				{
531					tcu::Vec4(0.75f, -0.25f, 0.0f, 1.0f),
532					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
533				}
534			};
535
536			vertices = std::vector<Vertex4RGBA>(vertexData, vertexData + 2);
537			break;
538		}
539
540		case GEOMETRY_TYPE_OPAQUE_POINT:
541		{
542			topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
543
544			const Vertex4RGBA vertex =
545			{
546				tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
547				tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
548			};
549
550			vertices = std::vector<Vertex4RGBA>(1, vertex);
551			break;
552		}
553
554		case GEOMETRY_TYPE_OPAQUE_QUAD:
555		case GEOMETRY_TYPE_TRANSLUCENT_QUAD:
556		case GEOMETRY_TYPE_INVISIBLE_QUAD:
557		case GEOMETRY_TYPE_GRADIENT_QUAD:
558		{
559			topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
560
561			Vertex4RGBA vertexData[4] =
562			{
563				{
564					tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
565					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
566				},
567				{
568					tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f),
569					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
570				},
571				{
572					tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
573					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
574				},
575				{
576					tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
577					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
578				}
579			};
580
581			if (m_geometryType == GEOMETRY_TYPE_TRANSLUCENT_QUAD)
582			{
583				for (int i = 0; i < 4; i++)
584					vertexData[i].color.w() = 0.25f;
585			}
586			else if (m_geometryType == GEOMETRY_TYPE_INVISIBLE_QUAD)
587			{
588				for (int i = 0; i < 4; i++)
589					vertexData[i].color.w() = 0.0f;
590			}
591			else if (m_geometryType == GEOMETRY_TYPE_GRADIENT_QUAD)
592			{
593				vertexData[0].color.w() = 0.0f;
594				vertexData[2].color.w() = 0.0f;
595			}
596
597			vertices = std::vector<Vertex4RGBA>(vertexData, vertexData + 4);
598			break;
599		}
600
601		default:
602			topology = VK_PRIMITIVE_TOPOLOGY_LAST;
603			DE_ASSERT(false);
604	}
605
606	return createMultisampleTestInstance(context, topology, vertices, m_multisampleStateParams, m_colorBlendState);
607}
608
609
610// RasterizationSamplesTest
611
612RasterizationSamplesTest::RasterizationSamplesTest (tcu::TestContext&		testContext,
613													const std::string&		name,
614													const std::string&		description,
615													VkSampleCountFlagBits	rasterizationSamples,
616													GeometryType			geometryType)
617	: MultisampleTest	(testContext, name, description, getRasterizationSamplesStateParams(rasterizationSamples), getDefaultColorBlendAttachmentState(), geometryType)
618{
619}
620
621VkPipelineMultisampleStateCreateInfo RasterizationSamplesTest::getRasterizationSamplesStateParams (VkSampleCountFlagBits rasterizationSamples)
622{
623	const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
624	{
625		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
626		DE_NULL,													// const void*								pNext;
627		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
628		rasterizationSamples,										// VkSampleCountFlagBits					rasterizationSamples;
629		false,														// VkBool32									sampleShadingEnable;
630		0.0f,														// float									minSampleShading;
631		DE_NULL,													// const VkSampleMask*						pSampleMask;
632		false,														// VkBool32									alphaToCoverageEnable;
633		false														// VkBool32									alphaToOneEnable;
634	};
635
636	return multisampleStateParams;
637}
638
639TestInstance* RasterizationSamplesTest::createMultisampleTestInstance (Context&										context,
640																	   VkPrimitiveTopology							topology,
641																	   const std::vector<Vertex4RGBA>&				vertices,
642																	   const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
643																	   const VkPipelineColorBlendAttachmentState&	colorBlendState) const
644{
645	return new RasterizationSamplesInstance(context, topology, vertices, multisampleStateParams, colorBlendState);
646}
647
648
649// MinSampleShadingTest
650
651MinSampleShadingTest::MinSampleShadingTest (tcu::TestContext&		testContext,
652											const std::string&		name,
653											const std::string&		description,
654											VkSampleCountFlagBits	rasterizationSamples,
655											float					minSampleShading,
656											GeometryType			geometryType)
657	: MultisampleTest	(testContext, name, description, getMinSampleShadingStateParams(rasterizationSamples, minSampleShading), getDefaultColorBlendAttachmentState(), geometryType)
658{
659}
660
661TestInstance* MinSampleShadingTest::createMultisampleTestInstance (Context&										context,
662																   VkPrimitiveTopology							topology,
663																   const std::vector<Vertex4RGBA>&				vertices,
664																   const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
665																   const VkPipelineColorBlendAttachmentState&	colorBlendState) const
666{
667	return new MinSampleShadingInstance(context, topology, vertices, multisampleStateParams, colorBlendState);
668}
669
670VkPipelineMultisampleStateCreateInfo MinSampleShadingTest::getMinSampleShadingStateParams (VkSampleCountFlagBits rasterizationSamples, float minSampleShading)
671{
672	const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
673	{
674		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
675		DE_NULL,													// const void*								pNext;
676		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
677		rasterizationSamples,										// VkSampleCountFlagBits					rasterizationSamples;
678		true,														// VkBool32									sampleShadingEnable;
679		minSampleShading,											// float									minSampleShading;
680		DE_NULL,													// const VkSampleMask*						pSampleMask;
681		false,														//  VkBool32								alphaToCoverageEnable;
682		false														//  VkBool32								alphaToOneEnable;
683	};
684
685	return multisampleStateParams;
686}
687
688
689// SampleMaskTest
690
691SampleMaskTest::SampleMaskTest (tcu::TestContext&					testContext,
692								const std::string&					name,
693								const std::string&					description,
694								VkSampleCountFlagBits				rasterizationSamples,
695								const std::vector<VkSampleMask>&	sampleMask,
696								GeometryType						geometryType)
697	: MultisampleTest	(testContext, name, description, getSampleMaskStateParams(rasterizationSamples, sampleMask), getDefaultColorBlendAttachmentState(), geometryType)
698{
699}
700
701TestInstance* SampleMaskTest::createMultisampleTestInstance (Context&										context,
702															 VkPrimitiveTopology							topology,
703															 const std::vector<Vertex4RGBA>&				vertices,
704															 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
705															 const VkPipelineColorBlendAttachmentState&		colorBlendState) const
706{
707	return new SampleMaskInstance(context, topology,vertices, multisampleStateParams, colorBlendState);
708}
709
710VkPipelineMultisampleStateCreateInfo SampleMaskTest::getSampleMaskStateParams (VkSampleCountFlagBits rasterizationSamples, const std::vector<VkSampleMask>& sampleMask)
711{
712	const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
713	{
714		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
715		DE_NULL,													// const void*								pNext;
716		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
717		rasterizationSamples,										// VkSampleCountFlagBits					rasterizationSamples;
718		false,														// VkBool32									sampleShadingEnable;
719		0.0f,														// float									minSampleShading;
720		sampleMask.data(),											// const VkSampleMask*						pSampleMask;
721		false,														// VkBool32									alphaToCoverageEnable;
722		false														// VkBool32									alphaToOneEnable;
723	};
724
725	return multisampleStateParams;
726}
727
728
729// AlphaToOneTest
730
731AlphaToOneTest::AlphaToOneTest (tcu::TestContext&		testContext,
732								const std::string&		name,
733								const std::string&		description,
734								VkSampleCountFlagBits	rasterizationSamples)
735	: MultisampleTest	(testContext, name, description, getAlphaToOneStateParams(rasterizationSamples), getAlphaToOneBlendState(), GEOMETRY_TYPE_GRADIENT_QUAD)
736{
737}
738
739TestInstance* AlphaToOneTest::createMultisampleTestInstance (Context&										context,
740															 VkPrimitiveTopology							topology,
741															 const std::vector<Vertex4RGBA>&				vertices,
742															 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
743															 const VkPipelineColorBlendAttachmentState&		colorBlendState) const
744{
745	return new AlphaToOneInstance(context, topology, vertices, multisampleStateParams, colorBlendState);
746}
747
748VkPipelineMultisampleStateCreateInfo AlphaToOneTest::getAlphaToOneStateParams (VkSampleCountFlagBits rasterizationSamples)
749{
750	const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
751	{
752		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
753		DE_NULL,													// const void*								pNext;
754		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
755		rasterizationSamples,										// VkSampleCountFlagBits					rasterizationSamples;
756		false,														// VkBool32									sampleShadingEnable;
757		0.0f,														// float									minSampleShading;
758		DE_NULL,													// const VkSampleMask*						pSampleMask;
759		false,														// VkBool32									alphaToCoverageEnable;
760		true														// VkBool32									alphaToOneEnable;
761	};
762
763	return multisampleStateParams;
764}
765
766VkPipelineColorBlendAttachmentState AlphaToOneTest::getAlphaToOneBlendState (void)
767{
768	const VkPipelineColorBlendAttachmentState colorBlendState =
769	{
770		true,														// VkBool32					blendEnable;
771		VK_BLEND_FACTOR_SRC_ALPHA,									// VkBlendFactor			srcColorBlendFactor;
772		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,						// VkBlendFactor			dstColorBlendFactor;
773		VK_BLEND_OP_ADD,											// VkBlendOp				colorBlendOp;
774		VK_BLEND_FACTOR_SRC_ALPHA,									// VkBlendFactor			srcAlphaBlendFactor;
775		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,						// VkBlendFactor			dstAlphaBlendFactor;
776		VK_BLEND_OP_ADD,											// VkBlendOp				alphaBlendOp;
777		VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |		// VkColorComponentFlags	colorWriteMask;
778			VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
779	};
780
781	return colorBlendState;
782}
783
784
785// AlphaToCoverageTest
786
787AlphaToCoverageTest::AlphaToCoverageTest (tcu::TestContext&			testContext,
788										  const std::string&		name,
789										  const std::string&		description,
790										  VkSampleCountFlagBits		rasterizationSamples,
791										  GeometryType				geometryType)
792	: MultisampleTest	(testContext, name, description, getAlphaToCoverageStateParams(rasterizationSamples), getDefaultColorBlendAttachmentState(), geometryType)
793	, m_geometryType	(geometryType)
794{
795}
796
797TestInstance* AlphaToCoverageTest::createMultisampleTestInstance (Context&										context,
798																  VkPrimitiveTopology							topology,
799																  const std::vector<Vertex4RGBA>&				vertices,
800																  const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
801																  const VkPipelineColorBlendAttachmentState&	colorBlendState) const
802{
803	return new AlphaToCoverageInstance(context, topology, vertices, multisampleStateParams, colorBlendState, m_geometryType);
804}
805
806VkPipelineMultisampleStateCreateInfo AlphaToCoverageTest::getAlphaToCoverageStateParams (VkSampleCountFlagBits rasterizationSamples)
807{
808	const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
809	{
810		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
811		DE_NULL,													// const void*								pNext;
812		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
813		rasterizationSamples,										// VkSampleCountFlagBits					rasterizationSamples;
814		false,														// VkBool32									sampleShadingEnable;
815		0.0f,														// float									minSampleShading;
816		DE_NULL,													// const VkSampleMask*						pSampleMask;
817		true,														// VkBool32									alphaToCoverageEnable;
818		false														// VkBool32									alphaToOneEnable;
819	};
820
821	return multisampleStateParams;
822}
823
824// RasterizationSamplesInstance
825
826RasterizationSamplesInstance::RasterizationSamplesInstance (Context&										context,
827															VkPrimitiveTopology								topology,
828															const std::vector<Vertex4RGBA>&					vertices,
829															const VkPipelineMultisampleStateCreateInfo&		multisampleStateParams,
830															const VkPipelineColorBlendAttachmentState&		blendState)
831	: vkt::TestInstance		(context)
832	, m_colorFormat			(VK_FORMAT_R8G8B8A8_UNORM)
833	, m_renderSize			(32, 32)
834	, m_primitiveTopology	(topology)
835	, m_vertices			(vertices)
836	, m_multisampleRenderer	(context, m_colorFormat, m_renderSize, topology, vertices, multisampleStateParams, blendState)
837{
838}
839
840tcu::TestStatus RasterizationSamplesInstance::iterate (void)
841{
842	de::MovePtr<tcu::TextureLevel> level(m_multisampleRenderer.render());
843	return verifyImage(level->getAccess());
844}
845
846tcu::TestStatus RasterizationSamplesInstance::verifyImage (const tcu::ConstPixelBufferAccess& result)
847{
848	// Verify range of unique pixels
849	{
850		const deUint32	numUniqueColors = getUniqueColorsCount(result);
851		const deUint32	minUniqueColors	= 3;
852
853		tcu::TestLog& log = m_context.getTestContext().getLog();
854
855		log << tcu::TestLog::Message
856			<< "\nMin. unique colors expected: " << minUniqueColors << "\n"
857			<< "Unique colors found: " << numUniqueColors << "\n"
858			<< tcu::TestLog::EndMessage;
859
860		if (numUniqueColors < minUniqueColors)
861			return tcu::TestStatus::fail("Unique colors out of expected bounds");
862	}
863
864	// Verify shape of the rendered primitive (fuzzy-compare)
865	{
866		const tcu::TextureFormat	tcuColorFormat	= mapVkFormat(m_colorFormat);
867		const tcu::TextureFormat	tcuDepthFormat	= tcu::TextureFormat();
868		const ColorVertexShader		vertexShader;
869		const ColorFragmentShader	fragmentShader	(tcuColorFormat, tcuDepthFormat);
870		const rr::Program			program			(&vertexShader, &fragmentShader);
871		ReferenceRenderer			refRenderer		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
872		rr::RenderState				renderState		(refRenderer.getViewportState());
873
874		if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
875		{
876			VkPhysicalDeviceProperties deviceProperties;
877
878			m_context.getInstanceInterface().getPhysicalDeviceProperties(m_context.getPhysicalDevice(), &deviceProperties);
879
880			// gl_PointSize is clamped to pointSizeRange
881			renderState.point.pointSize = deFloatMin(3.0f, deviceProperties.limits.pointSizeRange[1]);
882		}
883
884		refRenderer.colorClear(tcu::Vec4(0.0f));
885		refRenderer.draw(renderState, mapVkPrimitiveTopology(m_primitiveTopology), m_vertices);
886
887		if (!tcu::fuzzyCompare(m_context.getTestContext().getLog(), "FuzzyImageCompare", "Image comparison", refRenderer.getAccess(), result, 0.05f, tcu::COMPARE_LOG_RESULT))
888			return tcu::TestStatus::fail("Primitive has unexpected shape");
889
890	}
891
892	return tcu::TestStatus::pass("Primitive rendered, unique colors within expected bounds");
893}
894
895
896// MinSampleShadingInstance
897
898MinSampleShadingInstance::MinSampleShadingInstance (Context&									context,
899													VkPrimitiveTopology							topology,
900													const std::vector<Vertex4RGBA>&				vertices,
901													const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
902													const VkPipelineColorBlendAttachmentState&	colorBlendState)
903	: vkt::TestInstance			(context)
904	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
905	, m_renderSize				(32, 32)
906	, m_primitiveTopology		(topology)
907	, m_vertices				(vertices)
908	, m_multisampleStateParams	(multisampleStateParams)
909	, m_colorBlendState			(colorBlendState)
910{
911	VkPhysicalDeviceFeatures deviceFeatures;
912
913	m_context.getInstanceInterface().getPhysicalDeviceFeatures(m_context.getPhysicalDevice(), &deviceFeatures);
914
915	if (!deviceFeatures.sampleRateShading)
916		throw tcu::NotSupportedError("Sample shading is not supported");
917}
918
919tcu::TestStatus MinSampleShadingInstance::iterate (void)
920{
921	de::MovePtr<tcu::TextureLevel>				testShadingImage;
922	de::MovePtr<tcu::TextureLevel>				minShadingImage;
923	de::MovePtr<tcu::TextureLevel>				maxShadingImage;
924
925	// Render with test minSampleShading
926	{
927		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState);
928		testShadingImage = renderer.render();
929	}
930
931	// Render with minSampleShading = 0.0f
932	{
933		VkPipelineMultisampleStateCreateInfo	multisampleParams	= m_multisampleStateParams;
934		multisampleParams.minSampleShading = 0.0f;
935
936		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState);
937		minShadingImage = renderer.render();
938	}
939
940	// Render with minSampleShading = 1.0f
941	{
942		VkPipelineMultisampleStateCreateInfo	multisampleParams	= m_multisampleStateParams;
943		multisampleParams.minSampleShading = 1.0f;
944
945		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState);
946		maxShadingImage = renderer.render();
947	}
948
949	return verifyImage(testShadingImage->getAccess(), minShadingImage->getAccess(), maxShadingImage->getAccess());
950}
951
952tcu::TestStatus MinSampleShadingInstance::verifyImage (const tcu::ConstPixelBufferAccess& testShadingImage, const tcu::ConstPixelBufferAccess& minShadingImage, const tcu::ConstPixelBufferAccess& maxShadingImage)
953{
954	const deUint32	testColorCount	= getUniqueColorsCount(testShadingImage);
955	const deUint32	minColorCount	= getUniqueColorsCount(minShadingImage);
956	const deUint32	maxColorCount	= getUniqueColorsCount(maxShadingImage);
957
958	tcu::TestLog& log = m_context.getTestContext().getLog();
959
960	log << tcu::TestLog::Message
961		<< "\nColors found: " << testColorCount << "\n"
962		<< "Min. colors expected: " << minColorCount << "\n"
963		<< "Max. colors expected: " << maxColorCount << "\n"
964		<< tcu::TestLog::EndMessage;
965
966	if (minColorCount > testColorCount || testColorCount > maxColorCount)
967		return tcu::TestStatus::fail("Unique colors out of expected bounds");
968	else
969		return tcu::TestStatus::pass("Unique colors within expected bounds");
970}
971
972SampleMaskInstance::SampleMaskInstance (Context&										context,
973										VkPrimitiveTopology								topology,
974										const std::vector<Vertex4RGBA>&					vertices,
975										const VkPipelineMultisampleStateCreateInfo&		multisampleStateParams,
976										const VkPipelineColorBlendAttachmentState&		blendState)
977	: vkt::TestInstance			(context)
978	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
979	, m_renderSize				(32, 32)
980	, m_primitiveTopology		(topology)
981	, m_vertices				(vertices)
982	, m_multisampleStateParams	(multisampleStateParams)
983	, m_colorBlendState			(blendState)
984{
985}
986
987tcu::TestStatus SampleMaskInstance::iterate (void)
988{
989	de::MovePtr<tcu::TextureLevel>				testSampleMaskImage;
990	de::MovePtr<tcu::TextureLevel>				minSampleMaskImage;
991	de::MovePtr<tcu::TextureLevel>				maxSampleMaskImage;
992
993	// Render with test flags
994	{
995		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState);
996		testSampleMaskImage = renderer.render();
997	}
998
999	// Render with all flags off
1000	{
1001		VkPipelineMultisampleStateCreateInfo	multisampleParams	= m_multisampleStateParams;
1002		const std::vector<VkSampleMask>			sampleMask			(multisampleParams.rasterizationSamples / 32, (VkSampleMask)0);
1003
1004		multisampleParams.pSampleMask = sampleMask.data();
1005
1006		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState);
1007		minSampleMaskImage = renderer.render();
1008	}
1009
1010	// Render with all flags on
1011	{
1012		VkPipelineMultisampleStateCreateInfo	multisampleParams	= m_multisampleStateParams;
1013		const std::vector<VkSampleMask>			sampleMask			(multisampleParams.rasterizationSamples / 32, ~((VkSampleMask)0));
1014
1015		multisampleParams.pSampleMask = sampleMask.data();
1016
1017		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState);
1018		maxSampleMaskImage = renderer.render();
1019	}
1020
1021	return verifyImage(testSampleMaskImage->getAccess(), minSampleMaskImage->getAccess(), maxSampleMaskImage->getAccess());
1022}
1023
1024tcu::TestStatus SampleMaskInstance::verifyImage (const tcu::ConstPixelBufferAccess& testSampleMaskImage,
1025												 const tcu::ConstPixelBufferAccess& minSampleMaskImage,
1026												 const tcu::ConstPixelBufferAccess& maxSampleMaskImage)
1027{
1028	const deUint32	testColorCount	= getUniqueColorsCount(testSampleMaskImage);
1029	const deUint32	minColorCount	= getUniqueColorsCount(minSampleMaskImage);
1030	const deUint32	maxColorCount	= getUniqueColorsCount(maxSampleMaskImage);
1031
1032	tcu::TestLog& log = m_context.getTestContext().getLog();
1033
1034	log << tcu::TestLog::Message
1035		<< "\nColors found: " << testColorCount << "\n"
1036		<< "Min. colors expected: " << minColorCount << "\n"
1037		<< "Max. colors expected: " << maxColorCount << "\n"
1038		<< tcu::TestLog::EndMessage;
1039
1040	if (minColorCount > testColorCount || testColorCount > maxColorCount)
1041		return tcu::TestStatus::fail("Unique colors out of expected bounds");
1042	else
1043		return tcu::TestStatus::pass("Unique colors within expected bounds");
1044}
1045
1046tcu::TestStatus testRasterSamplesConsistency (Context& context, GeometryType geometryType)
1047{
1048	// Use triangle only.
1049	DE_UNREF(geometryType);
1050
1051	const VkSampleCountFlagBits samples[] =
1052	{
1053		VK_SAMPLE_COUNT_1_BIT,
1054		VK_SAMPLE_COUNT_2_BIT,
1055		VK_SAMPLE_COUNT_4_BIT,
1056		VK_SAMPLE_COUNT_8_BIT,
1057		VK_SAMPLE_COUNT_16_BIT,
1058		VK_SAMPLE_COUNT_32_BIT,
1059		VK_SAMPLE_COUNT_64_BIT
1060	};
1061
1062	const Vertex4RGBA vertexData[3] =
1063	{
1064		{
1065			tcu::Vec4(-0.75f, 0.0f, 0.0f, 1.0f),
1066			tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
1067		},
1068		{
1069			tcu::Vec4(0.75f, 0.125f, 0.0f, 1.0f),
1070			tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
1071		},
1072		{
1073			tcu::Vec4(0.75f, -0.125f, 0.0f, 1.0f),
1074			tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
1075		}
1076	};
1077
1078	const std::vector<Vertex4RGBA>	vertices			(vertexData, vertexData + 3);
1079	deUint32						prevUniqueColors	= 2;
1080	int								renderCount			= 0;
1081
1082	// Do not render with 1 sample (start with samplesNdx = 1).
1083	for (int samplesNdx = 1; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
1084	{
1085		if (!isSupportedSampleCount(context.getInstanceInterface(), context.getPhysicalDevice(), samples[samplesNdx]))
1086			continue;
1087
1088		const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
1089		{
1090			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
1091			DE_NULL,													// const void*								pNext;
1092			0u,															// VkPipelineMultisampleStateCreateFlags	flags;
1093			samples[samplesNdx],										// VkSampleCountFlagBits					rasterizationSamples;
1094			false,														// VkBool32									sampleShadingEnable;
1095			0.0f,														// float									minSampleShading;
1096			DE_NULL,													// const VkSampleMask*						pSampleMask;
1097			false,														// VkBool32									alphaToCoverageEnable;
1098			false														// VkBool32									alphaToOneEnable;
1099		};
1100
1101		MultisampleRenderer				renderer		(context, VK_FORMAT_R8G8B8A8_UNORM, tcu::IVec2(32, 32), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, vertices, multisampleStateParams, getDefaultColorBlendAttachmentState());
1102		de::MovePtr<tcu::TextureLevel>	result			= renderer.render();
1103		const deUint32					uniqueColors	= getUniqueColorsCount(result->getAccess());
1104
1105		renderCount++;
1106
1107		if (prevUniqueColors > uniqueColors)
1108		{
1109			std::ostringstream message;
1110
1111			message << "More unique colors generated with " << samples[samplesNdx - 1] << " than with " << samples[samplesNdx];
1112			return tcu::TestStatus::fail(message.str());
1113		}
1114
1115		prevUniqueColors = uniqueColors;
1116	}
1117
1118	if (renderCount == 0)
1119		throw tcu::NotSupportedError("Multisampling is unsupported");
1120
1121	return tcu::TestStatus::pass("Number of unique colors increases as the sample count increases");
1122}
1123
1124
1125// AlphaToOneInstance
1126
1127AlphaToOneInstance::AlphaToOneInstance (Context&									context,
1128										VkPrimitiveTopology							topology,
1129										const std::vector<Vertex4RGBA>&				vertices,
1130										const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
1131										const VkPipelineColorBlendAttachmentState&	blendState)
1132	: vkt::TestInstance			(context)
1133	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
1134	, m_renderSize				(32, 32)
1135	, m_primitiveTopology		(topology)
1136	, m_vertices				(vertices)
1137	, m_multisampleStateParams	(multisampleStateParams)
1138	, m_colorBlendState			(blendState)
1139{
1140	VkPhysicalDeviceFeatures deviceFeatures;
1141
1142	context.getInstanceInterface().getPhysicalDeviceFeatures(context.getPhysicalDevice(), &deviceFeatures);
1143
1144	if (!deviceFeatures.alphaToOne)
1145		throw tcu::NotSupportedError("Alpha-to-one is not supported");
1146}
1147
1148tcu::TestStatus AlphaToOneInstance::iterate	(void)
1149{
1150	DE_ASSERT(m_multisampleStateParams.alphaToOneEnable);
1151	DE_ASSERT(m_colorBlendState.blendEnable);
1152
1153	de::MovePtr<tcu::TextureLevel>	alphaOneImage;
1154	de::MovePtr<tcu::TextureLevel>	noAlphaOneImage;
1155
1156	// Render with blend enabled and alpha to one on
1157	{
1158		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState);
1159		alphaOneImage = renderer.render();
1160	}
1161
1162	// Render with blend enabled and alpha to one off
1163	{
1164		VkPipelineMultisampleStateCreateInfo	multisampleParams	= m_multisampleStateParams;
1165		multisampleParams.alphaToOneEnable = false;
1166
1167		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState);
1168		noAlphaOneImage = renderer.render();
1169	}
1170
1171	return verifyImage(alphaOneImage->getAccess(), noAlphaOneImage->getAccess());
1172}
1173
1174tcu::TestStatus AlphaToOneInstance::verifyImage (const tcu::ConstPixelBufferAccess&	alphaOneImage,
1175												 const tcu::ConstPixelBufferAccess&	noAlphaOneImage)
1176{
1177	for (int y = 0; y < m_renderSize.y(); y++)
1178	{
1179		for (int x = 0; x < m_renderSize.x(); x++)
1180		{
1181			if (!tcu::boolAll(tcu::greaterThanEqual(alphaOneImage.getPixel(x, y), noAlphaOneImage.getPixel(x, y))))
1182			{
1183				std::ostringstream message;
1184				message << "Unsatisfied condition: " << alphaOneImage.getPixel(x, y) << " >= " << noAlphaOneImage.getPixel(x, y);
1185				return tcu::TestStatus::fail(message.str());
1186			}
1187		}
1188	}
1189
1190	return tcu::TestStatus::pass("Image rendered with alpha-to-one contains pixels of image rendered with no alpha-to-one");
1191}
1192
1193
1194// AlphaToCoverageInstance
1195
1196AlphaToCoverageInstance::AlphaToCoverageInstance (Context&										context,
1197												  VkPrimitiveTopology							topology,
1198												  const std::vector<Vertex4RGBA>&				vertices,
1199												  const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
1200												  const VkPipelineColorBlendAttachmentState&	blendState,
1201												  GeometryType									geometryType)
1202	: vkt::TestInstance			(context)
1203	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
1204	, m_renderSize				(32, 32)
1205	, m_primitiveTopology		(topology)
1206	, m_vertices				(vertices)
1207	, m_multisampleStateParams	(multisampleStateParams)
1208	, m_colorBlendState			(blendState)
1209	, m_geometryType			(geometryType)
1210{
1211}
1212
1213tcu::TestStatus AlphaToCoverageInstance::iterate (void)
1214{
1215	DE_ASSERT(m_multisampleStateParams.alphaToCoverageEnable);
1216
1217	de::MovePtr<tcu::TextureLevel>	result;
1218	MultisampleRenderer				renderer	(m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState);
1219
1220	result = renderer.render();
1221
1222	return verifyImage(result->getAccess());
1223}
1224
1225tcu::TestStatus AlphaToCoverageInstance::verifyImage (const tcu::ConstPixelBufferAccess&	result)
1226{
1227	float maxColorValue;
1228
1229	switch (m_geometryType)
1230	{
1231		case GEOMETRY_TYPE_OPAQUE_QUAD:
1232			maxColorValue = 1.01f;
1233			break;
1234
1235		case GEOMETRY_TYPE_TRANSLUCENT_QUAD:
1236			maxColorValue = 0.52f;
1237			break;
1238
1239		case GEOMETRY_TYPE_INVISIBLE_QUAD:
1240			maxColorValue = 0.01f;
1241			break;
1242
1243		default:
1244			maxColorValue = 0.0f;
1245			DE_ASSERT(false);
1246	}
1247
1248	for (int y = 0; y < m_renderSize.y(); y++)
1249	{
1250		for (int x = 0; x < m_renderSize.x(); x++)
1251		{
1252			if (result.getPixel(x, y).x() > maxColorValue)
1253			{
1254				std::ostringstream message;
1255				message << "Pixel is not below the threshold value (" << result.getPixel(x, y).x() << " > " << maxColorValue << ")";
1256				return tcu::TestStatus::fail(message.str());
1257			}
1258		}
1259	}
1260
1261	return tcu::TestStatus::pass("Image matches reference value");
1262}
1263
1264
1265// MultisampleRenderer
1266
1267MultisampleRenderer::MultisampleRenderer (Context&										context,
1268										  VkFormat										colorFormat,
1269										  const tcu::IVec2&								renderSize,
1270										  VkPrimitiveTopology							topology,
1271										  const std::vector<Vertex4RGBA>&				vertices,
1272										  const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
1273										  const VkPipelineColorBlendAttachmentState&	blendState)
1274
1275	: m_context					(context)
1276	, m_colorFormat				(colorFormat)
1277	, m_renderSize				(renderSize)
1278	, m_multisampleStateParams	(multisampleStateParams)
1279	, m_colorBlendState			(blendState)
1280{
1281	if (!isSupportedSampleCount(context.getInstanceInterface(), context.getPhysicalDevice(), multisampleStateParams.rasterizationSamples))
1282		throw tcu::NotSupportedError("Unsupported number of rasterization samples");
1283
1284	const DeviceInterface&		vk						= context.getDeviceInterface();
1285	const VkDevice				vkDevice				= context.getDevice();
1286	const deUint32				queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
1287	SimpleAllocator				memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
1288	const VkComponentMapping	componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
1289
1290	// Create color image
1291	{
1292		const VkImageCreateInfo colorImageParams =
1293		{
1294			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
1295			DE_NULL,																	// const void*				pNext;
1296			0u,																			// VkImageCreateFlags		flags;
1297			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
1298			m_colorFormat,																// VkFormat					format;
1299			{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u },				// VkExtent3D				extent;
1300			1u,																			// deUint32					mipLevels;
1301			1u,																			// deUint32					arrayLayers;
1302			m_multisampleStateParams.rasterizationSamples,								// VkSampleCountFlagBits	samples;
1303			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
1304			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
1305			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
1306			1u,																			// deUint32					queueFamilyIndexCount;
1307			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
1308			VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout			initialLayout;
1309		};
1310
1311		m_colorImage			= createImage(vk, vkDevice, &colorImageParams);
1312
1313		// Allocate and bind color image memory
1314		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
1315		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
1316	}
1317
1318	// Create resolve image
1319	{
1320		const VkImageCreateInfo resolveImageParams =
1321		{
1322			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,											// VkStructureType			sType;
1323			DE_NULL,																		// const void*				pNext;
1324			0u,																				// VkImageCreateFlags		flags;
1325			VK_IMAGE_TYPE_2D,																// VkImageType				imageType;
1326			m_colorFormat,																	// VkFormat					format;
1327			{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u },					// VkExtent3D				extent;
1328			1u,																				// deUint32					mipLevels;
1329			1u,																				// deUint32					arrayLayers;
1330			VK_SAMPLE_COUNT_1_BIT,															// VkSampleCountFlagBits	samples;
1331			VK_IMAGE_TILING_OPTIMAL,														// VkImageTiling			tiling;
1332			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |			// VkImageUsageFlags		usage;
1333				VK_IMAGE_USAGE_TRANSFER_DST_BIT,
1334			VK_SHARING_MODE_EXCLUSIVE,														// VkSharingMode			sharingMode;
1335			1u,																				// deUint32					queueFamilyIndexCount;
1336			&queueFamilyIndex,																// const deUint32*			pQueueFamilyIndices;
1337			VK_IMAGE_LAYOUT_UNDEFINED														// VkImageLayout			initialLayout;
1338		};
1339
1340		m_resolveImage = createImage(vk, vkDevice, &resolveImageParams);
1341
1342		// Allocate and bind resolve image memory
1343		m_resolveImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_resolveImage), MemoryRequirement::Any);
1344		VK_CHECK(vk.bindImageMemory(vkDevice, *m_resolveImage, m_resolveImageAlloc->getMemory(), m_resolveImageAlloc->getOffset()));
1345	}
1346
1347	// Create color attachment view
1348	{
1349		const VkImageViewCreateInfo colorAttachmentViewParams =
1350		{
1351			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
1352			DE_NULL,										// const void*				pNext;
1353			0u,												// VkImageViewCreateFlags	flags;
1354			*m_colorImage,									// VkImage					image;
1355			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
1356			m_colorFormat,									// VkFormat					format;
1357			componentMappingRGBA,							// VkComponentMapping		components;
1358			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
1359		};
1360
1361		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
1362	}
1363
1364	// Create resolve attachment view
1365	{
1366		const VkImageViewCreateInfo resolveAttachmentViewParams =
1367		{
1368			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
1369			DE_NULL,										// const void*				pNext;
1370			0u,												// VkImageViewCreateFlags	flags;
1371			*m_resolveImage,								// VkImage					image;
1372			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
1373			m_colorFormat,									// VkFormat					format;
1374			componentMappingRGBA,							// VkComponentMapping		components;
1375			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
1376		};
1377
1378		m_resolveAttachmentView = createImageView(vk, vkDevice, &resolveAttachmentViewParams);
1379	}
1380
1381	// Create render pass
1382	{
1383		const VkAttachmentDescription attachmentDescriptions[2] =
1384		{
1385			{
1386				0u,													// VkAttachmentDescriptionFlags		flags;
1387				m_colorFormat,										// VkFormat							format;
1388				m_multisampleStateParams.rasterizationSamples,		// VkSampleCountFlagBits			samples;
1389				VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
1390				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
1391				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
1392				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
1393				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
1394				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout;
1395			},
1396			{
1397				0u,													// VkAttachmentDescriptionFlags		flags;
1398				m_colorFormat,										// VkFormat							format;
1399				VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
1400				VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
1401				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
1402				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
1403				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
1404				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
1405				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout;
1406			}
1407		};
1408
1409		const VkAttachmentReference colorAttachmentReference =
1410		{
1411			0u,													// deUint32			attachment;
1412			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
1413		};
1414
1415		const VkAttachmentReference resolveAttachmentReference =
1416		{
1417			1u,													// deUint32			attachment;
1418			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
1419		};
1420
1421		const VkSubpassDescription subpassDescription =
1422		{
1423			0u,														// VkSubpassDescriptionFlags	flags;
1424			VK_PIPELINE_BIND_POINT_GRAPHICS,						// VkPipelineBindPoint			pipelineBindPoint;
1425			0u,														// deUint32						inputAttachmentCount;
1426			DE_NULL,												// const VkAttachmentReference*	pInputAttachments;
1427			1u,														// deUint32						colorAttachmentCount;
1428			&colorAttachmentReference,								// const VkAttachmentReference*	pColorAttachments;
1429			&resolveAttachmentReference,							// const VkAttachmentReference*	pResolveAttachments;
1430			DE_NULL,												// const VkAttachmentReference*	pDepthStencilAttachment;
1431			0u,														// deUint32						preserveAttachmentCount;
1432			DE_NULL													// const VkAttachmentReference*	pPreserveAttachments;
1433		};
1434
1435		const VkRenderPassCreateInfo renderPassParams =
1436		{
1437			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
1438			DE_NULL,											// const void*						pNext;
1439			0u,													// VkRenderPassCreateFlags			flags;
1440			2u,													// deUint32							attachmentCount;
1441			attachmentDescriptions,								// const VkAttachmentDescription*	pAttachments;
1442			1u,													// deUint32							subpassCount;
1443			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
1444			0u,													// deUint32							dependencyCount;
1445			DE_NULL												// const VkSubpassDependency*		pDependencies;
1446		};
1447
1448		m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
1449	}
1450
1451	// Create framebuffer
1452	{
1453		const VkImageView attachments[2] =
1454		{
1455			*m_colorAttachmentView,
1456			*m_resolveAttachmentView
1457		};
1458
1459		const VkFramebufferCreateInfo framebufferParams =
1460		{
1461			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType				sType;
1462			DE_NULL,											// const void*					pNext;
1463			0u,													// VkFramebufferCreateFlags		flags;
1464			*m_renderPass,										// VkRenderPass					renderPass;
1465			2u,													// deUint32						attachmentCount;
1466			attachments,										// const VkImageView*			pAttachments;
1467			(deUint32)m_renderSize.x(),							// deUint32						width;
1468			(deUint32)m_renderSize.y(),							// deUint32						height;
1469			1u													// deUint32						layers;
1470		};
1471
1472		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
1473	}
1474
1475	// Create pipeline layout
1476	{
1477		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
1478		{
1479			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
1480			DE_NULL,											// const void*						pNext;
1481			0u,													// VkPipelineLayoutCreateFlags		flags;
1482			0u,													// deUint32							setLayoutCount;
1483			DE_NULL,											// const VkDescriptorSetLayout*		pSetLayouts;
1484			0u,													// deUint32							pushConstantRangeCount;
1485			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
1486		};
1487
1488		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1489	}
1490
1491	m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
1492	m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
1493
1494	// Create pipeline
1495	{
1496		const VkPipelineShaderStageCreateInfo shaderStageParams[2] =
1497		{
1498			{
1499				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
1500				DE_NULL,													// const void*							pNext;
1501				0u,															// VkPipelineShaderStageCreateFlags		flags;
1502				VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStageFlagBits				stage;
1503				*m_vertexShaderModule,										// VkShaderModule						module;
1504				"main",														// const char*							pName;
1505				DE_NULL														// const VkSpecializationInfo*			pSpecializationInfo;
1506			},
1507			{
1508				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
1509				DE_NULL,													// const void*							pNext;
1510				0u,															// VkPipelineShaderStageCreateFlags		flags;
1511				VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlagBits				stage;
1512				*m_fragmentShaderModule,									// VkShaderModule						module;
1513				"main",														// const char*							pName;
1514				DE_NULL														// const VkSpecializationInfo*			pSpecializationInfo;
1515			}
1516		};
1517
1518		const VkVertexInputBindingDescription vertexInputBindingDescription =
1519		{
1520			0u,									// deUint32				binding;
1521			sizeof(Vertex4RGBA),				// deUint32				stride;
1522			VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputRate	inputRate;
1523		};
1524
1525		const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
1526		{
1527			{
1528				0u,									// deUint32	location;
1529				0u,									// deUint32	binding;
1530				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
1531				0u									// deUint32	offset;
1532			},
1533			{
1534				1u,									// deUint32	location;
1535				0u,									// deUint32	binding;
1536				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
1537				DE_OFFSET_OF(Vertex4RGBA, color),	// deUint32	offset;
1538			}
1539		};
1540
1541		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
1542		{
1543			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
1544			DE_NULL,														// const void*								pNext;
1545			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
1546			1u,																// deUint32									vertexBindingDescriptionCount;
1547			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
1548			2u,																// deUint32									vertexAttributeDescriptionCount;
1549			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1550		};
1551
1552		const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
1553		{
1554			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
1555			DE_NULL,														// const void*								pNext;
1556			0u,																// VkPipelineInputAssemblyStateCreateFlags	flags;
1557			topology,														// VkPrimitiveTopology						topology;
1558			false															// VkBool32									primitiveRestartEnable;
1559		};
1560
1561		const VkViewport viewport =
1562		{
1563			0.0f,						// float	x;
1564			0.0f,						// float	y;
1565			(float)m_renderSize.x(),	// float	width;
1566			(float)m_renderSize.y(),	// float	height;
1567			0.0f,						// float	minDepth;
1568			1.0f						// float	maxDepth;
1569		};
1570
1571		const VkRect2D scissor =
1572		{
1573			{ 0, 0 },													// VkOffset2D  offset;
1574			{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() }	// VkExtent2D  extent;
1575		};
1576
1577		const VkPipelineViewportStateCreateInfo viewportStateParams =
1578		{
1579			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType						sType;
1580			DE_NULL,														// const void*							pNext;
1581			0u,																// VkPipelineViewportStateCreateFlags	flags;
1582			1u,																// deUint32								viewportCount;
1583			&viewport,														// const VkViewport*					pViewports;
1584			1u,																// deUint32								scissorCount;
1585			&scissor														// const VkRect2D*						pScissors;
1586		};
1587
1588		const VkPipelineRasterizationStateCreateInfo rasterStateParams =
1589		{
1590			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
1591			DE_NULL,														// const void*								pNext;
1592			0u,																// VkPipelineRasterizationStateCreateFlags	flags;
1593			false,															// VkBool32									depthClampEnable;
1594			false,															// VkBool32									rasterizerDiscardEnable;
1595			VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
1596			VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
1597			VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
1598			VK_FALSE,														// VkBool32									depthBiasEnable;
1599			0.0f,															// float									depthBiasConstantFactor;
1600			0.0f,															// float									depthBiasClamp;
1601			0.0f,															// float									depthBiasSlopeFactor;
1602			1.0f															// float									lineWidth;
1603		};
1604
1605		const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
1606		{
1607			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
1608			DE_NULL,													// const void*									pNext;
1609			0u,															// VkPipelineColorBlendStateCreateFlags			flags;
1610			false,														// VkBool32										logicOpEnable;
1611			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
1612			1u,															// deUint32										attachmentCount;
1613			&m_colorBlendState,											// const VkPipelineColorBlendAttachmentState*	pAttachments;
1614			{ 0.0f, 0.0f, 0.0f, 0.0f }									// float										blendConstants[4];
1615		};
1616
1617		const VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
1618		{
1619			VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
1620			DE_NULL,													// const void*								pNext;
1621			0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
1622			false,														// VkBool32									depthTestEnable;
1623			false,														// VkBool32									depthWriteEnable;
1624			VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
1625			false,														// VkBool32									depthBoundsTestEnable;
1626			false,														// VkBool32									stencilTestEnable;
1627			// VkStencilOpState	front;
1628			{
1629				VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp;
1630				VK_STENCIL_OP_KEEP,		// VkStencilOp	passOp;
1631				VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp;
1632				VK_COMPARE_OP_NEVER,	// VkCompareOp	compareOp;
1633				0u,						// deUint32		compareMask;
1634				0u,						// deUint32		writeMask;
1635				0u,						// deUint32		reference;
1636			},
1637			// VkStencilOpState	back;
1638			{
1639				VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp;
1640				VK_STENCIL_OP_KEEP,		// VkStencilOp	passOp;
1641				VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp;
1642				VK_COMPARE_OP_NEVER,	// VkCompareOp	compareOp;
1643				0u,						// deUint32		compareMask;
1644				0u,						// deUint32		writeMask;
1645				0u,						// deUint32		reference;
1646			},
1647			0.0f,														// float			minDepthBounds;
1648			1.0f,														// float			maxDepthBounds;
1649		};
1650
1651		const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
1652		{
1653			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
1654			DE_NULL,											// const void*										pNext;
1655			0u,													// VkPipelineCreateFlags							flags;
1656			2u,													// deUint32											stageCount;
1657			shaderStageParams,									// const VkPipelineShaderStageCreateInfo*			pStages;
1658			&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
1659			&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
1660			DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
1661			&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
1662			&rasterStateParams,									// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
1663			&m_multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
1664			&depthStencilStateParams,							// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
1665			&colorBlendStateParams,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
1666			(const VkPipelineDynamicStateCreateInfo*)DE_NULL,	// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
1667			*m_pipelineLayout,									// VkPipelineLayout									layout;
1668			*m_renderPass,										// VkRenderPass										renderPass;
1669			0u,													// deUint32											subpass;
1670			0u,													// VkPipeline										basePipelineHandle;
1671			0u													// deInt32											basePipelineIndex;
1672		};
1673
1674		m_graphicsPipeline	= createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
1675	}
1676
1677	// Create vertex buffer
1678	{
1679		const VkBufferCreateInfo vertexBufferParams =
1680		{
1681			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
1682			DE_NULL,									// const void*			pNext;
1683			0u,											// VkBufferCreateFlags	flags;
1684			1024u,										// VkDeviceSize			size;
1685			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
1686			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
1687			1u,											// deUint32				queueFamilyIndexCount;
1688			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
1689		};
1690
1691		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
1692		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
1693
1694		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
1695
1696		// Load vertices into vertex buffer
1697		deMemcpy(m_vertexBufferAlloc->getHostPtr(), vertices.data(), vertices.size() * sizeof(Vertex4RGBA));
1698		flushMappedMemoryRange(vk, vkDevice, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), vertexBufferParams.size);
1699	}
1700
1701	// Create command pool
1702	{
1703		const VkCommandPoolCreateInfo cmdPoolParams =
1704		{
1705			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,		// VkStructureType				sType;
1706			DE_NULL,										// const void*					pNext;
1707			VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// VkCommandPoolCreateFlags		flags;
1708			queueFamilyIndex,								// deUint32						queueFamilyIndex;
1709		};
1710
1711		m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
1712	}
1713
1714	// Create command buffer
1715	{
1716		const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
1717		{
1718			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
1719			DE_NULL,										// const void*				pNext;
1720			*m_cmdPool,										// VkCommandPool			commandPool;
1721			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel	level;
1722			1u												// deUint32				bufferCount;
1723		};
1724
1725		const VkCommandBufferBeginInfo cmdBufferBeginInfo =
1726		{
1727			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType;
1728			DE_NULL,										// const void*						pNext;
1729			0u,												// VkCommandBufferUsageFlags		flags;
1730			(const VkCommandBufferInheritanceInfo*)DE_NULL,
1731		};
1732
1733		VkClearValue colorClearValue;
1734		colorClearValue.color.float32[0] = 0.0f;
1735		colorClearValue.color.float32[1] = 0.0f;
1736		colorClearValue.color.float32[2] = 0.0f;
1737		colorClearValue.color.float32[3] = 0.0f;
1738
1739		const VkClearValue clearValues[2] =
1740		{
1741			colorClearValue,
1742			colorClearValue
1743		};
1744
1745		const VkRenderPassBeginInfo renderPassBeginInfo =
1746		{
1747			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,				// VkStructureType		sType;
1748			DE_NULL,												// const void*			pNext;
1749			*m_renderPass,											// VkRenderPass			renderPass;
1750			*m_framebuffer,											// VkFramebuffer		framebuffer;
1751			{
1752				{ 0, 0 },
1753				{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() }
1754			},														// VkRect2D				renderArea;
1755			2,														// deUint32				clearValueCount;
1756			clearValues												// const VkClearValue*	pClearValues;
1757		};
1758
1759		const VkImageMemoryBarrier imageLayoutBarriers[] =
1760		{
1761			// color attachment image
1762			{
1763				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
1764				DE_NULL,										// const void*				pNext;
1765				0u,												// VkAccessFlags			srcAccessMask;
1766				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
1767				VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
1768				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			newLayout;
1769				VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
1770				VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
1771				*m_colorImage,									// VkImage					image;
1772				{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
1773			},
1774			// resolve attachment image
1775			{
1776				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
1777				DE_NULL,										// const void*				pNext;
1778				0u,												// VkAccessFlags			srcAccessMask;
1779				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
1780				VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
1781				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			newLayout;
1782				VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
1783				VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
1784				*m_resolveImage,								// VkImage					image;
1785				{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
1786			},
1787		};
1788
1789		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
1790
1791		VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
1792
1793		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0,
1794			0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(imageLayoutBarriers), imageLayoutBarriers);
1795
1796		vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1797
1798		VkDeviceSize vertexBufferOffset = 0u;
1799
1800		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
1801		vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1802		vk.cmdDraw(*m_cmdBuffer, (deUint32)vertices.size(), 1, 0, 0);
1803
1804		vk.cmdEndRenderPass(*m_cmdBuffer);
1805
1806		VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
1807	}
1808
1809	// Create fence
1810	{
1811		const VkFenceCreateInfo fenceParams =
1812		{
1813			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
1814			DE_NULL,								// const void*			pNext;
1815			0u										// VkFenceCreateFlags	flags;
1816		};
1817
1818		m_fence = createFence(vk, vkDevice, &fenceParams);
1819	}
1820}
1821
1822MultisampleRenderer::~MultisampleRenderer (void)
1823{
1824}
1825
1826de::MovePtr<tcu::TextureLevel> MultisampleRenderer::render (void)
1827{
1828	const DeviceInterface&		vk					= m_context.getDeviceInterface();
1829	const VkDevice				vkDevice			= m_context.getDevice();
1830	const VkQueue				queue				= m_context.getUniversalQueue();
1831	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1832	SimpleAllocator				allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1833	const VkSubmitInfo			submitInfo	=
1834	{
1835		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
1836		DE_NULL,						// const void*				pNext;
1837		0u,								// deUint32					waitSemaphoreCount;
1838		DE_NULL,						// const VkSemaphore*		pWaitSemaphores;
1839		(const VkPipelineStageFlags*)DE_NULL,
1840		1u,								// deUint32					commandBufferCount;
1841		&m_cmdBuffer.get(),				// const VkCommandBuffer*	pCommandBuffers;
1842		0u,								// deUint32					signalSemaphoreCount;
1843		DE_NULL							// const VkSemaphore*		pSignalSemaphores;
1844	};
1845
1846	VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
1847	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
1848	VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
1849
1850	return readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_resolveImage, m_colorFormat, m_renderSize.cast<deUint32>());
1851}
1852
1853} // anonymous
1854
1855tcu::TestCaseGroup* createMultisampleTests (tcu::TestContext& testCtx)
1856{
1857	const VkSampleCountFlagBits samples[] =
1858	{
1859		VK_SAMPLE_COUNT_2_BIT,
1860		VK_SAMPLE_COUNT_4_BIT,
1861		VK_SAMPLE_COUNT_8_BIT,
1862		VK_SAMPLE_COUNT_16_BIT,
1863		VK_SAMPLE_COUNT_32_BIT,
1864		VK_SAMPLE_COUNT_64_BIT
1865	};
1866
1867	de::MovePtr<tcu::TestCaseGroup> multisampleTests (new tcu::TestCaseGroup(testCtx, "multisample", ""));
1868
1869	// Rasterization samples tests
1870	{
1871		de::MovePtr<tcu::TestCaseGroup> rasterizationSamplesTests(new tcu::TestCaseGroup(testCtx, "raster_samples", ""));
1872
1873		for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
1874		{
1875			std::ostringstream caseName;
1876			caseName << "samples_" << samples[samplesNdx];
1877
1878			de::MovePtr<tcu::TestCaseGroup> samplesTests	(new tcu::TestCaseGroup(testCtx, caseName.str().c_str(), ""));
1879
1880			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_triangle", "", samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_TRIANGLE));
1881			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_line", "", samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_LINE));
1882			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_point", "", samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_POINT));
1883
1884			rasterizationSamplesTests->addChild(samplesTests.release());
1885		}
1886
1887		multisampleTests->addChild(rasterizationSamplesTests.release());
1888	}
1889
1890	// Raster samples consistency check
1891	{
1892		de::MovePtr<tcu::TestCaseGroup> rasterSamplesConsistencyTests(new tcu::TestCaseGroup(testCtx, "raster_samples_consistency", ""));
1893
1894		addFunctionCaseWithPrograms(rasterSamplesConsistencyTests.get(),
1895									"unique_colors_check",
1896									"",
1897									initMultisamplePrograms,
1898									testRasterSamplesConsistency,
1899									GEOMETRY_TYPE_OPAQUE_TRIANGLE);
1900
1901		multisampleTests->addChild(rasterSamplesConsistencyTests.release());
1902	}
1903
1904	// minSampleShading tests
1905	{
1906		struct TestConfig
1907		{
1908			const char*	name;
1909			float		minSampleShading;
1910		};
1911
1912		const TestConfig testConfigs[] =
1913		{
1914			{ "min_0_0",	0.0f },
1915			{ "min_0_25",	0.25f },
1916			{ "min_0_5",	0.5f },
1917			{ "min_0_75",	0.75f },
1918			{ "min_1_0",	1.0f }
1919		};
1920
1921		de::MovePtr<tcu::TestCaseGroup> minSampleShadingTests(new tcu::TestCaseGroup(testCtx, "min_sample_shading", ""));
1922
1923		for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testConfigs); configNdx++)
1924		{
1925			const TestConfig&				testConfig				= testConfigs[configNdx];
1926			de::MovePtr<tcu::TestCaseGroup>	minShadingValueTests	(new tcu::TestCaseGroup(testCtx, testConfigs[configNdx].name, ""));
1927
1928			for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
1929			{
1930				std::ostringstream caseName;
1931				caseName << "samples_" << samples[samplesNdx];
1932
1933				de::MovePtr<tcu::TestCaseGroup> samplesTests	(new tcu::TestCaseGroup(testCtx, caseName.str().c_str(), ""));
1934
1935				samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_triangle", "", samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_TRIANGLE));
1936				samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_line", "", samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_LINE));
1937				samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_point", "", samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_POINT));
1938
1939				minShadingValueTests->addChild(samplesTests.release());
1940			}
1941
1942			minSampleShadingTests->addChild(minShadingValueTests.release());
1943		}
1944
1945		multisampleTests->addChild(minSampleShadingTests.release());
1946	}
1947
1948	// pSampleMask tests
1949	{
1950		struct TestConfig
1951		{
1952			const char*		name;
1953			const char*		description;
1954			VkSampleMask	sampleMask;
1955		};
1956
1957		const TestConfig testConfigs[] =
1958		{
1959			{ "mask_all_on",	"All mask bits are off",			0x0 },
1960			{ "mask_all_off",	"All mask bits are on",				0xFFFFFFFF },
1961			{ "mask_one",		"All mask elements are 0x1",		0x1},
1962			{ "mask_random",	"All mask elements are 0xAAAAAAAA",	0xAAAAAAAA },
1963		};
1964
1965		de::MovePtr<tcu::TestCaseGroup> sampleMaskTests(new tcu::TestCaseGroup(testCtx, "sample_mask", ""));
1966
1967		for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testConfigs); configNdx++)
1968		{
1969			const TestConfig&				testConfig				= testConfigs[configNdx];
1970			de::MovePtr<tcu::TestCaseGroup>	sampleMaskValueTests	(new tcu::TestCaseGroup(testCtx, testConfig.name, testConfig.description));
1971
1972			for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
1973			{
1974				std::ostringstream caseName;
1975				caseName << "samples_" << samples[samplesNdx];
1976
1977				const deUint32					sampleMaskCount	= samples[samplesNdx] / 32;
1978				de::MovePtr<tcu::TestCaseGroup> samplesTests	(new tcu::TestCaseGroup(testCtx, caseName.str().c_str(), ""));
1979
1980				std::vector<VkSampleMask> mask;
1981				for (deUint32 maskNdx = 0; maskNdx < sampleMaskCount; maskNdx++)
1982					mask.push_back(testConfig.sampleMask);
1983
1984				samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_triangle", "", samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_TRIANGLE));
1985				samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_line", "", samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_LINE));
1986				samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_point", "", samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_POINT));
1987
1988				sampleMaskValueTests->addChild(samplesTests.release());
1989			}
1990
1991			sampleMaskTests->addChild(sampleMaskValueTests.release());
1992		}
1993
1994		multisampleTests->addChild(sampleMaskTests.release());
1995
1996	}
1997
1998	// AlphaToOne tests
1999	{
2000		de::MovePtr<tcu::TestCaseGroup> alphaToOneTests(new tcu::TestCaseGroup(testCtx, "alpha_to_one", ""));
2001
2002		for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
2003		{
2004			std::ostringstream caseName;
2005			caseName << "samples_" << samples[samplesNdx];
2006
2007			alphaToOneTests->addChild(new AlphaToOneTest(testCtx, caseName.str(), "", samples[samplesNdx]));
2008		}
2009
2010		multisampleTests->addChild(alphaToOneTests.release());
2011	}
2012
2013	// AlphaToCoverageEnable tests
2014	{
2015		de::MovePtr<tcu::TestCaseGroup> alphaToCoverageTests (new tcu::TestCaseGroup(testCtx, "alpha_to_coverage", ""));
2016
2017		for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
2018		{
2019			std::ostringstream caseName;
2020			caseName << "samples_" << samples[samplesNdx];
2021
2022			de::MovePtr<tcu::TestCaseGroup> samplesTests	(new tcu::TestCaseGroup(testCtx, caseName.str().c_str(), ""));
2023
2024			samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_opaque", "", samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_QUAD));
2025			samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_translucent", "", samples[samplesNdx], GEOMETRY_TYPE_TRANSLUCENT_QUAD));
2026			samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_invisible", "", samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_QUAD));
2027
2028			alphaToCoverageTests->addChild(samplesTests.release());
2029		}
2030		multisampleTests->addChild(alphaToCoverageTests.release());
2031	}
2032
2033	return multisampleTests.release();
2034}
2035
2036} // pipeline
2037} // vkt
2038