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