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 "tcuTestLog.hpp"
41#include "deUniquePtr.hpp"
42#include "deSharedPtr.hpp"
43#include "deStringUtil.hpp"
44#include "deMemory.h"
45
46#include <sstream>
47#include <vector>
48#include <map>
49
50namespace vkt
51{
52namespace pipeline
53{
54
55using namespace vk;
56
57namespace
58{
59enum GeometryType
60{
61	GEOMETRY_TYPE_OPAQUE_TRIANGLE,
62	GEOMETRY_TYPE_OPAQUE_LINE,
63	GEOMETRY_TYPE_OPAQUE_POINT,
64	GEOMETRY_TYPE_OPAQUE_QUAD,
65	GEOMETRY_TYPE_OPAQUE_QUAD_NONZERO_DEPTH,	//!< placed at z = 0.5
66	GEOMETRY_TYPE_TRANSLUCENT_QUAD,
67	GEOMETRY_TYPE_INVISIBLE_TRIANGLE,
68	GEOMETRY_TYPE_INVISIBLE_QUAD,
69	GEOMETRY_TYPE_GRADIENT_QUAD
70};
71
72enum TestModeBits
73{
74	TEST_MODE_DEPTH_BIT		= 1u,
75	TEST_MODE_STENCIL_BIT	= 2u,
76};
77typedef deUint32 TestModeFlags;
78
79enum RenderType
80{
81	// resolve multisample rendering to single sampled image
82	RENDER_TYPE_RESOLVE		= 0u,
83
84	// copy samples to an array of single sampled images
85	RENDER_TYPE_COPY_SAMPLES
86};
87
88void									initMultisamplePrograms				(SourceCollections& sources, GeometryType geometryType);
89bool									isSupportedSampleCount				(const InstanceInterface& instanceInterface, VkPhysicalDevice physicalDevice, VkSampleCountFlagBits rasterizationSamples);
90bool									isSupportedDepthStencilFormat		(const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkFormat format);
91VkPipelineColorBlendAttachmentState		getDefaultColorBlendAttachmentState	(void);
92deUint32								getUniqueColorsCount				(const tcu::ConstPixelBufferAccess& image);
93VkImageAspectFlags						getImageAspectFlags					(const VkFormat format);
94VkPrimitiveTopology						getPrimitiveTopology				(const GeometryType geometryType);
95std::vector<Vertex4RGBA>				generateVertices					(const GeometryType geometryType);
96VkFormat								findSupportedDepthStencilFormat		(Context& context, const bool useDepth, const bool useStencil);
97
98class MultisampleTest : public vkt::TestCase
99{
100public:
101
102												MultisampleTest						(tcu::TestContext&								testContext,
103																					 const std::string&								name,
104																					 const std::string&								description,
105																					 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
106																					 const VkPipelineColorBlendAttachmentState&		blendState,
107																					 GeometryType									geometryType);
108	virtual										~MultisampleTest					(void) {}
109
110	virtual void								initPrograms						(SourceCollections& programCollection) const;
111	virtual TestInstance*						createInstance						(Context& context) const;
112
113protected:
114	virtual TestInstance*						createMultisampleTestInstance		(Context&										context,
115																					 VkPrimitiveTopology							topology,
116																					 const std::vector<Vertex4RGBA>&				vertices,
117																					 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
118																					 const VkPipelineColorBlendAttachmentState&		colorBlendState) const = 0;
119	VkPipelineMultisampleStateCreateInfo		m_multisampleStateParams;
120	const VkPipelineColorBlendAttachmentState	m_colorBlendState;
121	const GeometryType							m_geometryType;
122	std::vector<VkSampleMask>					m_sampleMask;
123};
124
125class RasterizationSamplesTest : public MultisampleTest
126{
127public:
128												RasterizationSamplesTest			(tcu::TestContext&		testContext,
129																					 const std::string&		name,
130																					 const std::string&		description,
131																					 VkSampleCountFlagBits	rasterizationSamples,
132																					 GeometryType			geometryType,
133																					 TestModeFlags			modeFlags				= 0u);
134	virtual										~RasterizationSamplesTest			(void) {}
135
136protected:
137	virtual TestInstance*						createMultisampleTestInstance		(Context&										context,
138																					 VkPrimitiveTopology							topology,
139																					 const std::vector<Vertex4RGBA>&				vertices,
140																					 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
141																					 const VkPipelineColorBlendAttachmentState&		colorBlendState) const;
142
143	static VkPipelineMultisampleStateCreateInfo	getRasterizationSamplesStateParams	(VkSampleCountFlagBits rasterizationSamples);
144
145	const TestModeFlags							m_modeFlags;
146};
147
148class MinSampleShadingTest : public MultisampleTest
149{
150public:
151												MinSampleShadingTest				(tcu::TestContext&		testContext,
152																					 const std::string&		name,
153																					 const std::string&		description,
154																					 VkSampleCountFlagBits	rasterizationSamples,
155																					 float					minSampleShading,
156																					 GeometryType			geometryType);
157	virtual										~MinSampleShadingTest				(void) {}
158
159protected:
160	virtual void								initPrograms						(SourceCollections& programCollection) const;
161	virtual TestInstance*						createMultisampleTestInstance		(Context&										context,
162																					 VkPrimitiveTopology							topology,
163																					 const std::vector<Vertex4RGBA>&				vertices,
164																					 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
165																					 const VkPipelineColorBlendAttachmentState&		colorBlendState) const;
166
167	static VkPipelineMultisampleStateCreateInfo	getMinSampleShadingStateParams		(VkSampleCountFlagBits rasterizationSamples, float minSampleShading);
168};
169
170class SampleMaskTest : public MultisampleTest
171{
172public:
173												SampleMaskTest						(tcu::TestContext&					testContext,
174																					 const std::string&					name,
175																					 const std::string&					description,
176																					 VkSampleCountFlagBits				rasterizationSamples,
177																					 const std::vector<VkSampleMask>&	sampleMask,
178																					 GeometryType						geometryType);
179
180	virtual										~SampleMaskTest						(void) {}
181
182protected:
183	virtual TestInstance*						createMultisampleTestInstance		(Context&										context,
184																					 VkPrimitiveTopology							topology,
185																					 const std::vector<Vertex4RGBA>&				vertices,
186																					 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
187																					 const VkPipelineColorBlendAttachmentState&		colorBlendState) const;
188
189	static VkPipelineMultisampleStateCreateInfo	getSampleMaskStateParams			(VkSampleCountFlagBits rasterizationSamples, const std::vector<VkSampleMask>& sampleMask);
190};
191
192class AlphaToOneTest : public MultisampleTest
193{
194public:
195												AlphaToOneTest					(tcu::TestContext&					testContext,
196																				 const std::string&					name,
197																				 const std::string&					description,
198																				 VkSampleCountFlagBits				rasterizationSamples);
199
200	virtual										~AlphaToOneTest					(void) {}
201
202protected:
203	virtual TestInstance*						createMultisampleTestInstance	(Context&										context,
204																				 VkPrimitiveTopology							topology,
205																				 const std::vector<Vertex4RGBA>&				vertices,
206																				 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
207																				 const VkPipelineColorBlendAttachmentState&		colorBlendState) const;
208
209	static VkPipelineMultisampleStateCreateInfo	getAlphaToOneStateParams		(VkSampleCountFlagBits rasterizationSamples);
210	static VkPipelineColorBlendAttachmentState	getAlphaToOneBlendState			(void);
211};
212
213class AlphaToCoverageTest : public MultisampleTest
214{
215public:
216												AlphaToCoverageTest				(tcu::TestContext&		testContext,
217																				 const std::string&		name,
218																				 const std::string&		description,
219																				 VkSampleCountFlagBits	rasterizationSamples,
220																				 GeometryType			geometryType);
221
222	virtual										~AlphaToCoverageTest			(void) {}
223
224protected:
225	virtual TestInstance*						createMultisampleTestInstance	(Context&										context,
226																				 VkPrimitiveTopology							topology,
227																				 const std::vector<Vertex4RGBA>&				vertices,
228																				 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
229																				 const VkPipelineColorBlendAttachmentState&		colorBlendState) const;
230
231	static VkPipelineMultisampleStateCreateInfo	getAlphaToCoverageStateParams	(VkSampleCountFlagBits rasterizationSamples);
232
233	GeometryType								m_geometryType;
234};
235
236typedef de::SharedPtr<Unique<VkPipeline> > VkPipelineSp;
237
238class MultisampleRenderer
239{
240public:
241												MultisampleRenderer			(Context&										context,
242																			 const VkFormat									colorFormat,
243																			 const tcu::IVec2&								renderSize,
244																			 const VkPrimitiveTopology						topology,
245																			 const std::vector<Vertex4RGBA>&				vertices,
246																			 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
247																			 const VkPipelineColorBlendAttachmentState&		blendState,
248																			 const RenderType								renderType);
249
250												MultisampleRenderer			(Context&										context,
251																			 const VkFormat									colorFormat,
252																			 const VkFormat									depthStencilFormat,
253																			 const tcu::IVec2&								renderSize,
254																			 const bool										useDepth,
255																			 const bool										useStencil,
256																			 const deUint32									numTopologies,
257																			 const VkPrimitiveTopology*						pTopology,
258																			 const std::vector<Vertex4RGBA>*				pVertices,
259																			 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
260																			 const VkPipelineColorBlendAttachmentState&		blendState,
261																		     const RenderType								renderType);
262
263	virtual										~MultisampleRenderer		(void);
264
265	de::MovePtr<tcu::TextureLevel>				render						(void);
266	de::MovePtr<tcu::TextureLevel>				getSingleSampledImage		(deUint32 sampleId);
267
268protected:
269	void										initialize					(Context&										context,
270																			 const deUint32									numTopologies,
271																			 const VkPrimitiveTopology*						pTopology,
272																			 const std::vector<Vertex4RGBA>*				pVertices);
273
274	Context&									m_context;
275
276	const VkFormat								m_colorFormat;
277	const VkFormat								m_depthStencilFormat;
278	tcu::IVec2									m_renderSize;
279	const bool									m_useDepth;
280	const bool									m_useStencil;
281
282	const VkPipelineMultisampleStateCreateInfo	m_multisampleStateParams;
283	const VkPipelineColorBlendAttachmentState	m_colorBlendState;
284
285	const RenderType							m_renderType;
286
287	Move<VkImage>								m_colorImage;
288	de::MovePtr<Allocation>						m_colorImageAlloc;
289	Move<VkImageView>							m_colorAttachmentView;
290
291	Move<VkImage>								m_resolveImage;
292	de::MovePtr<Allocation>						m_resolveImageAlloc;
293	Move<VkImageView>							m_resolveAttachmentView;
294
295	struct PerSampleImage
296	{
297		Move<VkImage>								m_image;
298		de::MovePtr<Allocation>						m_imageAlloc;
299		Move<VkImageView>							m_attachmentView;
300	};
301	std::vector<de::SharedPtr<PerSampleImage> >	m_perSampleImages;
302
303	Move<VkImage>								m_depthStencilImage;
304	de::MovePtr<Allocation>						m_depthStencilImageAlloc;
305	Move<VkImageView>							m_depthStencilAttachmentView;
306
307	Move<VkRenderPass>							m_renderPass;
308	Move<VkFramebuffer>							m_framebuffer;
309
310	Move<VkShaderModule>						m_vertexShaderModule;
311	Move<VkShaderModule>						m_fragmentShaderModule;
312
313	Move<VkShaderModule>						m_copySampleVertexShaderModule;
314	Move<VkShaderModule>						m_copySampleFragmentShaderModule;
315
316	Move<VkBuffer>								m_vertexBuffer;
317	de::MovePtr<Allocation>						m_vertexBufferAlloc;
318
319	Move<VkPipelineLayout>						m_pipelineLayout;
320	std::vector<VkPipelineSp>					m_graphicsPipelines;
321
322	Move<VkDescriptorSetLayout>					m_copySampleDesciptorLayout;
323	Move<VkDescriptorPool>						m_copySampleDesciptorPool;
324	Move<VkDescriptorSet>						m_copySampleDesciptorSet;
325
326	Move<VkPipelineLayout>						m_copySamplePipelineLayout;
327	std::vector<VkPipelineSp>					m_copySamplePipelines;
328
329	Move<VkCommandPool>							m_cmdPool;
330	Move<VkCommandBuffer>						m_cmdBuffer;
331
332	Move<VkFence>								m_fence;
333};
334
335class RasterizationSamplesInstance : public vkt::TestInstance
336{
337public:
338										RasterizationSamplesInstance	(Context&										context,
339																		 VkPrimitiveTopology							topology,
340																		 const std::vector<Vertex4RGBA>&				vertices,
341																		 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
342																		 const VkPipelineColorBlendAttachmentState&		blendState,
343																		 const TestModeFlags							modeFlags);
344	virtual								~RasterizationSamplesInstance	(void) {}
345
346	virtual tcu::TestStatus				iterate							(void);
347
348protected:
349	virtual tcu::TestStatus				verifyImage						(const tcu::ConstPixelBufferAccess& result);
350
351	const VkFormat						m_colorFormat;
352	const tcu::IVec2					m_renderSize;
353	const VkPrimitiveTopology			m_primitiveTopology;
354	const std::vector<Vertex4RGBA>		m_vertices;
355	const std::vector<Vertex4RGBA>		m_fullQuadVertices;			//!< used by depth/stencil case
356	const TestModeFlags					m_modeFlags;
357	de::MovePtr<MultisampleRenderer>	m_multisampleRenderer;
358};
359
360class MinSampleShadingInstance : public vkt::TestInstance
361{
362public:
363												MinSampleShadingInstance	(Context&										context,
364																			 VkPrimitiveTopology							topology,
365																			 const std::vector<Vertex4RGBA>&				vertices,
366																			 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
367																			 const VkPipelineColorBlendAttachmentState&		blendState);
368	virtual										~MinSampleShadingInstance	(void) {}
369
370	virtual tcu::TestStatus						iterate						(void);
371
372protected:
373	virtual tcu::TestStatus						verifySampleShadedImage		(const std::vector<tcu::TextureLevel>& testShadingImages,
374																			 const tcu::ConstPixelBufferAccess& noSampleshadingImage);
375
376	const VkFormat								m_colorFormat;
377	const tcu::IVec2							m_renderSize;
378	const VkPrimitiveTopology					m_primitiveTopology;
379	const std::vector<Vertex4RGBA>				m_vertices;
380	const VkPipelineMultisampleStateCreateInfo	m_multisampleStateParams;
381	const VkPipelineColorBlendAttachmentState	m_colorBlendState;
382};
383
384class SampleMaskInstance : public vkt::TestInstance
385{
386public:
387												SampleMaskInstance			(Context&										context,
388																			 VkPrimitiveTopology							topology,
389																			 const std::vector<Vertex4RGBA>&				vertices,
390																			 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
391																			 const VkPipelineColorBlendAttachmentState&		blendState);
392	virtual										~SampleMaskInstance			(void) {}
393
394	virtual tcu::TestStatus						iterate						(void);
395
396protected:
397	virtual tcu::TestStatus						verifyImage					(const tcu::ConstPixelBufferAccess& testShadingImage,
398																			 const tcu::ConstPixelBufferAccess& minShadingImage,
399																			 const tcu::ConstPixelBufferAccess& maxShadingImage);
400	const VkFormat								m_colorFormat;
401	const tcu::IVec2							m_renderSize;
402	const VkPrimitiveTopology					m_primitiveTopology;
403	const std::vector<Vertex4RGBA>				m_vertices;
404	const VkPipelineMultisampleStateCreateInfo	m_multisampleStateParams;
405	const VkPipelineColorBlendAttachmentState	m_colorBlendState;
406};
407
408class AlphaToOneInstance : public vkt::TestInstance
409{
410public:
411												AlphaToOneInstance			(Context&										context,
412																			 VkPrimitiveTopology							topology,
413																			 const std::vector<Vertex4RGBA>&				vertices,
414																			 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
415																			 const VkPipelineColorBlendAttachmentState&		blendState);
416	virtual										~AlphaToOneInstance			(void) {}
417
418	virtual tcu::TestStatus						iterate						(void);
419
420protected:
421	virtual tcu::TestStatus						verifyImage					(const tcu::ConstPixelBufferAccess& alphaOneImage,
422																			 const tcu::ConstPixelBufferAccess& noAlphaOneImage);
423	const VkFormat								m_colorFormat;
424	const tcu::IVec2							m_renderSize;
425	const VkPrimitiveTopology					m_primitiveTopology;
426	const std::vector<Vertex4RGBA>				m_vertices;
427	const VkPipelineMultisampleStateCreateInfo	m_multisampleStateParams;
428	const VkPipelineColorBlendAttachmentState	m_colorBlendState;
429};
430
431class AlphaToCoverageInstance : public vkt::TestInstance
432{
433public:
434												AlphaToCoverageInstance		(Context&										context,
435																			 VkPrimitiveTopology							topology,
436																			 const std::vector<Vertex4RGBA>&				vertices,
437																			 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
438																			 const VkPipelineColorBlendAttachmentState&		blendState,
439																			 GeometryType									geometryType);
440	virtual										~AlphaToCoverageInstance	(void) {}
441
442	virtual tcu::TestStatus						iterate						(void);
443
444protected:
445	virtual tcu::TestStatus						verifyImage					(const tcu::ConstPixelBufferAccess& result);
446	const VkFormat								m_colorFormat;
447	const tcu::IVec2							m_renderSize;
448	const VkPrimitiveTopology					m_primitiveTopology;
449	const std::vector<Vertex4RGBA>				m_vertices;
450	const VkPipelineMultisampleStateCreateInfo	m_multisampleStateParams;
451	const VkPipelineColorBlendAttachmentState	m_colorBlendState;
452	const GeometryType							m_geometryType;
453};
454
455
456// Helper functions
457
458void initMultisamplePrograms (SourceCollections& sources, GeometryType geometryType)
459{
460	std::ostringstream vertexSource;
461
462	vertexSource <<
463		"#version 310 es\n"
464		"layout(location = 0) in vec4 position;\n"
465		"layout(location = 1) in vec4 color;\n"
466		"layout(location = 0) out highp vec4 vtxColor;\n"
467		"void main (void)\n"
468		"{\n"
469		"	gl_Position = position;\n"
470		"	vtxColor = color;\n"
471		<< (geometryType == GEOMETRY_TYPE_OPAQUE_POINT ? "	gl_PointSize = 3.0f;\n"
472			: "")
473		<< "}\n";
474
475	static const char* fragmentSource =
476		"#version 310 es\n"
477		"layout(location = 0) in highp vec4 vtxColor;\n"
478		"layout(location = 0) out highp vec4 fragColor;\n"
479		"void main (void)\n"
480		"{\n"
481		"	fragColor = vtxColor;\n"
482		"}\n";
483
484	sources.glslSources.add("color_vert") << glu::VertexSource(vertexSource.str());
485	sources.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource);
486}
487
488void initSampleShadingPrograms (SourceCollections& sources, GeometryType geometryType)
489{
490	{
491		std::ostringstream vertexSource;
492
493		vertexSource <<
494			"#version 440\n"
495			"layout(location = 0) in vec4 position;\n"
496			"layout(location = 1) in vec4 color;\n"
497			"void main (void)\n"
498			"{\n"
499			"	gl_Position = position;\n"
500			<< (geometryType == GEOMETRY_TYPE_OPAQUE_POINT ? "	gl_PointSize = 3.0f;\n"
501				: "")
502			<< "}\n";
503
504		static const char* fragmentSource =
505			"#version 440\n"
506			"layout(location = 0) out highp vec4 fragColor;\n"
507			"void main (void)\n"
508			"{\n"
509			"	fragColor = vec4(fract(gl_FragCoord.xy), 0.0, 1.0);\n"
510			"}\n";
511
512		sources.glslSources.add("color_vert") << glu::VertexSource(vertexSource.str());
513		sources.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource);
514	}
515
516	{
517		static const char*  vertexSource =
518			"#version 440\n"
519			"void main (void)\n"
520			"{\n"
521			"	const vec4 positions[4] = vec4[4](\n"
522			"		vec4(-1.0, -1.0, 0.0, 1.0),\n"
523			"		vec4(-1.0,  1.0, 0.0, 1.0),\n"
524			"		vec4( 1.0, -1.0, 0.0, 1.0),\n"
525			"		vec4( 1.0,  1.0, 0.0, 1.0)\n"
526			"	);\n"
527			"	gl_Position = positions[gl_VertexIndex];\n"
528			"}\n";
529
530		static const char* fragmentSource =
531			"#version 440\n"
532			"precision highp float;\n"
533			"layout(location = 0) out highp vec4 fragColor;\n"
534			"layout(set = 0, binding = 0, input_attachment_index = 0) uniform subpassInputMS imageMS;\n"
535			"layout(push_constant) uniform PushConstantsBlock\n"
536			"{\n"
537			"	int sampleId;\n"
538			"} pushConstants;\n"
539			"void main (void)\n"
540			"{\n"
541			"	fragColor = subpassLoad(imageMS, pushConstants.sampleId);\n"
542			"}\n";
543
544		sources.glslSources.add("quad_vert") << glu::VertexSource(vertexSource);
545		sources.glslSources.add("copy_sample_frag") << glu::FragmentSource(fragmentSource);
546	}
547}
548
549bool isSupportedSampleCount (const InstanceInterface& instanceInterface, VkPhysicalDevice physicalDevice, VkSampleCountFlagBits rasterizationSamples)
550{
551	VkPhysicalDeviceProperties deviceProperties;
552
553	instanceInterface.getPhysicalDeviceProperties(physicalDevice, &deviceProperties);
554
555	return !!(deviceProperties.limits.framebufferColorSampleCounts & rasterizationSamples);
556}
557
558VkPipelineColorBlendAttachmentState getDefaultColorBlendAttachmentState (void)
559{
560	const VkPipelineColorBlendAttachmentState colorBlendState =
561	{
562		false,														// VkBool32					blendEnable;
563		VK_BLEND_FACTOR_ONE,										// VkBlendFactor			srcColorBlendFactor;
564		VK_BLEND_FACTOR_ZERO,										// VkBlendFactor			dstColorBlendFactor;
565		VK_BLEND_OP_ADD,											// VkBlendOp				colorBlendOp;
566		VK_BLEND_FACTOR_ONE,										// VkBlendFactor			srcAlphaBlendFactor;
567		VK_BLEND_FACTOR_ZERO,										// VkBlendFactor			dstAlphaBlendFactor;
568		VK_BLEND_OP_ADD,											// VkBlendOp				alphaBlendOp;
569		VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |		// VkColorComponentFlags	colorWriteMask;
570			VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
571	};
572
573	return colorBlendState;
574}
575
576deUint32 getUniqueColorsCount (const tcu::ConstPixelBufferAccess& image)
577{
578	DE_ASSERT(image.getFormat().getPixelSize() == 4);
579
580	std::map<deUint32, deUint32>	histogram; // map<pixel value, number of occurrences>
581	const deUint32					pixelCount	= image.getWidth() * image.getHeight() * image.getDepth();
582
583	for (deUint32 pixelNdx = 0; pixelNdx < pixelCount; pixelNdx++)
584	{
585		const deUint32 pixelValue = *((const deUint32*)image.getDataPtr() + pixelNdx);
586
587		if (histogram.find(pixelValue) != histogram.end())
588			histogram[pixelValue]++;
589		else
590			histogram[pixelValue] = 1;
591	}
592
593	return (deUint32)histogram.size();
594}
595
596VkImageAspectFlags getImageAspectFlags (const VkFormat format)
597{
598	const tcu::TextureFormat tcuFormat = mapVkFormat(format);
599
600	if      (tcuFormat.order == tcu::TextureFormat::DS)		return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
601	else if (tcuFormat.order == tcu::TextureFormat::D)		return VK_IMAGE_ASPECT_DEPTH_BIT;
602	else if (tcuFormat.order == tcu::TextureFormat::S)		return VK_IMAGE_ASPECT_STENCIL_BIT;
603
604	DE_ASSERT(false);
605	return 0u;
606}
607
608std::vector<Vertex4RGBA> generateVertices (const GeometryType geometryType)
609{
610	std::vector<Vertex4RGBA> vertices;
611
612	switch (geometryType)
613	{
614		case GEOMETRY_TYPE_OPAQUE_TRIANGLE:
615		case GEOMETRY_TYPE_INVISIBLE_TRIANGLE:
616		{
617			Vertex4RGBA vertexData[3] =
618			{
619				{
620					tcu::Vec4(-0.75f, 0.0f, 0.0f, 1.0f),
621					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
622				},
623				{
624					tcu::Vec4(0.75f, 0.125f, 0.0f, 1.0f),
625					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
626				},
627				{
628					tcu::Vec4(0.75f, -0.125f, 0.0f, 1.0f),
629					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
630				}
631			};
632
633			if (geometryType == GEOMETRY_TYPE_INVISIBLE_TRIANGLE)
634			{
635				for (int i = 0; i < 3; i++)
636					vertexData[i].color = tcu::Vec4();
637			}
638
639			vertices = std::vector<Vertex4RGBA>(vertexData, vertexData + 3);
640			break;
641		}
642
643		case GEOMETRY_TYPE_OPAQUE_LINE:
644		{
645			const Vertex4RGBA vertexData[2] =
646			{
647				{
648					tcu::Vec4(-0.75f, 0.25f, 0.0f, 1.0f),
649					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
650				},
651				{
652					tcu::Vec4(0.75f, -0.25f, 0.0f, 1.0f),
653					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
654				}
655			};
656
657			vertices = std::vector<Vertex4RGBA>(vertexData, vertexData + 2);
658			break;
659		}
660
661		case GEOMETRY_TYPE_OPAQUE_POINT:
662		{
663			const Vertex4RGBA vertex =
664			{
665				tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
666				tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
667			};
668
669			vertices = std::vector<Vertex4RGBA>(1, vertex);
670			break;
671		}
672
673		case GEOMETRY_TYPE_OPAQUE_QUAD:
674		case GEOMETRY_TYPE_OPAQUE_QUAD_NONZERO_DEPTH:
675		case GEOMETRY_TYPE_TRANSLUCENT_QUAD:
676		case GEOMETRY_TYPE_INVISIBLE_QUAD:
677		case GEOMETRY_TYPE_GRADIENT_QUAD:
678		{
679			Vertex4RGBA vertexData[4] =
680			{
681				{
682					tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
683					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
684				},
685				{
686					tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f),
687					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
688				},
689				{
690					tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
691					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
692				},
693				{
694					tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
695					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
696				}
697			};
698
699			if (geometryType == GEOMETRY_TYPE_TRANSLUCENT_QUAD)
700			{
701				for (int i = 0; i < 4; i++)
702					vertexData[i].color.w() = 0.25f;
703			}
704			else if (geometryType == GEOMETRY_TYPE_INVISIBLE_QUAD)
705			{
706				for (int i = 0; i < 4; i++)
707					vertexData[i].color.w() = 0.0f;
708			}
709			else if (geometryType == GEOMETRY_TYPE_GRADIENT_QUAD)
710			{
711				vertexData[0].color.w() = 0.0f;
712				vertexData[2].color.w() = 0.0f;
713			}
714			else if (geometryType == GEOMETRY_TYPE_OPAQUE_QUAD_NONZERO_DEPTH)
715			{
716				for (int i = 0; i < 4; i++)
717					vertexData[i].position.z() = 0.5f;
718			}
719
720			vertices = std::vector<Vertex4RGBA>(vertexData, vertexData + 4);
721			break;
722		}
723
724		default:
725			DE_ASSERT(false);
726	}
727	return vertices;
728}
729
730VkPrimitiveTopology getPrimitiveTopology (const GeometryType geometryType)
731{
732	switch (geometryType)
733	{
734		case GEOMETRY_TYPE_OPAQUE_TRIANGLE:
735		case GEOMETRY_TYPE_INVISIBLE_TRIANGLE:			return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
736
737		case GEOMETRY_TYPE_OPAQUE_LINE:					return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
738		case GEOMETRY_TYPE_OPAQUE_POINT:				return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
739
740		case GEOMETRY_TYPE_OPAQUE_QUAD:
741		case GEOMETRY_TYPE_OPAQUE_QUAD_NONZERO_DEPTH:
742		case GEOMETRY_TYPE_TRANSLUCENT_QUAD:
743		case GEOMETRY_TYPE_INVISIBLE_QUAD:
744		case GEOMETRY_TYPE_GRADIENT_QUAD:				return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
745
746		default:
747			DE_ASSERT(false);
748			return VK_PRIMITIVE_TOPOLOGY_LAST;
749	}
750}
751
752bool isSupportedDepthStencilFormat (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkFormat format)
753{
754	VkFormatProperties formatProps;
755	vki.getPhysicalDeviceFormatProperties(physDevice, format, &formatProps);
756	return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
757}
758
759VkFormat findSupportedDepthStencilFormat (Context& context, const bool useDepth, const bool useStencil)
760{
761	if (useDepth && !useStencil)
762		return VK_FORMAT_D16_UNORM;		// must be supported
763
764	const InstanceInterface&	vki			= context.getInstanceInterface();
765	const VkPhysicalDevice		physDevice	= context.getPhysicalDevice();
766
767	// One of these formats must be supported.
768
769	if (isSupportedDepthStencilFormat(vki, physDevice, VK_FORMAT_D24_UNORM_S8_UINT))
770		return VK_FORMAT_D24_UNORM_S8_UINT;
771
772	if (isSupportedDepthStencilFormat(vki, physDevice, VK_FORMAT_D32_SFLOAT_S8_UINT))
773		return VK_FORMAT_D32_SFLOAT_S8_UINT;
774
775	return VK_FORMAT_UNDEFINED;
776}
777
778
779// MultisampleTest
780
781MultisampleTest::MultisampleTest (tcu::TestContext&								testContext,
782								  const std::string&							name,
783								  const std::string&							description,
784								  const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
785								  const VkPipelineColorBlendAttachmentState&	blendState,
786								  GeometryType									geometryType)
787	: vkt::TestCase				(testContext, name, description)
788	, m_multisampleStateParams	(multisampleStateParams)
789	, m_colorBlendState			(blendState)
790	, m_geometryType			(geometryType)
791{
792	if (m_multisampleStateParams.pSampleMask)
793	{
794		// Copy pSampleMask to avoid dependencies with other classes
795
796		const deUint32 maskCount = deCeilFloatToInt32(float(m_multisampleStateParams.rasterizationSamples) / 32);
797
798		for (deUint32 maskNdx = 0; maskNdx < maskCount; maskNdx++)
799			m_sampleMask.push_back(m_multisampleStateParams.pSampleMask[maskNdx]);
800
801		m_multisampleStateParams.pSampleMask = m_sampleMask.data();
802	}
803}
804
805void MultisampleTest::initPrograms (SourceCollections& programCollection) const
806{
807	initMultisamplePrograms(programCollection, m_geometryType);
808}
809
810TestInstance* MultisampleTest::createInstance (Context& context) const
811{
812	return createMultisampleTestInstance(context, getPrimitiveTopology(m_geometryType), generateVertices(m_geometryType), m_multisampleStateParams, m_colorBlendState);
813}
814
815
816// RasterizationSamplesTest
817
818RasterizationSamplesTest::RasterizationSamplesTest (tcu::TestContext&		testContext,
819													const std::string&		name,
820													const std::string&		description,
821													VkSampleCountFlagBits	rasterizationSamples,
822													GeometryType			geometryType,
823													TestModeFlags			modeFlags)
824	: MultisampleTest	(testContext, name, description, getRasterizationSamplesStateParams(rasterizationSamples), getDefaultColorBlendAttachmentState(), geometryType)
825	, m_modeFlags		(modeFlags)
826{
827}
828
829VkPipelineMultisampleStateCreateInfo RasterizationSamplesTest::getRasterizationSamplesStateParams (VkSampleCountFlagBits rasterizationSamples)
830{
831	const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
832	{
833		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
834		DE_NULL,													// const void*								pNext;
835		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
836		rasterizationSamples,										// VkSampleCountFlagBits					rasterizationSamples;
837		false,														// VkBool32									sampleShadingEnable;
838		0.0f,														// float									minSampleShading;
839		DE_NULL,													// const VkSampleMask*						pSampleMask;
840		false,														// VkBool32									alphaToCoverageEnable;
841		false														// VkBool32									alphaToOneEnable;
842	};
843
844	return multisampleStateParams;
845}
846
847TestInstance* RasterizationSamplesTest::createMultisampleTestInstance (Context&										context,
848																	   VkPrimitiveTopology							topology,
849																	   const std::vector<Vertex4RGBA>&				vertices,
850																	   const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
851																	   const VkPipelineColorBlendAttachmentState&	colorBlendState) const
852{
853	return new RasterizationSamplesInstance(context, topology, vertices, multisampleStateParams, colorBlendState, m_modeFlags);
854}
855
856
857// MinSampleShadingTest
858
859MinSampleShadingTest::MinSampleShadingTest (tcu::TestContext&		testContext,
860											const std::string&		name,
861											const std::string&		description,
862											VkSampleCountFlagBits	rasterizationSamples,
863											float					minSampleShading,
864											GeometryType			geometryType)
865	: MultisampleTest	(testContext, name, description, getMinSampleShadingStateParams(rasterizationSamples, minSampleShading), getDefaultColorBlendAttachmentState(), geometryType)
866{
867}
868
869void MinSampleShadingTest::initPrograms (SourceCollections& programCollection) const
870{
871	initSampleShadingPrograms(programCollection, m_geometryType);
872}
873
874TestInstance* MinSampleShadingTest::createMultisampleTestInstance (Context&										context,
875																   VkPrimitiveTopology							topology,
876																   const std::vector<Vertex4RGBA>&				vertices,
877																   const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
878																   const VkPipelineColorBlendAttachmentState&	colorBlendState) const
879{
880	return new MinSampleShadingInstance(context, topology, vertices, multisampleStateParams, colorBlendState);
881}
882
883VkPipelineMultisampleStateCreateInfo MinSampleShadingTest::getMinSampleShadingStateParams (VkSampleCountFlagBits rasterizationSamples, float minSampleShading)
884{
885	const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
886	{
887		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
888		DE_NULL,													// const void*								pNext;
889		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
890		rasterizationSamples,										// VkSampleCountFlagBits					rasterizationSamples;
891		true,														// VkBool32									sampleShadingEnable;
892		minSampleShading,											// float									minSampleShading;
893		DE_NULL,													// const VkSampleMask*						pSampleMask;
894		false,														//  VkBool32								alphaToCoverageEnable;
895		false														//  VkBool32								alphaToOneEnable;
896	};
897
898	return multisampleStateParams;
899}
900
901
902// SampleMaskTest
903
904SampleMaskTest::SampleMaskTest (tcu::TestContext&					testContext,
905								const std::string&					name,
906								const std::string&					description,
907								VkSampleCountFlagBits				rasterizationSamples,
908								const std::vector<VkSampleMask>&	sampleMask,
909								GeometryType						geometryType)
910	: MultisampleTest	(testContext, name, description, getSampleMaskStateParams(rasterizationSamples, sampleMask), getDefaultColorBlendAttachmentState(), geometryType)
911{
912}
913
914TestInstance* SampleMaskTest::createMultisampleTestInstance (Context&										context,
915															 VkPrimitiveTopology							topology,
916															 const std::vector<Vertex4RGBA>&				vertices,
917															 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
918															 const VkPipelineColorBlendAttachmentState&		colorBlendState) const
919{
920	return new SampleMaskInstance(context, topology,vertices, multisampleStateParams, colorBlendState);
921}
922
923VkPipelineMultisampleStateCreateInfo SampleMaskTest::getSampleMaskStateParams (VkSampleCountFlagBits rasterizationSamples, const std::vector<VkSampleMask>& sampleMask)
924{
925	const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
926	{
927		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
928		DE_NULL,													// const void*								pNext;
929		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
930		rasterizationSamples,										// VkSampleCountFlagBits					rasterizationSamples;
931		false,														// VkBool32									sampleShadingEnable;
932		0.0f,														// float									minSampleShading;
933		sampleMask.data(),											// const VkSampleMask*						pSampleMask;
934		false,														// VkBool32									alphaToCoverageEnable;
935		false														// VkBool32									alphaToOneEnable;
936	};
937
938	return multisampleStateParams;
939}
940
941
942// AlphaToOneTest
943
944AlphaToOneTest::AlphaToOneTest (tcu::TestContext&		testContext,
945								const std::string&		name,
946								const std::string&		description,
947								VkSampleCountFlagBits	rasterizationSamples)
948	: MultisampleTest	(testContext, name, description, getAlphaToOneStateParams(rasterizationSamples), getAlphaToOneBlendState(), GEOMETRY_TYPE_GRADIENT_QUAD)
949{
950}
951
952TestInstance* AlphaToOneTest::createMultisampleTestInstance (Context&										context,
953															 VkPrimitiveTopology							topology,
954															 const std::vector<Vertex4RGBA>&				vertices,
955															 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
956															 const VkPipelineColorBlendAttachmentState&		colorBlendState) const
957{
958	return new AlphaToOneInstance(context, topology, vertices, multisampleStateParams, colorBlendState);
959}
960
961VkPipelineMultisampleStateCreateInfo AlphaToOneTest::getAlphaToOneStateParams (VkSampleCountFlagBits rasterizationSamples)
962{
963	const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
964	{
965		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
966		DE_NULL,													// const void*								pNext;
967		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
968		rasterizationSamples,										// VkSampleCountFlagBits					rasterizationSamples;
969		false,														// VkBool32									sampleShadingEnable;
970		0.0f,														// float									minSampleShading;
971		DE_NULL,													// const VkSampleMask*						pSampleMask;
972		false,														// VkBool32									alphaToCoverageEnable;
973		true														// VkBool32									alphaToOneEnable;
974	};
975
976	return multisampleStateParams;
977}
978
979VkPipelineColorBlendAttachmentState AlphaToOneTest::getAlphaToOneBlendState (void)
980{
981	const VkPipelineColorBlendAttachmentState colorBlendState =
982	{
983		true,														// VkBool32					blendEnable;
984		VK_BLEND_FACTOR_SRC_ALPHA,									// VkBlendFactor			srcColorBlendFactor;
985		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,						// VkBlendFactor			dstColorBlendFactor;
986		VK_BLEND_OP_ADD,											// VkBlendOp				colorBlendOp;
987		VK_BLEND_FACTOR_SRC_ALPHA,									// VkBlendFactor			srcAlphaBlendFactor;
988		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,						// VkBlendFactor			dstAlphaBlendFactor;
989		VK_BLEND_OP_ADD,											// VkBlendOp				alphaBlendOp;
990		VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |		// VkColorComponentFlags	colorWriteMask;
991			VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
992	};
993
994	return colorBlendState;
995}
996
997
998// AlphaToCoverageTest
999
1000AlphaToCoverageTest::AlphaToCoverageTest (tcu::TestContext&			testContext,
1001										  const std::string&		name,
1002										  const std::string&		description,
1003										  VkSampleCountFlagBits		rasterizationSamples,
1004										  GeometryType				geometryType)
1005	: MultisampleTest	(testContext, name, description, getAlphaToCoverageStateParams(rasterizationSamples), getDefaultColorBlendAttachmentState(), geometryType)
1006	, m_geometryType	(geometryType)
1007{
1008}
1009
1010TestInstance* AlphaToCoverageTest::createMultisampleTestInstance (Context&										context,
1011																  VkPrimitiveTopology							topology,
1012																  const std::vector<Vertex4RGBA>&				vertices,
1013																  const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
1014																  const VkPipelineColorBlendAttachmentState&	colorBlendState) const
1015{
1016	return new AlphaToCoverageInstance(context, topology, vertices, multisampleStateParams, colorBlendState, m_geometryType);
1017}
1018
1019VkPipelineMultisampleStateCreateInfo AlphaToCoverageTest::getAlphaToCoverageStateParams (VkSampleCountFlagBits rasterizationSamples)
1020{
1021	const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
1022	{
1023		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
1024		DE_NULL,													// const void*								pNext;
1025		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
1026		rasterizationSamples,										// VkSampleCountFlagBits					rasterizationSamples;
1027		false,														// VkBool32									sampleShadingEnable;
1028		0.0f,														// float									minSampleShading;
1029		DE_NULL,													// const VkSampleMask*						pSampleMask;
1030		true,														// VkBool32									alphaToCoverageEnable;
1031		false														// VkBool32									alphaToOneEnable;
1032	};
1033
1034	return multisampleStateParams;
1035}
1036
1037// RasterizationSamplesInstance
1038
1039RasterizationSamplesInstance::RasterizationSamplesInstance (Context&										context,
1040															VkPrimitiveTopology								topology,
1041															const std::vector<Vertex4RGBA>&					vertices,
1042															const VkPipelineMultisampleStateCreateInfo&		multisampleStateParams,
1043															const VkPipelineColorBlendAttachmentState&		blendState,
1044															const TestModeFlags								modeFlags)
1045	: vkt::TestInstance		(context)
1046	, m_colorFormat			(VK_FORMAT_R8G8B8A8_UNORM)
1047	, m_renderSize			(32, 32)
1048	, m_primitiveTopology	(topology)
1049	, m_vertices			(vertices)
1050	, m_fullQuadVertices	(generateVertices(GEOMETRY_TYPE_OPAQUE_QUAD_NONZERO_DEPTH))
1051	, m_modeFlags			(modeFlags)
1052{
1053	if (m_modeFlags != 0)
1054	{
1055		const bool		useDepth			= (m_modeFlags & TEST_MODE_DEPTH_BIT) != 0;
1056		const bool		useStencil			= (m_modeFlags & TEST_MODE_STENCIL_BIT) != 0;
1057		const VkFormat	depthStencilFormat	= findSupportedDepthStencilFormat(context, useDepth, useStencil);
1058
1059		if (depthStencilFormat == VK_FORMAT_UNDEFINED)
1060			TCU_THROW(NotSupportedError, "Required depth/stencil format is not supported");
1061
1062		const VkPrimitiveTopology		pTopology[2] = { m_primitiveTopology, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP };
1063		const std::vector<Vertex4RGBA>	pVertices[2] = { m_vertices, m_fullQuadVertices };
1064
1065		m_multisampleRenderer = de::MovePtr<MultisampleRenderer>(
1066			new MultisampleRenderer(
1067				context, m_colorFormat, depthStencilFormat, m_renderSize, useDepth, useStencil, 2u, pTopology, pVertices, multisampleStateParams, blendState, RENDER_TYPE_RESOLVE));
1068	}
1069	else
1070	{
1071		m_multisampleRenderer = de::MovePtr<MultisampleRenderer>(
1072			new MultisampleRenderer(context, m_colorFormat, m_renderSize, topology, vertices, multisampleStateParams, blendState, RENDER_TYPE_RESOLVE));
1073	}
1074}
1075
1076tcu::TestStatus RasterizationSamplesInstance::iterate (void)
1077{
1078	de::MovePtr<tcu::TextureLevel> level(m_multisampleRenderer->render());
1079	return verifyImage(level->getAccess());
1080}
1081
1082tcu::TestStatus RasterizationSamplesInstance::verifyImage (const tcu::ConstPixelBufferAccess& result)
1083{
1084	// Verify range of unique pixels
1085	{
1086		const deUint32	numUniqueColors = getUniqueColorsCount(result);
1087		const deUint32	minUniqueColors	= 3;
1088
1089		tcu::TestLog& log = m_context.getTestContext().getLog();
1090
1091		log << tcu::TestLog::Message
1092			<< "\nMin. unique colors expected: " << minUniqueColors << "\n"
1093			<< "Unique colors found: " << numUniqueColors << "\n"
1094			<< tcu::TestLog::EndMessage;
1095
1096		if (numUniqueColors < minUniqueColors)
1097			return tcu::TestStatus::fail("Unique colors out of expected bounds");
1098	}
1099
1100	// Verify shape of the rendered primitive (fuzzy-compare)
1101	{
1102		const tcu::TextureFormat	tcuColorFormat	= mapVkFormat(m_colorFormat);
1103		const tcu::TextureFormat	tcuDepthFormat	= tcu::TextureFormat();
1104		const ColorVertexShader		vertexShader;
1105		const ColorFragmentShader	fragmentShader	(tcuColorFormat, tcuDepthFormat);
1106		const rr::Program			program			(&vertexShader, &fragmentShader);
1107		ReferenceRenderer			refRenderer		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
1108		rr::RenderState				renderState		(refRenderer.getViewportState());
1109
1110		if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
1111		{
1112			VkPhysicalDeviceProperties deviceProperties;
1113
1114			m_context.getInstanceInterface().getPhysicalDeviceProperties(m_context.getPhysicalDevice(), &deviceProperties);
1115
1116			// gl_PointSize is clamped to pointSizeRange
1117			renderState.point.pointSize = deFloatMin(3.0f, deviceProperties.limits.pointSizeRange[1]);
1118		}
1119
1120		if (m_modeFlags == 0)
1121		{
1122			refRenderer.colorClear(tcu::Vec4(0.0f));
1123			refRenderer.draw(renderState, mapVkPrimitiveTopology(m_primitiveTopology), m_vertices);
1124		}
1125		else
1126		{
1127			// For depth/stencil case the primitive is invisible and the surroundings are filled red.
1128			refRenderer.colorClear(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
1129			refRenderer.draw(renderState, mapVkPrimitiveTopology(m_primitiveTopology), m_vertices);
1130		}
1131
1132		if (!tcu::fuzzyCompare(m_context.getTestContext().getLog(), "FuzzyImageCompare", "Image comparison", refRenderer.getAccess(), result, 0.05f, tcu::COMPARE_LOG_RESULT))
1133			return tcu::TestStatus::fail("Primitive has unexpected shape");
1134	}
1135
1136	return tcu::TestStatus::pass("Primitive rendered, unique colors within expected bounds");
1137}
1138
1139
1140// MinSampleShadingInstance
1141
1142MinSampleShadingInstance::MinSampleShadingInstance (Context&									context,
1143													VkPrimitiveTopology							topology,
1144													const std::vector<Vertex4RGBA>&				vertices,
1145													const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
1146													const VkPipelineColorBlendAttachmentState&	colorBlendState)
1147	: vkt::TestInstance			(context)
1148	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
1149	, m_renderSize				(32, 32)
1150	, m_primitiveTopology		(topology)
1151	, m_vertices				(vertices)
1152	, m_multisampleStateParams	(multisampleStateParams)
1153	, m_colorBlendState			(colorBlendState)
1154{
1155	VkPhysicalDeviceFeatures deviceFeatures;
1156
1157	m_context.getInstanceInterface().getPhysicalDeviceFeatures(m_context.getPhysicalDevice(), &deviceFeatures);
1158
1159	if (!deviceFeatures.sampleRateShading)
1160		throw tcu::NotSupportedError("Sample shading is not supported");
1161}
1162
1163tcu::TestStatus MinSampleShadingInstance::iterate (void)
1164{
1165	de::MovePtr<tcu::TextureLevel>	noSampleshadingImage;
1166	std::vector<tcu::TextureLevel>	sampleShadedImages;
1167
1168	// Render and resolve without sample shading
1169	{
1170		VkPipelineMultisampleStateCreateInfo multisampleStateParms = m_multisampleStateParams;
1171		multisampleStateParms.sampleShadingEnable	= VK_FALSE;
1172		multisampleStateParms.minSampleShading		= 0.0;
1173
1174		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleStateParms, m_colorBlendState, RENDER_TYPE_RESOLVE);
1175		noSampleshadingImage  = renderer.render();
1176	}
1177
1178	// Render with test minSampleShading and collect per-sample images
1179	{
1180		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState, RENDER_TYPE_COPY_SAMPLES);
1181		renderer.render();
1182
1183		sampleShadedImages.resize(m_multisampleStateParams.rasterizationSamples);
1184		for (deUint32 sampleId = 0; sampleId < sampleShadedImages.size(); sampleId++)
1185		{
1186			sampleShadedImages[sampleId] = *renderer.getSingleSampledImage(sampleId);
1187		}
1188	}
1189
1190	// Log images
1191	{
1192		tcu::TestLog& testLog	= m_context.getTestContext().getLog();
1193
1194		testLog << tcu::TestLog::ImageSet("Images", "Images")
1195				<< tcu::TestLog::Image("noSampleshadingImage", "Image rendered without sample shading", noSampleshadingImage->getAccess());
1196
1197		for (deUint32 sampleId = 0; sampleId < sampleShadedImages.size(); sampleId++)
1198		{
1199			testLog << tcu::TestLog::Image("sampleShadedImage", "One sample of sample shaded image", sampleShadedImages[sampleId].getAccess());
1200		}
1201		testLog << tcu::TestLog::EndImageSet;
1202	}
1203
1204	return verifySampleShadedImage(sampleShadedImages, noSampleshadingImage->getAccess());
1205}
1206
1207tcu::TestStatus MinSampleShadingInstance::verifySampleShadedImage (const std::vector<tcu::TextureLevel>& sampleShadedImages, const tcu::ConstPixelBufferAccess& noSampleshadingImage)
1208{
1209	const deUint32	pixelCount	= noSampleshadingImage.getWidth() * noSampleshadingImage.getHeight() * noSampleshadingImage.getDepth();
1210
1211	bool anyPixelCovered		= false;
1212
1213	for (deUint32 pixelNdx = 0; pixelNdx < pixelCount; pixelNdx++)
1214	{
1215		const deUint32 noSampleShadingValue = *((const deUint32*)noSampleshadingImage.getDataPtr() + pixelNdx);
1216
1217		if (noSampleShadingValue == 0)
1218		{
1219			// non-covered pixel, continue
1220			continue;
1221		}
1222		else
1223		{
1224			anyPixelCovered = true;
1225		}
1226
1227		int numNotCoveredSamples = 0;
1228
1229		std::map<deUint32, deUint32>	histogram; // map<pixel value, number of occurrences>
1230
1231		// Collect histogram of occurrences or each pixel across all samples
1232		for (size_t i = 0; i < sampleShadedImages.size(); ++i)
1233		{
1234			const deUint32 sampleShadedValue = *((const deUint32*)sampleShadedImages[i].getAccess().getDataPtr() + pixelNdx);
1235
1236			if (sampleShadedValue == 0)
1237			{
1238				numNotCoveredSamples++;
1239				continue;
1240			}
1241
1242			if (histogram.find(sampleShadedValue) != histogram.end())
1243				histogram[sampleShadedValue]++;
1244			else
1245				histogram[sampleShadedValue] = 1;
1246		}
1247
1248		if (numNotCoveredSamples == static_cast<int>(sampleShadedImages.size()))
1249		{
1250			return tcu::TestStatus::fail("Got uncovered pixel, where covered samples were expected");
1251		}
1252
1253		const int uniqueColorsCount				= (int)histogram.size();
1254		const int expectedUniqueSamplesCount	= static_cast<int>(m_multisampleStateParams.minSampleShading * static_cast<float>(sampleShadedImages.size()) + 0.5f);
1255
1256		if (uniqueColorsCount + numNotCoveredSamples < expectedUniqueSamplesCount)
1257		{
1258			return tcu::TestStatus::fail("Got less unique colors than requested through minSampleShading");
1259		}
1260	}
1261
1262	if (!anyPixelCovered)
1263	{
1264		return tcu::TestStatus::fail("Did not get any covered pixel, cannot test minSampleShading");
1265	}
1266
1267	return tcu::TestStatus::pass("Got proper count of unique colors");
1268}
1269
1270SampleMaskInstance::SampleMaskInstance (Context&										context,
1271										VkPrimitiveTopology								topology,
1272										const std::vector<Vertex4RGBA>&					vertices,
1273										const VkPipelineMultisampleStateCreateInfo&		multisampleStateParams,
1274										const VkPipelineColorBlendAttachmentState&		blendState)
1275	: vkt::TestInstance			(context)
1276	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
1277	, m_renderSize				(32, 32)
1278	, m_primitiveTopology		(topology)
1279	, m_vertices				(vertices)
1280	, m_multisampleStateParams	(multisampleStateParams)
1281	, m_colorBlendState			(blendState)
1282{
1283}
1284
1285tcu::TestStatus SampleMaskInstance::iterate (void)
1286{
1287	de::MovePtr<tcu::TextureLevel>				testSampleMaskImage;
1288	de::MovePtr<tcu::TextureLevel>				minSampleMaskImage;
1289	de::MovePtr<tcu::TextureLevel>				maxSampleMaskImage;
1290
1291	// Render with test flags
1292	{
1293		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState, RENDER_TYPE_RESOLVE);
1294		testSampleMaskImage = renderer.render();
1295	}
1296
1297	// Render with all flags off
1298	{
1299		VkPipelineMultisampleStateCreateInfo	multisampleParams	= m_multisampleStateParams;
1300		const std::vector<VkSampleMask>			sampleMask			(multisampleParams.rasterizationSamples / 32, (VkSampleMask)0);
1301
1302		multisampleParams.pSampleMask = sampleMask.data();
1303
1304		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState, RENDER_TYPE_RESOLVE);
1305		minSampleMaskImage = renderer.render();
1306	}
1307
1308	// Render with all flags on
1309	{
1310		VkPipelineMultisampleStateCreateInfo	multisampleParams	= m_multisampleStateParams;
1311		const std::vector<VkSampleMask>			sampleMask			(multisampleParams.rasterizationSamples / 32, ~((VkSampleMask)0));
1312
1313		multisampleParams.pSampleMask = sampleMask.data();
1314
1315		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState, RENDER_TYPE_RESOLVE);
1316		maxSampleMaskImage = renderer.render();
1317	}
1318
1319	return verifyImage(testSampleMaskImage->getAccess(), minSampleMaskImage->getAccess(), maxSampleMaskImage->getAccess());
1320}
1321
1322tcu::TestStatus SampleMaskInstance::verifyImage (const tcu::ConstPixelBufferAccess& testSampleMaskImage,
1323												 const tcu::ConstPixelBufferAccess& minSampleMaskImage,
1324												 const tcu::ConstPixelBufferAccess& maxSampleMaskImage)
1325{
1326	const deUint32	testColorCount	= getUniqueColorsCount(testSampleMaskImage);
1327	const deUint32	minColorCount	= getUniqueColorsCount(minSampleMaskImage);
1328	const deUint32	maxColorCount	= getUniqueColorsCount(maxSampleMaskImage);
1329
1330	tcu::TestLog& log = m_context.getTestContext().getLog();
1331
1332	log << tcu::TestLog::Message
1333		<< "\nColors found: " << testColorCount << "\n"
1334		<< "Min. colors expected: " << minColorCount << "\n"
1335		<< "Max. colors expected: " << maxColorCount << "\n"
1336		<< tcu::TestLog::EndMessage;
1337
1338	if (minColorCount > testColorCount || testColorCount > maxColorCount)
1339		return tcu::TestStatus::fail("Unique colors out of expected bounds");
1340	else
1341		return tcu::TestStatus::pass("Unique colors within expected bounds");
1342}
1343
1344tcu::TestStatus testRasterSamplesConsistency (Context& context, GeometryType geometryType)
1345{
1346	// Use triangle only.
1347	DE_UNREF(geometryType);
1348
1349	const VkSampleCountFlagBits samples[] =
1350	{
1351		VK_SAMPLE_COUNT_1_BIT,
1352		VK_SAMPLE_COUNT_2_BIT,
1353		VK_SAMPLE_COUNT_4_BIT,
1354		VK_SAMPLE_COUNT_8_BIT,
1355		VK_SAMPLE_COUNT_16_BIT,
1356		VK_SAMPLE_COUNT_32_BIT,
1357		VK_SAMPLE_COUNT_64_BIT
1358	};
1359
1360	const Vertex4RGBA vertexData[3] =
1361	{
1362		{
1363			tcu::Vec4(-0.75f, 0.0f, 0.0f, 1.0f),
1364			tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
1365		},
1366		{
1367			tcu::Vec4(0.75f, 0.125f, 0.0f, 1.0f),
1368			tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
1369		},
1370		{
1371			tcu::Vec4(0.75f, -0.125f, 0.0f, 1.0f),
1372			tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
1373		}
1374	};
1375
1376	const std::vector<Vertex4RGBA>	vertices			(vertexData, vertexData + 3);
1377	deUint32						prevUniqueColors	= 2;
1378	int								renderCount			= 0;
1379
1380	// Do not render with 1 sample (start with samplesNdx = 1).
1381	for (int samplesNdx = 1; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
1382	{
1383		if (!isSupportedSampleCount(context.getInstanceInterface(), context.getPhysicalDevice(), samples[samplesNdx]))
1384			continue;
1385
1386		const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
1387		{
1388			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
1389			DE_NULL,													// const void*								pNext;
1390			0u,															// VkPipelineMultisampleStateCreateFlags	flags;
1391			samples[samplesNdx],										// VkSampleCountFlagBits					rasterizationSamples;
1392			false,														// VkBool32									sampleShadingEnable;
1393			0.0f,														// float									minSampleShading;
1394			DE_NULL,													// const VkSampleMask*						pSampleMask;
1395			false,														// VkBool32									alphaToCoverageEnable;
1396			false														// VkBool32									alphaToOneEnable;
1397		};
1398
1399		MultisampleRenderer				renderer		(context, VK_FORMAT_R8G8B8A8_UNORM, tcu::IVec2(32, 32), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, vertices, multisampleStateParams, getDefaultColorBlendAttachmentState(), RENDER_TYPE_RESOLVE);
1400		de::MovePtr<tcu::TextureLevel>	result			= renderer.render();
1401		const deUint32					uniqueColors	= getUniqueColorsCount(result->getAccess());
1402
1403		renderCount++;
1404
1405		if (prevUniqueColors > uniqueColors)
1406		{
1407			std::ostringstream message;
1408
1409			message << "More unique colors generated with " << samples[samplesNdx - 1] << " than with " << samples[samplesNdx];
1410			return tcu::TestStatus::fail(message.str());
1411		}
1412
1413		prevUniqueColors = uniqueColors;
1414	}
1415
1416	if (renderCount == 0)
1417		throw tcu::NotSupportedError("Multisampling is unsupported");
1418
1419	return tcu::TestStatus::pass("Number of unique colors increases as the sample count increases");
1420}
1421
1422
1423// AlphaToOneInstance
1424
1425AlphaToOneInstance::AlphaToOneInstance (Context&									context,
1426										VkPrimitiveTopology							topology,
1427										const std::vector<Vertex4RGBA>&				vertices,
1428										const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
1429										const VkPipelineColorBlendAttachmentState&	blendState)
1430	: vkt::TestInstance			(context)
1431	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
1432	, m_renderSize				(32, 32)
1433	, m_primitiveTopology		(topology)
1434	, m_vertices				(vertices)
1435	, m_multisampleStateParams	(multisampleStateParams)
1436	, m_colorBlendState			(blendState)
1437{
1438	VkPhysicalDeviceFeatures deviceFeatures;
1439
1440	context.getInstanceInterface().getPhysicalDeviceFeatures(context.getPhysicalDevice(), &deviceFeatures);
1441
1442	if (!deviceFeatures.alphaToOne)
1443		throw tcu::NotSupportedError("Alpha-to-one is not supported");
1444}
1445
1446tcu::TestStatus AlphaToOneInstance::iterate	(void)
1447{
1448	DE_ASSERT(m_multisampleStateParams.alphaToOneEnable);
1449	DE_ASSERT(m_colorBlendState.blendEnable);
1450
1451	de::MovePtr<tcu::TextureLevel>	alphaOneImage;
1452	de::MovePtr<tcu::TextureLevel>	noAlphaOneImage;
1453
1454	// Render with blend enabled and alpha to one on
1455	{
1456		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState, RENDER_TYPE_RESOLVE);
1457		alphaOneImage = renderer.render();
1458	}
1459
1460	// Render with blend enabled and alpha to one off
1461	{
1462		VkPipelineMultisampleStateCreateInfo	multisampleParams	= m_multisampleStateParams;
1463		multisampleParams.alphaToOneEnable = false;
1464
1465		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState, RENDER_TYPE_RESOLVE);
1466		noAlphaOneImage = renderer.render();
1467	}
1468
1469	return verifyImage(alphaOneImage->getAccess(), noAlphaOneImage->getAccess());
1470}
1471
1472tcu::TestStatus AlphaToOneInstance::verifyImage (const tcu::ConstPixelBufferAccess&	alphaOneImage,
1473												 const tcu::ConstPixelBufferAccess&	noAlphaOneImage)
1474{
1475	for (int y = 0; y < m_renderSize.y(); y++)
1476	{
1477		for (int x = 0; x < m_renderSize.x(); x++)
1478		{
1479			if (!tcu::boolAll(tcu::greaterThanEqual(alphaOneImage.getPixel(x, y), noAlphaOneImage.getPixel(x, y))))
1480			{
1481				std::ostringstream message;
1482				message << "Unsatisfied condition: " << alphaOneImage.getPixel(x, y) << " >= " << noAlphaOneImage.getPixel(x, y);
1483				return tcu::TestStatus::fail(message.str());
1484			}
1485		}
1486	}
1487
1488	return tcu::TestStatus::pass("Image rendered with alpha-to-one contains pixels of image rendered with no alpha-to-one");
1489}
1490
1491
1492// AlphaToCoverageInstance
1493
1494AlphaToCoverageInstance::AlphaToCoverageInstance (Context&										context,
1495												  VkPrimitiveTopology							topology,
1496												  const std::vector<Vertex4RGBA>&				vertices,
1497												  const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
1498												  const VkPipelineColorBlendAttachmentState&	blendState,
1499												  GeometryType									geometryType)
1500	: vkt::TestInstance			(context)
1501	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
1502	, m_renderSize				(32, 32)
1503	, m_primitiveTopology		(topology)
1504	, m_vertices				(vertices)
1505	, m_multisampleStateParams	(multisampleStateParams)
1506	, m_colorBlendState			(blendState)
1507	, m_geometryType			(geometryType)
1508{
1509}
1510
1511tcu::TestStatus AlphaToCoverageInstance::iterate (void)
1512{
1513	DE_ASSERT(m_multisampleStateParams.alphaToCoverageEnable);
1514
1515	de::MovePtr<tcu::TextureLevel>	result;
1516	MultisampleRenderer				renderer	(m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState, RENDER_TYPE_RESOLVE);
1517
1518	result = renderer.render();
1519
1520	return verifyImage(result->getAccess());
1521}
1522
1523tcu::TestStatus AlphaToCoverageInstance::verifyImage (const tcu::ConstPixelBufferAccess&	result)
1524{
1525	float maxColorValue;
1526
1527	switch (m_geometryType)
1528	{
1529		case GEOMETRY_TYPE_OPAQUE_QUAD:
1530			maxColorValue = 1.01f;
1531			break;
1532
1533		case GEOMETRY_TYPE_TRANSLUCENT_QUAD:
1534			maxColorValue = 0.52f;
1535			break;
1536
1537		case GEOMETRY_TYPE_INVISIBLE_QUAD:
1538			maxColorValue = 0.01f;
1539			break;
1540
1541		default:
1542			maxColorValue = 0.0f;
1543			DE_ASSERT(false);
1544	}
1545
1546	for (int y = 0; y < m_renderSize.y(); y++)
1547	{
1548		for (int x = 0; x < m_renderSize.x(); x++)
1549		{
1550			if (result.getPixel(x, y).x() > maxColorValue)
1551			{
1552				std::ostringstream message;
1553				message << "Pixel is not below the threshold value (" << result.getPixel(x, y).x() << " > " << maxColorValue << ")";
1554				return tcu::TestStatus::fail(message.str());
1555			}
1556		}
1557	}
1558
1559	return tcu::TestStatus::pass("Image matches reference value");
1560}
1561
1562
1563// MultisampleRenderer
1564
1565MultisampleRenderer::MultisampleRenderer (Context&										context,
1566										  const VkFormat								colorFormat,
1567										  const tcu::IVec2&								renderSize,
1568										  const VkPrimitiveTopology						topology,
1569										  const std::vector<Vertex4RGBA>&				vertices,
1570										  const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
1571										  const VkPipelineColorBlendAttachmentState&	blendState,
1572										  const RenderType								renderType)
1573	: m_context					(context)
1574	, m_colorFormat				(colorFormat)
1575	, m_depthStencilFormat		(VK_FORMAT_UNDEFINED)
1576	, m_renderSize				(renderSize)
1577	, m_useDepth				(false)
1578	, m_useStencil				(false)
1579	, m_multisampleStateParams	(multisampleStateParams)
1580	, m_colorBlendState			(blendState)
1581	, m_renderType				(renderType)
1582{
1583	initialize(context, 1u, &topology, &vertices);
1584}
1585
1586MultisampleRenderer::MultisampleRenderer (Context&										context,
1587										  const VkFormat								colorFormat,
1588										  const VkFormat								depthStencilFormat,
1589										  const tcu::IVec2&								renderSize,
1590										  const bool									useDepth,
1591										  const bool									useStencil,
1592										  const deUint32								numTopologies,
1593										  const VkPrimitiveTopology*					pTopology,
1594										  const std::vector<Vertex4RGBA>*				pVertices,
1595										  const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
1596										  const VkPipelineColorBlendAttachmentState&	blendState,
1597										  const RenderType								renderType)
1598	: m_context					(context)
1599	, m_colorFormat				(colorFormat)
1600	, m_depthStencilFormat		(depthStencilFormat)
1601	, m_renderSize				(renderSize)
1602	, m_useDepth				(useDepth)
1603	, m_useStencil				(useStencil)
1604	, m_multisampleStateParams	(multisampleStateParams)
1605	, m_colorBlendState			(blendState)
1606	, m_renderType				(renderType)
1607{
1608	initialize(context, numTopologies, pTopology, pVertices);
1609}
1610
1611void MultisampleRenderer::initialize (Context&									context,
1612									  const deUint32							numTopologies,
1613									  const VkPrimitiveTopology*				pTopology,
1614									  const std::vector<Vertex4RGBA>*			pVertices)
1615{
1616	if (!isSupportedSampleCount(context.getInstanceInterface(), context.getPhysicalDevice(), m_multisampleStateParams.rasterizationSamples))
1617		throw tcu::NotSupportedError("Unsupported number of rasterization samples");
1618
1619	const DeviceInterface&		vk						= context.getDeviceInterface();
1620	const VkDevice				vkDevice				= context.getDevice();
1621	const deUint32				queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
1622	SimpleAllocator				memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
1623	const VkComponentMapping	componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
1624
1625	// Create color image
1626	{
1627
1628		const VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1629			(m_renderType == RENDER_TYPE_COPY_SAMPLES ? VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT : (VkImageUsageFlagBits)0u);
1630
1631		const VkImageCreateInfo colorImageParams =
1632		{
1633			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
1634			DE_NULL,																	// const void*				pNext;
1635			0u,																			// VkImageCreateFlags		flags;
1636			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
1637			m_colorFormat,																// VkFormat					format;
1638			{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u },				// VkExtent3D				extent;
1639			1u,																			// deUint32					mipLevels;
1640			1u,																			// deUint32					arrayLayers;
1641			m_multisampleStateParams.rasterizationSamples,								// VkSampleCountFlagBits	samples;
1642			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
1643			imageUsageFlags,															// VkImageUsageFlags		usage;
1644			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
1645			1u,																			// deUint32					queueFamilyIndexCount;
1646			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
1647			VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout			initialLayout;
1648		};
1649
1650		m_colorImage			= createImage(vk, vkDevice, &colorImageParams);
1651
1652		// Allocate and bind color image memory
1653		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
1654		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
1655	}
1656
1657	// Create resolve image
1658	if (m_renderType == RENDER_TYPE_RESOLVE)
1659	{
1660		const VkImageCreateInfo resolveImageParams =
1661		{
1662			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,											// VkStructureType			sType;
1663			DE_NULL,																		// const void*				pNext;
1664			0u,																				// VkImageCreateFlags		flags;
1665			VK_IMAGE_TYPE_2D,																// VkImageType				imageType;
1666			m_colorFormat,																	// VkFormat					format;
1667			{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u },					// VkExtent3D				extent;
1668			1u,																				// deUint32					mipLevels;
1669			1u,																				// deUint32					arrayLayers;
1670			VK_SAMPLE_COUNT_1_BIT,															// VkSampleCountFlagBits	samples;
1671			VK_IMAGE_TILING_OPTIMAL,														// VkImageTiling			tiling;
1672			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |			// VkImageUsageFlags		usage;
1673				VK_IMAGE_USAGE_TRANSFER_DST_BIT,
1674			VK_SHARING_MODE_EXCLUSIVE,														// VkSharingMode			sharingMode;
1675			1u,																				// deUint32					queueFamilyIndexCount;
1676			&queueFamilyIndex,																// const deUint32*			pQueueFamilyIndices;
1677			VK_IMAGE_LAYOUT_UNDEFINED														// VkImageLayout			initialLayout;
1678		};
1679
1680		m_resolveImage = createImage(vk, vkDevice, &resolveImageParams);
1681
1682		// Allocate and bind resolve image memory
1683		m_resolveImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_resolveImage), MemoryRequirement::Any);
1684		VK_CHECK(vk.bindImageMemory(vkDevice, *m_resolveImage, m_resolveImageAlloc->getMemory(), m_resolveImageAlloc->getOffset()));
1685
1686		// Create resolve attachment view
1687		{
1688			const VkImageViewCreateInfo resolveAttachmentViewParams =
1689			{
1690				VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
1691				DE_NULL,										// const void*				pNext;
1692				0u,												// VkImageViewCreateFlags	flags;
1693				*m_resolveImage,								// VkImage					image;
1694				VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
1695				m_colorFormat,									// VkFormat					format;
1696				componentMappingRGBA,							// VkComponentMapping		components;
1697				{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
1698			};
1699
1700			m_resolveAttachmentView = createImageView(vk, vkDevice, &resolveAttachmentViewParams);
1701		}
1702	}
1703
1704	// Create per-sample output images
1705	if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
1706	{
1707		const VkImageCreateInfo perSampleImageParams =
1708		{
1709			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,											// VkStructureType			sType;
1710			DE_NULL,																		// const void*				pNext;
1711			0u,																				// VkImageCreateFlags		flags;
1712			VK_IMAGE_TYPE_2D,																// VkImageType				imageType;
1713			m_colorFormat,																	// VkFormat					format;
1714			{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u },					// VkExtent3D				extent;
1715			1u,																				// deUint32					mipLevels;
1716			1u,																				// deUint32					arrayLayers;
1717			VK_SAMPLE_COUNT_1_BIT,															// VkSampleCountFlagBits	samples;
1718			VK_IMAGE_TILING_OPTIMAL,														// VkImageTiling			tiling;
1719			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |			// VkImageUsageFlags		usage;
1720			VK_IMAGE_USAGE_TRANSFER_DST_BIT,
1721			VK_SHARING_MODE_EXCLUSIVE,														// VkSharingMode			sharingMode;
1722			1u,																				// deUint32					queueFamilyIndexCount;
1723			&queueFamilyIndex,																// const deUint32*			pQueueFamilyIndices;
1724			VK_IMAGE_LAYOUT_UNDEFINED														// VkImageLayout			initialLayout;
1725		};
1726
1727		m_perSampleImages.resize(static_cast<size_t>(m_multisampleStateParams.rasterizationSamples));
1728
1729		for (size_t i = 0; i < m_perSampleImages.size(); ++i)
1730		{
1731			m_perSampleImages[i]	= de::SharedPtr<PerSampleImage>(new PerSampleImage);
1732			PerSampleImage& image	= *m_perSampleImages[i];
1733
1734			image.m_image			= createImage(vk, vkDevice, &perSampleImageParams);
1735
1736			// Allocate and bind image memory
1737			image.m_imageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *image.m_image), MemoryRequirement::Any);
1738			VK_CHECK(vk.bindImageMemory(vkDevice, *image.m_image, image.m_imageAlloc->getMemory(), image.m_imageAlloc->getOffset()));
1739
1740			// Create per-sample attachment view
1741			{
1742				const VkImageViewCreateInfo perSampleAttachmentViewParams =
1743				{
1744					VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
1745					DE_NULL,										// const void*				pNext;
1746					0u,												// VkImageViewCreateFlags	flags;
1747					*image.m_image,									// VkImage					image;
1748					VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
1749					m_colorFormat,									// VkFormat					format;
1750					componentMappingRGBA,							// VkComponentMapping		components;
1751					{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
1752				};
1753
1754				image.m_attachmentView = createImageView(vk, vkDevice, &perSampleAttachmentViewParams);
1755			}
1756		}
1757	}
1758
1759	// Create a depth/stencil image
1760	if (m_useDepth || m_useStencil)
1761	{
1762		const VkImageCreateInfo depthStencilImageParams =
1763		{
1764			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,											// VkStructureType			sType;
1765			DE_NULL,																		// const void*				pNext;
1766			0u,																				// VkImageCreateFlags		flags;
1767			VK_IMAGE_TYPE_2D,																// VkImageType				imageType;
1768			m_depthStencilFormat,															// VkFormat					format;
1769			{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u },					// VkExtent3D				extent;
1770			1u,																				// deUint32					mipLevels;
1771			1u,																				// deUint32					arrayLayers;
1772			m_multisampleStateParams.rasterizationSamples,									// VkSampleCountFlagBits	samples;
1773			VK_IMAGE_TILING_OPTIMAL,														// VkImageTiling			tiling;
1774			VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,									// VkImageUsageFlags		usage;
1775			VK_SHARING_MODE_EXCLUSIVE,														// VkSharingMode			sharingMode;
1776			1u,																				// deUint32					queueFamilyIndexCount;
1777			&queueFamilyIndex,																// const deUint32*			pQueueFamilyIndices;
1778			VK_IMAGE_LAYOUT_UNDEFINED														// VkImageLayout			initialLayout;
1779		};
1780
1781		m_depthStencilImage = createImage(vk, vkDevice, &depthStencilImageParams);
1782
1783		// Allocate and bind depth/stencil image memory
1784		m_depthStencilImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_depthStencilImage), MemoryRequirement::Any);
1785		VK_CHECK(vk.bindImageMemory(vkDevice, *m_depthStencilImage, m_depthStencilImageAlloc->getMemory(), m_depthStencilImageAlloc->getOffset()));
1786	}
1787
1788	// Create color attachment view
1789	{
1790		const VkImageViewCreateInfo colorAttachmentViewParams =
1791		{
1792			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
1793			DE_NULL,										// const void*				pNext;
1794			0u,												// VkImageViewCreateFlags	flags;
1795			*m_colorImage,									// VkImage					image;
1796			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
1797			m_colorFormat,									// VkFormat					format;
1798			componentMappingRGBA,							// VkComponentMapping		components;
1799			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
1800		};
1801
1802		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
1803	}
1804
1805	VkImageAspectFlags	depthStencilAttachmentAspect	= (VkImageAspectFlagBits)0;
1806
1807	// Create depth/stencil attachment view
1808	if (m_useDepth || m_useStencil)
1809	{
1810		depthStencilAttachmentAspect = getImageAspectFlags(m_depthStencilFormat);
1811
1812		const VkImageViewCreateInfo depthStencilAttachmentViewParams =
1813		{
1814			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
1815			DE_NULL,											// const void*				pNext;
1816			0u,													// VkImageViewCreateFlags	flags;
1817			*m_depthStencilImage,								// VkImage					image;
1818			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
1819			m_depthStencilFormat,								// VkFormat					format;
1820			componentMappingRGBA,								// VkComponentMapping		components;
1821			{ depthStencilAttachmentAspect, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
1822		};
1823
1824		m_depthStencilAttachmentView = createImageView(vk, vkDevice, &depthStencilAttachmentViewParams);
1825	}
1826
1827	// Create render pass
1828	{
1829		std::vector<VkAttachmentDescription> attachmentDescriptions;
1830		{
1831			const VkAttachmentDescription colorAttachmentDescription =
1832			{
1833				0u,													// VkAttachmentDescriptionFlags		flags;
1834				m_colorFormat,										// VkFormat							format;
1835				m_multisampleStateParams.rasterizationSamples,		// VkSampleCountFlagBits			samples;
1836				VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
1837				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
1838				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
1839				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
1840				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
1841				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout;
1842			};
1843			attachmentDescriptions.push_back(colorAttachmentDescription);
1844		}
1845
1846		deUint32 resolveAttachmentIndex = VK_ATTACHMENT_UNUSED;
1847
1848		if (m_renderType == RENDER_TYPE_RESOLVE)
1849		{
1850			resolveAttachmentIndex = static_cast<deUint32>(attachmentDescriptions.size());
1851
1852			const VkAttachmentDescription resolveAttachmentDescription =
1853			{
1854				0u,													// VkAttachmentDescriptionFlags		flags;
1855				m_colorFormat,										// VkFormat							format;
1856				VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
1857				VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
1858				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
1859				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
1860				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
1861				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
1862				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout;
1863			};
1864			attachmentDescriptions.push_back(resolveAttachmentDescription);
1865		}
1866
1867		deUint32 perSampleAttachmentIndex = VK_ATTACHMENT_UNUSED;
1868
1869		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
1870		{
1871			perSampleAttachmentIndex = static_cast<deUint32>(attachmentDescriptions.size());
1872
1873			const VkAttachmentDescription perSampleAttachmentDescription =
1874			{
1875				0u,													// VkAttachmentDescriptionFlags		flags;
1876				m_colorFormat,										// VkFormat							format;
1877				VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
1878				VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
1879				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
1880				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
1881				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
1882				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
1883				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout;
1884			};
1885
1886			for (size_t i = 0; i < m_perSampleImages.size(); ++i)
1887			{
1888				attachmentDescriptions.push_back(perSampleAttachmentDescription);
1889			}
1890		}
1891
1892		deUint32 depthStencilAttachmentIndex = VK_ATTACHMENT_UNUSED;
1893
1894		if (m_useDepth || m_useStencil)
1895		{
1896			depthStencilAttachmentIndex = static_cast<deUint32>(attachmentDescriptions.size());
1897
1898			const VkAttachmentDescription depthStencilAttachmentDescription =
1899			{
1900				0u,																					// VkAttachmentDescriptionFlags		flags;
1901				m_depthStencilFormat,																// VkFormat							format;
1902				m_multisampleStateParams.rasterizationSamples,										// VkSampleCountFlagBits			samples;
1903				(m_useDepth ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_DONT_CARE),		// VkAttachmentLoadOp				loadOp;
1904				(m_useDepth ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE),		// VkAttachmentStoreOp				storeOp;
1905				(m_useStencil ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_DONT_CARE),		// VkAttachmentStoreOp				stencilLoadOp;
1906				(m_useStencil ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE),	// VkAttachmentStoreOp				stencilStoreOp;
1907				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,									// VkImageLayout					initialLayout;
1908				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL									// VkImageLayout					finalLayout;
1909			};
1910			attachmentDescriptions.push_back(depthStencilAttachmentDescription);
1911		};
1912
1913		const VkAttachmentReference colorAttachmentReference =
1914		{
1915			0u,													// deUint32			attachment;
1916			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
1917		};
1918
1919		const VkAttachmentReference inputAttachmentReference =
1920		{
1921			0u,													// deUint32			attachment;
1922			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL			// VkImageLayout	layout;
1923		};
1924
1925		const VkAttachmentReference resolveAttachmentReference =
1926		{
1927			resolveAttachmentIndex,								// deUint32			attachment;
1928			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
1929		};
1930
1931		std::vector<VkAttachmentReference> perSampleAttachmentReferences(m_perSampleImages.size());
1932		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
1933		{
1934			for (size_t i = 0; i < m_perSampleImages.size(); ++i)
1935			{
1936				const VkAttachmentReference perSampleAttachmentReference =
1937				{
1938					perSampleAttachmentIndex + static_cast<deUint32>(i),	// deUint32			attachment;
1939					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL				// VkImageLayout	layout;
1940				};
1941				perSampleAttachmentReferences[i] = perSampleAttachmentReference;
1942			}
1943		}
1944
1945		const VkAttachmentReference depthStencilAttachmentReference =
1946		{
1947			depthStencilAttachmentIndex,						// deUint32			attachment;
1948			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
1949		};
1950
1951		std::vector<VkSubpassDescription>	subpassDescriptions;
1952		std::vector<VkSubpassDependency>	subpassDependencies;
1953
1954		{
1955			const VkSubpassDescription renderSubpassDescription =
1956			{
1957				0u,																				// VkSubpassDescriptionFlags	flags;
1958				VK_PIPELINE_BIND_POINT_GRAPHICS,												// VkPipelineBindPoint			pipelineBindPoint;
1959				0u,																				// deUint32						inputAttachmentCount;
1960				DE_NULL,																		// const VkAttachmentReference*	pInputAttachments;
1961				1u,																				// deUint32						colorAttachmentCount;
1962				&colorAttachmentReference,														// const VkAttachmentReference*	pColorAttachments;
1963				(m_renderType == RENDER_TYPE_RESOLVE) ? &resolveAttachmentReference : DE_NULL,	// const VkAttachmentReference*	pResolveAttachments;
1964				(m_useDepth || m_useStencil ? &depthStencilAttachmentReference : DE_NULL),		// const VkAttachmentReference*	pDepthStencilAttachment;
1965				0u,																				// deUint32						preserveAttachmentCount;
1966				DE_NULL																			// const VkAttachmentReference*	pPreserveAttachments;
1967			};
1968			subpassDescriptions.push_back(renderSubpassDescription);
1969		}
1970
1971		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
1972		{
1973
1974			for (size_t i = 0; i < m_perSampleImages.size(); ++i)
1975			{
1976				const VkSubpassDescription copySampleSubpassDescription =
1977				{
1978					0u,													// VkSubpassDescriptionFlags		flags;
1979					VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
1980					1u,													// deUint32							inputAttachmentCount;
1981					&inputAttachmentReference,							// const VkAttachmentReference*		pInputAttachments;
1982					1u,													// deUint32							colorAttachmentCount;
1983					&perSampleAttachmentReferences[i],					// const VkAttachmentReference*		pColorAttachments;
1984					DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
1985					DE_NULL,											// const VkAttachmentReference*		pDepthStencilAttachment;
1986					0u,													// deUint32							preserveAttachmentCount;
1987					DE_NULL												// const VkAttachmentReference*		pPreserveAttachments;
1988				};
1989				subpassDescriptions.push_back(copySampleSubpassDescription);
1990
1991				const VkSubpassDependency copySampleSubpassDependency =
1992				{
1993					0u,													// deUint32							srcSubpass
1994					1u + static_cast<deUint32>(i),						// deUint32							dstSubpass
1995					VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,					// VkPipelineStageFlags				srcStageMask
1996					VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,				// VkPipelineStageFlags				dstStageMask
1997					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags					srcAccessMask
1998					VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,				// VkAccessFlags					dstAccessMask
1999					0u,													// VkDependencyFlags				dependencyFlags
2000				};
2001				subpassDependencies.push_back(copySampleSubpassDependency);
2002			}
2003		}
2004
2005		const VkRenderPassCreateInfo renderPassParams =
2006		{
2007			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,					// VkStructureType					sType;
2008			DE_NULL,													// const void*						pNext;
2009			0u,															// VkRenderPassCreateFlags			flags;
2010			(deUint32)attachmentDescriptions.size(),					// deUint32							attachmentCount;
2011			&attachmentDescriptions[0],									// const VkAttachmentDescription*	pAttachments;
2012			(deUint32)subpassDescriptions.size(),						// deUint32							subpassCount;
2013			&subpassDescriptions[0],									// const VkSubpassDescription*		pSubpasses;
2014			(deUint32)subpassDependencies.size(),						// deUint32							dependencyCount;
2015			subpassDependencies.size() != 0 ? &subpassDependencies[0] : DE_NULL
2016		};
2017
2018		m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
2019	}
2020
2021	// Create framebuffer
2022	{
2023		std::vector<VkImageView> attachments;
2024		attachments.push_back(*m_colorAttachmentView);
2025		if (m_renderType == RENDER_TYPE_RESOLVE)
2026		{
2027			attachments.push_back(*m_resolveAttachmentView);
2028		}
2029		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
2030		{
2031			for (size_t i = 0; i < m_perSampleImages.size(); ++i)
2032			{
2033				attachments.push_back(*m_perSampleImages[i]->m_attachmentView);
2034			}
2035		}
2036
2037		if (m_useDepth || m_useStencil)
2038		{
2039			attachments.push_back(*m_depthStencilAttachmentView);
2040		}
2041
2042		const VkFramebufferCreateInfo framebufferParams =
2043		{
2044			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType					sType;
2045			DE_NULL,											// const void*						pNext;
2046			0u,													// VkFramebufferCreateFlags			flags;
2047			*m_renderPass,										// VkRenderPass						renderPass;
2048			(deUint32)attachments.size(),						// deUint32							attachmentCount;
2049			&attachments[0],									// const VkImageView*				pAttachments;
2050			(deUint32)m_renderSize.x(),							// deUint32							width;
2051			(deUint32)m_renderSize.y(),							// deUint32							height;
2052			1u													// deUint32							layers;
2053		};
2054
2055		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
2056	}
2057
2058	// Create pipeline layout
2059	{
2060		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
2061		{
2062			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
2063			DE_NULL,											// const void*						pNext;
2064			0u,													// VkPipelineLayoutCreateFlags		flags;
2065			0u,													// deUint32							setLayoutCount;
2066			DE_NULL,											// const VkDescriptorSetLayout*		pSetLayouts;
2067			0u,													// deUint32							pushConstantRangeCount;
2068			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
2069		};
2070
2071		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
2072
2073		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
2074		{
2075
2076			// Create descriptor set layout
2077			const VkDescriptorSetLayoutBinding		layoutBinding					=
2078			{
2079				0u,															// deUint32								binding;
2080				VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,						// VkDescriptorType						descriptorType;
2081				1u,															// deUint32								descriptorCount;
2082				VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlags					stageFlags;
2083				DE_NULL,													// const VkSampler*						pImmutableSamplers;
2084			};
2085
2086			const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutParams		=
2087			{
2088				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,		// VkStructureType						sType
2089				DE_NULL,													// const void*							pNext
2090				0u,															// VkDescriptorSetLayoutCreateFlags		flags
2091				1u,															// deUint32								bindingCount
2092				&layoutBinding												// const VkDescriptorSetLayoutBinding*	pBindings
2093			};
2094			m_copySampleDesciptorLayout	= createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
2095
2096			// Create pipeline layout
2097
2098			const VkPushConstantRange				pushConstantRange				=
2099			{
2100				VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlags					stageFlags;
2101				0u,															// deUint32								offset;
2102				sizeof(deInt32)												// deUint32								size;
2103			};
2104			const VkPipelineLayoutCreateInfo		copySamplePipelineLayoutParams	=
2105			{
2106				VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,				// VkStructureType						sType;
2107				DE_NULL,													// const void*							pNext;
2108				0u,															// VkPipelineLayoutCreateFlags			flags;
2109				1u,															// deUint32								setLayoutCount;
2110				&m_copySampleDesciptorLayout.get(),							// const VkDescriptorSetLayout*			pSetLayouts;
2111				1u,															// deUint32								pushConstantRangeCount;
2112				&pushConstantRange											// const VkPushConstantRange*			pPushConstantRanges;
2113			};
2114			m_copySamplePipelineLayout		= createPipelineLayout(vk, vkDevice, &copySamplePipelineLayoutParams);
2115		}
2116	}
2117
2118	m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
2119	m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
2120
2121	if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
2122	{
2123		m_copySampleVertexShaderModule		= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("quad_vert"), 0);
2124		m_copySampleFragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("copy_sample_frag"), 0);
2125	}
2126
2127	// Create pipeline
2128	{
2129		const VkPipelineShaderStageCreateInfo	shaderStageParams[2] =
2130		{
2131			{
2132				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
2133				DE_NULL,													// const void*							pNext;
2134				0u,															// VkPipelineShaderStageCreateFlags		flags;
2135				VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStageFlagBits				stage;
2136				*m_vertexShaderModule,										// VkShaderModule						module;
2137				"main",														// const char*							pName;
2138				DE_NULL														// const VkSpecializationInfo*			pSpecializationInfo;
2139			},
2140			{
2141				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
2142				DE_NULL,													// const void*							pNext;
2143				0u,															// VkPipelineShaderStageCreateFlags		flags;
2144				VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlagBits				stage;
2145				*m_fragmentShaderModule,									// VkShaderModule						module;
2146				"main",														// const char*							pName;
2147				DE_NULL														// const VkSpecializationInfo*			pSpecializationInfo;
2148			}
2149		};
2150
2151		const VkVertexInputBindingDescription	vertexInputBindingDescription =
2152		{
2153			0u,									// deUint32				binding;
2154			sizeof(Vertex4RGBA),				// deUint32				stride;
2155			VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputRate	inputRate;
2156		};
2157
2158		const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
2159		{
2160			{
2161				0u,									// deUint32	location;
2162				0u,									// deUint32	binding;
2163				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
2164				0u									// deUint32	offset;
2165			},
2166			{
2167				1u,									// deUint32	location;
2168				0u,									// deUint32	binding;
2169				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
2170				DE_OFFSET_OF(Vertex4RGBA, color),	// deUint32	offset;
2171			}
2172		};
2173
2174		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
2175		{
2176			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
2177			DE_NULL,														// const void*								pNext;
2178			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
2179			1u,																// deUint32									vertexBindingDescriptionCount;
2180			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
2181			2u,																// deUint32									vertexAttributeDescriptionCount;
2182			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
2183		};
2184
2185		// Topology is set before the pipeline creation.
2186		VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
2187		{
2188			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
2189			DE_NULL,														// const void*								pNext;
2190			0u,																// VkPipelineInputAssemblyStateCreateFlags	flags;
2191			VK_PRIMITIVE_TOPOLOGY_LAST,										// VkPrimitiveTopology						topology;
2192			false															// VkBool32									primitiveRestartEnable;
2193		};
2194
2195		const VkViewport viewport =
2196		{
2197			0.0f,						// float	x;
2198			0.0f,						// float	y;
2199			(float)m_renderSize.x(),	// float	width;
2200			(float)m_renderSize.y(),	// float	height;
2201			0.0f,						// float	minDepth;
2202			1.0f						// float	maxDepth;
2203		};
2204
2205		const VkRect2D scissor =
2206		{
2207			{ 0, 0 },													// VkOffset2D  offset;
2208			{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() }	// VkExtent2D  extent;
2209		};
2210
2211		const VkPipelineViewportStateCreateInfo viewportStateParams =
2212		{
2213			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType						sType;
2214			DE_NULL,														// const void*							pNext;
2215			0u,																// VkPipelineViewportStateCreateFlags	flags;
2216			1u,																// deUint32								viewportCount;
2217			&viewport,														// const VkViewport*					pViewports;
2218			1u,																// deUint32								scissorCount;
2219			&scissor														// const VkRect2D*						pScissors;
2220		};
2221
2222		const VkPipelineRasterizationStateCreateInfo rasterStateParams =
2223		{
2224			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
2225			DE_NULL,														// const void*								pNext;
2226			0u,																// VkPipelineRasterizationStateCreateFlags	flags;
2227			false,															// VkBool32									depthClampEnable;
2228			false,															// VkBool32									rasterizerDiscardEnable;
2229			VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
2230			VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
2231			VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
2232			VK_FALSE,														// VkBool32									depthBiasEnable;
2233			0.0f,															// float									depthBiasConstantFactor;
2234			0.0f,															// float									depthBiasClamp;
2235			0.0f,															// float									depthBiasSlopeFactor;
2236			1.0f															// float									lineWidth;
2237		};
2238
2239		const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
2240		{
2241			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
2242			DE_NULL,													// const void*									pNext;
2243			0u,															// VkPipelineColorBlendStateCreateFlags			flags;
2244			false,														// VkBool32										logicOpEnable;
2245			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
2246			1u,															// deUint32										attachmentCount;
2247			&m_colorBlendState,											// const VkPipelineColorBlendAttachmentState*	pAttachments;
2248			{ 0.0f, 0.0f, 0.0f, 0.0f }									// float										blendConstants[4];
2249		};
2250
2251		const VkStencilOpState stencilOpState =
2252		{
2253			VK_STENCIL_OP_KEEP,						// VkStencilOp	failOp;
2254			VK_STENCIL_OP_REPLACE,					// VkStencilOp	passOp;
2255			VK_STENCIL_OP_KEEP,						// VkStencilOp	depthFailOp;
2256			VK_COMPARE_OP_GREATER,					// VkCompareOp	compareOp;
2257			1u,										// deUint32		compareMask;
2258			1u,										// deUint32		writeMask;
2259			1u,										// deUint32		reference;
2260		};
2261
2262		const VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
2263		{
2264			VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
2265			DE_NULL,													// const void*								pNext;
2266			0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
2267			m_useDepth,													// VkBool32									depthTestEnable;
2268			m_useDepth,													// VkBool32									depthWriteEnable;
2269			VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
2270			false,														// VkBool32									depthBoundsTestEnable;
2271			m_useStencil,												// VkBool32									stencilTestEnable;
2272			stencilOpState,												// VkStencilOpState	front;
2273			stencilOpState,												// VkStencilOpState	back;
2274			0.0f,														// float			minDepthBounds;
2275			1.0f,														// float			maxDepthBounds;
2276		};
2277
2278		const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
2279		{
2280			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
2281			DE_NULL,											// const void*										pNext;
2282			0u,													// VkPipelineCreateFlags							flags;
2283			2u,													// deUint32											stageCount;
2284			shaderStageParams,									// const VkPipelineShaderStageCreateInfo*			pStages;
2285			&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
2286			&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
2287			DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
2288			&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
2289			&rasterStateParams,									// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
2290			&m_multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
2291			&depthStencilStateParams,							// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
2292			&colorBlendStateParams,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
2293			(const VkPipelineDynamicStateCreateInfo*)DE_NULL,	// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
2294			*m_pipelineLayout,									// VkPipelineLayout									layout;
2295			*m_renderPass,										// VkRenderPass										renderPass;
2296			0u,													// deUint32											subpass;
2297			0u,													// VkPipeline										basePipelineHandle;
2298			0u													// deInt32											basePipelineIndex;
2299		};
2300
2301		for (deUint32 i = 0u; i < numTopologies; ++i)
2302		{
2303			inputAssemblyStateParams.topology = pTopology[i];
2304			m_graphicsPipelines.push_back(VkPipelineSp(new Unique<VkPipeline>(createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams))));
2305		}
2306	}
2307
2308	if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
2309	{
2310		// Create pipelines for copying samples to single sampled images
2311		{
2312			const VkPipelineShaderStageCreateInfo shaderStageParams[2] =
2313			{
2314				{
2315					VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType							sType;
2316					DE_NULL,													// const void*								pNext;
2317					0u,															// VkPipelineShaderStageCreateFlags			flags;
2318					VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStageFlagBits					stage;
2319					*m_copySampleVertexShaderModule,							// VkShaderModule							module;
2320					"main",														// const char*								pName;
2321					DE_NULL														// const VkSpecializationInfo*				pSpecializationInfo;
2322				},
2323				{
2324					VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType							sType;
2325					DE_NULL,													// const void*								pNext;
2326					0u,															// VkPipelineShaderStageCreateFlags			flags;
2327					VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlagBits					stage;
2328					*m_copySampleFragmentShaderModule,							// VkShaderModule							module;
2329					"main",														// const char*								pName;
2330					DE_NULL														// const VkSpecializationInfo*				pSpecializationInfo;
2331				}
2332			};
2333
2334			const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
2335			{
2336				VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
2337				DE_NULL,														// const void*								pNext;
2338				0u,																// VkPipelineVertexInputStateCreateFlags	flags;
2339				0u,																// deUint32									vertexBindingDescriptionCount;
2340				DE_NULL,														// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
2341				0u,																// deUint32									vertexAttributeDescriptionCount;
2342				DE_NULL															// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
2343			};
2344
2345			// Topology is set before the pipeline creation.
2346			VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
2347			{
2348				VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
2349				DE_NULL,														// const void*								pNext;
2350				0u,																// VkPipelineInputAssemblyStateCreateFlags	flags;
2351				VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,							// VkPrimitiveTopology						topology;
2352				false															// VkBool32									primitiveRestartEnable;
2353			};
2354
2355			const VkViewport viewport =
2356			{
2357				0.0f,						// float	x;
2358				0.0f,						// float	y;
2359				(float)m_renderSize.x(),	// float	width;
2360				(float)m_renderSize.y(),	// float	height;
2361				0.0f,						// float	minDepth;
2362				1.0f						// float	maxDepth;
2363			};
2364
2365			const VkRect2D scissor =
2366			{
2367				{ 0, 0 },													// VkOffset2D  offset;
2368				{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() }	// VkExtent2D  extent;
2369			};
2370
2371			const VkPipelineViewportStateCreateInfo viewportStateParams =
2372			{
2373				VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType							sType;
2374				DE_NULL,														// const void*								pNext;
2375				0u,																// VkPipelineViewportStateCreateFlags		flags;
2376				1u,																// deUint32									viewportCount;
2377				&viewport,														// const VkViewport*						pViewports;
2378				1u,																// deUint32									scissorCount;
2379				&scissor														// const VkRect2D*							pScissors;
2380			};
2381
2382			const VkPipelineRasterizationStateCreateInfo rasterStateParams =
2383			{
2384				VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
2385				DE_NULL,														// const void*								pNext;
2386				0u,																// VkPipelineRasterizationStateCreateFlags	flags;
2387				false,															// VkBool32									depthClampEnable;
2388				false,															// VkBool32									rasterizerDiscardEnable;
2389				VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
2390				VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
2391				VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
2392				VK_FALSE,														// VkBool32									depthBiasEnable;
2393				0.0f,															// float									depthBiasConstantFactor;
2394				0.0f,															// float									depthBiasClamp;
2395				0.0f,															// float									depthBiasSlopeFactor;
2396				1.0f															// float									lineWidth;
2397			};
2398
2399			const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
2400			{
2401				VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
2402				DE_NULL,													// const void*									pNext;
2403				0u,															// VkPipelineColorBlendStateCreateFlags			flags;
2404				false,														// VkBool32										logicOpEnable;
2405				VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
2406				1u,															// deUint32										attachmentCount;
2407				&m_colorBlendState,											// const VkPipelineColorBlendAttachmentState*	pAttachments;
2408				{ 0.0f, 0.0f, 0.0f, 0.0f }									// float										blendConstants[4];
2409			};
2410
2411			const  VkPipelineMultisampleStateCreateInfo multisampleStateParams =
2412			{
2413				VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType
2414				DE_NULL,													// const void*								pNext
2415				0u,															// VkPipelineMultisampleStateCreateFlags	flags
2416				VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples
2417				VK_FALSE,													// VkBool32									sampleShadingEnable
2418				0.0f,														// float									minSampleShading
2419				DE_NULL,													// const VkSampleMask*						pSampleMask
2420				VK_FALSE,													// VkBool32									alphaToCoverageEnable
2421				VK_FALSE,													// VkBool32									alphaToOneEnable
2422			};
2423
2424			const VkGraphicsPipelineCreateInfo graphicsPipelineTemplate =
2425			{
2426				VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
2427				DE_NULL,											// const void*										pNext;
2428				0u,													// VkPipelineCreateFlags							flags;
2429				2u,													// deUint32											stageCount;
2430				shaderStageParams,									// const VkPipelineShaderStageCreateInfo*			pStages;
2431				&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
2432				&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
2433				DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
2434				&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
2435				&rasterStateParams,									// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
2436				&multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
2437				DE_NULL,											// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
2438				&colorBlendStateParams,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
2439				(const VkPipelineDynamicStateCreateInfo*)DE_NULL,	// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
2440				*m_copySamplePipelineLayout,						// VkPipelineLayout									layout;
2441				*m_renderPass,										// VkRenderPass										renderPass;
2442				0u,													// deUint32											subpass;
2443				0u,													// VkPipeline										basePipelineHandle;
2444				0u													// deInt32											basePipelineIndex;
2445			};
2446
2447			for (size_t i = 0; i < m_perSampleImages.size(); ++i)
2448			{
2449				VkGraphicsPipelineCreateInfo graphicsPipelineParams = graphicsPipelineTemplate;
2450
2451				// Pipeline is to be used in subpasses subsequent to sample-shading subpass
2452				graphicsPipelineParams.subpass = 1u + (deUint32)i;
2453
2454				m_copySamplePipelines.push_back(VkPipelineSp(new Unique<VkPipeline>(createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams))));
2455			}
2456		}
2457
2458
2459		const VkDescriptorPoolSize			descriptorPoolSize			=
2460		{
2461			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,					// VkDescriptorType					type;
2462			1u														// deUint32							descriptorCount;
2463		};
2464
2465		const VkDescriptorPoolCreateInfo	descriptorPoolCreateInfo	=
2466		{
2467			VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,			// VkStructureType					sType
2468			DE_NULL,												// const void*						pNext
2469			VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,		// VkDescriptorPoolCreateFlags		flags
2470			1u,													// deUint32							maxSets
2471			1u,														// deUint32							poolSizeCount
2472			&descriptorPoolSize										// const VkDescriptorPoolSize*		pPoolSizes
2473		};
2474
2475		m_copySampleDesciptorPool = createDescriptorPool(vk, vkDevice, &descriptorPoolCreateInfo);
2476
2477		const VkDescriptorSetAllocateInfo	descriptorSetAllocateInfo	=
2478		{
2479			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,			// VkStructureType					sType
2480			DE_NULL,												// const void*						pNext
2481			*m_copySampleDesciptorPool,								// VkDescriptorPool					descriptorPool
2482			1u,														// deUint32							descriptorSetCount
2483			&m_copySampleDesciptorLayout.get(),						// const VkDescriptorSetLayout*		pSetLayouts
2484		};
2485
2486		m_copySampleDesciptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
2487
2488		const VkDescriptorImageInfo			imageInfo					=
2489		{
2490			DE_NULL,
2491			*m_colorAttachmentView,
2492			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
2493		};
2494		const VkWriteDescriptorSet			descriptorWrite				=
2495		{
2496			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,			// VkStructureType					sType;
2497			DE_NULL,										// const void*						pNext;
2498			*m_copySampleDesciptorSet,						// VkDescriptorSet					dstSet;
2499			0u,												// deUint32							dstBinding;
2500			0u,												// deUint32							dstArrayElement;
2501			1u,												// deUint32							descriptorCount;
2502			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,			// VkDescriptorType					descriptorType;
2503			&imageInfo,										// const VkDescriptorImageInfo*		pImageInfo;
2504			DE_NULL,										// const VkDescriptorBufferInfo*	pBufferInfo;
2505			DE_NULL,										// const VkBufferView*				pTexelBufferView;
2506		};
2507		vk.updateDescriptorSets(vkDevice, 1u, &descriptorWrite, 0u, DE_NULL);
2508	}
2509
2510	// Create vertex buffer
2511	{
2512		const VkBufferCreateInfo vertexBufferParams =
2513		{
2514			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
2515			DE_NULL,									// const void*			pNext;
2516			0u,											// VkBufferCreateFlags	flags;
2517			1024u,										// VkDeviceSize			size;
2518			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
2519			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
2520			1u,											// deUint32				queueFamilyIndexCount;
2521			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
2522		};
2523
2524		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
2525		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
2526
2527		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
2528
2529		// Load vertices into vertex buffer
2530		{
2531			Vertex4RGBA* pDst = static_cast<Vertex4RGBA*>(m_vertexBufferAlloc->getHostPtr());
2532			for (deUint32 i = 0u; i < numTopologies; ++i)
2533			{
2534				deMemcpy(pDst, &pVertices[i][0], pVertices[i].size() * sizeof(Vertex4RGBA));
2535				pDst += pVertices[i].size();
2536			}
2537		}
2538		flushMappedMemoryRange(vk, vkDevice, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), vertexBufferParams.size);
2539	}
2540
2541	// Create command pool
2542	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
2543
2544	// Create command buffer
2545	{
2546		const VkCommandBufferBeginInfo cmdBufferBeginInfo =
2547		{
2548			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType;
2549			DE_NULL,										// const void*						pNext;
2550			0u,												// VkCommandBufferUsageFlags		flags;
2551			(const VkCommandBufferInheritanceInfo*)DE_NULL,
2552		};
2553
2554		VkClearValue colorClearValue;
2555		colorClearValue.color.float32[0] = 0.0f;
2556		colorClearValue.color.float32[1] = 0.0f;
2557		colorClearValue.color.float32[2] = 0.0f;
2558		colorClearValue.color.float32[3] = 0.0f;
2559
2560		VkClearValue depthStencilClearValue;
2561		depthStencilClearValue.depthStencil.depth = 1.0f;
2562		depthStencilClearValue.depthStencil.stencil = 0u;
2563
2564		std::vector<VkClearValue> clearValues;
2565		clearValues.push_back(colorClearValue);
2566		if (m_renderType == RENDER_TYPE_RESOLVE)
2567		{
2568			clearValues.push_back(colorClearValue);
2569		}
2570		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
2571		{
2572			for (size_t i = 0; i < m_perSampleImages.size(); ++i)
2573			{
2574				clearValues.push_back(colorClearValue);
2575			}
2576		}
2577		if (m_useDepth || m_useStencil)
2578		{
2579			clearValues.push_back(depthStencilClearValue);
2580		}
2581
2582		const VkRenderPassBeginInfo renderPassBeginInfo =
2583		{
2584			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,				// VkStructureType		sType;
2585			DE_NULL,												// const void*			pNext;
2586			*m_renderPass,											// VkRenderPass			renderPass;
2587			*m_framebuffer,											// VkFramebuffer		framebuffer;
2588			{
2589				{ 0, 0 },
2590				{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() }
2591			},														// VkRect2D				renderArea;
2592			(deUint32)clearValues.size(),							// deUint32				clearValueCount;
2593			&clearValues[0]											// const VkClearValue*	pClearValues;
2594		};
2595
2596		std::vector<VkImageMemoryBarrier> imageLayoutBarriers;
2597
2598		{
2599			const VkImageMemoryBarrier colorImageBarrier =
2600				// color attachment image
2601			{
2602				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
2603				DE_NULL,										// const void*				pNext;
2604				0u,												// VkAccessFlags			srcAccessMask;
2605				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
2606				VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
2607				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			newLayout;
2608				VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
2609				VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
2610				*m_colorImage,									// VkImage					image;
2611				{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
2612			};
2613			imageLayoutBarriers.push_back(colorImageBarrier);
2614		}
2615		if (m_renderType == RENDER_TYPE_RESOLVE)
2616		{
2617			const VkImageMemoryBarrier resolveImageBarrier =
2618			// resolve attachment image
2619			{
2620				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
2621				DE_NULL,										// const void*				pNext;
2622				0u,												// VkAccessFlags			srcAccessMask;
2623				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
2624				VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
2625				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			newLayout;
2626				VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
2627				VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
2628				*m_resolveImage,								// VkImage					image;
2629				{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
2630			};
2631			imageLayoutBarriers.push_back(resolveImageBarrier);
2632		}
2633		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
2634		{
2635			for (size_t i = 0; i < m_perSampleImages.size(); ++i)
2636			{
2637				const VkImageMemoryBarrier perSampleImageBarrier =
2638				// resolve attachment image
2639				{
2640					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
2641					DE_NULL,										// const void*				pNext;
2642					0u,												// VkAccessFlags			srcAccessMask;
2643					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
2644					VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
2645					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			newLayout;
2646					VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
2647					VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
2648					*m_perSampleImages[i]->m_image,					// VkImage					image;
2649					{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
2650				};
2651				imageLayoutBarriers.push_back(perSampleImageBarrier);
2652			}
2653		}
2654		if (m_useDepth || m_useStencil)
2655		{
2656			const VkImageMemoryBarrier depthStencilImageBarrier =
2657			// depth/stencil attachment image
2658			{
2659				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
2660				DE_NULL,											// const void*				pNext;
2661				0u,													// VkAccessFlags			srcAccessMask;
2662				VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			dstAccessMask;
2663				VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			oldLayout;
2664				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout			newLayout;
2665				VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
2666				VK_QUEUE_FAMILY_IGNORED,							// deUint32					dstQueueFamilyIndex;
2667				*m_depthStencilImage,								// VkImage					image;
2668				{ depthStencilAttachmentAspect, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
2669			};
2670			imageLayoutBarriers.push_back(depthStencilImageBarrier);
2671		};
2672
2673		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2674
2675		VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
2676
2677		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0,
2678			0u, DE_NULL, 0u, DE_NULL, (deUint32)imageLayoutBarriers.size(), &imageLayoutBarriers[0]);
2679
2680		vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
2681
2682		VkDeviceSize vertexBufferOffset = 0u;
2683
2684		for (deUint32 i = 0u; i < numTopologies; ++i)
2685		{
2686			vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **m_graphicsPipelines[i]);
2687			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
2688			vk.cmdDraw(*m_cmdBuffer, (deUint32)pVertices[i].size(), 1, 0, 0);
2689
2690			vertexBufferOffset += static_cast<VkDeviceSize>(pVertices[i].size() * sizeof(Vertex4RGBA));
2691		}
2692
2693		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
2694		{
2695			// Copy each sample id to single sampled image
2696			for (deInt32 sampleId = 0; sampleId < (deInt32)m_perSampleImages.size(); ++sampleId)
2697			{
2698				vk.cmdNextSubpass(*m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
2699				vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **m_copySamplePipelines[sampleId]);
2700				vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_copySamplePipelineLayout, 0u, 1u, &m_copySampleDesciptorSet.get(), 0u, DE_NULL);
2701				vk.cmdPushConstants(*m_cmdBuffer, *m_copySamplePipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(deInt32), &sampleId);
2702				vk.cmdDraw(*m_cmdBuffer, 4, 1, 0, 0);
2703			}
2704		}
2705
2706		vk.cmdEndRenderPass(*m_cmdBuffer);
2707
2708		VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
2709	}
2710
2711	// Create fence
2712	m_fence = createFence(vk, vkDevice);
2713}
2714
2715MultisampleRenderer::~MultisampleRenderer (void)
2716{
2717}
2718
2719de::MovePtr<tcu::TextureLevel> MultisampleRenderer::render (void)
2720{
2721	const DeviceInterface&		vk					= m_context.getDeviceInterface();
2722	const VkDevice				vkDevice			= m_context.getDevice();
2723	const VkQueue				queue				= m_context.getUniversalQueue();
2724	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
2725	SimpleAllocator				allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
2726	const VkSubmitInfo			submitInfo	=
2727	{
2728		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
2729		DE_NULL,						// const void*				pNext;
2730		0u,								// deUint32					waitSemaphoreCount;
2731		DE_NULL,						// const VkSemaphore*		pWaitSemaphores;
2732		(const VkPipelineStageFlags*)DE_NULL,
2733		1u,								// deUint32					commandBufferCount;
2734		&m_cmdBuffer.get(),				// const VkCommandBuffer*	pCommandBuffers;
2735		0u,								// deUint32					signalSemaphoreCount;
2736		DE_NULL							// const VkSemaphore*		pSignalSemaphores;
2737	};
2738
2739	VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
2740	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
2741	VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
2742
2743	if (m_renderType == RENDER_TYPE_RESOLVE)
2744	{
2745		return readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_resolveImage, m_colorFormat, m_renderSize.cast<deUint32>());
2746	}
2747	else
2748	{
2749		return de::MovePtr<tcu::TextureLevel>();
2750	}
2751}
2752
2753de::MovePtr<tcu::TextureLevel> MultisampleRenderer::getSingleSampledImage (deUint32 sampleId)
2754{
2755	const DeviceInterface&		vk					= m_context.getDeviceInterface();
2756	const VkDevice				vkDevice			= m_context.getDevice();
2757	const VkQueue				queue				= m_context.getUniversalQueue();
2758	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
2759	SimpleAllocator				allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
2760
2761	return readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_perSampleImages[sampleId]->m_image, m_colorFormat, m_renderSize.cast<deUint32>());
2762}
2763
2764} // anonymous
2765
2766tcu::TestCaseGroup* createMultisampleTests (tcu::TestContext& testCtx)
2767{
2768	const VkSampleCountFlagBits samples[] =
2769	{
2770		VK_SAMPLE_COUNT_2_BIT,
2771		VK_SAMPLE_COUNT_4_BIT,
2772		VK_SAMPLE_COUNT_8_BIT,
2773		VK_SAMPLE_COUNT_16_BIT,
2774		VK_SAMPLE_COUNT_32_BIT,
2775		VK_SAMPLE_COUNT_64_BIT
2776	};
2777
2778	de::MovePtr<tcu::TestCaseGroup> multisampleTests (new tcu::TestCaseGroup(testCtx, "multisample", ""));
2779
2780	// Rasterization samples tests
2781	{
2782		de::MovePtr<tcu::TestCaseGroup> rasterizationSamplesTests(new tcu::TestCaseGroup(testCtx, "raster_samples", ""));
2783
2784		for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
2785		{
2786			std::ostringstream caseName;
2787			caseName << "samples_" << samples[samplesNdx];
2788
2789			de::MovePtr<tcu::TestCaseGroup> samplesTests	(new tcu::TestCaseGroup(testCtx, caseName.str().c_str(), ""));
2790
2791			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_triangle", "",	samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_TRIANGLE));
2792			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_line", "",		samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_LINE));
2793			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_point", "",		samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_POINT));
2794
2795			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "depth", "",			samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE, TEST_MODE_DEPTH_BIT));
2796			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "stencil", "",			samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE, TEST_MODE_STENCIL_BIT));
2797			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "depth_stencil", "",	samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE, TEST_MODE_DEPTH_BIT | TEST_MODE_STENCIL_BIT));
2798
2799			rasterizationSamplesTests->addChild(samplesTests.release());
2800		}
2801
2802		multisampleTests->addChild(rasterizationSamplesTests.release());
2803	}
2804
2805	// Raster samples consistency check
2806	{
2807		de::MovePtr<tcu::TestCaseGroup> rasterSamplesConsistencyTests(new tcu::TestCaseGroup(testCtx, "raster_samples_consistency", ""));
2808
2809		addFunctionCaseWithPrograms(rasterSamplesConsistencyTests.get(),
2810									"unique_colors_check",
2811									"",
2812									initMultisamplePrograms,
2813									testRasterSamplesConsistency,
2814									GEOMETRY_TYPE_OPAQUE_TRIANGLE);
2815
2816		multisampleTests->addChild(rasterSamplesConsistencyTests.release());
2817	}
2818
2819	// minSampleShading tests
2820	{
2821		struct TestConfig
2822		{
2823			const char*	name;
2824			float		minSampleShading;
2825		};
2826
2827		const TestConfig testConfigs[] =
2828		{
2829			{ "min_0_0",	0.0f },
2830			{ "min_0_25",	0.25f },
2831			{ "min_0_5",	0.5f },
2832			{ "min_0_75",	0.75f },
2833			{ "min_1_0",	1.0f }
2834		};
2835
2836		de::MovePtr<tcu::TestCaseGroup> minSampleShadingTests(new tcu::TestCaseGroup(testCtx, "min_sample_shading", ""));
2837
2838		for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testConfigs); configNdx++)
2839		{
2840			const TestConfig&				testConfig				= testConfigs[configNdx];
2841			de::MovePtr<tcu::TestCaseGroup>	minShadingValueTests	(new tcu::TestCaseGroup(testCtx, testConfigs[configNdx].name, ""));
2842
2843			for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
2844			{
2845				std::ostringstream caseName;
2846				caseName << "samples_" << samples[samplesNdx];
2847
2848				de::MovePtr<tcu::TestCaseGroup> samplesTests	(new tcu::TestCaseGroup(testCtx, caseName.str().c_str(), ""));
2849
2850				samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_triangle", "", samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_TRIANGLE));
2851				samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_line", "", samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_LINE));
2852				samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_point", "", samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_POINT));
2853
2854				minShadingValueTests->addChild(samplesTests.release());
2855			}
2856
2857			minSampleShadingTests->addChild(minShadingValueTests.release());
2858		}
2859
2860		multisampleTests->addChild(minSampleShadingTests.release());
2861	}
2862
2863	// pSampleMask tests
2864	{
2865		struct TestConfig
2866		{
2867			const char*		name;
2868			const char*		description;
2869			VkSampleMask	sampleMask;
2870		};
2871
2872		const TestConfig testConfigs[] =
2873		{
2874			{ "mask_all_on",	"All mask bits are off",			0x0 },
2875			{ "mask_all_off",	"All mask bits are on",				0xFFFFFFFF },
2876			{ "mask_one",		"All mask elements are 0x1",		0x1},
2877			{ "mask_random",	"All mask elements are 0xAAAAAAAA",	0xAAAAAAAA },
2878		};
2879
2880		de::MovePtr<tcu::TestCaseGroup> sampleMaskTests(new tcu::TestCaseGroup(testCtx, "sample_mask", ""));
2881
2882		for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testConfigs); configNdx++)
2883		{
2884			const TestConfig&				testConfig				= testConfigs[configNdx];
2885			de::MovePtr<tcu::TestCaseGroup>	sampleMaskValueTests	(new tcu::TestCaseGroup(testCtx, testConfig.name, testConfig.description));
2886
2887			for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
2888			{
2889				std::ostringstream caseName;
2890				caseName << "samples_" << samples[samplesNdx];
2891
2892				const deUint32					sampleMaskCount	= samples[samplesNdx] / 32;
2893				de::MovePtr<tcu::TestCaseGroup> samplesTests	(new tcu::TestCaseGroup(testCtx, caseName.str().c_str(), ""));
2894
2895				std::vector<VkSampleMask> mask;
2896				for (deUint32 maskNdx = 0; maskNdx < sampleMaskCount; maskNdx++)
2897					mask.push_back(testConfig.sampleMask);
2898
2899				samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_triangle", "", samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_TRIANGLE));
2900				samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_line", "", samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_LINE));
2901				samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_point", "", samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_POINT));
2902
2903				sampleMaskValueTests->addChild(samplesTests.release());
2904			}
2905
2906			sampleMaskTests->addChild(sampleMaskValueTests.release());
2907		}
2908
2909		multisampleTests->addChild(sampleMaskTests.release());
2910
2911	}
2912
2913	// AlphaToOne tests
2914	{
2915		de::MovePtr<tcu::TestCaseGroup> alphaToOneTests(new tcu::TestCaseGroup(testCtx, "alpha_to_one", ""));
2916
2917		for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
2918		{
2919			std::ostringstream caseName;
2920			caseName << "samples_" << samples[samplesNdx];
2921
2922			alphaToOneTests->addChild(new AlphaToOneTest(testCtx, caseName.str(), "", samples[samplesNdx]));
2923		}
2924
2925		multisampleTests->addChild(alphaToOneTests.release());
2926	}
2927
2928	// AlphaToCoverageEnable tests
2929	{
2930		de::MovePtr<tcu::TestCaseGroup> alphaToCoverageTests (new tcu::TestCaseGroup(testCtx, "alpha_to_coverage", ""));
2931
2932		for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
2933		{
2934			std::ostringstream caseName;
2935			caseName << "samples_" << samples[samplesNdx];
2936
2937			de::MovePtr<tcu::TestCaseGroup> samplesTests	(new tcu::TestCaseGroup(testCtx, caseName.str().c_str(), ""));
2938
2939			samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_opaque", "", samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_QUAD));
2940			samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_translucent", "", samples[samplesNdx], GEOMETRY_TYPE_TRANSLUCENT_QUAD));
2941			samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_invisible", "", samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_QUAD));
2942
2943			alphaToCoverageTests->addChild(samplesTests.release());
2944		}
2945		multisampleTests->addChild(alphaToCoverageTests.release());
2946	}
2947
2948	// Sampling from a multisampled image texture (texelFetch)
2949	{
2950		multisampleTests->addChild(createMultisampleSampledImageTests(testCtx));
2951	}
2952
2953	// Load/store on a multisampled rendered image (different kinds of access: color attachment write, storage image, etc.)
2954	{
2955		multisampleTests->addChild(createMultisampleStorageImageTests(testCtx));
2956	}
2957
2958	return multisampleTests.release();
2959}
2960
2961} // pipeline
2962} // vkt
2963