1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Imagination Technologies Ltd.
7 * Copyright (c) 2017 Google Inc.
8 * Copyright (c) 2023 LunarG, Inc.
9 * Copyright (c) 2023 Nintendo
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 *      http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 *
23 *//*!
24 * \file
25 * \brief Multisample Tests
26 *//*--------------------------------------------------------------------*/
27
28#include "vktPipelineMultisampleTests.hpp"
29#include "vktPipelineMultisampleImageTests.hpp"
30#include "vktPipelineMultisampleSampleLocationsExtTests.hpp"
31#include "vktPipelineMultisampleMixedAttachmentSamplesTests.hpp"
32#include "vktPipelineMultisampleResolveRenderAreaTests.hpp"
33#include "vktPipelineMultisampleShaderFragmentMaskTests.hpp"
34#include "vktPipelineMultisampledRenderToSingleSampledTests.hpp"
35#include "vktPipelineClearUtil.hpp"
36#include "vktPipelineImageUtil.hpp"
37#include "vktPipelineVertexUtil.hpp"
38#include "vktPipelineReferenceRenderer.hpp"
39#include "vktTestCase.hpp"
40#include "vktTestCaseUtil.hpp"
41#include "vkImageUtil.hpp"
42#include "vkMemUtil.hpp"
43#include "vkPrograms.hpp"
44#include "vkQueryUtil.hpp"
45#include "vkRef.hpp"
46#include "vkRefUtil.hpp"
47#include "vkCmdUtil.hpp"
48#include "vkTypeUtil.hpp"
49#include "vkObjUtil.hpp"
50#include "vkBufferWithMemory.hpp"
51#include "vkImageWithMemory.hpp"
52#include "vkBuilderUtil.hpp"
53#include "vkBarrierUtil.hpp"
54#include "tcuImageCompare.hpp"
55#include "tcuTestLog.hpp"
56#include "deUniquePtr.hpp"
57#include "deSharedPtr.hpp"
58#include "deStringUtil.hpp"
59#include "deMemory.h"
60
61#include <sstream>
62#include <vector>
63#include <map>
64#include <memory>
65#include <algorithm>
66#include <set>
67#include <array>
68#include <utility>
69
70namespace vkt
71{
72namespace pipeline
73{
74
75using namespace vk;
76
77namespace
78{
79enum GeometryType
80{
81	GEOMETRY_TYPE_OPAQUE_TRIANGLE,
82	GEOMETRY_TYPE_OPAQUE_LINE,
83	GEOMETRY_TYPE_OPAQUE_POINT,
84	GEOMETRY_TYPE_OPAQUE_QUAD,
85	GEOMETRY_TYPE_OPAQUE_QUAD_NONZERO_DEPTH,	//!< placed at z = 0.5
86	GEOMETRY_TYPE_TRANSLUCENT_QUAD,
87	GEOMETRY_TYPE_INVISIBLE_TRIANGLE,
88	GEOMETRY_TYPE_INVISIBLE_QUAD,
89	GEOMETRY_TYPE_GRADIENT_QUAD
90};
91
92enum TestModeBits
93{
94	TEST_MODE_DEPTH_BIT		= 1u,
95	TEST_MODE_STENCIL_BIT	= 2u,
96};
97typedef deUint32 TestModeFlags;
98
99enum RenderType
100{
101	// resolve multisample rendering to single sampled image
102	RENDER_TYPE_RESOLVE				= 0u,
103
104	// copy samples to an array of single sampled images
105	RENDER_TYPE_COPY_SAMPLES		= 1u,
106
107	// render first with only depth/stencil and then with color + depth/stencil
108	RENDER_TYPE_DEPTHSTENCIL_ONLY	= 2u,
109
110	// render using color attachment at location 1 and location 0 set as unused
111	RENDER_TYPE_UNUSED_ATTACHMENT	= 3u,
112
113	// render using color attachment with single sample, required by alpha_to_one tests.
114	RENDER_TYPE_SINGLE_SAMPLE		= 4u
115};
116
117enum ImageBackingMode
118{
119	IMAGE_BACKING_MODE_REGULAR	= 0u,
120	IMAGE_BACKING_MODE_SPARSE
121};
122
123struct MultisampleTestParams
124{
125	PipelineConstructionType	pipelineConstructionType;
126	GeometryType				geometryType;
127	float						pointSize;
128	ImageBackingMode			backingMode;
129	bool						useFragmentShadingRate;
130};
131
132void									initMultisamplePrograms				(SourceCollections& sources, MultisampleTestParams params);
133bool									isSupportedSampleCount				(const InstanceInterface& instanceInterface, VkPhysicalDevice physicalDevice, VkSampleCountFlagBits rasterizationSamples);
134bool									isSupportedDepthStencilFormat		(const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkFormat format);
135VkPipelineColorBlendAttachmentState		getDefaultColorBlendAttachmentState	(void);
136VkPipelineColorBlendAttachmentState		getAlphaToCoverageBlendState		(bool blendEnable);
137deUint32								getUniqueColorsCount				(const tcu::ConstPixelBufferAccess& image);
138VkImageAspectFlags						getImageAspectFlags					(const VkFormat format);
139VkPrimitiveTopology						getPrimitiveTopology				(const GeometryType geometryType);
140std::vector<Vertex4RGBA>				generateVertices					(const GeometryType geometryType);
141VkFormat								findSupportedDepthStencilFormat		(Context& context, const bool useDepth, const bool useStencil);
142
143class MultisampleTest : public vkt::TestCase
144{
145public:
146
147												MultisampleTest						(tcu::TestContext&								testContext,
148																					 const std::string&								name,
149																					 PipelineConstructionType						pipelineConstructionType,
150																					 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
151																					 const VkPipelineColorBlendAttachmentState&		blendState,
152																					 GeometryType									geometryType,
153																					 float											pointSize,
154																					 ImageBackingMode								backingMode,
155																					 const bool										useFragmentShadingRate);
156	virtual										~MultisampleTest					(void) {}
157
158	virtual void								initPrograms						(SourceCollections& programCollection) const;
159	virtual TestInstance*						createInstance						(Context& context) const;
160	virtual void								checkSupport						(Context& context) const;
161
162protected:
163	virtual TestInstance*						createMultisampleTestInstance		(Context&										context,
164																					 VkPrimitiveTopology							topology,
165																					 float											pointSize,
166																					 const std::vector<Vertex4RGBA>&				vertices,
167																					 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
168																					 const VkPipelineColorBlendAttachmentState&		colorBlendState) const = 0;
169
170	const PipelineConstructionType				m_pipelineConstructionType;
171	VkPipelineMultisampleStateCreateInfo		m_multisampleStateParams;
172	const VkPipelineColorBlendAttachmentState	m_colorBlendState;
173	const GeometryType							m_geometryType;
174	const float									m_pointSize;
175	const ImageBackingMode						m_backingMode;
176	std::vector<VkSampleMask>					m_sampleMask;
177	bool										m_useFragmentShadingRate;
178};
179
180class RasterizationSamplesTest : public MultisampleTest
181{
182public:
183												RasterizationSamplesTest			(tcu::TestContext&			testContext,
184																					 const std::string&			name,
185																					 PipelineConstructionType	pipelineConstructionType,
186																					 VkSampleCountFlagBits		rasterizationSamples,
187																					 GeometryType				geometryType,
188																					 float						pointSize,
189																					 ImageBackingMode			backingMode,
190																					 TestModeFlags				modeFlags,
191																					 const bool					useFragmentShadingRate);
192	virtual										~RasterizationSamplesTest			(void) {}
193
194protected:
195	virtual TestInstance*						createMultisampleTestInstance		(Context&										context,
196																					 VkPrimitiveTopology							topology,
197																					 float											pointSize,
198																					 const std::vector<Vertex4RGBA>&				vertices,
199																					 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
200																					 const VkPipelineColorBlendAttachmentState&		colorBlendState) const;
201
202	static VkPipelineMultisampleStateCreateInfo	getRasterizationSamplesStateParams	(VkSampleCountFlagBits rasterizationSamples);
203
204	const ImageBackingMode						m_backingMode;
205	const TestModeFlags							m_modeFlags;
206};
207
208class MinSampleShadingTest : public MultisampleTest
209{
210public:
211												MinSampleShadingTest				(tcu::TestContext&				testContext,
212																					 const std::string&				name,
213																					 const PipelineConstructionType	pipelineConstructionType,
214																					 VkSampleCountFlagBits			rasterizationSamples,
215																					 float							minSampleShading,
216																					 GeometryType					geometryType,
217																					 float							pointSize,
218																					 ImageBackingMode				backingMode,
219																					 const bool						minSampleShadingEnabled,
220																					 const bool						useFragmentShadingRate);
221	virtual										~MinSampleShadingTest				(void) {}
222
223protected:
224	virtual void								initPrograms						(SourceCollections& programCollection) const;
225	virtual void								checkSupport						(Context& context) const;
226	virtual TestInstance*						createMultisampleTestInstance		(Context&										context,
227																					 VkPrimitiveTopology							topology,
228																					 float											pointSize,
229																					 const std::vector<Vertex4RGBA>&				vertices,
230																					 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
231																					 const VkPipelineColorBlendAttachmentState&		colorBlendState) const;
232
233	static VkPipelineMultisampleStateCreateInfo	getMinSampleShadingStateParams		(VkSampleCountFlagBits	rasterizationSamples,
234																					 float					minSampleShading,
235																					 bool					minSampleShadingEnabled);
236
237	const float									m_pointSize;
238	const ImageBackingMode						m_backingMode;
239	const bool									m_minSampleShadingEnabled;
240};
241
242class SampleMaskTest : public MultisampleTest
243{
244public:
245												SampleMaskTest						(tcu::TestContext&					testContext,
246																					 const std::string&					name,
247																					 const PipelineConstructionType		pipelineConstructionType,
248																					 VkSampleCountFlagBits				rasterizationSamples,
249																					 const std::vector<VkSampleMask>&	sampleMask,
250																					 GeometryType						geometryType,
251																					 float								pointSize,
252																					 ImageBackingMode					backingMode,
253																					 const bool							useFragmentShadingRate);
254
255	virtual										~SampleMaskTest						(void) {}
256
257protected:
258	virtual TestInstance*						createMultisampleTestInstance		(Context&										context,
259																					 VkPrimitiveTopology							topology,
260																					 float											pointSize,
261																					 const std::vector<Vertex4RGBA>&				vertices,
262																					 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
263																					 const VkPipelineColorBlendAttachmentState&		colorBlendState) const;
264
265	static VkPipelineMultisampleStateCreateInfo	getSampleMaskStateParams			(VkSampleCountFlagBits rasterizationSamples, const std::vector<VkSampleMask>& sampleMask);
266
267	const ImageBackingMode						m_backingMode;
268};
269
270class AlphaToOneTest : public MultisampleTest
271{
272public:
273												AlphaToOneTest					(tcu::TestContext&					testContext,
274																				 const std::string&					name,
275																				 const PipelineConstructionType		pipelineConstructionType,
276																				 VkSampleCountFlagBits				rasterizationSamples,
277																				 ImageBackingMode					backingMode,
278																				 const bool							useFragmentShadingRate);
279
280	virtual										~AlphaToOneTest					(void) {}
281
282protected:
283	virtual void								checkSupport					(Context& context) const;
284	virtual TestInstance*						createMultisampleTestInstance	(Context&										context,
285																				 VkPrimitiveTopology							topology,
286																				 float											pointSize,
287																				 const std::vector<Vertex4RGBA>&				vertices,
288																				 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
289																				 const VkPipelineColorBlendAttachmentState&		colorBlendState) const;
290
291	static VkPipelineMultisampleStateCreateInfo	getAlphaToOneStateParams		(VkSampleCountFlagBits rasterizationSamples);
292	static VkPipelineColorBlendAttachmentState	getAlphaToOneBlendState			(void);
293
294	const ImageBackingMode						m_backingMode;
295};
296
297class AlphaToCoverageTest : public MultisampleTest
298{
299public:
300												AlphaToCoverageTest				(tcu::TestContext&					testContext,
301																				 const std::string&					name,
302																				 const PipelineConstructionType		pipelineConstructionType,
303																				 VkSampleCountFlagBits				rasterizationSamples,
304																				 GeometryType						geometryType,
305																				 ImageBackingMode					backingMode,
306																				 const bool							useFragmentShadingRate,
307																				 const bool							checkDepthBuffer);
308
309	virtual										~AlphaToCoverageTest			(void) {}
310	void										initPrograms					(SourceCollections& programCollection) const override;
311
312protected:
313	TestInstance*								createMultisampleTestInstance	(Context&										context,
314																				 VkPrimitiveTopology							topology,
315																				 float											pointSize,
316																				 const std::vector<Vertex4RGBA>&				vertices,
317																				 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
318																				 const VkPipelineColorBlendAttachmentState&		colorBlendState) const override;
319
320	static VkPipelineMultisampleStateCreateInfo	getAlphaToCoverageStateParams	(VkSampleCountFlagBits rasterizationSamples);
321
322	GeometryType								m_geometryType;
323	const ImageBackingMode						m_backingMode;
324	const bool									m_checkDepthBuffer;
325};
326
327class AlphaToCoverageNoColorAttachmentTest : public MultisampleTest
328{
329public:
330												AlphaToCoverageNoColorAttachmentTest	(tcu::TestContext&					testContext,
331																						 const std::string&					name,
332																						 const PipelineConstructionType		pipelineConstructionType,
333																						 VkSampleCountFlagBits				rasterizationSamples,
334																						 GeometryType						geometryType,
335																						 ImageBackingMode					backingMode,
336																						 const bool							useFragmentShadingRate);
337
338	virtual										~AlphaToCoverageNoColorAttachmentTest	(void) {}
339
340protected:
341	virtual TestInstance*						createMultisampleTestInstance			(Context&										context,
342																						 VkPrimitiveTopology							topology,
343																						 float											pointSize,
344																						 const std::vector<Vertex4RGBA>&				vertices,
345																						 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
346																						 const VkPipelineColorBlendAttachmentState&		colorBlendState) const;
347
348	static VkPipelineMultisampleStateCreateInfo	getStateParams							(VkSampleCountFlagBits rasterizationSamples);
349
350	GeometryType								m_geometryType;
351	const ImageBackingMode						m_backingMode;
352};
353
354class AlphaToCoverageColorUnusedAttachmentTest : public MultisampleTest
355{
356public:
357												AlphaToCoverageColorUnusedAttachmentTest	(tcu::TestContext&					testContext,
358																							 const std::string&					name,
359																							 const PipelineConstructionType		pipelineConstructionType,
360																							 VkSampleCountFlagBits				rasterizationSamples,
361																							 GeometryType						geometryType,
362																							 ImageBackingMode					backingMode,
363																							 const bool							useFragmentShadingRate);
364
365	virtual										~AlphaToCoverageColorUnusedAttachmentTest	(void) {}
366
367protected:
368	virtual void								initPrograms								(SourceCollections& programCollection) const;
369
370	virtual TestInstance*						createMultisampleTestInstance				(Context&										context,
371																							 VkPrimitiveTopology							topology,
372																							 float											pointSize,
373																							 const std::vector<Vertex4RGBA>&				vertices,
374																							 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
375																							 const VkPipelineColorBlendAttachmentState&		colorBlendState) const;
376
377	static VkPipelineMultisampleStateCreateInfo	getStateParams								(VkSampleCountFlagBits rasterizationSamples);
378
379	GeometryType								m_geometryType;
380	const ImageBackingMode						m_backingMode;
381};
382
383class SampleMaskWithConservativeTest : public vkt::TestCase
384{
385	public:
386												SampleMaskWithConservativeTest(tcu::TestContext&							testContext,
387																				const std::string&							name,
388																				const PipelineConstructionType				pipelineConstructionType,
389																				const VkSampleCountFlagBits					rasterizationSamples,
390																				const VkConservativeRasterizationModeEXT	conservativeRasterizationMode,
391																				const bool									enableMinSampleShading,
392																				const float									minSampleShading,
393																				const bool									enableSampleMask,
394																				const VkSampleMask							sampleMask,
395																				const bool									enablePostDepthCoverage,
396																				const bool									useFragmentShadingRate);
397
398												~SampleMaskWithConservativeTest	(void) {}
399
400	void										initPrograms					(SourceCollections&		programCollection)	const;
401	TestInstance*								createInstance					(Context&				context)			const;
402	virtual void								checkSupport					(Context&				context)			const;
403
404private:
405	const PipelineConstructionType				m_pipelineConstructionType;
406	const VkSampleCountFlagBits					m_rasterizationSamples;
407	const bool									m_enableMinSampleShading;
408	float										m_minSampleShading;
409	const bool									m_enableSampleMask;
410	const VkSampleMask							m_sampleMask;
411	const VkConservativeRasterizationModeEXT	m_conservativeRasterizationMode;
412	const bool									m_enablePostDepthCoverage;
413	const RenderType							m_renderType;
414	const bool									m_useFragmentShadingRate;
415};
416#ifndef CTS_USES_VULKANSC
417class SampleMaskWithDepthTestTest : public vkt::TestCase
418{
419public:
420												SampleMaskWithDepthTestTest		(tcu::TestContext&				testContext,
421																				 const std::string&				name,
422																				 const PipelineConstructionType	pipelineConstructionType,
423																				 const VkSampleCountFlagBits	rasterizationSamples,
424																				 const bool						enablePostDepthCoverage,
425																				 const bool						useFragmentShadingRate);
426
427												~SampleMaskWithDepthTestTest	(void) {}
428
429	void										initPrograms					(SourceCollections&		programCollection)	const;
430	TestInstance*								createInstance					(Context&				context)			const;
431	virtual void								checkSupport					(Context&				context)			const;
432private:
433	const PipelineConstructionType				m_pipelineConstructionType;
434	const VkSampleCountFlagBits					m_rasterizationSamples;
435	const bool									m_enablePostDepthCoverage;
436	const bool									m_useFragmentShadingRate;
437};
438#endif // CTS_USES_VULKANSC
439class MultisampleRenderer
440{
441public:
442
443												MultisampleRenderer			(Context&										context,
444																			 PipelineConstructionType						pipelineConstructionType,
445																			 const VkFormat									colorFormat,
446																			 const tcu::IVec2&								renderSize,
447																			 const VkPrimitiveTopology						topology,
448																			 const std::vector<Vertex4RGBA>&				vertices,
449																			 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
450																			 const VkPipelineColorBlendAttachmentState&		blendState,
451																			 const RenderType								renderType,
452																			 const ImageBackingMode							backingMode,
453																			 const bool										useFragmentShadingRate);
454
455												MultisampleRenderer			(Context&										context,
456																			 PipelineConstructionType						pipelineConstructionType,
457																			 const VkFormat									colorFormat,
458																			 const VkFormat									depthStencilFormat,
459																			 const tcu::IVec2&								renderSize,
460																			 const bool										useDepth,
461																			 const bool										useStencil,
462																			 const deUint32									numTopologies,
463																			 const VkPrimitiveTopology*						pTopology,
464																			 const std::vector<Vertex4RGBA>*				pVertices,
465																			 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
466																			 const VkPipelineColorBlendAttachmentState&		blendState,
467																			 const RenderType								renderType,
468																			 const ImageBackingMode							backingMode,
469																			 const bool										useFragmentShadingRate,
470																			 const float									depthClearValue			= 1.0f);
471
472												MultisampleRenderer			(Context&														context,
473																			 PipelineConstructionType										pipelineConstructionType,
474																			 const VkFormat													colorFormat,
475																			 const VkFormat													depthStencilFormat,
476																			 const tcu::IVec2&												renderSize,
477																			 const bool														useDepth,
478																			 const bool														useStencil,
479																			 const bool														useConservative,
480																			 const bool														useFragmentShadingRate,
481																			 const deUint32													numTopologies,
482																			 const VkPrimitiveTopology*										pTopology,
483																			 const std::vector<Vertex4RGBA>*								pVertices,
484																			 const VkPipelineMultisampleStateCreateInfo&					multisampleStateParams,
485																			 const VkPipelineColorBlendAttachmentState&						blendState,
486																			 const VkPipelineRasterizationConservativeStateCreateInfoEXT&	conservativeStateCreateInfo,
487																			 const RenderType												renderType,
488																			 const ImageBackingMode											backingMode,
489																			 const float													depthClearValue			= 1.0f);
490
491	virtual										~MultisampleRenderer		(void);
492
493	de::MovePtr<tcu::TextureLevel>				render						(void);
494	de::MovePtr<tcu::TextureLevel>				getSingleSampledImage		(deUint32 sampleId);
495	de::MovePtr<tcu::TextureLevel>				renderReusingDepth			();
496
497
498protected:
499	void										initialize					(Context&										context,
500																			 const deUint32									numTopologies,
501																			 const VkPrimitiveTopology*						pTopology,
502																			 const std::vector<Vertex4RGBA>*				pVertices);
503
504	Context&													m_context;
505	const PipelineConstructionType								m_pipelineConstructionType;
506
507	const Unique<VkSemaphore>									m_bindSemaphore;
508
509	const VkFormat												m_colorFormat;
510	const VkFormat												m_depthStencilFormat;
511	tcu::IVec2													m_renderSize;
512	const bool													m_useDepth;
513	const bool													m_useStencil;
514	const bool													m_useConservative;
515
516	const VkPipelineMultisampleStateCreateInfo					m_multisampleStateParams;
517	const VkPipelineColorBlendAttachmentState					m_colorBlendState;
518	const VkPipelineRasterizationConservativeStateCreateInfoEXT m_rasterizationConservativeStateCreateInfo;
519
520	const RenderType											m_renderType;
521
522	Move<VkImage>												m_colorImage;
523	de::MovePtr<Allocation>										m_colorImageAlloc;
524	Move<VkImageView>											m_colorAttachmentView;
525
526	Move<VkImage>												m_resolveImage;
527	de::MovePtr<Allocation>										m_resolveImageAlloc;
528	Move<VkImageView>											m_resolveAttachmentView;
529
530	struct PerSampleImage
531	{
532		Move<VkImage>								m_image;
533		de::MovePtr<Allocation>						m_imageAlloc;
534		Move<VkImageView>							m_attachmentView;
535	};
536	std::vector<de::SharedPtr<PerSampleImage> >					m_perSampleImages;
537
538	Move<VkImage>												m_depthStencilImage;
539	de::MovePtr<Allocation>										m_depthStencilImageAlloc;
540	Move<VkImageView>											m_depthStencilAttachmentView;
541
542	RenderPassWrapper											m_renderPass;
543
544	ShaderWrapper												m_vertexShaderModule;
545	ShaderWrapper												m_fragmentShaderModule;
546
547	ShaderWrapper												m_copySampleVertexShaderModule;
548	ShaderWrapper												m_copySampleFragmentShaderModule;
549
550	Move<VkBuffer>												m_vertexBuffer;
551	de::MovePtr<Allocation>										m_vertexBufferAlloc;
552
553	PipelineLayoutWrapper										m_pipelineLayout;
554	std::vector<GraphicsPipelineWrapper>						m_graphicsPipelines;
555
556	Move<VkDescriptorSetLayout>									m_copySampleDesciptorLayout;
557	Move<VkDescriptorPool>										m_copySampleDesciptorPool;
558	Move<VkDescriptorSet>										m_copySampleDesciptorSet;
559
560	PipelineLayoutWrapper										m_copySamplePipelineLayout;
561	std::vector<GraphicsPipelineWrapper>						m_copySamplePipelines;
562
563	Move<VkCommandPool>											m_cmdPool;
564	Move<VkCommandBuffer>										m_cmdBuffer;
565
566	std::vector<de::SharedPtr<Allocation> >						m_allocations;
567
568	ImageBackingMode											m_backingMode;
569	const float													m_depthClearValue;
570	const bool													m_useFragmentShadingRate;
571};
572
573class RasterizationSamplesInstance : public vkt::TestInstance
574{
575public:
576										RasterizationSamplesInstance	(Context&										context,
577																		 const PipelineConstructionType					pipelineConstructionType,
578																		 VkPrimitiveTopology							topology,
579																		 float											pointSize,
580																		 const std::vector<Vertex4RGBA>&				vertices,
581																		 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
582																		 const VkPipelineColorBlendAttachmentState&		blendState,
583																		 const TestModeFlags							modeFlags,
584																		 ImageBackingMode								backingMode,
585																		 const bool										useFragmentShadingRate);
586	virtual								~RasterizationSamplesInstance	(void) {}
587
588	virtual tcu::TestStatus				iterate							(void);
589
590protected:
591	virtual tcu::TestStatus				verifyImage						(const tcu::ConstPixelBufferAccess& result);
592
593	const VkFormat						m_colorFormat;
594	const tcu::IVec2					m_renderSize;
595	const VkPrimitiveTopology			m_primitiveTopology;
596	const float							m_pointSize;
597	const std::vector<Vertex4RGBA>		m_vertices;
598	const std::vector<Vertex4RGBA>		m_fullQuadVertices;			//!< used by depth/stencil case
599	const TestModeFlags					m_modeFlags;
600	de::MovePtr<MultisampleRenderer>	m_multisampleRenderer;
601	const bool							m_useFragmentShadingRate;
602};
603
604class MinSampleShadingInstance : public vkt::TestInstance
605{
606public:
607												MinSampleShadingInstance	(Context&										context,
608																			 const PipelineConstructionType					pipelineConstructionType,
609																			 VkPrimitiveTopology							topology,
610																			 float											pointSize,
611																			 const std::vector<Vertex4RGBA>&				vertices,
612																			 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
613																			 const VkPipelineColorBlendAttachmentState&		blendState,
614																			 ImageBackingMode								backingMode,
615																			 const bool										useFragmentShadingRate);
616	virtual										~MinSampleShadingInstance	(void) {}
617
618	virtual tcu::TestStatus						iterate						(void);
619
620protected:
621	virtual tcu::TestStatus						verifySampleShadedImage		(const std::vector<tcu::TextureLevel>& testShadingImages,
622																			 const tcu::ConstPixelBufferAccess& noSampleshadingImage);
623
624	const PipelineConstructionType				m_pipelineConstructionType;
625	const VkFormat								m_colorFormat;
626	const tcu::IVec2							m_renderSize;
627	const VkPrimitiveTopology					m_primitiveTopology;
628	const std::vector<Vertex4RGBA>				m_vertices;
629	const VkPipelineMultisampleStateCreateInfo	m_multisampleStateParams;
630	const VkPipelineColorBlendAttachmentState	m_colorBlendState;
631	const ImageBackingMode						m_backingMode;
632	const bool									m_useFragmentShadingRate;
633};
634
635class MinSampleShadingDisabledInstance : public MinSampleShadingInstance
636{
637public:
638												MinSampleShadingDisabledInstance	(Context&										context,
639																					 const PipelineConstructionType					pipelineConstructionType,
640																					 VkPrimitiveTopology							topology,
641																					 float											pointSize,
642																					 const std::vector<Vertex4RGBA>&				vertices,
643																					 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
644																					 const VkPipelineColorBlendAttachmentState&		blendState,
645																					 ImageBackingMode								backingMode,
646																					 const bool										useFragmentShadingRate);
647	virtual										~MinSampleShadingDisabledInstance	(void) {}
648
649protected:
650	virtual tcu::TestStatus						verifySampleShadedImage				(const std::vector<tcu::TextureLevel>&	sampleShadedImages,
651																					 const tcu::ConstPixelBufferAccess&		noSampleshadingImage);
652};
653
654class SampleMaskInstance : public vkt::TestInstance
655{
656public:
657												SampleMaskInstance			(Context&										context,
658																			 const PipelineConstructionType					pipelineConstructionType,
659																			 VkPrimitiveTopology							topology,
660																			 float											pointSize,
661																			 const std::vector<Vertex4RGBA>&				vertices,
662																			 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
663																			 const VkPipelineColorBlendAttachmentState&		blendState,
664																			 ImageBackingMode								backingMode,
665																			 const bool										useFragmentShadingRate);
666	virtual										~SampleMaskInstance			(void) {}
667
668	virtual tcu::TestStatus						iterate						(void);
669
670protected:
671	virtual tcu::TestStatus						verifyImage					(const tcu::ConstPixelBufferAccess& testShadingImage,
672																			 const tcu::ConstPixelBufferAccess& minShadingImage,
673																			 const tcu::ConstPixelBufferAccess& maxShadingImage);
674	const PipelineConstructionType				m_pipelineConstructionType;
675	const VkFormat								m_colorFormat;
676	const tcu::IVec2							m_renderSize;
677	const VkPrimitiveTopology					m_primitiveTopology;
678	const std::vector<Vertex4RGBA>				m_vertices;
679	const VkPipelineMultisampleStateCreateInfo	m_multisampleStateParams;
680	const VkPipelineColorBlendAttachmentState	m_colorBlendState;
681	const ImageBackingMode						m_backingMode;
682	const bool									m_useFragmentShadingRate;
683};
684
685class AlphaToOneInstance : public vkt::TestInstance
686{
687public:
688												AlphaToOneInstance			(Context&										context,
689																			 const PipelineConstructionType					pipelineConstructionType,
690																			 VkPrimitiveTopology							topology,
691																			 const std::vector<Vertex4RGBA>&				vertices,
692																			 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
693																			 const VkPipelineColorBlendAttachmentState&		blendState,
694																			 ImageBackingMode								backingMode,
695																			 const bool										useFragmentShadingRate);
696	virtual										~AlphaToOneInstance			(void) {}
697
698	virtual tcu::TestStatus						iterate						(void);
699
700protected:
701	virtual tcu::TestStatus						verifyImage					(const tcu::ConstPixelBufferAccess& alphaOneImage,
702																			 const tcu::ConstPixelBufferAccess& noAlphaOneImage);
703	const PipelineConstructionType				m_pipelineConstructionType;
704	const VkFormat								m_colorFormat;
705	const tcu::IVec2							m_renderSize;
706	const VkPrimitiveTopology					m_primitiveTopology;
707	const std::vector<Vertex4RGBA>				m_vertices;
708	const VkPipelineMultisampleStateCreateInfo	m_multisampleStateParams;
709	const VkPipelineColorBlendAttachmentState	m_colorBlendState;
710	const ImageBackingMode						m_backingMode;
711	const bool									m_useFragmentShadingRate;
712};
713
714class AlphaToCoverageInstance : public vkt::TestInstance
715{
716public:
717												AlphaToCoverageInstance		(Context&										context,
718																			 const PipelineConstructionType					pipelineConstructionType,
719																			 VkPrimitiveTopology							topology,
720																			 const std::vector<Vertex4RGBA>&				vertices,
721																			 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
722																			 const VkPipelineColorBlendAttachmentState&		blendState,
723																			 GeometryType									geometryType,
724																			 ImageBackingMode								backingMode,
725																			 const bool										useFragmentShadingRate,
726																			 const bool										checkDepthBuffer);
727	virtual										~AlphaToCoverageInstance	(void) {}
728
729	virtual tcu::TestStatus						iterate						(void);
730
731protected:
732	virtual tcu::TestStatus						verifyImage					(const tcu::ConstPixelBufferAccess& result);
733	virtual tcu::TestStatus						verifyDepthBufferCheck		(const tcu::ConstPixelBufferAccess& result);
734
735	const PipelineConstructionType				m_pipelineConstructionType;
736	const VkFormat								m_colorFormat;
737	const VkFormat								m_depthStencilFormat;
738	const tcu::IVec2							m_renderSize;
739	const VkPrimitiveTopology					m_primitiveTopology;
740	const std::vector<Vertex4RGBA>				m_vertices;
741	const VkPipelineMultisampleStateCreateInfo	m_multisampleStateParams;
742	const VkPipelineColorBlendAttachmentState	m_colorBlendState;
743	const GeometryType							m_geometryType;
744	const ImageBackingMode						m_backingMode;
745	const bool									m_useFragmentShadingRate;
746	const bool									m_checkDepthBuffer;
747};
748
749class AlphaToCoverageNoColorAttachmentInstance : public vkt::TestInstance
750{
751public:
752												AlphaToCoverageNoColorAttachmentInstance	(Context&										context,
753																							 const PipelineConstructionType					pipelineConstructionType,
754																							 VkPrimitiveTopology							topology,
755																							 const std::vector<Vertex4RGBA>&				vertices,
756																							 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
757																							 const VkPipelineColorBlendAttachmentState&		blendState,
758																							 GeometryType									geometryType,
759																							 ImageBackingMode								backingMode,
760																							 const bool										useFragmentShadingRate);
761	virtual										~AlphaToCoverageNoColorAttachmentInstance	(void) {}
762
763	virtual tcu::TestStatus						iterate										(void);
764
765protected:
766	virtual tcu::TestStatus						verifyImage									(const tcu::ConstPixelBufferAccess& result);
767
768	const PipelineConstructionType				m_pipelineConstructionType;
769	const VkFormat								m_colorFormat;
770	const VkFormat								m_depthStencilFormat;
771	const tcu::IVec2							m_renderSize;
772	const VkPrimitiveTopology					m_primitiveTopology;
773	const std::vector<Vertex4RGBA>				m_vertices;
774	const VkPipelineMultisampleStateCreateInfo	m_multisampleStateParams;
775	const VkPipelineColorBlendAttachmentState	m_colorBlendState;
776	const GeometryType							m_geometryType;
777	const ImageBackingMode						m_backingMode;
778	const bool									m_useFragmentShadingRate;
779};
780
781class AlphaToCoverageColorUnusedAttachmentInstance : public vkt::TestInstance
782{
783public:
784												AlphaToCoverageColorUnusedAttachmentInstance	(Context&										context,
785																								 const PipelineConstructionType					pipelineConstructionType,
786																								 VkPrimitiveTopology							topology,
787																								 const std::vector<Vertex4RGBA>&				vertices,
788																								 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
789																								 const VkPipelineColorBlendAttachmentState&		blendState,
790																								 GeometryType									geometryType,
791																								 ImageBackingMode								backingMode,
792																								 const bool										useFragmentShadingRate);
793	virtual										~AlphaToCoverageColorUnusedAttachmentInstance	(void) {}
794
795	virtual tcu::TestStatus						iterate											(void);
796
797protected:
798	virtual tcu::TestStatus						verifyImage										(const tcu::ConstPixelBufferAccess& result);
799
800	const PipelineConstructionType				m_pipelineConstructionType;
801	const VkFormat								m_colorFormat;
802	const tcu::IVec2							m_renderSize;
803	const VkPrimitiveTopology					m_primitiveTopology;
804	const std::vector<Vertex4RGBA>				m_vertices;
805	const VkPipelineMultisampleStateCreateInfo	m_multisampleStateParams;
806	const VkPipelineColorBlendAttachmentState	m_colorBlendState;
807	const GeometryType							m_geometryType;
808	const ImageBackingMode						m_backingMode;
809	const bool									m_useFragmentShadingRate;
810};
811
812class SampleMaskWithConservativeInstance : public vkt::TestInstance
813{
814public:
815															SampleMaskWithConservativeInstance			(Context&									context,
816																										 const PipelineConstructionType				pipelineConstructionType,
817																										 const VkSampleCountFlagBits				rasterizationSamples,
818																										 const bool									enableMinSampleShading,
819																										 const float								minSampleShading,
820																										 const bool									enableSampleMask,
821																										 const VkSampleMask							sampleMask,
822																										 const VkConservativeRasterizationModeEXT	conservativeRasterizationMode,
823																										 const bool									enablePostDepthCoverage,
824																										 const bool									enableFullyCoveredEXT,
825																										 const RenderType							renderType,
826																										 const bool									useFragmentShadingRate);
827															~SampleMaskWithConservativeInstance			(void) {}
828
829	tcu::TestStatus											iterate										(void);
830
831protected:
832	VkPipelineMultisampleStateCreateInfo					getMultisampleState							(const VkSampleCountFlagBits rasterizationSamples, const bool enableMinSampleShading, const float minSampleShading, const bool enableSampleMask);
833	VkPipelineRasterizationConservativeStateCreateInfoEXT	getRasterizationConservativeStateCreateInfo	(const VkConservativeRasterizationModeEXT	conservativeRasterizationMode);
834	std::vector<Vertex4RGBA>								generateVertices							(void);
835	tcu::TestStatus											verifyImage									(const std::vector<tcu::TextureLevel>& sampleShadedImages,  const tcu::ConstPixelBufferAccess&		result);
836
837	const PipelineConstructionType								m_pipelineConstructionType;
838	const VkSampleCountFlagBits									m_rasterizationSamples;
839	const bool													m_enablePostDepthCoverage;
840	const bool													m_enableFullyCoveredEXT;
841	const VkFormat												m_colorFormat;
842	const VkFormat												m_depthStencilFormat;
843	const tcu::IVec2											m_renderSize;
844	const bool													m_useDepth;
845	const bool													m_useStencil;
846	const bool													m_useConservative;
847	const bool													m_useFragmentShadingRate;
848	const VkConservativeRasterizationModeEXT					m_conservativeRasterizationMode;
849	const VkPrimitiveTopology									m_topology;
850	const tcu::Vec4												m_renderColor;
851	const float													m_depthClearValue;
852	const std::vector<Vertex4RGBA>								m_vertices;
853	const bool													m_enableSampleMask;
854	const std::vector<VkSampleMask>								m_sampleMask;
855	const bool													m_enableMinSampleShading;
856	const float													m_minSampleShading;
857	const VkPipelineMultisampleStateCreateInfo					m_multisampleStateParams;
858	const VkPipelineRasterizationConservativeStateCreateInfoEXT m_rasterizationConservativeStateCreateInfo;
859	const VkPipelineColorBlendAttachmentState					m_blendState;
860	const RenderType											m_renderType;
861	const ImageBackingMode										m_imageBackingMode;
862};
863
864#ifndef CTS_USES_VULKANSC
865class SampleMaskWithDepthTestInstance : public vkt::TestInstance
866{
867public:
868													SampleMaskWithDepthTestInstance		(Context&							context,
869																						 const PipelineConstructionType		pipelineConstructionType,
870																						 const VkSampleCountFlagBits		rasterizationSamples,
871																						 const bool							enablePostDepthCoverage,
872																						 const bool							useFragmentShadingRate);
873													~SampleMaskWithDepthTestInstance	(void) {}
874
875	tcu::TestStatus									iterate								(void);
876
877protected:
878	VkPipelineMultisampleStateCreateInfo			getMultisampleState					(const VkSampleCountFlagBits		rasterizationSamples);
879	std::vector<Vertex4RGBA>						generateVertices					(void);
880	tcu::TestStatus									verifyImage							(const tcu::ConstPixelBufferAccess&	result);
881
882	struct SampleCoverage
883	{
884		SampleCoverage() {}
885		SampleCoverage(deUint32 min_, deUint32 max_)
886			: min(min_), max(max_) {}
887
888		deUint32	min;
889		deUint32	max;
890	};
891
892	const PipelineConstructionType					m_pipelineConstructionType;
893	const VkSampleCountFlagBits						m_rasterizationSamples;
894	const bool										m_enablePostDepthCoverage;
895	const VkFormat									m_colorFormat;
896	const VkFormat									m_depthStencilFormat;
897	const tcu::IVec2								m_renderSize;
898	const bool										m_useDepth;
899	const bool										m_useStencil;
900	const VkPrimitiveTopology						m_topology;
901	const tcu::Vec4									m_renderColor;
902	const std::vector<Vertex4RGBA>					m_vertices;
903	const VkPipelineMultisampleStateCreateInfo		m_multisampleStateParams;
904	const VkPipelineColorBlendAttachmentState		m_blendState;
905	const RenderType								m_renderType;
906	const ImageBackingMode							m_imageBackingMode;
907	const float										m_depthClearValue;
908	std::map<VkSampleCountFlagBits, SampleCoverage>	m_refCoverageAfterDepthTest;
909	const bool										m_useFragmentShadingRate;
910};
911
912
913// Helper functions
914
915void checkSupport (Context& context, MultisampleTestParams params)
916{
917	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), params.pipelineConstructionType);
918}
919#endif // CTS_USES_VULKANSC
920
921void initMultisamplePrograms (SourceCollections& sources, MultisampleTestParams params)
922{
923	const std::string	pointSize		= params.geometryType == GEOMETRY_TYPE_OPAQUE_POINT ? (std::string("	gl_PointSize = ") + de::toString(params.pointSize) + ".0f;\n") : std::string("");
924	std::ostringstream	vertexSource;
925
926	vertexSource <<
927		"#version 310 es\n"
928		"layout(location = 0) in vec4 position;\n"
929		"layout(location = 1) in vec4 color;\n"
930		"layout(location = 0) out highp vec4 vtxColor;\n"
931		"void main (void)\n"
932		"{\n"
933		"	gl_Position = position;\n"
934		"	vtxColor = color;\n"
935		<< pointSize
936		<< "}\n";
937
938	static const char* fragmentSource =
939		"#version 310 es\n"
940		"layout(location = 0) in highp vec4 vtxColor;\n"
941		"layout(location = 0) out highp vec4 fragColor;\n"
942		"void main (void)\n"
943		"{\n"
944		"	fragColor = vtxColor;\n"
945		"}\n";
946
947	sources.glslSources.add("color_vert") << glu::VertexSource(vertexSource.str());
948	sources.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource);
949}
950
951void initSampleShadingPrograms (SourceCollections& sources, MultisampleTestParams params, bool minSampleShadingEnabled)
952{
953	{
954		const std::string	pointSize		= params.geometryType == GEOMETRY_TYPE_OPAQUE_POINT ? (std::string("	gl_PointSize = ") + de::toString(params.pointSize) + ".0f;\n") : std::string("");
955		std::ostringstream	vertexSource;
956		std::ostringstream	fragmentSource;
957
958		vertexSource <<
959			"#version 440\n"
960			"layout(location = 0) in vec4 position;\n"
961			"layout(location = 1) in vec4 color;\n"
962			"void main (void)\n"
963			"{\n"
964			"	gl_Position = position;\n"
965			<< pointSize
966			<< "}\n";
967
968		fragmentSource << "#version 440\n"
969			"layout(location = 0) out highp vec4 fragColor;\n"
970			"void main (void)\n"
971			"{\n";
972		if (minSampleShadingEnabled) {
973			fragmentSource << "    uint sampleId = gl_SampleID;\n"; // Enable sample shading for shader objects by reading gl_SampleID
974		}
975		fragmentSource << "    fragColor = vec4(fract(gl_FragCoord.xy), 0.0, 1.0);\n"
976			"}\n";
977
978		sources.glslSources.add("color_vert") << glu::VertexSource(vertexSource.str());
979		sources.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource.str());
980	}
981
982	{
983		static const char*  vertexSource =
984			"#version 440\n"
985			"void main (void)\n"
986			"{\n"
987			"	const vec4 positions[4] = vec4[4](\n"
988			"		vec4(-1.0, -1.0, 0.0, 1.0),\n"
989			"		vec4(-1.0,  1.0, 0.0, 1.0),\n"
990			"		vec4( 1.0, -1.0, 0.0, 1.0),\n"
991			"		vec4( 1.0,  1.0, 0.0, 1.0)\n"
992			"	);\n"
993			"	gl_Position = positions[gl_VertexIndex];\n"
994			"}\n";
995
996		static const char* fragmentSource =
997			"#version 440\n"
998			"precision highp float;\n"
999			"layout(location = 0) out highp vec4 fragColor;\n"
1000			"layout(set = 0, binding = 0, input_attachment_index = 0) uniform subpassInputMS imageMS;\n"
1001			"layout(push_constant) uniform PushConstantsBlock\n"
1002			"{\n"
1003			"	int sampleId;\n"
1004			"} pushConstants;\n"
1005			"void main (void)\n"
1006			"{\n"
1007			"	fragColor = subpassLoad(imageMS, pushConstants.sampleId);\n"
1008			"}\n";
1009
1010		sources.glslSources.add("quad_vert") << glu::VertexSource(vertexSource);
1011		sources.glslSources.add("copy_sample_frag") << glu::FragmentSource(fragmentSource);
1012	}
1013}
1014
1015void initAlphaToCoverageColorUnusedAttachmentPrograms (SourceCollections& sources)
1016{
1017	std::ostringstream vertexSource;
1018
1019	vertexSource <<
1020		"#version 310 es\n"
1021		"layout(location = 0) in vec4 position;\n"
1022		"layout(location = 1) in vec4 color;\n"
1023		"layout(location = 0) out highp vec4 vtxColor;\n"
1024		"void main (void)\n"
1025		"{\n"
1026		"	gl_Position = position;\n"
1027		"	vtxColor = color;\n"
1028		"}\n";
1029
1030	// Location 0 is unused, but the alpha for coverage is written there. Location 1 has no alpha channel.
1031	static const char* fragmentSource =
1032		"#version 310 es\n"
1033		"layout(location = 0) in highp vec4 vtxColor;\n"
1034		"layout(location = 0) out highp vec4 fragColor0;\n"
1035		"layout(location = 1) out highp vec3 fragColor1;\n"
1036		"void main (void)\n"
1037		"{\n"
1038		"	fragColor0 = vtxColor;\n"
1039		"	fragColor1 = vtxColor.rgb;\n"
1040		"}\n";
1041
1042	sources.glslSources.add("color_vert") << glu::VertexSource(vertexSource.str());
1043	sources.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource);
1044}
1045
1046bool isSupportedSampleCount (const InstanceInterface& instanceInterface, VkPhysicalDevice physicalDevice, VkSampleCountFlagBits rasterizationSamples)
1047{
1048	VkPhysicalDeviceProperties deviceProperties;
1049
1050	instanceInterface.getPhysicalDeviceProperties(physicalDevice, &deviceProperties);
1051
1052	return !!(deviceProperties.limits.framebufferColorSampleCounts & rasterizationSamples);
1053}
1054
1055bool checkFragmentShadingRateRequirements(Context& context, deUint32 sampleCount)
1056{
1057	const auto&	vki = context.getInstanceInterface();
1058	const auto	physicalDevice = context.getPhysicalDevice();
1059
1060	context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate");
1061
1062	if (!context.getFragmentShadingRateFeatures().pipelineFragmentShadingRate)
1063		TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate not supported");
1064
1065	// Fetch information about supported fragment shading rates
1066	deUint32 supportedFragmentShadingRateCount = 0;
1067	vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount, DE_NULL);
1068
1069	std::vector<vk::VkPhysicalDeviceFragmentShadingRateKHR> supportedFragmentShadingRates(supportedFragmentShadingRateCount,
1070		{
1071			vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR,
1072			DE_NULL,
1073			vk::VK_SAMPLE_COUNT_1_BIT,
1074			{1, 1}
1075		});
1076	vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount, supportedFragmentShadingRates.data());
1077
1078	for (const auto& rate : supportedFragmentShadingRates)
1079	{
1080		if ((rate.fragmentSize.width == 2u) &&
1081			(rate.fragmentSize.height == 2u) &&
1082			(rate.sampleCounts & sampleCount))
1083			return true;
1084	}
1085
1086	return false;
1087}
1088
1089VkPipelineColorBlendAttachmentState getDefaultColorBlendAttachmentState ()
1090{
1091	const VkPipelineColorBlendAttachmentState colorBlendState =
1092	{
1093		false,														// VkBool32					blendEnable;
1094		VK_BLEND_FACTOR_ONE,										// VkBlendFactor			srcColorBlendFactor;
1095		VK_BLEND_FACTOR_ZERO,										// VkBlendFactor			dstColorBlendFactor;
1096		VK_BLEND_OP_ADD,											// VkBlendOp				colorBlendOp;
1097		VK_BLEND_FACTOR_ONE,										// VkBlendFactor			srcAlphaBlendFactor;
1098		VK_BLEND_FACTOR_ZERO,										// VkBlendFactor			dstAlphaBlendFactor;
1099		VK_BLEND_OP_ADD,											// VkBlendOp				alphaBlendOp;
1100		VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |		// VkColorComponentFlags	colorWriteMask;
1101			VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
1102	};
1103
1104	return colorBlendState;
1105}
1106
1107VkPipelineColorBlendAttachmentState getAlphaToCoverageBlendState (bool blendEnable)
1108{
1109	const VkPipelineColorBlendAttachmentState colorBlendState =
1110	{
1111		blendEnable,												// VkBool32					blendEnable;
1112		VK_BLEND_FACTOR_SRC_ALPHA,									// VkBlendFactor			srcColorBlendFactor;
1113		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,						// VkBlendFactor			dstColorBlendFactor;
1114		VK_BLEND_OP_ADD,											// VkBlendOp				colorBlendOp;
1115		VK_BLEND_FACTOR_ZERO,										// VkBlendFactor			srcAlphaBlendFactor;
1116		VK_BLEND_FACTOR_ONE,										// VkBlendFactor			dstAlphaBlendFactor;
1117		VK_BLEND_OP_ADD,											// VkBlendOp				alphaBlendOp;
1118		VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |		// VkColorComponentFlags	colorWriteMask;
1119			VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
1120	};
1121
1122	return colorBlendState;
1123}
1124
1125deUint32 getUniqueColorsCount (const tcu::ConstPixelBufferAccess& image)
1126{
1127	DE_ASSERT(image.getFormat().getPixelSize() == 4);
1128
1129	std::map<deUint32, deUint32>	histogram; // map<pixel value, number of occurrences>
1130	const deUint32					pixelCount	= image.getWidth() * image.getHeight() * image.getDepth();
1131
1132	for (deUint32 pixelNdx = 0; pixelNdx < pixelCount; pixelNdx++)
1133	{
1134		const deUint32 pixelValue = *((const deUint32*)image.getDataPtr() + pixelNdx);
1135
1136		if (histogram.find(pixelValue) != histogram.end())
1137			histogram[pixelValue]++;
1138		else
1139			histogram[pixelValue] = 1;
1140	}
1141
1142	return (deUint32)histogram.size();
1143}
1144
1145VkImageAspectFlags getImageAspectFlags (const VkFormat format)
1146{
1147	const tcu::TextureFormat tcuFormat = mapVkFormat(format);
1148
1149	if      (tcuFormat.order == tcu::TextureFormat::DS)		return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
1150	else if (tcuFormat.order == tcu::TextureFormat::D)		return VK_IMAGE_ASPECT_DEPTH_BIT;
1151	else if (tcuFormat.order == tcu::TextureFormat::S)		return VK_IMAGE_ASPECT_STENCIL_BIT;
1152
1153	DE_ASSERT(false);
1154	return 0u;
1155}
1156
1157std::vector<Vertex4RGBA> generateVertices (const GeometryType geometryType)
1158{
1159	std::vector<Vertex4RGBA> vertices;
1160
1161	switch (geometryType)
1162	{
1163		case GEOMETRY_TYPE_OPAQUE_TRIANGLE:
1164		case GEOMETRY_TYPE_INVISIBLE_TRIANGLE:
1165		{
1166			Vertex4RGBA vertexData[3] =
1167			{
1168				{
1169					tcu::Vec4(-0.75f, 0.0f, 0.0f, 1.0f),
1170					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
1171				},
1172				{
1173					tcu::Vec4(0.75f, 0.125f, 0.0f, 1.0f),
1174					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
1175				},
1176				{
1177					tcu::Vec4(0.75f, -0.125f, 0.0f, 1.0f),
1178					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
1179				}
1180			};
1181
1182			if (geometryType == GEOMETRY_TYPE_INVISIBLE_TRIANGLE)
1183			{
1184				for (int i = 0; i < 3; i++)
1185					vertexData[i].color = tcu::Vec4();
1186			}
1187
1188			vertices = std::vector<Vertex4RGBA>(vertexData, vertexData + 3);
1189			break;
1190		}
1191
1192		case GEOMETRY_TYPE_OPAQUE_LINE:
1193		{
1194			const Vertex4RGBA vertexData[2] =
1195			{
1196				{
1197					tcu::Vec4(-0.75f, 0.25f, 0.0f, 1.0f),
1198					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
1199				},
1200				{
1201					tcu::Vec4(0.75f, -0.25f, 0.0f, 1.0f),
1202					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
1203				}
1204			};
1205
1206			vertices = std::vector<Vertex4RGBA>(vertexData, vertexData + 2);
1207			break;
1208		}
1209
1210		case GEOMETRY_TYPE_OPAQUE_POINT:
1211		{
1212			const Vertex4RGBA vertex =
1213			{
1214				tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
1215				tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
1216			};
1217
1218			vertices = std::vector<Vertex4RGBA>(1, vertex);
1219			break;
1220		}
1221
1222		case GEOMETRY_TYPE_OPAQUE_QUAD:
1223		case GEOMETRY_TYPE_OPAQUE_QUAD_NONZERO_DEPTH:
1224		case GEOMETRY_TYPE_TRANSLUCENT_QUAD:
1225		case GEOMETRY_TYPE_INVISIBLE_QUAD:
1226		case GEOMETRY_TYPE_GRADIENT_QUAD:
1227		{
1228			Vertex4RGBA vertexData[4] =
1229			{
1230				{
1231					tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
1232					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
1233				},
1234				{
1235					tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f),
1236					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
1237				},
1238				{
1239					tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
1240					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
1241				},
1242				{
1243					tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
1244					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
1245				}
1246			};
1247
1248			if (geometryType == GEOMETRY_TYPE_TRANSLUCENT_QUAD)
1249			{
1250				for (int i = 0; i < 4; i++)
1251					vertexData[i].color.w() = 0.25f;
1252			}
1253			else if (geometryType == GEOMETRY_TYPE_INVISIBLE_QUAD)
1254			{
1255				for (int i = 0; i < 4; i++)
1256					vertexData[i].color.w() = 0.0f;
1257			}
1258			else if (geometryType == GEOMETRY_TYPE_GRADIENT_QUAD)
1259			{
1260				vertexData[0].color.w() = 0.0f;
1261				vertexData[2].color.w() = 0.0f;
1262			}
1263			else if (geometryType == GEOMETRY_TYPE_OPAQUE_QUAD_NONZERO_DEPTH)
1264			{
1265				for (int i = 0; i < 4; i++)
1266					vertexData[i].position.z() = 0.5f;
1267			}
1268
1269			vertices = std::vector<Vertex4RGBA>(vertexData, vertexData + de::arrayLength(vertexData));
1270			break;
1271		}
1272
1273		default:
1274			DE_ASSERT(false);
1275	}
1276	return vertices;
1277}
1278
1279VkPrimitiveTopology getPrimitiveTopology (const GeometryType geometryType)
1280{
1281	switch (geometryType)
1282	{
1283		case GEOMETRY_TYPE_OPAQUE_TRIANGLE:
1284		case GEOMETRY_TYPE_INVISIBLE_TRIANGLE:			return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1285
1286		case GEOMETRY_TYPE_OPAQUE_LINE:					return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
1287		case GEOMETRY_TYPE_OPAQUE_POINT:				return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
1288
1289		case GEOMETRY_TYPE_OPAQUE_QUAD:
1290		case GEOMETRY_TYPE_OPAQUE_QUAD_NONZERO_DEPTH:
1291		case GEOMETRY_TYPE_TRANSLUCENT_QUAD:
1292		case GEOMETRY_TYPE_INVISIBLE_QUAD:
1293		case GEOMETRY_TYPE_GRADIENT_QUAD:				return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1294
1295		default:
1296			DE_ASSERT(false);
1297			return VK_PRIMITIVE_TOPOLOGY_LAST;
1298	}
1299}
1300
1301bool isSupportedDepthStencilFormat (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkFormat format)
1302{
1303	VkFormatProperties formatProps;
1304	vki.getPhysicalDeviceFormatProperties(physDevice, format, &formatProps);
1305	return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
1306}
1307
1308VkFormat findSupportedDepthStencilFormat (Context& context, const bool useDepth, const bool useStencil)
1309{
1310	if (useDepth && !useStencil)
1311		return VK_FORMAT_D16_UNORM;		// must be supported
1312
1313	const InstanceInterface&	vki			= context.getInstanceInterface();
1314	const VkPhysicalDevice		physDevice	= context.getPhysicalDevice();
1315
1316	// One of these formats must be supported.
1317
1318	if (isSupportedDepthStencilFormat(vki, physDevice, VK_FORMAT_D24_UNORM_S8_UINT))
1319		return VK_FORMAT_D24_UNORM_S8_UINT;
1320
1321	if (isSupportedDepthStencilFormat(vki, physDevice, VK_FORMAT_D32_SFLOAT_S8_UINT))
1322		return VK_FORMAT_D32_SFLOAT_S8_UINT;
1323
1324	return VK_FORMAT_UNDEFINED;
1325}
1326
1327
1328// MultisampleTest
1329
1330MultisampleTest::MultisampleTest (tcu::TestContext&								testContext,
1331								  const std::string&							name,
1332								  const PipelineConstructionType				pipelineConstructionType,
1333								  const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
1334								  const VkPipelineColorBlendAttachmentState&	blendState,
1335								  GeometryType									geometryType,
1336								  float											pointSize,
1337								  ImageBackingMode								backingMode,
1338								  const bool									useFragmentShadingRate)
1339	: vkt::TestCase				(testContext, name)
1340	, m_pipelineConstructionType(pipelineConstructionType)
1341	, m_multisampleStateParams	(multisampleStateParams)
1342	, m_colorBlendState			(blendState)
1343	, m_geometryType			(geometryType)
1344	, m_pointSize				(pointSize)
1345	, m_backingMode				(backingMode)
1346	, m_useFragmentShadingRate	(useFragmentShadingRate)
1347{
1348	if (m_multisampleStateParams.pSampleMask)
1349	{
1350		// Copy pSampleMask to avoid dependencies with other classes
1351
1352		const deUint32 maskCount = deCeilFloatToInt32(float(m_multisampleStateParams.rasterizationSamples) / 32);
1353
1354		for (deUint32 maskNdx = 0; maskNdx < maskCount; maskNdx++)
1355			m_sampleMask.push_back(m_multisampleStateParams.pSampleMask[maskNdx]);
1356
1357		m_multisampleStateParams.pSampleMask = m_sampleMask.data();
1358	}
1359}
1360
1361void MultisampleTest::initPrograms (SourceCollections& programCollection) const
1362{
1363	MultisampleTestParams params = {m_pipelineConstructionType, m_geometryType, m_pointSize, m_backingMode, m_useFragmentShadingRate};
1364	initMultisamplePrograms(programCollection, params);
1365}
1366
1367TestInstance* MultisampleTest::createInstance (Context& context) const
1368{
1369	return createMultisampleTestInstance(context, getPrimitiveTopology(m_geometryType), m_pointSize, generateVertices(m_geometryType), m_multisampleStateParams, m_colorBlendState);
1370}
1371
1372void MultisampleTest::checkSupport (Context& context) const
1373{
1374	if (m_geometryType == GEOMETRY_TYPE_OPAQUE_POINT && m_pointSize > 1.0f)
1375		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_LARGE_POINTS);
1376
1377	if (m_useFragmentShadingRate && !checkFragmentShadingRateRequirements(context, m_multisampleStateParams.rasterizationSamples))
1378		TCU_THROW(NotSupportedError, "Required FragmentShadingRate not supported");
1379
1380	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
1381}
1382
1383// RasterizationSamplesTest
1384
1385RasterizationSamplesTest::RasterizationSamplesTest (tcu::TestContext&			testContext,
1386													const std::string&			name,
1387													PipelineConstructionType	pipelineConstructionType,
1388													VkSampleCountFlagBits		rasterizationSamples,
1389													GeometryType				geometryType,
1390													float						pointSize,
1391													ImageBackingMode			backingMode,
1392													TestModeFlags				modeFlags,
1393													const bool					useFragmentShadingRate)
1394	: MultisampleTest	(testContext, name, pipelineConstructionType, getRasterizationSamplesStateParams(rasterizationSamples), getDefaultColorBlendAttachmentState(), geometryType, pointSize, backingMode, useFragmentShadingRate)
1395	, m_backingMode		(backingMode)
1396	, m_modeFlags		(modeFlags)
1397{
1398}
1399
1400VkPipelineMultisampleStateCreateInfo RasterizationSamplesTest::getRasterizationSamplesStateParams (VkSampleCountFlagBits rasterizationSamples)
1401{
1402	const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
1403	{
1404		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
1405		DE_NULL,													// const void*								pNext;
1406		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
1407		rasterizationSamples,										// VkSampleCountFlagBits					rasterizationSamples;
1408		false,														// VkBool32									sampleShadingEnable;
1409		0.0f,														// float									minSampleShading;
1410		DE_NULL,													// const VkSampleMask*						pSampleMask;
1411		false,														// VkBool32									alphaToCoverageEnable;
1412		false														// VkBool32									alphaToOneEnable;
1413	};
1414
1415	return multisampleStateParams;
1416}
1417
1418TestInstance* RasterizationSamplesTest::createMultisampleTestInstance (Context&										context,
1419																	   VkPrimitiveTopology							topology,
1420																	   float										pointSize,
1421																	   const std::vector<Vertex4RGBA>&				vertices,
1422																	   const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
1423																	   const VkPipelineColorBlendAttachmentState&	colorBlendState) const
1424{
1425	return new RasterizationSamplesInstance(context, m_pipelineConstructionType, topology, pointSize, vertices, multisampleStateParams, colorBlendState, m_modeFlags, m_backingMode, m_useFragmentShadingRate);
1426}
1427
1428
1429// MinSampleShadingTest
1430
1431MinSampleShadingTest::MinSampleShadingTest (tcu::TestContext&				testContext,
1432											const std::string&				name,
1433											const PipelineConstructionType	pipelineConstructionType,
1434											VkSampleCountFlagBits			rasterizationSamples,
1435											float							minSampleShading,
1436											GeometryType					geometryType,
1437											float							pointSize,
1438											ImageBackingMode				backingMode,
1439											const bool						minSampleShadingEnabled,
1440											const bool						useFragmentShadingRate)
1441	: MultisampleTest			(testContext, name, pipelineConstructionType, getMinSampleShadingStateParams(rasterizationSamples, minSampleShading, minSampleShadingEnabled), getDefaultColorBlendAttachmentState(), geometryType, pointSize, backingMode, useFragmentShadingRate)
1442	, m_pointSize				(pointSize)
1443	, m_backingMode				(backingMode)
1444	, m_minSampleShadingEnabled	(minSampleShadingEnabled)
1445{
1446}
1447
1448void MinSampleShadingTest::checkSupport (Context& context) const
1449{
1450	MultisampleTest::checkSupport(context);
1451
1452	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
1453}
1454
1455void MinSampleShadingTest::initPrograms (SourceCollections& programCollection) const
1456{
1457	MultisampleTestParams params = {m_pipelineConstructionType, m_geometryType, m_pointSize, m_backingMode, m_useFragmentShadingRate};
1458	initSampleShadingPrograms(programCollection, params, m_minSampleShadingEnabled);
1459}
1460
1461TestInstance* MinSampleShadingTest::createMultisampleTestInstance (Context&										context,
1462																   VkPrimitiveTopology							topology,
1463																   float										pointSize,
1464																   const std::vector<Vertex4RGBA>&				vertices,
1465																   const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
1466																   const VkPipelineColorBlendAttachmentState&	colorBlendState) const
1467{
1468	if (m_minSampleShadingEnabled)
1469		return new MinSampleShadingInstance(context, m_pipelineConstructionType, topology, pointSize, vertices, multisampleStateParams, colorBlendState, m_backingMode, m_useFragmentShadingRate);
1470	else
1471		return new MinSampleShadingDisabledInstance(context, m_pipelineConstructionType, topology, pointSize, vertices, multisampleStateParams, colorBlendState, m_backingMode, m_useFragmentShadingRate);
1472}
1473
1474VkPipelineMultisampleStateCreateInfo MinSampleShadingTest::getMinSampleShadingStateParams (VkSampleCountFlagBits rasterizationSamples, float minSampleShading, bool minSampleShadingEnabled)
1475{
1476	const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
1477	{
1478		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
1479		DE_NULL,													// const void*								pNext;
1480		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
1481		rasterizationSamples,										// VkSampleCountFlagBits					rasterizationSamples;
1482		minSampleShadingEnabled ? VK_TRUE : VK_FALSE,				// VkBool32									sampleShadingEnable;
1483		minSampleShading,											// float									minSampleShading;
1484		DE_NULL,													// const VkSampleMask*						pSampleMask;
1485		false,														//  VkBool32								alphaToCoverageEnable;
1486		false														//  VkBool32								alphaToOneEnable;
1487	};
1488
1489	return multisampleStateParams;
1490}
1491
1492
1493// SampleMaskTest
1494
1495SampleMaskTest::SampleMaskTest (tcu::TestContext&					testContext,
1496								const std::string&					name,
1497								const PipelineConstructionType		pipelineConstructionType,
1498								VkSampleCountFlagBits				rasterizationSamples,
1499								const std::vector<VkSampleMask>&	sampleMask,
1500								GeometryType						geometryType,
1501								float								pointSize,
1502								ImageBackingMode					backingMode,
1503								const bool							useFragmentShadingRate)
1504	: MultisampleTest	(testContext, name, pipelineConstructionType, getSampleMaskStateParams(rasterizationSamples, sampleMask), getDefaultColorBlendAttachmentState(), geometryType, pointSize, backingMode, useFragmentShadingRate)
1505	, m_backingMode		(backingMode)
1506{
1507}
1508
1509TestInstance* SampleMaskTest::createMultisampleTestInstance (Context&										context,
1510															 VkPrimitiveTopology							topology,
1511															 float											pointSize,
1512															 const std::vector<Vertex4RGBA>&				vertices,
1513															 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
1514															 const VkPipelineColorBlendAttachmentState&		colorBlendState) const
1515{
1516	DE_UNREF(pointSize);
1517	return new SampleMaskInstance(context, m_pipelineConstructionType, topology, pointSize, vertices, multisampleStateParams, colorBlendState, m_backingMode, m_useFragmentShadingRate);
1518}
1519
1520VkPipelineMultisampleStateCreateInfo SampleMaskTest::getSampleMaskStateParams (VkSampleCountFlagBits rasterizationSamples, const std::vector<VkSampleMask>& sampleMask)
1521{
1522	const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
1523	{
1524		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
1525		DE_NULL,													// const void*								pNext;
1526		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
1527		rasterizationSamples,										// VkSampleCountFlagBits					rasterizationSamples;
1528		false,														// VkBool32									sampleShadingEnable;
1529		0.0f,														// float									minSampleShading;
1530		sampleMask.data(),											// const VkSampleMask*						pSampleMask;
1531		false,														// VkBool32									alphaToCoverageEnable;
1532		false														// VkBool32									alphaToOneEnable;
1533	};
1534
1535	return multisampleStateParams;
1536}
1537
1538
1539// AlphaToOneTest
1540
1541AlphaToOneTest::AlphaToOneTest (tcu::TestContext&				testContext,
1542								const std::string&				name,
1543								const PipelineConstructionType	pipelineConstructionType,
1544								VkSampleCountFlagBits			rasterizationSamples,
1545								ImageBackingMode				backingMode,
1546								const bool						useFragmentShadingRate)
1547	: MultisampleTest	(testContext, name, pipelineConstructionType, getAlphaToOneStateParams(rasterizationSamples), getAlphaToOneBlendState(), GEOMETRY_TYPE_GRADIENT_QUAD, 1.0f, backingMode, useFragmentShadingRate)
1548	, m_backingMode(backingMode)
1549{
1550}
1551
1552void AlphaToOneTest::checkSupport (Context& context) const
1553{
1554	MultisampleTest::checkSupport(context);
1555
1556	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_ALPHA_TO_ONE);
1557}
1558
1559TestInstance* AlphaToOneTest::createMultisampleTestInstance (Context&										context,
1560															 VkPrimitiveTopology							topology,
1561															 float											pointSize,
1562															 const std::vector<Vertex4RGBA>&				vertices,
1563															 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
1564															 const VkPipelineColorBlendAttachmentState&		colorBlendState) const
1565{
1566	DE_UNREF(pointSize);
1567	return new AlphaToOneInstance(context, m_pipelineConstructionType, topology, vertices, multisampleStateParams, colorBlendState, m_backingMode, m_useFragmentShadingRate);
1568}
1569
1570VkPipelineMultisampleStateCreateInfo AlphaToOneTest::getAlphaToOneStateParams (VkSampleCountFlagBits rasterizationSamples)
1571{
1572	const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
1573	{
1574		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
1575		DE_NULL,													// const void*								pNext;
1576		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
1577		rasterizationSamples,										// VkSampleCountFlagBits					rasterizationSamples;
1578		false,														// VkBool32									sampleShadingEnable;
1579		0.0f,														// float									minSampleShading;
1580		DE_NULL,													// const VkSampleMask*						pSampleMask;
1581		false,														// VkBool32									alphaToCoverageEnable;
1582		true														// VkBool32									alphaToOneEnable;
1583	};
1584
1585	return multisampleStateParams;
1586}
1587
1588VkPipelineColorBlendAttachmentState AlphaToOneTest::getAlphaToOneBlendState (void)
1589{
1590	const VkPipelineColorBlendAttachmentState colorBlendState =
1591	{
1592		true,														// VkBool32					blendEnable;
1593		VK_BLEND_FACTOR_SRC_ALPHA,									// VkBlendFactor			srcColorBlendFactor;
1594		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,						// VkBlendFactor			dstColorBlendFactor;
1595		VK_BLEND_OP_ADD,											// VkBlendOp				colorBlendOp;
1596		VK_BLEND_FACTOR_SRC_ALPHA,									// VkBlendFactor			srcAlphaBlendFactor;
1597		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,						// VkBlendFactor			dstAlphaBlendFactor;
1598		VK_BLEND_OP_ADD,											// VkBlendOp				alphaBlendOp;
1599		VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |		// VkColorComponentFlags	colorWriteMask;
1600			VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
1601	};
1602
1603	return colorBlendState;
1604}
1605
1606
1607// AlphaToCoverageTest
1608
1609AlphaToCoverageTest::AlphaToCoverageTest (tcu::TestContext&					testContext,
1610										  const std::string&				name,
1611										  const PipelineConstructionType	pipelineConstructionType,
1612										  VkSampleCountFlagBits				rasterizationSamples,
1613										  GeometryType						geometryType,
1614										  ImageBackingMode					backingMode,
1615										  const bool						useFragmentShadingRate,
1616										  const bool						checkDepthBuffer)
1617	: MultisampleTest	(testContext,
1618						 name,
1619						 pipelineConstructionType,
1620						 getAlphaToCoverageStateParams(rasterizationSamples),
1621						 getAlphaToCoverageBlendState(checkDepthBuffer),
1622						 geometryType,
1623						 1.0f,
1624						 backingMode,
1625						 useFragmentShadingRate)
1626	, m_geometryType	(geometryType)
1627	, m_backingMode		(backingMode)
1628	, m_checkDepthBuffer(checkDepthBuffer)
1629{
1630	if (checkDepthBuffer)
1631		DE_ASSERT(geometryType == GEOMETRY_TYPE_INVISIBLE_QUAD);
1632}
1633
1634void AlphaToCoverageTest::initPrograms (SourceCollections &programCollection) const
1635{
1636	MultisampleTest::initPrograms(programCollection);
1637
1638	if (m_checkDepthBuffer)
1639	{
1640		std::ostringstream vert;
1641		vert
1642			<< "#version 460\n"
1643			<< "layout (push_constant, std430) uniform PushConstantBlock { float depth; } pc;\n"
1644			<< "layout (location=0) out vec4 vtxColor;\n"
1645			<< "vec2 positions[3] = vec2[](\n"
1646			<< "    vec2(-1.0, -1.0),\n"
1647			<< "    vec2(-1.0, 3.0),\n"
1648			<< "    vec2(3.0, -1.0)\n"
1649			<< ");\n"
1650			<< "void main (void) {\n"
1651			<< "    gl_Position = vec4(positions[gl_VertexIndex % 3], pc.depth, 1.0);\n"
1652			<< "    vtxColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
1653			<< "}\n"
1654			;
1655		programCollection.glslSources.add("checkDepth-vert") << glu::VertexSource(vert.str());
1656	}
1657}
1658
1659TestInstance* AlphaToCoverageTest::createMultisampleTestInstance (Context&										context,
1660																  VkPrimitiveTopology							topology,
1661																  float											pointSize,
1662																  const std::vector<Vertex4RGBA>&				vertices,
1663																  const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
1664																  const VkPipelineColorBlendAttachmentState&	colorBlendState) const
1665{
1666	DE_UNREF(pointSize);
1667	return new AlphaToCoverageInstance(context, m_pipelineConstructionType, topology, vertices, multisampleStateParams, colorBlendState, m_geometryType, m_backingMode, m_useFragmentShadingRate, m_checkDepthBuffer);
1668}
1669
1670VkPipelineMultisampleStateCreateInfo AlphaToCoverageTest::getAlphaToCoverageStateParams (VkSampleCountFlagBits rasterizationSamples)
1671{
1672	const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
1673	{
1674		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
1675		DE_NULL,													// const void*								pNext;
1676		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
1677		rasterizationSamples,										// VkSampleCountFlagBits					rasterizationSamples;
1678		false,														// VkBool32									sampleShadingEnable;
1679		0.0f,														// float									minSampleShading;
1680		DE_NULL,													// const VkSampleMask*						pSampleMask;
1681		true,														// VkBool32									alphaToCoverageEnable;
1682		false														// VkBool32									alphaToOneEnable;
1683	};
1684
1685	return multisampleStateParams;
1686}
1687
1688// AlphaToCoverageNoColorAttachmentTest
1689
1690AlphaToCoverageNoColorAttachmentTest::AlphaToCoverageNoColorAttachmentTest (tcu::TestContext&				testContext,
1691																			const std::string&				name,
1692																			const PipelineConstructionType	pipelineConstructionType,
1693																			VkSampleCountFlagBits			rasterizationSamples,
1694																			GeometryType					geometryType,
1695																			ImageBackingMode				backingMode,
1696																			const bool						useFragmentShadingRate)
1697	: MultisampleTest	(testContext, name, pipelineConstructionType, getStateParams(rasterizationSamples), getDefaultColorBlendAttachmentState(), geometryType, 1.0f, backingMode, useFragmentShadingRate)
1698	, m_geometryType	(geometryType)
1699	, m_backingMode		(backingMode)
1700{
1701}
1702
1703TestInstance* AlphaToCoverageNoColorAttachmentTest::createMultisampleTestInstance (Context&										context,
1704																				   VkPrimitiveTopology							topology,
1705																				   float										pointSize,
1706																				   const std::vector<Vertex4RGBA>&				vertices,
1707																				   const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
1708																				   const VkPipelineColorBlendAttachmentState&	colorBlendState) const
1709{
1710	DE_UNREF(pointSize);
1711	return new AlphaToCoverageNoColorAttachmentInstance(context, m_pipelineConstructionType, topology, vertices, multisampleStateParams, colorBlendState, m_geometryType, m_backingMode, m_useFragmentShadingRate);
1712}
1713
1714VkPipelineMultisampleStateCreateInfo AlphaToCoverageNoColorAttachmentTest::getStateParams (VkSampleCountFlagBits rasterizationSamples)
1715{
1716	const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
1717	{
1718		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
1719		DE_NULL,													// const void*								pNext;
1720		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
1721		rasterizationSamples,										// VkSampleCountFlagBits					rasterizationSamples;
1722		false,														// VkBool32									sampleShadingEnable;
1723		0.0f,														// float									minSampleShading;
1724		DE_NULL,													// const VkSampleMask*						pSampleMask;
1725		true,														// VkBool32									alphaToCoverageEnable;
1726		false														// VkBool32									alphaToOneEnable;
1727	};
1728
1729	return multisampleStateParams;
1730}
1731
1732// AlphaToCoverageColorUnusedAttachmentTest
1733
1734AlphaToCoverageColorUnusedAttachmentTest::AlphaToCoverageColorUnusedAttachmentTest (tcu::TestContext&				testContext,
1735																					const std::string&				name,
1736																					const PipelineConstructionType	pipelineConstructionType,
1737																					VkSampleCountFlagBits			rasterizationSamples,
1738																					GeometryType					geometryType,
1739																					ImageBackingMode				backingMode,
1740																					const bool						useFragmentShadingRate)
1741	: MultisampleTest	(testContext, name, pipelineConstructionType, getStateParams(rasterizationSamples), getDefaultColorBlendAttachmentState(), geometryType, 1.0f, backingMode, useFragmentShadingRate)
1742	, m_geometryType	(geometryType)
1743	, m_backingMode		(backingMode)
1744{
1745}
1746
1747void AlphaToCoverageColorUnusedAttachmentTest::initPrograms (SourceCollections& programCollection) const
1748{
1749	initAlphaToCoverageColorUnusedAttachmentPrograms(programCollection);
1750}
1751
1752TestInstance* AlphaToCoverageColorUnusedAttachmentTest::createMultisampleTestInstance (Context&										context,
1753																					   VkPrimitiveTopology							topology,
1754																					   float										pointSize,
1755																					   const std::vector<Vertex4RGBA>&				vertices,
1756																					   const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
1757																					   const VkPipelineColorBlendAttachmentState&	colorBlendState) const
1758{
1759	DE_UNREF(pointSize);
1760	return new AlphaToCoverageColorUnusedAttachmentInstance(context, m_pipelineConstructionType, topology, vertices, multisampleStateParams, colorBlendState, m_geometryType, m_backingMode, m_useFragmentShadingRate);
1761}
1762
1763VkPipelineMultisampleStateCreateInfo AlphaToCoverageColorUnusedAttachmentTest::getStateParams (VkSampleCountFlagBits rasterizationSamples)
1764{
1765	const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
1766	{
1767		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
1768		DE_NULL,													// const void*								pNext;
1769		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
1770		rasterizationSamples,										// VkSampleCountFlagBits					rasterizationSamples;
1771		false,														// VkBool32									sampleShadingEnable;
1772		0.0f,														// float									minSampleShading;
1773		DE_NULL,													// const VkSampleMask*						pSampleMask;
1774		true,														// VkBool32									alphaToCoverageEnable;
1775		false														// VkBool32									alphaToOneEnable;
1776	};
1777
1778	return multisampleStateParams;
1779}
1780
1781// SampleMaskWithConservativeTest
1782SampleMaskWithConservativeTest::SampleMaskWithConservativeTest (tcu::TestContext&							testContext,
1783																const std::string&							name,
1784																const PipelineConstructionType				pipelineConstructionType,
1785																const VkSampleCountFlagBits					rasterizationSamples,
1786																const VkConservativeRasterizationModeEXT	conservativeRasterizationMode,
1787																const bool									enableMinSampleShading,
1788																const float									minSampleShading,
1789																const bool									enableSampleMask,
1790																const VkSampleMask							sampleMask,
1791																const bool									enablePostDepthCoverage,
1792																const bool									useFragmentShadingRate)
1793	: vkt::TestCase						(testContext, name)
1794	, m_pipelineConstructionType		(pipelineConstructionType)
1795	, m_rasterizationSamples			(rasterizationSamples)
1796	, m_enableMinSampleShading			(enableMinSampleShading)
1797	, m_minSampleShading				(minSampleShading)
1798	, m_enableSampleMask				(enableSampleMask)
1799	, m_sampleMask						(sampleMask)
1800	, m_conservativeRasterizationMode	(conservativeRasterizationMode)
1801	, m_enablePostDepthCoverage			(enablePostDepthCoverage)
1802	, m_renderType						(RENDER_TYPE_RESOLVE)
1803	, m_useFragmentShadingRate			(useFragmentShadingRate)
1804{
1805}
1806
1807void SampleMaskWithConservativeTest::checkSupport(Context& context) const
1808{
1809	if (!context.getDeviceProperties().limits.standardSampleLocations)
1810		TCU_THROW(NotSupportedError, "standardSampleLocations required");
1811
1812	if (m_useFragmentShadingRate && !checkFragmentShadingRateRequirements(context, m_rasterizationSamples))
1813		TCU_THROW(NotSupportedError, "Required FragmentShadingRate not supported");
1814
1815	context.requireDeviceFunctionality("VK_EXT_conservative_rasterization");
1816
1817	const auto&		conservativeRasterizationProperties	= context.getConservativeRasterizationPropertiesEXT();
1818	const deUint32	subPixelPrecisionBits				= context.getDeviceProperties().limits.subPixelPrecisionBits;
1819	const deUint32	subPixelPrecision					= (1 << subPixelPrecisionBits);
1820	const float		primitiveOverestimationSizeMult		= float(subPixelPrecision) * conservativeRasterizationProperties.primitiveOverestimationSize;
1821
1822	DE_ASSERT(subPixelPrecisionBits < sizeof(deUint32) * 8);
1823
1824	if (m_enablePostDepthCoverage)
1825	{
1826		context.requireDeviceFunctionality("VK_EXT_post_depth_coverage");
1827		if (!conservativeRasterizationProperties.conservativeRasterizationPostDepthCoverage)
1828			TCU_THROW(NotSupportedError, "conservativeRasterizationPostDepthCoverage not supported");
1829	}
1830
1831	context.getTestContext().getLog()
1832		<< tcu::TestLog::Message
1833		<< "maxExtraPrimitiveOverestimationSize=" << conservativeRasterizationProperties.maxExtraPrimitiveOverestimationSize << '\n'
1834		<< "extraPrimitiveOverestimationSizeGranularity=" << conservativeRasterizationProperties.extraPrimitiveOverestimationSizeGranularity << '\n'
1835		<< "degenerateTrianglesRasterized=" << conservativeRasterizationProperties.degenerateTrianglesRasterized << '\n'
1836		<< "primitiveOverestimationSize=" << conservativeRasterizationProperties.primitiveOverestimationSize << " (==" << primitiveOverestimationSizeMult << '/' << subPixelPrecision << ")\n"
1837		<< tcu::TestLog::EndMessage;
1838
1839
1840	if (m_conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT)
1841	{
1842		if (conservativeRasterizationProperties.extraPrimitiveOverestimationSizeGranularity > conservativeRasterizationProperties.maxExtraPrimitiveOverestimationSize)
1843			TCU_FAIL("Granularity cannot be greater than maximum extra size");
1844	}
1845	else if (m_conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT)
1846	{
1847		if (conservativeRasterizationProperties.primitiveUnderestimation == DE_FALSE)
1848			TCU_THROW(NotSupportedError, "Underestimation is not supported");
1849	}
1850	else
1851		TCU_THROW(InternalError, "Non-conservative mode tests are not supported by this class");
1852
1853	if (!conservativeRasterizationProperties.fullyCoveredFragmentShaderInputVariable)
1854	{
1855		TCU_THROW(NotSupportedError, "FullyCoveredEXT input variable is not supported");
1856	}
1857
1858	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
1859}
1860
1861void SampleMaskWithConservativeTest::initPrograms(SourceCollections& programCollection) const
1862{
1863	{
1864		DE_ASSERT((int)m_rasterizationSamples <= 32);
1865
1866		static const char* vertexSource =
1867			"#version 440\n"
1868			"layout(location = 0) in vec4 position;\n"
1869			"layout(location = 1) in vec4 color;\n"
1870			"layout(location = 0) out vec4 vtxColor;\n"
1871			"out gl_PerVertex\n"
1872			"{\n"
1873			"    vec4 gl_Position;\n"
1874			"};\n"
1875			"\n"
1876			"void main (void)\n"
1877			"{\n"
1878			"    gl_Position = position;\n"
1879			"    vtxColor = color;\n"
1880			"}\n";
1881
1882		std::ostringstream fragmentSource;
1883		fragmentSource <<
1884			"#version 440\n"
1885			<< (m_enablePostDepthCoverage ? "#extension GL_ARB_post_depth_coverage : require\n" : "")
1886			<< (m_conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT ? "#extension GL_NV_conservative_raster_underestimation : enable\n" : "") <<
1887			"layout(early_fragment_tests) in;\n"
1888			<< (m_enablePostDepthCoverage ? "layout(post_depth_coverage) in;\n" : "") <<
1889			"layout(location = 0) in vec4 vtxColor;\n"
1890			"layout(location = 0) out vec4 fragColor;\n"
1891			"void main (void)\n"
1892			"{\n";
1893			if (m_enableMinSampleShading)
1894			{
1895		fragmentSource <<
1896			"    const int coveredSamples = bitCount(gl_SampleMaskIn[0]);\n"
1897			"    fragColor = vtxColor * (1.0 / " << (int32_t)m_rasterizationSamples << " * coveredSamples);\n";
1898			}
1899			else if (m_conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT)
1900			{
1901		fragmentSource <<
1902			"    fragColor = gl_FragFullyCoveredNV ? vtxColor : vec4(0.0f);\n";
1903			}
1904			else
1905			{
1906		fragmentSource <<
1907			"    fragColor = vtxColor;\n";
1908			}
1909		fragmentSource <<
1910			"}\n";
1911
1912
1913		programCollection.glslSources.add("color_vert") << glu::VertexSource(vertexSource);
1914		programCollection.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource.str());
1915	}
1916
1917	{
1918		static const char* vertexSource =
1919			"#version 440\n"
1920			"void main (void)\n"
1921			"{\n"
1922			"	const vec4 positions[4] = vec4[4](\n"
1923			"		vec4(-1.0, -1.0, 0.0, 1.0),\n"
1924			"		vec4(-1.0,  1.0, 0.0, 1.0),\n"
1925			"		vec4( 1.0, -1.0, 0.0, 1.0),\n"
1926			"		vec4( 1.0,  1.0, 0.0, 1.0)\n"
1927			"	);\n"
1928			"	gl_Position = positions[gl_VertexIndex];\n"
1929			"}\n";
1930
1931
1932		static const char* fragmentSource =
1933			"#version 440\n"
1934			"precision highp float;\n"
1935			"layout(location = 0) out highp vec4 fragColor;\n"
1936			"layout(set = 0, binding = 0, input_attachment_index = 0) uniform subpassInputMS imageMS;\n"
1937			"layout(push_constant) uniform PushConstantsBlock\n"
1938			"{\n"
1939			"	int sampleId;\n"
1940			"} pushConstants;\n"
1941			"void main (void)\n"
1942			"{\n"
1943			"	fragColor = subpassLoad(imageMS, pushConstants.sampleId);\n"
1944			"}\n";
1945
1946		programCollection.glslSources.add("quad_vert") << glu::VertexSource(vertexSource);
1947		programCollection.glslSources.add("copy_sample_frag") << glu::FragmentSource(fragmentSource);
1948	}
1949}
1950
1951
1952TestInstance* SampleMaskWithConservativeTest::createInstance (Context& context) const
1953{
1954	return new SampleMaskWithConservativeInstance(context, m_pipelineConstructionType, m_rasterizationSamples, m_enableMinSampleShading, m_minSampleShading, m_enableSampleMask, m_sampleMask,
1955												  m_conservativeRasterizationMode, m_enablePostDepthCoverage, true, m_renderType, m_useFragmentShadingRate);
1956}
1957
1958// SampleMaskWithDepthTestTest
1959#ifndef CTS_USES_VULKANSC
1960SampleMaskWithDepthTestTest::SampleMaskWithDepthTestTest (tcu::TestContext&					testContext,
1961														  const std::string&				name,
1962														  const PipelineConstructionType	pipelineConstructionType,
1963														  const VkSampleCountFlagBits		rasterizationSamples,
1964														  const bool						enablePostDepthCoverage,
1965														  const bool						useFragmentShadingRate)
1966	: vkt::TestCase					(testContext, name)
1967	, m_pipelineConstructionType	(pipelineConstructionType)
1968	, m_rasterizationSamples		(rasterizationSamples)
1969	, m_enablePostDepthCoverage		(enablePostDepthCoverage)
1970	, m_useFragmentShadingRate		(useFragmentShadingRate)
1971{
1972}
1973
1974void SampleMaskWithDepthTestTest::checkSupport (Context& context) const
1975{
1976	if (!context.getDeviceProperties().limits.standardSampleLocations)
1977		TCU_THROW(NotSupportedError, "standardSampleLocations required");
1978
1979	context.requireDeviceFunctionality("VK_EXT_post_depth_coverage");
1980
1981	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
1982
1983	if (m_useFragmentShadingRate)
1984	{
1985		if (!context.getFragmentShadingRateProperties().fragmentShadingRateWithShaderSampleMask)
1986			TCU_THROW(NotSupportedError, "fragmentShadingRateWithShaderSampleMask not supported");
1987
1988		if (!checkFragmentShadingRateRequirements(context, m_rasterizationSamples))
1989			TCU_THROW(NotSupportedError, "Required FragmentShadingRate not supported");
1990	}
1991}
1992
1993void SampleMaskWithDepthTestTest::initPrograms (SourceCollections& programCollection) const
1994{
1995	DE_ASSERT((int)m_rasterizationSamples <= 32);
1996
1997	static const char* vertexSource =
1998		"#version 440\n"
1999		"layout(location = 0) in vec4 position;\n"
2000		"layout(location = 1) in vec4 color;\n"
2001		"layout(location = 0) out vec4 vtxColor;\n"
2002		"out gl_PerVertex\n"
2003		"{\n"
2004		"    vec4 gl_Position;\n"
2005		"};\n"
2006		"\n"
2007		"void main (void)\n"
2008		"{\n"
2009		"    gl_Position = position;\n"
2010		"    vtxColor = color;\n"
2011		"}\n";
2012
2013	uint32_t samplesPerFragment = m_rasterizationSamples;
2014	if (m_useFragmentShadingRate)
2015	{
2016		// When FSR coverage is enabled the tests uses a pipeline FSR rate of {2,2},
2017		// which means each fragment shader invocation covers 4 pixels.
2018		samplesPerFragment *= 4;
2019
2020		if (!m_enablePostDepthCoverage)
2021			// For the 4 specific pixels this tests verifies, the primitive
2022			// drawn by the test fully covers 3 of those pixels and
2023			// partially covers 1 of them. When the fragment shader executes
2024			// for those 4 pixels the non-PostDepthCoverage sample mask
2025			// (the sample mask before the depth test) will only have
2026			// 7/8 of the samples set since the last 1/8 is not even covered
2027			// by the primitive.
2028			samplesPerFragment -= m_rasterizationSamples / 2;
2029	}
2030
2031	std::ostringstream fragmentSource;
2032	fragmentSource <<
2033		"#version 440\n"
2034		<< (m_enablePostDepthCoverage ? "#extension GL_ARB_post_depth_coverage : require\n" : "") <<
2035		"layout(early_fragment_tests) in;\n"
2036		<< (m_enablePostDepthCoverage ? "layout(post_depth_coverage) in;\n" : "") <<
2037		"layout(location = 0) in vec4 vtxColor;\n"
2038		"layout(location = 0) out vec4 fragColor;\n"
2039		"void main (void)\n"
2040		"{\n"
2041		"    const int coveredSamples = bitCount(gl_SampleMaskIn[0]);\n"
2042		"    fragColor = vtxColor * (1.0 / " << samplesPerFragment << " * coveredSamples);\n"
2043		"}\n";
2044
2045	programCollection.glslSources.add("color_vert") << glu::VertexSource(vertexSource);
2046	programCollection.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource.str());
2047}
2048
2049TestInstance* SampleMaskWithDepthTestTest::createInstance (Context& context) const
2050{
2051	return new SampleMaskWithDepthTestInstance(context, m_pipelineConstructionType, m_rasterizationSamples, m_enablePostDepthCoverage, m_useFragmentShadingRate);
2052}
2053#endif // CTS_USES_VULKANSC
2054
2055// RasterizationSamplesInstance
2056
2057RasterizationSamplesInstance::RasterizationSamplesInstance (Context&										context,
2058															PipelineConstructionType						pipelineConstructionType,
2059															VkPrimitiveTopology								topology,
2060															float											pointSize,
2061															const std::vector<Vertex4RGBA>&					vertices,
2062															const VkPipelineMultisampleStateCreateInfo&		multisampleStateParams,
2063															const VkPipelineColorBlendAttachmentState&		blendState,
2064															const TestModeFlags								modeFlags,
2065															ImageBackingMode								backingMode,
2066															const bool										useFragmentShadingRate)
2067	: vkt::TestInstance				(context)
2068	, m_colorFormat					(VK_FORMAT_R8G8B8A8_UNORM)
2069	, m_renderSize					(32, 32)
2070	, m_primitiveTopology			(topology)
2071	, m_pointSize					(pointSize)
2072	, m_vertices					(vertices)
2073	, m_fullQuadVertices			(generateVertices(GEOMETRY_TYPE_OPAQUE_QUAD_NONZERO_DEPTH))
2074	, m_modeFlags					(modeFlags)
2075	, m_useFragmentShadingRate		(useFragmentShadingRate)
2076{
2077	if (m_modeFlags != 0)
2078	{
2079		const bool		useDepth			= (m_modeFlags & TEST_MODE_DEPTH_BIT) != 0;
2080		const bool		useStencil			= (m_modeFlags & TEST_MODE_STENCIL_BIT) != 0;
2081		const VkFormat	depthStencilFormat	= findSupportedDepthStencilFormat(context, useDepth, useStencil);
2082
2083		if (depthStencilFormat == VK_FORMAT_UNDEFINED)
2084			TCU_THROW(NotSupportedError, "Required depth/stencil format is not supported");
2085
2086		const VkPrimitiveTopology		pTopology[2] = { m_primitiveTopology, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP };
2087		const std::vector<Vertex4RGBA>	pVertices[2] = { m_vertices, m_fullQuadVertices };
2088
2089		m_multisampleRenderer = de::MovePtr<MultisampleRenderer>(
2090			new MultisampleRenderer(
2091				context, pipelineConstructionType, m_colorFormat, depthStencilFormat, m_renderSize, useDepth, useStencil,
2092				2u, pTopology, pVertices, multisampleStateParams, blendState, RENDER_TYPE_RESOLVE, backingMode, m_useFragmentShadingRate));
2093	}
2094	else
2095	{
2096		m_multisampleRenderer = de::MovePtr<MultisampleRenderer>(
2097			new MultisampleRenderer(
2098				context, pipelineConstructionType, m_colorFormat, m_renderSize, topology, vertices, multisampleStateParams,
2099				blendState, RENDER_TYPE_RESOLVE, backingMode, m_useFragmentShadingRate));
2100	}
2101}
2102
2103tcu::TestStatus RasterizationSamplesInstance::iterate (void)
2104{
2105	de::MovePtr<tcu::TextureLevel> level(m_multisampleRenderer->render());
2106	return verifyImage(level->getAccess());
2107}
2108
2109tcu::TestStatus RasterizationSamplesInstance::verifyImage (const tcu::ConstPixelBufferAccess& result)
2110{
2111	// Verify range of unique pixels
2112	{
2113		const deUint32	numUniqueColors = getUniqueColorsCount(result);
2114		const deUint32	minUniqueColors	= (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST && m_pointSize == 1.0f) ? 2 : 3;
2115
2116		tcu::TestLog& log = m_context.getTestContext().getLog();
2117
2118		log << tcu::TestLog::Message
2119			<< "\nMin. unique colors expected: " << minUniqueColors << "\n"
2120			<< "Unique colors found: " << numUniqueColors << "\n"
2121			<< tcu::TestLog::EndMessage;
2122
2123		if (numUniqueColors < minUniqueColors)
2124			return tcu::TestStatus::fail("Unique colors out of expected bounds");
2125	}
2126
2127	// Verify shape of the rendered primitive (fuzzy-compare)
2128	{
2129		const tcu::TextureFormat	tcuColorFormat	= mapVkFormat(m_colorFormat);
2130		const tcu::TextureFormat	tcuDepthFormat	= tcu::TextureFormat();
2131		const ColorVertexShader		vertexShader;
2132		const ColorFragmentShader	fragmentShader	(tcuColorFormat, tcuDepthFormat);
2133		const rr::Program			program			(&vertexShader, &fragmentShader);
2134		ReferenceRenderer			refRenderer		(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
2135		rr::RenderState				renderState		(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
2136
2137		if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
2138		{
2139			VkPhysicalDeviceProperties deviceProperties;
2140
2141			m_context.getInstanceInterface().getPhysicalDeviceProperties(m_context.getPhysicalDevice(), &deviceProperties);
2142
2143			// gl_PointSize is clamped to pointSizeRange
2144			renderState.point.pointSize = deFloatMin(m_pointSize, deviceProperties.limits.pointSizeRange[1]);
2145		}
2146
2147		if (m_modeFlags == 0)
2148		{
2149			refRenderer.colorClear(tcu::Vec4(0.0f));
2150			refRenderer.draw(renderState, mapVkPrimitiveTopology(m_primitiveTopology), m_vertices);
2151		}
2152		else
2153		{
2154			// For depth/stencil case the primitive is invisible and the surroundings are filled red.
2155			refRenderer.colorClear(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
2156			refRenderer.draw(renderState, mapVkPrimitiveTopology(m_primitiveTopology), m_vertices);
2157		}
2158
2159		if (!tcu::fuzzyCompare(m_context.getTestContext().getLog(), "FuzzyImageCompare", "Image comparison", refRenderer.getAccess(), result, 0.05f, tcu::COMPARE_LOG_RESULT))
2160			return tcu::TestStatus::fail("Primitive has unexpected shape");
2161	}
2162
2163	return tcu::TestStatus::pass("Primitive rendered, unique colors within expected bounds");
2164}
2165
2166
2167// MinSampleShadingInstance
2168
2169MinSampleShadingInstance::MinSampleShadingInstance (Context&									context,
2170													const PipelineConstructionType				pipelineConstructionType,
2171													VkPrimitiveTopology							topology,
2172													float										pointSize,
2173													const std::vector<Vertex4RGBA>&				vertices,
2174													const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
2175													const VkPipelineColorBlendAttachmentState&	colorBlendState,
2176													ImageBackingMode							backingMode,
2177													const bool									useFragmentShadingRate)
2178	: vkt::TestInstance			(context)
2179	, m_pipelineConstructionType(pipelineConstructionType)
2180	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
2181	, m_renderSize				(32, 32)
2182	, m_primitiveTopology		(topology)
2183	, m_vertices				(vertices)
2184	, m_multisampleStateParams	(multisampleStateParams)
2185	, m_colorBlendState			(colorBlendState)
2186	, m_backingMode				(backingMode)
2187	, m_useFragmentShadingRate	(useFragmentShadingRate)
2188{
2189	DE_UNREF(pointSize);
2190}
2191
2192tcu::TestStatus MinSampleShadingInstance::iterate (void)
2193{
2194	de::MovePtr<tcu::TextureLevel>	noSampleshadingImage;
2195	std::vector<tcu::TextureLevel>	sampleShadedImages;
2196
2197	// Render and resolve without sample shading
2198	{
2199		VkPipelineMultisampleStateCreateInfo multisampleStateParms = m_multisampleStateParams;
2200		multisampleStateParms.sampleShadingEnable	= VK_FALSE;
2201		multisampleStateParms.minSampleShading		= 0.0;
2202
2203		MultisampleRenderer renderer (m_context, m_pipelineConstructionType, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleStateParms, m_colorBlendState, RENDER_TYPE_RESOLVE, m_backingMode, m_useFragmentShadingRate);
2204		noSampleshadingImage  = renderer.render();
2205	}
2206
2207	// Render with test minSampleShading and collect per-sample images
2208	{
2209		MultisampleRenderer renderer (m_context, m_pipelineConstructionType, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState, RENDER_TYPE_COPY_SAMPLES, m_backingMode, m_useFragmentShadingRate);
2210		renderer.render();
2211
2212		sampleShadedImages.resize(m_multisampleStateParams.rasterizationSamples);
2213		for (deUint32 sampleId = 0; sampleId < sampleShadedImages.size(); sampleId++)
2214		{
2215			sampleShadedImages[sampleId] = *renderer.getSingleSampledImage(sampleId);
2216		}
2217	}
2218
2219	// Log images
2220	{
2221		tcu::TestLog& testLog	= m_context.getTestContext().getLog();
2222
2223		testLog << tcu::TestLog::ImageSet("Images", "Images")
2224				<< tcu::TestLog::Image("noSampleshadingImage", "Image rendered without sample shading", noSampleshadingImage->getAccess());
2225
2226		for (deUint32 sampleId = 0; sampleId < sampleShadedImages.size(); sampleId++)
2227		{
2228			testLog << tcu::TestLog::Image("sampleShadedImage", "One sample of sample shaded image", sampleShadedImages[sampleId].getAccess());
2229		}
2230		testLog << tcu::TestLog::EndImageSet;
2231	}
2232
2233	return verifySampleShadedImage(sampleShadedImages, noSampleshadingImage->getAccess());
2234}
2235
2236tcu::TestStatus MinSampleShadingInstance::verifySampleShadedImage (const std::vector<tcu::TextureLevel>& sampleShadedImages, const tcu::ConstPixelBufferAccess& noSampleshadingImage)
2237{
2238	const deUint32	pixelCount	= noSampleshadingImage.getWidth() * noSampleshadingImage.getHeight() * noSampleshadingImage.getDepth();
2239
2240	bool anyPixelCovered		= false;
2241
2242	for (deUint32 pixelNdx = 0; pixelNdx < pixelCount; pixelNdx++)
2243	{
2244		const deUint32 noSampleShadingValue = *((const deUint32*)noSampleshadingImage.getDataPtr() + pixelNdx);
2245
2246		if (noSampleShadingValue == 0)
2247		{
2248			// non-covered pixel, continue
2249			continue;
2250		}
2251		else
2252		{
2253			anyPixelCovered = true;
2254		}
2255
2256		int numNotCoveredSamples = 0;
2257
2258		std::map<deUint32, deUint32>	histogram; // map<pixel value, number of occurrences>
2259
2260		// Collect histogram of occurrences or each pixel across all samples
2261		for (size_t i = 0; i < sampleShadedImages.size(); ++i)
2262		{
2263			const deUint32 sampleShadedValue = *((const deUint32*)sampleShadedImages[i].getAccess().getDataPtr() + pixelNdx);
2264
2265			if (sampleShadedValue == 0)
2266			{
2267				numNotCoveredSamples++;
2268				continue;
2269			}
2270
2271			if (histogram.find(sampleShadedValue) != histogram.end())
2272				histogram[sampleShadedValue]++;
2273			else
2274				histogram[sampleShadedValue] = 1;
2275		}
2276
2277		if (numNotCoveredSamples == static_cast<int>(sampleShadedImages.size()))
2278		{
2279			return tcu::TestStatus::fail("Got uncovered pixel, where covered samples were expected");
2280		}
2281
2282		const int uniqueColorsCount				= (int)histogram.size();
2283		const int expectedUniqueSamplesCount	= static_cast<int>(m_multisampleStateParams.minSampleShading * static_cast<float>(sampleShadedImages.size()) + 0.5f);
2284
2285		if (uniqueColorsCount + numNotCoveredSamples < expectedUniqueSamplesCount)
2286		{
2287			return tcu::TestStatus::fail("Got less unique colors than requested through minSampleShading");
2288		}
2289	}
2290
2291	if (!anyPixelCovered)
2292	{
2293		return tcu::TestStatus::fail("Did not get any covered pixel, cannot test minSampleShading");
2294	}
2295
2296	return tcu::TestStatus::pass("Got proper count of unique colors");
2297}
2298
2299MinSampleShadingDisabledInstance::MinSampleShadingDisabledInstance	(Context&										context,
2300																	 const PipelineConstructionType					pipelineConstructionType,
2301																	 VkPrimitiveTopology							topology,
2302																	 float											pointSize,
2303																	 const std::vector<Vertex4RGBA>&				vertices,
2304																	 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
2305																	 const VkPipelineColorBlendAttachmentState&		blendState,
2306																	 ImageBackingMode								backingMode,
2307																	 const bool										useFragmentShadingRate)
2308	: MinSampleShadingInstance	(context, pipelineConstructionType, topology, pointSize, vertices, multisampleStateParams, blendState, backingMode, useFragmentShadingRate)
2309{
2310}
2311
2312tcu::TestStatus MinSampleShadingDisabledInstance::verifySampleShadedImage	(const std::vector<tcu::TextureLevel>&	sampleShadedImages,
2313																			 const tcu::ConstPixelBufferAccess&		noSampleshadingImage)
2314{
2315	const deUint32		samplesCount		= (int)sampleShadedImages.size();
2316	const deUint32		width				= noSampleshadingImage.getWidth();
2317	const deUint32		height				= noSampleshadingImage.getHeight();
2318	const deUint32		depth				= noSampleshadingImage.getDepth();
2319	const tcu::UVec4	zeroPixel			= tcu::UVec4();
2320	bool				anyPixelCovered		= false;
2321
2322	DE_ASSERT(depth == 1);
2323	DE_UNREF(depth);
2324
2325	for (deUint32 y = 0; y < height; ++y)
2326	for (deUint32 x = 0; x < width; ++x)
2327	{
2328		const tcu::UVec4	noSampleShadingValue	= noSampleshadingImage.getPixelUint(x, y);
2329
2330		if (noSampleShadingValue == zeroPixel)
2331			continue;
2332
2333		anyPixelCovered = true;
2334		tcu::UVec4	sampleShadingValue	= tcu::UVec4();
2335
2336		// Collect histogram of occurrences or each pixel across all samples
2337		for (size_t i = 0; i < samplesCount; ++i)
2338		{
2339			const tcu::UVec4	sampleShadedValue	= sampleShadedImages[i].getAccess().getPixelUint(x, y);
2340
2341			sampleShadingValue += sampleShadedValue;
2342		}
2343
2344		sampleShadingValue = sampleShadingValue / samplesCount;
2345
2346		if (sampleShadingValue.w() != 255)
2347		{
2348			return tcu::TestStatus::fail("Invalid Alpha channel value");
2349		}
2350
2351		if (sampleShadingValue != noSampleShadingValue)
2352		{
2353			return tcu::TestStatus::fail("Invalid color");
2354		}
2355	}
2356
2357	if (!anyPixelCovered)
2358	{
2359		return tcu::TestStatus::fail("Did not get any covered pixel, cannot test minSampleShadingDisabled");
2360	}
2361
2362	return tcu::TestStatus::pass("Got proper count of unique colors");
2363}
2364
2365SampleMaskInstance::SampleMaskInstance (Context&										context,
2366										const PipelineConstructionType					pipelineConstructionType,
2367										VkPrimitiveTopology								topology,
2368										float											pointSize,
2369										const std::vector<Vertex4RGBA>&					vertices,
2370										const VkPipelineMultisampleStateCreateInfo&		multisampleStateParams,
2371										const VkPipelineColorBlendAttachmentState&		blendState,
2372										ImageBackingMode								backingMode,
2373										const bool										useFragmentShadingRate)
2374	: vkt::TestInstance			(context)
2375	, m_pipelineConstructionType(pipelineConstructionType)
2376	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
2377	, m_renderSize				(32, 32)
2378	, m_primitiveTopology		(topology)
2379	, m_vertices				(vertices)
2380	, m_multisampleStateParams	(multisampleStateParams)
2381	, m_colorBlendState			(blendState)
2382	, m_backingMode				(backingMode)
2383	, m_useFragmentShadingRate	(useFragmentShadingRate)
2384{
2385	DE_UNREF(pointSize);
2386}
2387
2388tcu::TestStatus SampleMaskInstance::iterate (void)
2389{
2390	de::MovePtr<tcu::TextureLevel>				testSampleMaskImage;
2391	de::MovePtr<tcu::TextureLevel>				minSampleMaskImage;
2392	de::MovePtr<tcu::TextureLevel>				maxSampleMaskImage;
2393
2394	// Render with test flags
2395	{
2396		MultisampleRenderer renderer (m_context, m_pipelineConstructionType, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState, RENDER_TYPE_RESOLVE, m_backingMode, m_useFragmentShadingRate);
2397		testSampleMaskImage = renderer.render();
2398	}
2399
2400	// Render with all flags off
2401	{
2402		VkPipelineMultisampleStateCreateInfo	multisampleParams	= m_multisampleStateParams;
2403		const std::vector<VkSampleMask>			sampleMask			(multisampleParams.rasterizationSamples / 32, (VkSampleMask)0);
2404
2405		multisampleParams.pSampleMask = sampleMask.data();
2406
2407		MultisampleRenderer renderer (m_context, m_pipelineConstructionType, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState, RENDER_TYPE_RESOLVE, m_backingMode, m_useFragmentShadingRate);
2408		minSampleMaskImage = renderer.render();
2409	}
2410
2411	// Render with all flags on
2412	{
2413		VkPipelineMultisampleStateCreateInfo	multisampleParams	= m_multisampleStateParams;
2414		const std::vector<VkSampleMask>			sampleMask			(multisampleParams.rasterizationSamples / 32, ~((VkSampleMask)0));
2415
2416		multisampleParams.pSampleMask = sampleMask.data();
2417
2418		MultisampleRenderer renderer (m_context, m_pipelineConstructionType, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState, RENDER_TYPE_RESOLVE, m_backingMode, m_useFragmentShadingRate);
2419		maxSampleMaskImage = renderer.render();
2420	}
2421
2422	return verifyImage(testSampleMaskImage->getAccess(), minSampleMaskImage->getAccess(), maxSampleMaskImage->getAccess());
2423}
2424
2425tcu::TestStatus SampleMaskInstance::verifyImage (const tcu::ConstPixelBufferAccess& testSampleMaskImage,
2426												 const tcu::ConstPixelBufferAccess& minSampleMaskImage,
2427												 const tcu::ConstPixelBufferAccess& maxSampleMaskImage)
2428{
2429	const deUint32	testColorCount	= getUniqueColorsCount(testSampleMaskImage);
2430	const deUint32	minColorCount	= getUniqueColorsCount(minSampleMaskImage);
2431	const deUint32	maxColorCount	= getUniqueColorsCount(maxSampleMaskImage);
2432
2433	tcu::TestLog& log = m_context.getTestContext().getLog();
2434
2435	log << tcu::TestLog::Message
2436		<< "\nColors found: " << testColorCount << "\n"
2437		<< "Min. colors expected: " << minColorCount << "\n"
2438		<< "Max. colors expected: " << maxColorCount << "\n"
2439		<< tcu::TestLog::EndMessage;
2440
2441	if (minColorCount > testColorCount || testColorCount > maxColorCount)
2442		return tcu::TestStatus::fail("Unique colors out of expected bounds");
2443	else
2444		return tcu::TestStatus::pass("Unique colors within expected bounds");
2445}
2446#ifndef CTS_USES_VULKANSC
2447tcu::TestStatus testRasterSamplesConsistency (Context& context, MultisampleTestParams params)
2448{
2449	const VkSampleCountFlagBits samples[] =
2450	{
2451		VK_SAMPLE_COUNT_1_BIT,
2452		VK_SAMPLE_COUNT_2_BIT,
2453		VK_SAMPLE_COUNT_4_BIT,
2454		VK_SAMPLE_COUNT_8_BIT,
2455		VK_SAMPLE_COUNT_16_BIT,
2456		VK_SAMPLE_COUNT_32_BIT,
2457		VK_SAMPLE_COUNT_64_BIT
2458	};
2459
2460	const Vertex4RGBA vertexData[3] =
2461	{
2462		{
2463			tcu::Vec4(-0.75f, 0.0f, 0.0f, 1.0f),
2464			tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
2465		},
2466		{
2467			tcu::Vec4(0.75f, 0.125f, 0.0f, 1.0f),
2468			tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
2469		},
2470		{
2471			tcu::Vec4(0.75f, -0.125f, 0.0f, 1.0f),
2472			tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)
2473		}
2474	};
2475
2476	const std::vector<Vertex4RGBA>	vertices			(vertexData, vertexData + 3);
2477	deUint32						prevUniqueColors	= 2;
2478	int								renderCount			= 0;
2479
2480	// Do not render with 1 sample (start with samplesNdx = 1).
2481	for (int samplesNdx = 1; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
2482	{
2483		if (!isSupportedSampleCount(context.getInstanceInterface(), context.getPhysicalDevice(), samples[samplesNdx]))
2484			continue;
2485
2486		if (params.useFragmentShadingRate && !checkFragmentShadingRateRequirements(context, samples[samplesNdx]))
2487			continue;
2488
2489		const VkPipelineMultisampleStateCreateInfo multisampleStateParams
2490		{
2491			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
2492			DE_NULL,													// const void*								pNext;
2493			0u,															// VkPipelineMultisampleStateCreateFlags	flags;
2494			samples[samplesNdx],										// VkSampleCountFlagBits					rasterizationSamples;
2495			false,														// VkBool32									sampleShadingEnable;
2496			0.0f,														// float									minSampleShading;
2497			DE_NULL,													// const VkSampleMask*						pSampleMask;
2498			false,														// VkBool32									alphaToCoverageEnable;
2499			false														// VkBool32									alphaToOneEnable;
2500		};
2501
2502		MultisampleRenderer				renderer		(context, params.pipelineConstructionType, VK_FORMAT_R8G8B8A8_UNORM, tcu::IVec2(32, 32), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, vertices, multisampleStateParams, getDefaultColorBlendAttachmentState(), RENDER_TYPE_RESOLVE, params.backingMode, params.useFragmentShadingRate);
2503		de::MovePtr<tcu::TextureLevel>	result			= renderer.render();
2504		const deUint32					uniqueColors	= getUniqueColorsCount(result->getAccess());
2505
2506		renderCount++;
2507
2508		if (prevUniqueColors > uniqueColors)
2509		{
2510			std::ostringstream message;
2511
2512			message << "More unique colors generated with " << samples[samplesNdx - 1] << " than with " << samples[samplesNdx];
2513			return tcu::TestStatus::fail(message.str());
2514		}
2515
2516		prevUniqueColors = uniqueColors;
2517	}
2518
2519	if (renderCount == 0)
2520	{
2521		if (params.useFragmentShadingRate && !context.getFragmentShadingRateFeatures().pipelineFragmentShadingRate)
2522			TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate is unsupported");
2523		TCU_THROW(NotSupportedError, "Multisampling is unsupported");
2524	}
2525
2526	return tcu::TestStatus::pass("Number of unique colors increases as the sample count increases");
2527}
2528#endif // CTS_USES_VULKANSC
2529
2530// AlphaToOneInstance
2531
2532AlphaToOneInstance::AlphaToOneInstance (Context&									context,
2533										const PipelineConstructionType				pipelineConstructionType,
2534										VkPrimitiveTopology							topology,
2535										const std::vector<Vertex4RGBA>&				vertices,
2536										const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
2537										const VkPipelineColorBlendAttachmentState&	blendState,
2538										ImageBackingMode							backingMode,
2539										const bool									useFragmentShadingRate)
2540	: vkt::TestInstance			(context)
2541	, m_pipelineConstructionType(pipelineConstructionType)
2542	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
2543	, m_renderSize				(32, 32)
2544	, m_primitiveTopology		(topology)
2545	, m_vertices				(vertices)
2546	, m_multisampleStateParams	(multisampleStateParams)
2547	, m_colorBlendState			(blendState)
2548	, m_backingMode				(backingMode)
2549	, m_useFragmentShadingRate	(useFragmentShadingRate)
2550{
2551}
2552
2553tcu::TestStatus AlphaToOneInstance::iterate	(void)
2554{
2555	DE_ASSERT(m_multisampleStateParams.alphaToOneEnable);
2556	DE_ASSERT(m_colorBlendState.blendEnable);
2557
2558	de::MovePtr<tcu::TextureLevel>	alphaOneImage;
2559	de::MovePtr<tcu::TextureLevel>	noAlphaOneImage;
2560
2561	RenderType renderType = m_multisampleStateParams.rasterizationSamples == vk::VK_SAMPLE_COUNT_1_BIT ? RENDER_TYPE_SINGLE_SAMPLE : RENDER_TYPE_RESOLVE;
2562
2563	// Render with blend enabled and alpha to one on
2564	{
2565		MultisampleRenderer renderer (m_context, m_pipelineConstructionType, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState, renderType, m_backingMode, m_useFragmentShadingRate);
2566		alphaOneImage = renderer.render();
2567	}
2568
2569	// Render with blend enabled and alpha to one off
2570	{
2571		VkPipelineMultisampleStateCreateInfo	multisampleParams	= m_multisampleStateParams;
2572		multisampleParams.alphaToOneEnable = false;
2573
2574		MultisampleRenderer renderer (m_context, m_pipelineConstructionType, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState, renderType, m_backingMode, m_useFragmentShadingRate);
2575		noAlphaOneImage = renderer.render();
2576	}
2577
2578	return verifyImage(alphaOneImage->getAccess(), noAlphaOneImage->getAccess());
2579}
2580
2581tcu::TestStatus AlphaToOneInstance::verifyImage (const tcu::ConstPixelBufferAccess&	alphaOneImage,
2582												 const tcu::ConstPixelBufferAccess&	noAlphaOneImage)
2583{
2584	for (int y = 0; y < m_renderSize.y(); y++)
2585	{
2586		for (int x = 0; x < m_renderSize.x(); x++)
2587		{
2588			if (alphaOneImage.getPixel(x, y).w() != 1.0)
2589			{
2590				std::ostringstream message;
2591				message << "Unsatisfied condition: " << alphaOneImage.getPixel(x, y) << " doesn't have alpha set to 1";
2592				return tcu::TestStatus::fail(message.str());
2593			}
2594
2595			if (!tcu::boolAll(tcu::greaterThanEqual(alphaOneImage.getPixel(x, y), noAlphaOneImage.getPixel(x, y))))
2596			{
2597				std::ostringstream message;
2598				message << "Unsatisfied condition: " << alphaOneImage.getPixel(x, y) << " >= " << noAlphaOneImage.getPixel(x, y);
2599				return tcu::TestStatus::fail(message.str());
2600			}
2601		}
2602	}
2603
2604	return tcu::TestStatus::pass("Image rendered with alpha-to-one contains pixels of image rendered with no alpha-to-one");
2605}
2606
2607
2608// AlphaToCoverageInstance
2609
2610AlphaToCoverageInstance::AlphaToCoverageInstance (Context&										context,
2611												  const PipelineConstructionType				pipelineConstructionType,
2612												  VkPrimitiveTopology							topology,
2613												  const std::vector<Vertex4RGBA>&				vertices,
2614												  const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
2615												  const VkPipelineColorBlendAttachmentState&	blendState,
2616												  GeometryType									geometryType,
2617												  ImageBackingMode								backingMode,
2618												  const bool									useFragmentShadingRate,
2619												  const bool									checkDepthBuffer)
2620	: vkt::TestInstance			(context)
2621	, m_pipelineConstructionType(pipelineConstructionType)
2622	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
2623	, m_depthStencilFormat		(VK_FORMAT_D16_UNORM)
2624	, m_renderSize				(32, 32)
2625	, m_primitiveTopology		(topology)
2626	, m_vertices				(vertices)
2627	, m_multisampleStateParams	(multisampleStateParams)
2628	, m_colorBlendState			(blendState)
2629	, m_geometryType			(geometryType)
2630	, m_backingMode				(backingMode)
2631	, m_useFragmentShadingRate	(useFragmentShadingRate)
2632	, m_checkDepthBuffer		(checkDepthBuffer)
2633{
2634}
2635
2636tcu::TestStatus AlphaToCoverageInstance::iterate (void)
2637{
2638	DE_ASSERT(m_multisampleStateParams.alphaToCoverageEnable);
2639
2640	de::MovePtr<tcu::TextureLevel>	result;
2641	MultisampleRenderer				renderer	(m_context, m_pipelineConstructionType, m_colorFormat, m_depthStencilFormat, m_renderSize, m_checkDepthBuffer, false, 1u, &m_primitiveTopology, &m_vertices, m_multisampleStateParams, m_colorBlendState, RENDER_TYPE_RESOLVE, m_backingMode, m_useFragmentShadingRate);
2642
2643	result = renderer.render();
2644
2645	const auto colorStatus = verifyImage(result->getAccess());
2646	auto depthStatus = tcu::TestStatus::pass("Pass");
2647
2648	if (m_checkDepthBuffer)
2649	{
2650		const auto redrawResult	= renderer.renderReusingDepth();
2651		depthStatus				= verifyDepthBufferCheck(redrawResult->getAccess());
2652	}
2653
2654	if (colorStatus.getCode() == QP_TEST_RESULT_FAIL)
2655		return colorStatus;
2656
2657	if (depthStatus.getCode() == QP_TEST_RESULT_FAIL)
2658		return depthStatus;
2659
2660	return colorStatus;
2661}
2662
2663tcu::TestStatus AlphaToCoverageInstance::verifyDepthBufferCheck (const tcu::ConstPixelBufferAccess& result)
2664{
2665	const tcu::Vec4 refColor	(0.0f, 0.0f, 1.0f, 1.0f); // Must match "checkDepth-vert".
2666	const tcu::Vec4 threshold	(0.0f, 0.0f, 0.0f, 0.0f);
2667
2668	if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "BlueColor", "", refColor, result, threshold, tcu::COMPARE_LOG_ON_ERROR))
2669		return tcu::TestStatus::fail("Depth buffer verification failed: depth buffer was not clear");
2670	return tcu::TestStatus::pass("Pass");
2671}
2672
2673tcu::TestStatus AlphaToCoverageInstance::verifyImage (const tcu::ConstPixelBufferAccess&	result)
2674{
2675	float maxColorValue;
2676	float minColorValue;
2677
2678	switch (m_geometryType)
2679	{
2680		case GEOMETRY_TYPE_OPAQUE_QUAD:
2681			maxColorValue = 1.01f;
2682			minColorValue = 0.99f;
2683			break;
2684
2685		case GEOMETRY_TYPE_TRANSLUCENT_QUAD:
2686			maxColorValue = 0.52f;
2687			minColorValue = 0.0f;
2688			break;
2689
2690		case GEOMETRY_TYPE_INVISIBLE_QUAD:
2691			maxColorValue = 0.01f;
2692			minColorValue = 0.0f;
2693			break;
2694
2695		default:
2696			maxColorValue = 0.0f;
2697			minColorValue = 0.0f;
2698			DE_ASSERT(false);
2699	}
2700
2701	auto& log = m_context.getTestContext().getLog();
2702	log << tcu::TestLog::Image("Result", "Result Image", result);
2703
2704	for (int y = 0; y < m_renderSize.y(); y++)
2705	{
2706		for (int x = 0; x < m_renderSize.x(); x++)
2707		{
2708			const auto pixel	= result.getPixel(x, y);
2709			const auto red		= pixel.x();
2710
2711			if (red > maxColorValue || red < minColorValue)
2712			{
2713				std::ostringstream message;
2714				message << "Pixel is not in the expected range: " << red << " not in [" << minColorValue << ", " << maxColorValue << "]";
2715				return tcu::TestStatus::fail(message.str());
2716			}
2717		}
2718	}
2719
2720	return tcu::TestStatus::pass("Image matches reference value");
2721}
2722
2723// AlphaToCoverageNoColorAttachmentInstance
2724
2725AlphaToCoverageNoColorAttachmentInstance::AlphaToCoverageNoColorAttachmentInstance (Context&									context,
2726																					const PipelineConstructionType				pipelineConstructionType,
2727																					VkPrimitiveTopology							topology,
2728																					const std::vector<Vertex4RGBA>&				vertices,
2729																					const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
2730																					const VkPipelineColorBlendAttachmentState&	blendState,
2731																					GeometryType								geometryType,
2732																					ImageBackingMode							backingMode,
2733																					const bool									useFragmentShadingRate)
2734	: vkt::TestInstance			(context)
2735	, m_pipelineConstructionType(pipelineConstructionType)
2736	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
2737	, m_depthStencilFormat		(VK_FORMAT_D16_UNORM)
2738	, m_renderSize				(32, 32)
2739	, m_primitiveTopology		(topology)
2740	, m_vertices				(vertices)
2741	, m_multisampleStateParams	(multisampleStateParams)
2742	, m_colorBlendState			(blendState)
2743	, m_geometryType			(geometryType)
2744	, m_backingMode				(backingMode)
2745	, m_useFragmentShadingRate	(useFragmentShadingRate)
2746{
2747}
2748
2749tcu::TestStatus AlphaToCoverageNoColorAttachmentInstance::iterate (void)
2750{
2751	DE_ASSERT(m_multisampleStateParams.alphaToCoverageEnable);
2752
2753	de::MovePtr<tcu::TextureLevel>	result;
2754	MultisampleRenderer				renderer	(m_context, m_pipelineConstructionType, m_colorFormat, m_depthStencilFormat, m_renderSize, true, false, 1u, &m_primitiveTopology, &m_vertices, m_multisampleStateParams, m_colorBlendState, RENDER_TYPE_DEPTHSTENCIL_ONLY, m_backingMode, m_useFragmentShadingRate, 1.0f);
2755
2756	result = renderer.render();
2757
2758	return verifyImage(result->getAccess());
2759}
2760
2761tcu::TestStatus AlphaToCoverageNoColorAttachmentInstance::verifyImage (const tcu::ConstPixelBufferAccess&	result)
2762{
2763	for (int y = 0; y < m_renderSize.y(); y++)
2764	{
2765		for (int x = 0; x < m_renderSize.x(); x++)
2766		{
2767			// Expect full red for each pixel. Fail if clear color is showing.
2768			if (result.getPixel(x, y).x() < 1.0f)
2769			{
2770				// Log result image when failing.
2771				m_context.getTestContext().getLog() << tcu::TestLog::ImageSet("Result", "Result image") << tcu::TestLog::Image("Rendered", "Rendered image", result) << tcu::TestLog::EndImageSet;
2772
2773				return tcu::TestStatus::fail("Fail");
2774			}
2775		}
2776	}
2777
2778	return tcu::TestStatus::pass("Pass");
2779}
2780
2781// AlphaToCoverageColorUnusedAttachmentInstance
2782
2783AlphaToCoverageColorUnusedAttachmentInstance::AlphaToCoverageColorUnusedAttachmentInstance (Context&									context,
2784																							const PipelineConstructionType				pipelineConstructionType,
2785																							VkPrimitiveTopology							topology,
2786																							const std::vector<Vertex4RGBA>&				vertices,
2787																							const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
2788																							const VkPipelineColorBlendAttachmentState&	blendState,
2789																							GeometryType								geometryType,
2790																							ImageBackingMode							backingMode,
2791																							const bool									useFragmentShadingRate)
2792	: vkt::TestInstance				(context)
2793	, m_pipelineConstructionType	(pipelineConstructionType)
2794	, m_colorFormat					(VK_FORMAT_R5G6B5_UNORM_PACK16)
2795	, m_renderSize					(32, 32)
2796	, m_primitiveTopology			(topology)
2797	, m_vertices					(vertices)
2798	, m_multisampleStateParams		(multisampleStateParams)
2799	, m_colorBlendState				(blendState)
2800	, m_geometryType				(geometryType)
2801	, m_backingMode					(backingMode)
2802	, m_useFragmentShadingRate		(useFragmentShadingRate)
2803{
2804}
2805
2806tcu::TestStatus AlphaToCoverageColorUnusedAttachmentInstance::iterate (void)
2807{
2808	DE_ASSERT(m_multisampleStateParams.alphaToCoverageEnable);
2809
2810	de::MovePtr<tcu::TextureLevel>	result;
2811	MultisampleRenderer				renderer	(m_context, m_pipelineConstructionType, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState, RENDER_TYPE_UNUSED_ATTACHMENT, m_backingMode, m_useFragmentShadingRate);
2812
2813	result = renderer.render();
2814
2815	return verifyImage(result->getAccess());
2816}
2817
2818tcu::TestStatus AlphaToCoverageColorUnusedAttachmentInstance::verifyImage (const tcu::ConstPixelBufferAccess&	result)
2819{
2820	for (int y = 0; y < m_renderSize.y(); y++)
2821	{
2822		for (int x = 0; x < m_renderSize.x(); x++)
2823		{
2824			// Quad color gets written to color buffer at location 1, and the alpha value to location 0 which is unused.
2825			// The coverage should still be affected by the alpha written to location 0.
2826			if ((m_geometryType == GEOMETRY_TYPE_OPAQUE_QUAD && result.getPixel(x, y).x() < 1.0f)
2827				|| (m_geometryType == GEOMETRY_TYPE_INVISIBLE_QUAD && result.getPixel(x, y).x() > 0.0f))
2828			{
2829				// Log result image when failing.
2830				m_context.getTestContext().getLog() << tcu::TestLog::ImageSet("Result", "Result image") << tcu::TestLog::Image("Rendered", "Rendered image", result) << tcu::TestLog::EndImageSet;
2831
2832				return tcu::TestStatus::fail("Fail");
2833			}
2834		}
2835	}
2836
2837	return tcu::TestStatus::pass("Pass");
2838}
2839
2840// SampleMaskWithConservativeInstance
2841
2842SampleMaskWithConservativeInstance::SampleMaskWithConservativeInstance (Context&									context,
2843																		const PipelineConstructionType				pipelineConstructionType,
2844																		const VkSampleCountFlagBits					rasterizationSamples,
2845																		const bool									enableMinSampleShading,
2846																		const float									minSampleShading,
2847																		const bool									enableSampleMask,
2848																		const VkSampleMask							sampleMask,
2849																		const VkConservativeRasterizationModeEXT	conservativeRasterizationMode,
2850																		const bool									enablePostDepthCoverage,
2851																		const bool									enableFullyCoveredEXT,
2852																		const RenderType							renderType,
2853																		const bool									useFragmentShadingRate)
2854	: vkt::TestInstance								(context)
2855	, m_pipelineConstructionType					(pipelineConstructionType)
2856	, m_rasterizationSamples						(rasterizationSamples)
2857	, m_enablePostDepthCoverage						(enablePostDepthCoverage)
2858	, m_enableFullyCoveredEXT						(enableFullyCoveredEXT)
2859	, m_colorFormat									(VK_FORMAT_R8G8B8A8_UNORM)
2860	, m_depthStencilFormat							(VK_FORMAT_D16_UNORM)
2861	, m_renderSize									(tcu::IVec2(10, 10))
2862	, m_useDepth									(true)
2863	, m_useStencil									(false)
2864	, m_useConservative								(true)
2865	, m_useFragmentShadingRate						(useFragmentShadingRate)
2866	, m_conservativeRasterizationMode				(conservativeRasterizationMode)
2867	, m_topology									(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
2868	, m_renderColor									(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f))
2869	, m_depthClearValue								(0.5f)
2870	, m_vertices									(generateVertices())
2871	, m_enableSampleMask							(enableSampleMask)
2872	, m_sampleMask									(std::vector<VkSampleMask>{sampleMask})
2873	, m_enableMinSampleShading						(enableMinSampleShading)
2874	, m_minSampleShading							(minSampleShading)
2875	, m_multisampleStateParams						(getMultisampleState(rasterizationSamples, enableMinSampleShading, minSampleShading, enableSampleMask))
2876	, m_rasterizationConservativeStateCreateInfo	(getRasterizationConservativeStateCreateInfo(conservativeRasterizationMode))
2877	, m_blendState									(getDefaultColorBlendAttachmentState())
2878	, m_renderType									(renderType)
2879	, m_imageBackingMode							(IMAGE_BACKING_MODE_REGULAR)
2880{
2881}
2882
2883tcu::TestStatus SampleMaskWithConservativeInstance::iterate (void)
2884{
2885
2886	de::MovePtr<tcu::TextureLevel>	noSampleshadingImage;
2887	std::vector<tcu::TextureLevel>	sampleShadedImages;
2888
2889	{
2890		MultisampleRenderer renderer(m_context, m_pipelineConstructionType, m_colorFormat, m_depthStencilFormat, m_renderSize, m_useDepth, m_useStencil, m_useConservative, m_useFragmentShadingRate, 1u,
2891			&m_topology, &m_vertices, m_multisampleStateParams, m_blendState, m_rasterizationConservativeStateCreateInfo, RENDER_TYPE_RESOLVE, m_imageBackingMode, m_depthClearValue);
2892		noSampleshadingImage = renderer.render();
2893	}
2894
2895	{
2896		const VkPipelineColorBlendAttachmentState colorBlendState =
2897		{
2898			false,														// VkBool32					blendEnable;
2899			VK_BLEND_FACTOR_ONE,										// VkBlendFactor			srcColorBlendFactor;
2900			VK_BLEND_FACTOR_ZERO,										// VkBlendFactor			dstColorBlendFactor;
2901			VK_BLEND_OP_ADD,											// VkBlendOp				colorBlendOp;
2902			VK_BLEND_FACTOR_ONE,										// VkBlendFactor			srcAlphaBlendFactor;
2903			VK_BLEND_FACTOR_ZERO,										// VkBlendFactor			dstAlphaBlendFactor;
2904			VK_BLEND_OP_ADD,											// VkBlendOp				alphaBlendOp;
2905			VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |		// VkColorComponentFlags	colorWriteMask;
2906				VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
2907		};
2908
2909		MultisampleRenderer mRenderer (m_context, m_pipelineConstructionType, m_colorFormat, m_renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, m_vertices, m_multisampleStateParams, colorBlendState, RENDER_TYPE_COPY_SAMPLES, IMAGE_BACKING_MODE_REGULAR, m_useFragmentShadingRate);
2910		mRenderer.render();
2911
2912		sampleShadedImages.resize(m_multisampleStateParams.rasterizationSamples);
2913		for (deUint32 sampleId = 0; sampleId < sampleShadedImages.size(); sampleId++)
2914		{
2915			sampleShadedImages[sampleId] = *mRenderer.getSingleSampledImage(sampleId);
2916		}
2917
2918	}
2919
2920	return verifyImage(sampleShadedImages, noSampleshadingImage->getAccess());
2921}
2922
2923VkPipelineMultisampleStateCreateInfo SampleMaskWithConservativeInstance::getMultisampleState (const VkSampleCountFlagBits rasterizationSamples, const bool enableMinSampleShading, const float minSampleShading, const bool enableSampleMask)
2924{
2925	const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
2926	{
2927		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
2928		DE_NULL,													// const void*								pNext;
2929		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
2930		rasterizationSamples,										// VkSampleCountFlagBits					rasterizationSamples;
2931		enableMinSampleShading ? VK_TRUE : VK_FALSE,				// VkBool32									sampleShadingEnable;
2932		enableMinSampleShading ? minSampleShading : 0.0f,			// float									minSampleShading;
2933		enableSampleMask ? m_sampleMask.data() : DE_NULL,			// const VkSampleMask*						pSampleMask;
2934		false,														// VkBool32									alphaToCoverageEnable;
2935		false														// VkBool32									alphaToOneEnable;
2936	};
2937
2938	return multisampleStateParams;
2939}
2940
2941VkPipelineRasterizationConservativeStateCreateInfoEXT  SampleMaskWithConservativeInstance::getRasterizationConservativeStateCreateInfo(const VkConservativeRasterizationModeEXT	conservativeRasterizationMode)
2942{
2943	const VkPipelineRasterizationConservativeStateCreateInfoEXT	rasterizationConservativeStateCreateInfo =
2944		{
2945			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT,	//  VkStructureType											sType;
2946			DE_NULL,																		//  const void*												pNext;
2947			(VkPipelineRasterizationConservativeStateCreateFlagsEXT)0,						//  VkPipelineRasterizationConservativeStateCreateFlagsEXT	flags;
2948			conservativeRasterizationMode,													//  VkConservativeRasterizationModeEXT						conservativeRasterizationMode;
2949			0.0f																			//  float													extraPrimitiveOverestimationSize;
2950		};
2951
2952	return rasterizationConservativeStateCreateInfo;
2953}
2954
2955std::vector<Vertex4RGBA> SampleMaskWithConservativeInstance::generateVertices (void)
2956{
2957	std::vector<Vertex4RGBA> vertices;
2958
2959	{
2960		const Vertex4RGBA vertexInput = { tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), m_renderColor };
2961		vertices.push_back(vertexInput);
2962	}
2963	{
2964		const Vertex4RGBA vertexInput = { tcu::Vec4(1.0f, -1.0f, 1.0f, 1.0f), m_renderColor };
2965		vertices.push_back(vertexInput);
2966	}
2967	{
2968		const Vertex4RGBA vertexInput = { tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f), m_renderColor };
2969		vertices.push_back(vertexInput);
2970	}
2971
2972	return vertices;
2973}
2974
2975tcu::TestStatus SampleMaskWithConservativeInstance::verifyImage (const std::vector<tcu::TextureLevel>& sampleShadedImages, const tcu::ConstPixelBufferAccess& result)
2976{
2977	bool			pass	= true;
2978	const int		width	= result.getWidth();
2979	const int		height	= result.getHeight();
2980	tcu::TestLog&	log		= m_context.getTestContext().getLog();
2981
2982	const deUint32		samplesCount		= (int)sampleShadedImages.size();
2983
2984	for (size_t i = 0; i < samplesCount; ++i)
2985	{
2986		const tcu::ConstPixelBufferAccess &s = sampleShadedImages[i].getAccess();
2987
2988		log << tcu::TestLog::ImageSet("Per sample image", "Per sampe image")
2989			<< tcu::TestLog::Image("Layer", "Layer", s)
2990			<< tcu::TestLog::EndImageSet;
2991	}
2992
2993	// Leave sample count intact (return 1) if multiplication by minSampleShading won't exceed base 2
2994	// otherwise round up to the nearest power of 2
2995	auto sampleCountDivider = [](float x) {
2996		float power = 1.0;
2997		while (power < x)
2998		{
2999			power *= 2;
3000		}
3001		return power;
3002	};
3003
3004	DE_ASSERT(width == 10);
3005	DE_ASSERT(height == 10);
3006
3007	const tcu::Vec4 clearColor = tcu::Vec4(0.0f);
3008	std::vector<std::pair<int, int>> fullyCoveredPixelsCoordinateSet;
3009
3010	// Generating set of pixel coordinate values covered by the triangle
3011	if (m_conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT)
3012	{
3013		for (int i = 0; i < width; i++)
3014		{
3015			for (int j = 0; j < height; j++)
3016			{
3017				// Rasterization will cover half of the triangle plus 1 pixel edge due to the overeestimation
3018				if (i < 5 && i + j < 11)
3019					fullyCoveredPixelsCoordinateSet.push_back(std::make_pair(i, j));
3020			}
3021		}
3022	}
3023	else
3024	{
3025		if (m_useFragmentShadingRate && !m_enableMinSampleShading)
3026		{
3027			// When m_enableMinSampleShading is not enabled shader uses gl_FragFullyCoveredNV.
3028			// Additionaly when FSR coverage is enabled the tests uses a pipeline FSR rate of { 2,2 }
3029			// and as a result rasterization will cover only four pixels due to the underestimation.
3030			for (int i = 2; i < 4; i++)
3031				for (int j = 2; j < 4; j++)
3032					fullyCoveredPixelsCoordinateSet.push_back(std::make_pair(i, j));
3033		}
3034		else
3035		{
3036			for (int i = 1; i < width; i++)
3037			{
3038				for (int j = 1; j < height; j++)
3039				{
3040					// Rasterization will cover half of the triangle minus 1 pixel edge due to the underestimation
3041					if (i < 5 && i + j < 8)
3042						fullyCoveredPixelsCoordinateSet.push_back(std::make_pair(i, j));
3043				}
3044			}
3045		}
3046	}
3047
3048	for (int x = 0; x < width; ++x)
3049		for (int y = 0; y < height; ++y)
3050		{
3051			const tcu::Vec4 resultPixel = result.getPixel(x, y);
3052
3053			if (std::find(fullyCoveredPixelsCoordinateSet.begin(), fullyCoveredPixelsCoordinateSet.end(), std::make_pair(x, y)) != fullyCoveredPixelsCoordinateSet.end())
3054			{
3055				if (m_enableMinSampleShading)
3056				{
3057					tcu::UVec4	sampleShadingValue = tcu::UVec4();
3058					for (size_t i = 0; i < samplesCount; ++i)
3059					{
3060						const tcu::UVec4	sampleShadedValue = sampleShadedImages[i].getAccess().getPixelUint(x, y);
3061
3062						sampleShadingValue += sampleShadedValue;
3063					}
3064
3065					//Calculate coverage of a single sample Image based on accumulated value from the whole set
3066					int sampleCoverageValue = sampleShadingValue.w() / samplesCount;
3067					//Calculates an estimated coverage value based on the number of samples and the minimumSampleShading
3068					int expectedCovergaveValue = (int)(255.0 / sampleCountDivider((float)m_rasterizationSamples * m_minSampleShading)) + 1;
3069
3070					//The specification allows for larger sample count than minimum value, however resulted coverage should never be lower than minimum
3071					if (sampleCoverageValue > expectedCovergaveValue)
3072					{
3073						log << tcu::TestLog::Message << "Coverage value " << sampleCoverageValue <<  " greather than expected: " << expectedCovergaveValue << tcu::TestLog::EndMessage;
3074
3075						pass = false;
3076					}
3077				}
3078				else if (m_enableSampleMask)
3079				{
3080					// Sample mask with all bits on will not affect fragment coverage
3081					if (m_sampleMask[0] == 0xFFFFFFFF)
3082					{
3083						if (resultPixel != m_renderColor)
3084						{
3085							log << tcu::TestLog::Message << "x: " << x << " y: " << y << " Result: " << resultPixel
3086								<< " Reference: " << m_renderColor << tcu::TestLog::EndMessage;
3087
3088							pass = false;
3089						}
3090					}
3091					// Sample mask with half bits off will reduce sample coverage by half
3092					else if (m_sampleMask[0] == 0xAAAAAAAA)
3093					{
3094
3095						const tcu::Vec4 renderColorHalfOpacity(0.0f, 0.5f, 0.0f, 0.5f);
3096						const float		threshold = 0.02f;
3097
3098						for (deUint32 componentNdx = 0u; componentNdx < m_renderColor.SIZE; ++componentNdx)
3099						{
3100							if ((renderColorHalfOpacity[componentNdx] != 0.0f && resultPixel[componentNdx] <= (renderColorHalfOpacity[componentNdx] - threshold))
3101								|| resultPixel[componentNdx] >= (renderColorHalfOpacity[componentNdx] + threshold))
3102							{
3103								log << tcu::TestLog::Message << "x: " << x << " y: " << y << " Result: " << resultPixel
3104									<< " Reference: " << renderColorHalfOpacity << " +/- " << threshold << tcu::TestLog::EndMessage;
3105
3106								pass = false;
3107							}
3108						}
3109					}
3110					// Sample mask with all bits off will cause all fragment to failed opacity test
3111					else if (m_sampleMask[0] == 0x00000000)
3112					{
3113						if (resultPixel != clearColor)
3114						{
3115							log << tcu::TestLog::Message << "x: " << x << " y: " << y << " Result: " << resultPixel
3116								<< " Reference: " << clearColor << tcu::TestLog::EndMessage;
3117
3118							pass = false;
3119						}
3120					}
3121					else
3122					{
3123						log << tcu::TestLog::Message << "Unexpected sample mask value" << tcu::TestLog::EndMessage;
3124
3125						pass = false;
3126					}
3127				}
3128				else
3129				{
3130					if (resultPixel != m_renderColor)
3131					{
3132						log << tcu::TestLog::Message << "x: " << x << " y: " << y << " Result: " << resultPixel
3133							<< " Reference: " << m_renderColor << tcu::TestLog::EndMessage;
3134
3135						pass = false;
3136					}
3137				}
3138			}
3139			else
3140			{
3141				if (resultPixel != clearColor)
3142				{
3143					log << tcu::TestLog::Message << "x: " << x << " y: " << y << " Result: " << resultPixel
3144						<< " Reference: " << clearColor << tcu::TestLog::EndMessage;
3145
3146					pass = false;
3147				}
3148			}
3149		}
3150
3151	if (pass)
3152		return tcu::TestStatus::pass("Passed");
3153	else
3154	{
3155		log << tcu::TestLog::ImageSet("LayerContent", "Layer content")
3156			<< tcu::TestLog::Image("Layer", "Layer", result)
3157			<< tcu::TestLog::EndImageSet;
3158
3159		return tcu::TestStatus::fail("Failed");
3160	}
3161
3162}
3163
3164// SampleMaskWithDepthTestInstance
3165#ifndef CTS_USES_VULKANSC
3166SampleMaskWithDepthTestInstance::SampleMaskWithDepthTestInstance (Context&							context,
3167																  const PipelineConstructionType	pipelineConstructionType,
3168																  const VkSampleCountFlagBits		rasterizationSamples,
3169																  const bool						enablePostDepthCoverage,
3170																  const bool						useFragmentShadingRate)
3171	: vkt::TestInstance			(context)
3172	, m_pipelineConstructionType(pipelineConstructionType)
3173	, m_rasterizationSamples	(rasterizationSamples)
3174	, m_enablePostDepthCoverage	(enablePostDepthCoverage)
3175	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
3176	, m_depthStencilFormat		(VK_FORMAT_D16_UNORM)
3177	, m_renderSize				(tcu::IVec2(3, 3))
3178	, m_useDepth				(true)
3179	, m_useStencil				(false)
3180	, m_topology				(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
3181	, m_renderColor				(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f))
3182	, m_vertices				(generateVertices())
3183	, m_multisampleStateParams	(getMultisampleState(rasterizationSamples))
3184	, m_blendState				(getDefaultColorBlendAttachmentState())
3185	, m_renderType				(RENDER_TYPE_RESOLVE)
3186	, m_imageBackingMode		(IMAGE_BACKING_MODE_REGULAR)
3187	, m_depthClearValue			(0.667f)
3188	, m_useFragmentShadingRate	(useFragmentShadingRate)
3189{
3190	m_refCoverageAfterDepthTest[VK_SAMPLE_COUNT_2_BIT]	= SampleCoverage(1u, 1u);	// !< Sample coverage of the diagonally halved pixel,
3191	m_refCoverageAfterDepthTest[VK_SAMPLE_COUNT_4_BIT]	= SampleCoverage(2u, 2u);	// !< with max possible subPixelPrecisionBits threshold
3192	m_refCoverageAfterDepthTest[VK_SAMPLE_COUNT_8_BIT]	= SampleCoverage(2u, 6u);	// !<
3193	m_refCoverageAfterDepthTest[VK_SAMPLE_COUNT_16_BIT]	= SampleCoverage(6u, 11u);	// !<
3194}
3195
3196tcu::TestStatus SampleMaskWithDepthTestInstance::iterate (void)
3197{
3198	de::MovePtr<tcu::TextureLevel>	result;
3199
3200	MultisampleRenderer renderer (m_context, m_pipelineConstructionType, m_colorFormat, m_depthStencilFormat, m_renderSize, m_useDepth, m_useStencil, 1u, &m_topology,
3201								  &m_vertices, m_multisampleStateParams, m_blendState, m_renderType, m_imageBackingMode, m_useFragmentShadingRate, m_depthClearValue);
3202	result = renderer.render();
3203
3204	return verifyImage(result->getAccess());
3205}
3206
3207VkPipelineMultisampleStateCreateInfo SampleMaskWithDepthTestInstance::getMultisampleState (const VkSampleCountFlagBits rasterizationSamples)
3208{
3209	const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
3210	{
3211		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
3212		DE_NULL,													// const void*								pNext;
3213		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
3214		rasterizationSamples,										// VkSampleCountFlagBits					rasterizationSamples;
3215		false,														// VkBool32									sampleShadingEnable;
3216		0.0f,														// float									minSampleShading;
3217		DE_NULL,													// const VkSampleMask*						pSampleMask;
3218		false,														// VkBool32									alphaToCoverageEnable;
3219		false														// VkBool32									alphaToOneEnable;
3220	};
3221
3222	return multisampleStateParams;
3223}
3224
3225std::vector<Vertex4RGBA> SampleMaskWithDepthTestInstance::generateVertices (void)
3226{
3227	std::vector<Vertex4RGBA> vertices;
3228
3229	{
3230		const Vertex4RGBA vertexInput = { tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), m_renderColor };
3231		vertices.push_back(vertexInput);
3232	}
3233	{
3234		const Vertex4RGBA vertexInput = { tcu::Vec4(1.0f, -1.0f, 1.0f, 1.0f), m_renderColor };
3235		vertices.push_back(vertexInput);
3236	}
3237	{
3238		const Vertex4RGBA vertexInput = { tcu::Vec4(-1.0f,  1.0f, 1.0f, 1.0f), m_renderColor };
3239		vertices.push_back(vertexInput);
3240	}
3241
3242	return vertices;
3243}
3244
3245tcu::TestStatus SampleMaskWithDepthTestInstance::verifyImage (const tcu::ConstPixelBufferAccess& result)
3246{
3247	bool			pass	= true;
3248	const int		width	= result.getWidth();
3249	const int		height	= result.getHeight();
3250	tcu::TestLog&	log		= m_context.getTestContext().getLog();
3251
3252	DE_ASSERT(width == 3);
3253	DE_ASSERT(height == 3);
3254
3255	const tcu::Vec4 clearColor = tcu::Vec4(0.0f);
3256
3257	for (int x = 0; x < width; ++x)
3258	for (int y = 0; y < height; ++y)
3259	{
3260		const tcu::Vec4 resultPixel = result.getPixel(x, y);
3261
3262		if (x + y == 0)
3263		{
3264			const float		threshold		= 0.02f;
3265			tcu::Vec4		expectedPixel	= m_renderColor;
3266
3267			if (m_useFragmentShadingRate && m_enablePostDepthCoverage)
3268			{
3269				// The fragment shader for this test outputs a fragment value that
3270				// is based off gl_SampleMaskIn. For the FSR case that sample mask
3271				// applies to 4 pixels, rather than the usual 1 pixel per fragment
3272				// shader invocation. Those 4 pixels represent:
3273				//   a) The fully covered pixel (this "x + y == 0" case)
3274				//   b) The two partially covered pixels (the "x + y == 1" case below)
3275				//   c) The non-covered pixel (the "else" case below)
3276				//
3277				// For the PostDepthCoverage case, the gl_SampleMaskIn represents
3278				// coverage after the depth test, so it has roughly 50% of the bits
3279				// set. This means that the expected result for this case (a)
3280				// will not be the "m_renderColor" but ~50% of the m_renderColor.
3281				expectedPixel = expectedPixel * tcu::Vec4(0.5f);
3282			}
3283
3284			bool			localPass		= true;
3285			for (deUint32 componentNdx = 0u; componentNdx < m_renderColor.SIZE; ++componentNdx)
3286			{
3287				if (m_renderColor[componentNdx] != 0.0f && (resultPixel[componentNdx] <= expectedPixel[componentNdx] * (1.0f - threshold)
3288					|| resultPixel[componentNdx] >= expectedPixel[componentNdx] * (1.0f + threshold)))
3289					localPass = false;
3290			}
3291
3292			if (!localPass)
3293			{
3294				log << tcu::TestLog::Message << "x: " << x << " y: " << y << " Result: " << resultPixel
3295					<< " Reference range ( " << expectedPixel * (1.0f - threshold) << " ; " << expectedPixel * (1.0f + threshold) << " )" << tcu::TestLog::EndMessage;
3296				pass = false;
3297			}
3298		}
3299		else if (x + y == 1)
3300		{
3301			const float		threshold	= 0.02f;
3302			float			minCoverage = (float)m_refCoverageAfterDepthTest[m_rasterizationSamples].min / (float)m_rasterizationSamples;
3303			float			maxCoverage = (float)m_refCoverageAfterDepthTest[m_rasterizationSamples].max / (float)m_rasterizationSamples;
3304
3305			// default: m_rasterizationSamples bits set in FS's gl_SampleMaskIn[0] (before depth test)
3306			// post_depth_coverage: m_refCoverageAfterDepthTest[m_rasterizationSamples] bits set in FS's gl_SampleMaskIn[0] (after depth test)
3307
3308			if (m_enablePostDepthCoverage)
3309			{
3310				minCoverage *= minCoverage;
3311				maxCoverage *= maxCoverage;
3312			}
3313
3314			bool			localPass	= true;
3315			for (deUint32 componentNdx = 0u; componentNdx < m_renderColor.SIZE; ++componentNdx)
3316			{
3317				if (m_renderColor[componentNdx] != 0.0f && (resultPixel[componentNdx] <= m_renderColor[componentNdx] * (minCoverage - threshold)
3318															|| resultPixel[componentNdx] >= m_renderColor[componentNdx] * (maxCoverage + threshold)))
3319					localPass = false;
3320			}
3321
3322			if (!localPass)
3323			{
3324				log << tcu::TestLog::Message << "x: " << x << " y: " << y << " Result: " << resultPixel
3325					<< " Reference range ( " << m_renderColor * (minCoverage - threshold) << " ; " << m_renderColor * (maxCoverage + threshold) << " )" << tcu::TestLog::EndMessage;
3326				pass = false;
3327			}
3328		}
3329		else
3330		{
3331			if (resultPixel != clearColor)
3332			{
3333				log << tcu::TestLog::Message << "x: " << x << " y: " << y << " Result: " << resultPixel
3334					<< " Reference: " << clearColor << tcu::TestLog::EndMessage;
3335				pass = false;
3336			}
3337		}
3338	}
3339
3340	if (pass)
3341		return tcu::TestStatus::pass("Passed");
3342	else
3343		return tcu::TestStatus::fail("Failed");
3344}
3345#endif // CTS_USES_VULKANSC
3346// MultisampleRenderer
3347
3348MultisampleRenderer::MultisampleRenderer (Context&										context,
3349										  const PipelineConstructionType				pipelineConstructionType,
3350										  const VkFormat								colorFormat,
3351										  const tcu::IVec2&								renderSize,
3352										  const VkPrimitiveTopology						topology,
3353										  const std::vector<Vertex4RGBA>&				vertices,
3354										  const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
3355										  const VkPipelineColorBlendAttachmentState&	blendState,
3356										  const RenderType								renderType,
3357										  const ImageBackingMode						backingMode,
3358										  const bool									useFragmentShadingRate)
3359	: m_context					(context)
3360	, m_pipelineConstructionType(pipelineConstructionType)
3361	, m_bindSemaphore			(createSemaphore(context.getDeviceInterface(), context.getDevice()))
3362	, m_colorFormat				(colorFormat)
3363	, m_depthStencilFormat		(VK_FORMAT_UNDEFINED)
3364	, m_renderSize				(renderSize)
3365	, m_useDepth				(false)
3366	, m_useStencil				(false)
3367	, m_useConservative			(false)
3368	, m_multisampleStateParams	(multisampleStateParams)
3369	, m_colorBlendState			(blendState)
3370	, m_rasterizationConservativeStateCreateInfo ()
3371	, m_renderType				(renderType)
3372	, m_backingMode				(backingMode)
3373	, m_depthClearValue			(1.0f)
3374	, m_useFragmentShadingRate	(useFragmentShadingRate)
3375{
3376	initialize(context, 1u, &topology, &vertices);
3377}
3378
3379MultisampleRenderer::MultisampleRenderer (Context&										context,
3380										  const PipelineConstructionType				pipelineConstructionType,
3381										  const VkFormat								colorFormat,
3382										  const VkFormat								depthStencilFormat,
3383										  const tcu::IVec2&								renderSize,
3384										  const bool									useDepth,
3385										  const bool									useStencil,
3386										  const deUint32								numTopologies,
3387										  const VkPrimitiveTopology*					pTopology,
3388										  const std::vector<Vertex4RGBA>*				pVertices,
3389										  const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
3390										  const VkPipelineColorBlendAttachmentState&	blendState,
3391										  const RenderType								renderType,
3392										  const ImageBackingMode						backingMode,
3393										  const bool									useFragmentShadingRate,
3394										  const float									depthClearValue)
3395	: m_context					(context)
3396	, m_pipelineConstructionType(pipelineConstructionType)
3397	, m_bindSemaphore			(createSemaphore(context.getDeviceInterface(), context.getDevice()))
3398	, m_colorFormat				(colorFormat)
3399	, m_depthStencilFormat		(depthStencilFormat)
3400	, m_renderSize				(renderSize)
3401	, m_useDepth				(useDepth)
3402	, m_useStencil				(useStencil)
3403	, m_useConservative			(false)
3404	, m_multisampleStateParams	(multisampleStateParams)
3405	, m_colorBlendState			(blendState)
3406	, m_rasterizationConservativeStateCreateInfo ()
3407	, m_renderType				(renderType)
3408	, m_backingMode				(backingMode)
3409	, m_depthClearValue			(depthClearValue)
3410	, m_useFragmentShadingRate	(useFragmentShadingRate)
3411{
3412	initialize(context, numTopologies, pTopology, pVertices);
3413}
3414
3415MultisampleRenderer::MultisampleRenderer (Context&										context,
3416										  const PipelineConstructionType				pipelineConstructionType,
3417										  const VkFormat								colorFormat,
3418										  const VkFormat								depthStencilFormat,
3419										  const tcu::IVec2&								renderSize,
3420										  const bool									useDepth,
3421										  const bool									useStencil,
3422										  const bool									useConservative,
3423										  const bool									useFragmentShadingRate,
3424										  const deUint32								numTopologies,
3425										  const VkPrimitiveTopology*					pTopology,
3426										  const std::vector<Vertex4RGBA>*				pVertices,
3427										  const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
3428										  const VkPipelineColorBlendAttachmentState&	blendState,
3429										  const VkPipelineRasterizationConservativeStateCreateInfoEXT&	conservativeStateCreateInfo,
3430										  const RenderType								renderType,
3431										  const ImageBackingMode						backingMode,
3432										  const float									depthClearValue)
3433	: m_context					(context)
3434	, m_pipelineConstructionType(pipelineConstructionType)
3435	, m_bindSemaphore			(createSemaphore(context.getDeviceInterface(), context.getDevice()))
3436	, m_colorFormat				(colorFormat)
3437	, m_depthStencilFormat		(depthStencilFormat)
3438	, m_renderSize				(renderSize)
3439	, m_useDepth				(useDepth)
3440	, m_useStencil				(useStencil)
3441	, m_useConservative			(useConservative)
3442	, m_multisampleStateParams	(multisampleStateParams)
3443	, m_colorBlendState			(blendState)
3444	, m_rasterizationConservativeStateCreateInfo (conservativeStateCreateInfo)
3445	, m_renderType				(renderType)
3446	, m_backingMode				(backingMode)
3447	, m_depthClearValue			(depthClearValue)
3448	, m_useFragmentShadingRate	(useFragmentShadingRate)
3449{
3450	initialize(context, numTopologies, pTopology, pVertices);
3451}
3452
3453void MultisampleRenderer::initialize (Context&									context,
3454									  const deUint32							numTopologies,
3455									  const VkPrimitiveTopology*				pTopology,
3456									  const std::vector<Vertex4RGBA>*			pVertices)
3457{
3458	if (!isSupportedSampleCount(context.getInstanceInterface(), context.getPhysicalDevice(), m_multisampleStateParams.rasterizationSamples))
3459		throw tcu::NotSupportedError("Unsupported number of rasterization samples");
3460
3461	const InstanceInterface&		vki						= context.getInstanceInterface();
3462	const DeviceInterface&			vk						= context.getDeviceInterface();
3463	const VkPhysicalDevice			physicalDevice			= context.getPhysicalDevice();
3464	const VkDevice					vkDevice				= context.getDevice();
3465	const VkPhysicalDeviceFeatures	features				= context.getDeviceFeatures();
3466	const deUint32					queueFamilyIndices[]	= { context.getUniversalQueueFamilyIndex(), context.getSparseQueueFamilyIndex() };
3467	const bool						sparse					= m_backingMode == IMAGE_BACKING_MODE_SPARSE;
3468	const VkComponentMapping		componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
3469	const VkImageCreateFlags		imageCreateFlags		= sparse ? (VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) : 0u;
3470	const VkSharingMode				sharingMode				= (sparse && context.getUniversalQueueFamilyIndex() != context.getSparseQueueFamilyIndex()) ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE;
3471	Allocator&						memAlloc				= m_context.getDefaultAllocator();
3472	const bool						usesResolveImage		= m_renderType == RENDER_TYPE_RESOLVE || m_renderType == RENDER_TYPE_DEPTHSTENCIL_ONLY || m_renderType == RENDER_TYPE_UNUSED_ATTACHMENT;
3473
3474	if (sparse)
3475	{
3476		bool sparseSamplesSupported = false;
3477		switch(m_multisampleStateParams.rasterizationSamples)
3478		{
3479			case VK_SAMPLE_COUNT_1_BIT:
3480				sparseSamplesSupported = features.sparseResidencyImage2D;
3481				break;
3482			case VK_SAMPLE_COUNT_2_BIT:
3483				sparseSamplesSupported = features.sparseResidency2Samples;
3484				break;
3485			case VK_SAMPLE_COUNT_4_BIT:
3486				sparseSamplesSupported = features.sparseResidency4Samples;
3487				break;
3488			case VK_SAMPLE_COUNT_8_BIT:
3489				sparseSamplesSupported = features.sparseResidency8Samples;
3490				break;
3491			case VK_SAMPLE_COUNT_16_BIT:
3492				sparseSamplesSupported = features.sparseResidency16Samples;
3493				break;
3494			default:
3495				break;
3496		}
3497
3498		if (!sparseSamplesSupported)
3499			throw tcu::NotSupportedError("Unsupported number of rasterization samples for sparse residency");
3500	}
3501
3502	if (sparse && !context.getDeviceFeatures().sparseBinding)
3503		throw tcu::NotSupportedError("No sparseBinding support");
3504
3505	// Create color image
3506	{
3507		const VkImageUsageFlags	imageUsageFlags		= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
3508			(m_renderType == RENDER_TYPE_COPY_SAMPLES ? VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT : (VkImageUsageFlagBits)0u);
3509
3510		const VkImageCreateInfo colorImageParams	=
3511		{
3512			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
3513			DE_NULL,																	// const void*				pNext;
3514			imageCreateFlags,															// VkImageCreateFlags		flags;
3515			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
3516			m_colorFormat,																// VkFormat					format;
3517			{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u },				// VkExtent3D				extent;
3518			1u,																			// deUint32					mipLevels;
3519			1u,																			// deUint32					arrayLayers;
3520			m_multisampleStateParams.rasterizationSamples,								// VkSampleCountFlagBits	samples;
3521			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
3522			imageUsageFlags,															// VkImageUsageFlags		usage;
3523			sharingMode,																// VkSharingMode			sharingMode;
3524			sharingMode == VK_SHARING_MODE_CONCURRENT ? 2u : 1u,						// deUint32					queueFamilyIndexCount;
3525			queueFamilyIndices,															// const deUint32*			pQueueFamilyIndices;
3526			VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout			initialLayout;
3527		};
3528
3529#ifndef CTS_USES_VULKANSC
3530		if (sparse && !checkSparseImageFormatSupport(context.getPhysicalDevice(), context.getInstanceInterface(), colorImageParams))
3531			TCU_THROW(NotSupportedError, "The image format does not support sparse operations.");
3532#endif // CTS_USES_VULKANSC
3533
3534		m_colorImage = createImage(vk, vkDevice, &colorImageParams);
3535
3536		// Allocate and bind color image memory
3537		if (sparse)
3538		{
3539#ifndef CTS_USES_VULKANSC
3540			allocateAndBindSparseImage(vk, vkDevice, context.getPhysicalDevice(), context.getInstanceInterface(), colorImageParams, *m_bindSemaphore, context.getSparseQueue(), memAlloc, m_allocations, mapVkFormat(m_colorFormat), *m_colorImage);
3541#endif // CTS_USES_VULKANSC
3542		}
3543		else
3544		{
3545			m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
3546			VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
3547		}
3548	}
3549
3550	// Create resolve image
3551	if (usesResolveImage)
3552	{
3553		const VkImageCreateInfo resolveImageParams =
3554		{
3555			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,											// VkStructureType			sType;
3556			DE_NULL,																		// const void*				pNext;
3557			0u,																				// VkImageCreateFlags		flags;
3558			VK_IMAGE_TYPE_2D,																// VkImageType				imageType;
3559			m_colorFormat,																	// VkFormat					format;
3560			{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u },					// VkExtent3D				extent;
3561			1u,																				// deUint32					mipLevels;
3562			1u,																				// deUint32					arrayLayers;
3563			VK_SAMPLE_COUNT_1_BIT,															// VkSampleCountFlagBits	samples;
3564			VK_IMAGE_TILING_OPTIMAL,														// VkImageTiling			tiling;
3565			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |			// VkImageUsageFlags		usage;
3566				VK_IMAGE_USAGE_TRANSFER_DST_BIT,
3567			VK_SHARING_MODE_EXCLUSIVE,														// VkSharingMode			sharingMode;
3568			1u,																				// deUint32					queueFamilyIndexCount;
3569			queueFamilyIndices,																// const deUint32*			pQueueFamilyIndices;
3570			VK_IMAGE_LAYOUT_UNDEFINED														// VkImageLayout			initialLayout;
3571		};
3572
3573		m_resolveImage = createImage(vk, vkDevice, &resolveImageParams);
3574
3575		// Allocate and bind resolve image memory
3576		m_resolveImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_resolveImage), MemoryRequirement::Any);
3577		VK_CHECK(vk.bindImageMemory(vkDevice, *m_resolveImage, m_resolveImageAlloc->getMemory(), m_resolveImageAlloc->getOffset()));
3578
3579		// Create resolve attachment view
3580		{
3581			const VkImageViewCreateInfo resolveAttachmentViewParams =
3582			{
3583				VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
3584				DE_NULL,										// const void*				pNext;
3585				0u,												// VkImageViewCreateFlags	flags;
3586				*m_resolveImage,								// VkImage					image;
3587				VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
3588				m_colorFormat,									// VkFormat					format;
3589				componentMappingRGBA,							// VkComponentMapping		components;
3590				{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
3591			};
3592
3593			m_resolveAttachmentView = createImageView(vk, vkDevice, &resolveAttachmentViewParams);
3594		}
3595	}
3596
3597	// Create per-sample output images
3598	if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
3599	{
3600		const VkImageCreateInfo perSampleImageParams =
3601		{
3602			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,											// VkStructureType			sType;
3603			DE_NULL,																		// const void*				pNext;
3604			0u,																				// VkImageCreateFlags		flags;
3605			VK_IMAGE_TYPE_2D,																// VkImageType				imageType;
3606			m_colorFormat,																	// VkFormat					format;
3607			{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u },					// VkExtent3D				extent;
3608			1u,																				// deUint32					mipLevels;
3609			1u,																				// deUint32					arrayLayers;
3610			VK_SAMPLE_COUNT_1_BIT,															// VkSampleCountFlagBits	samples;
3611			VK_IMAGE_TILING_OPTIMAL,														// VkImageTiling			tiling;
3612			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |			// VkImageUsageFlags		usage;
3613			VK_IMAGE_USAGE_TRANSFER_DST_BIT,
3614			VK_SHARING_MODE_EXCLUSIVE,														// VkSharingMode			sharingMode;
3615			1u,																				// deUint32					queueFamilyIndexCount;
3616			queueFamilyIndices,																// const deUint32*			pQueueFamilyIndices;
3617			VK_IMAGE_LAYOUT_UNDEFINED														// VkImageLayout			initialLayout;
3618		};
3619
3620		m_perSampleImages.resize(static_cast<size_t>(m_multisampleStateParams.rasterizationSamples));
3621
3622		for (size_t i = 0; i < m_perSampleImages.size(); ++i)
3623		{
3624			m_perSampleImages[i]	= de::SharedPtr<PerSampleImage>(new PerSampleImage);
3625			PerSampleImage& image	= *m_perSampleImages[i];
3626
3627			image.m_image			= createImage(vk, vkDevice, &perSampleImageParams);
3628
3629			// Allocate and bind image memory
3630			image.m_imageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *image.m_image), MemoryRequirement::Any);
3631			VK_CHECK(vk.bindImageMemory(vkDevice, *image.m_image, image.m_imageAlloc->getMemory(), image.m_imageAlloc->getOffset()));
3632
3633			// Create per-sample attachment view
3634			{
3635				const VkImageViewCreateInfo perSampleAttachmentViewParams =
3636				{
3637					VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
3638					DE_NULL,										// const void*				pNext;
3639					0u,												// VkImageViewCreateFlags	flags;
3640					*image.m_image,									// VkImage					image;
3641					VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
3642					m_colorFormat,									// VkFormat					format;
3643					componentMappingRGBA,							// VkComponentMapping		components;
3644					{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
3645				};
3646
3647				image.m_attachmentView = createImageView(vk, vkDevice, &perSampleAttachmentViewParams);
3648			}
3649		}
3650	}
3651
3652	// Create a depth/stencil image
3653	if (m_useDepth || m_useStencil)
3654	{
3655		const VkImageCreateInfo depthStencilImageParams =
3656		{
3657			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,											// VkStructureType			sType;
3658			DE_NULL,																		// const void*				pNext;
3659			0u,																				// VkImageCreateFlags		flags;
3660			VK_IMAGE_TYPE_2D,																// VkImageType				imageType;
3661			m_depthStencilFormat,															// VkFormat					format;
3662			{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u },					// VkExtent3D				extent;
3663			1u,																				// deUint32					mipLevels;
3664			1u,																				// deUint32					arrayLayers;
3665			m_multisampleStateParams.rasterizationSamples,									// VkSampleCountFlagBits	samples;
3666			VK_IMAGE_TILING_OPTIMAL,														// VkImageTiling			tiling;
3667			VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,									// VkImageUsageFlags		usage;
3668			VK_SHARING_MODE_EXCLUSIVE,														// VkSharingMode			sharingMode;
3669			1u,																				// deUint32					queueFamilyIndexCount;
3670			queueFamilyIndices,																// const deUint32*			pQueueFamilyIndices;
3671			VK_IMAGE_LAYOUT_UNDEFINED														// VkImageLayout			initialLayout;
3672		};
3673
3674		m_depthStencilImage = createImage(vk, vkDevice, &depthStencilImageParams);
3675
3676		// Allocate and bind depth/stencil image memory
3677		m_depthStencilImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_depthStencilImage), MemoryRequirement::Any);
3678		VK_CHECK(vk.bindImageMemory(vkDevice, *m_depthStencilImage, m_depthStencilImageAlloc->getMemory(), m_depthStencilImageAlloc->getOffset()));
3679	}
3680
3681	// Create color attachment view
3682	{
3683		const VkImageViewCreateInfo colorAttachmentViewParams =
3684		{
3685			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
3686			DE_NULL,										// const void*				pNext;
3687			0u,												// VkImageViewCreateFlags	flags;
3688			*m_colorImage,									// VkImage					image;
3689			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
3690			m_colorFormat,									// VkFormat					format;
3691			componentMappingRGBA,							// VkComponentMapping		components;
3692			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
3693		};
3694
3695		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
3696	}
3697
3698	VkImageAspectFlags	depthStencilAttachmentAspect	= (VkImageAspectFlagBits)0;
3699
3700	// Create depth/stencil attachment view
3701	if (m_useDepth || m_useStencil)
3702	{
3703		depthStencilAttachmentAspect = getImageAspectFlags(m_depthStencilFormat);
3704
3705		const VkImageViewCreateInfo depthStencilAttachmentViewParams =
3706		{
3707			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
3708			DE_NULL,											// const void*				pNext;
3709			0u,													// VkImageViewCreateFlags	flags;
3710			*m_depthStencilImage,								// VkImage					image;
3711			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
3712			m_depthStencilFormat,								// VkFormat					format;
3713			componentMappingRGBA,								// VkComponentMapping		components;
3714			{ depthStencilAttachmentAspect, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
3715		};
3716
3717		m_depthStencilAttachmentView = createImageView(vk, vkDevice, &depthStencilAttachmentViewParams);
3718	}
3719
3720	// Create render pass
3721	{
3722		std::vector<VkAttachmentDescription> attachmentDescriptions;
3723		{
3724			const VkAttachmentDescription colorAttachmentDescription =
3725			{
3726				0u,													// VkAttachmentDescriptionFlags		flags;
3727				m_colorFormat,										// VkFormat							format;
3728				m_multisampleStateParams.rasterizationSamples,		// VkSampleCountFlagBits			samples;
3729				VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
3730				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
3731				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
3732				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
3733				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
3734				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout;
3735			};
3736			attachmentDescriptions.push_back(colorAttachmentDescription);
3737		}
3738
3739		deUint32 resolveAttachmentIndex = VK_ATTACHMENT_UNUSED;
3740
3741		if (usesResolveImage)
3742		{
3743			resolveAttachmentIndex = static_cast<deUint32>(attachmentDescriptions.size());
3744
3745			const VkAttachmentDescription resolveAttachmentDescription =
3746			{
3747				0u,													// VkAttachmentDescriptionFlags		flags;
3748				m_colorFormat,										// VkFormat							format;
3749				VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
3750				VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
3751				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
3752				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
3753				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
3754				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
3755				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout;
3756			};
3757			attachmentDescriptions.push_back(resolveAttachmentDescription);
3758		}
3759
3760		deUint32 perSampleAttachmentIndex = VK_ATTACHMENT_UNUSED;
3761
3762		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
3763		{
3764			perSampleAttachmentIndex = static_cast<deUint32>(attachmentDescriptions.size());
3765
3766			const VkAttachmentDescription perSampleAttachmentDescription =
3767			{
3768				0u,													// VkAttachmentDescriptionFlags		flags;
3769				m_colorFormat,										// VkFormat							format;
3770				VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
3771				VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
3772				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
3773				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
3774				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
3775				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
3776				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout;
3777			};
3778
3779			for (size_t i = 0; i < m_perSampleImages.size(); ++i)
3780			{
3781				attachmentDescriptions.push_back(perSampleAttachmentDescription);
3782			}
3783		}
3784
3785		deUint32 depthStencilAttachmentIndex = VK_ATTACHMENT_UNUSED;
3786
3787		if (m_useDepth || m_useStencil)
3788		{
3789			depthStencilAttachmentIndex = static_cast<deUint32>(attachmentDescriptions.size());
3790
3791			const VkAttachmentDescription depthStencilAttachmentDescription =
3792			{
3793				0u,																					// VkAttachmentDescriptionFlags		flags;
3794				m_depthStencilFormat,																// VkFormat							format;
3795				m_multisampleStateParams.rasterizationSamples,										// VkSampleCountFlagBits			samples;
3796				(m_useDepth ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_DONT_CARE),		// VkAttachmentLoadOp				loadOp;
3797				(m_useDepth ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE),		// VkAttachmentStoreOp				storeOp;
3798				(m_useStencil ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_DONT_CARE),		// VkAttachmentStoreOp				stencilLoadOp;
3799				(m_useStencil ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE),	// VkAttachmentStoreOp				stencilStoreOp;
3800				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,									// VkImageLayout					initialLayout;
3801				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL									// VkImageLayout					finalLayout;
3802			};
3803			attachmentDescriptions.push_back(depthStencilAttachmentDescription);
3804		}
3805
3806		const VkAttachmentReference colorAttachmentReference =
3807		{
3808			0u,													// deUint32			attachment;
3809			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
3810		};
3811
3812		const VkAttachmentReference inputAttachmentReference =
3813		{
3814			0u,													// deUint32			attachment;
3815			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL			// VkImageLayout	layout;
3816		};
3817
3818		const VkAttachmentReference resolveAttachmentReference =
3819		{
3820			resolveAttachmentIndex,								// deUint32			attachment;
3821			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
3822		};
3823
3824		const VkAttachmentReference colorAttachmentReferencesUnusedAttachment[] =
3825		{
3826			{
3827				VK_ATTACHMENT_UNUSED,		// deUint32			attachment
3828				VK_IMAGE_LAYOUT_UNDEFINED	// VkImageLayout	layout
3829			},
3830			{
3831				0u,											// deUint32			attachment
3832				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout
3833			}
3834		};
3835
3836		const VkAttachmentReference resolveAttachmentReferencesUnusedAttachment[] =
3837		{
3838			{
3839				VK_ATTACHMENT_UNUSED,		// deUint32			attachment
3840				VK_IMAGE_LAYOUT_UNDEFINED	// VkImageLayout	layout
3841			},
3842			{
3843				resolveAttachmentIndex,						// deUint32			attachment
3844				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout
3845			}
3846		};
3847
3848		std::vector<VkAttachmentReference> perSampleAttachmentReferences(m_perSampleImages.size());
3849		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
3850		{
3851			for (size_t i = 0; i < m_perSampleImages.size(); ++i)
3852			{
3853				const VkAttachmentReference perSampleAttachmentReference =
3854				{
3855					perSampleAttachmentIndex + static_cast<deUint32>(i),	// deUint32			attachment;
3856					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL				// VkImageLayout	layout;
3857				};
3858				perSampleAttachmentReferences[i] = perSampleAttachmentReference;
3859			}
3860		}
3861
3862		const VkAttachmentReference depthStencilAttachmentReference =
3863		{
3864			depthStencilAttachmentIndex,						// deUint32			attachment;
3865			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
3866		};
3867
3868		std::vector<VkSubpassDescription>	subpassDescriptions;
3869		std::vector<VkSubpassDependency>	subpassDependencies;
3870
3871		if (m_renderType == RENDER_TYPE_DEPTHSTENCIL_ONLY)
3872		{
3873				const VkSubpassDescription	subpassDescription0	=
3874				{
3875					0u,										// VkSubpassDescriptionFlags	flags
3876					VK_PIPELINE_BIND_POINT_GRAPHICS,		// VkPipelineBindPoint			pipelineBindPoint
3877					0u,										// deUint32						inputAttachmentCount
3878					DE_NULL,								// const VkAttachmentReference*	pInputAttachments
3879					0u,										// deUint32						colorAttachmentCount
3880					DE_NULL,								// const VkAttachmentReference*	pColorAttachments
3881					DE_NULL,								// const VkAttachmentReference*	pResolveAttachments
3882					&depthStencilAttachmentReference,		// const VkAttachmentReference*	pDepthStencilAttachment
3883					0u,										// deUint32						preserveAttachmentCount
3884					DE_NULL									// const VkAttachmentReference*	pPreserveAttachments
3885				};
3886
3887				const VkSubpassDescription	subpassDescription1	=
3888				{
3889					0u,									// VkSubpassDescriptionFlags	flags
3890					VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint			pipelineBindPoint
3891					0u,									// deUint32						inputAttachmentCount
3892					DE_NULL,							// const VkAttachmentReference*	pInputAttachments
3893					1u,									// deUint32						colorAttachmentCount
3894					&colorAttachmentReference,			// const VkAttachmentReference*	pColorAttachments
3895					&resolveAttachmentReference,		// const VkAttachmentReference*	pResolveAttachments
3896					&depthStencilAttachmentReference,	// const VkAttachmentReference*	pDepthStencilAttachment
3897					0u,									// deUint32						preserveAttachmentCount
3898					DE_NULL								// const VkAttachmentReference*	pPreserveAttachments
3899				};
3900
3901				const VkSubpassDependency	subpassDependency	=
3902				{
3903					0u,												// deUint32				srcSubpass
3904					1u,												// deUint32				dstSubpass
3905					VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,		// VkPipelineStageFlags	srcStageMask
3906					VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,		// VkPipelineStageFlags	dstStageMask
3907					VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,	// VkAccessFlags		srcAccessMask
3908					VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,	// VkAccessFlags		dstAccessMask
3909					0u												// VkDependencyFlags	dependencyFlags
3910				};
3911
3912				subpassDescriptions.push_back(subpassDescription0);
3913				subpassDescriptions.push_back(subpassDescription1);
3914				subpassDependencies.push_back(subpassDependency);
3915		}
3916		else if (m_renderType == RENDER_TYPE_UNUSED_ATTACHMENT)
3917		{
3918			const VkSubpassDescription renderSubpassDescription =
3919			{
3920				0u,												// VkSubpassDescriptionFlags	flags
3921				VK_PIPELINE_BIND_POINT_GRAPHICS,				// VkPipelineBindPoint			pipelineBindPoint
3922				0u,												// deUint32						inputAttachmentCount
3923				DE_NULL,										// const VkAttachmentReference*	pInputAttachments
3924				2u,												// deUint32						colorAttachmentCount
3925				colorAttachmentReferencesUnusedAttachment,		// const VkAttachmentReference*	pColorAttachments
3926				resolveAttachmentReferencesUnusedAttachment,	// const VkAttachmentReference*	pResolveAttachments
3927				DE_NULL,										// const VkAttachmentReference*	pDepthStencilAttachment
3928				0u,												// deUint32						preserveAttachmentCount
3929				DE_NULL											// const VkAttachmentReference*	pPreserveAttachments
3930			};
3931
3932			subpassDescriptions.push_back(renderSubpassDescription);
3933		}
3934		else
3935		{
3936			{
3937				const VkSubpassDescription renderSubpassDescription =
3938				{
3939					0u,																				// VkSubpassDescriptionFlags	flags;
3940					VK_PIPELINE_BIND_POINT_GRAPHICS,												// VkPipelineBindPoint			pipelineBindPoint;
3941					0u,																				// deUint32						inputAttachmentCount;
3942					DE_NULL,																		// const VkAttachmentReference*	pInputAttachments;
3943					1u,																				// deUint32						colorAttachmentCount;
3944					&colorAttachmentReference,														// const VkAttachmentReference*	pColorAttachments;
3945					usesResolveImage ? &resolveAttachmentReference : DE_NULL,						// const VkAttachmentReference*	pResolveAttachments;
3946					(m_useDepth || m_useStencil ? &depthStencilAttachmentReference : DE_NULL),		// const VkAttachmentReference*	pDepthStencilAttachment;
3947					0u,																				// deUint32						preserveAttachmentCount;
3948					DE_NULL																			// const VkAttachmentReference*	pPreserveAttachments;
3949				};
3950				subpassDescriptions.push_back(renderSubpassDescription);
3951			}
3952
3953			if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
3954			{
3955
3956				for (size_t i = 0; i < m_perSampleImages.size(); ++i)
3957				{
3958					const VkSubpassDescription copySampleSubpassDescription =
3959					{
3960						0u,													// VkSubpassDescriptionFlags		flags;
3961						VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
3962						1u,													// deUint32							inputAttachmentCount;
3963						&inputAttachmentReference,							// const VkAttachmentReference*		pInputAttachments;
3964						1u,													// deUint32							colorAttachmentCount;
3965						&perSampleAttachmentReferences[i],					// const VkAttachmentReference*		pColorAttachments;
3966						DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
3967						DE_NULL,											// const VkAttachmentReference*		pDepthStencilAttachment;
3968						0u,													// deUint32							preserveAttachmentCount;
3969						DE_NULL												// const VkAttachmentReference*		pPreserveAttachments;
3970					};
3971					subpassDescriptions.push_back(copySampleSubpassDescription);
3972
3973					const VkSubpassDependency copySampleSubpassDependency =
3974					{
3975						0u,													// deUint32							srcSubpass
3976						1u + static_cast<deUint32>(i),						// deUint32							dstSubpass
3977						VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,		// VkPipelineStageFlags				srcStageMask
3978						VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,				// VkPipelineStageFlags				dstStageMask
3979						VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags					srcAccessMask
3980						VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,				// VkAccessFlags					dstAccessMask
3981						0u,													// VkDependencyFlags				dependencyFlags
3982					};
3983					subpassDependencies.push_back(copySampleSubpassDependency);
3984				}
3985				// the very last sample pass must synchronize with all prior subpasses
3986				for (size_t i = 0; i < (m_perSampleImages.size() - 1); ++i)
3987				{
3988					const VkSubpassDependency storeSubpassDependency =
3989					{
3990						1u + static_cast<deUint32>(i),						// deUint32							srcSubpass
3991						static_cast<deUint32>(m_perSampleImages.size()),    // deUint32							dstSubpass
3992						VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,		// VkPipelineStageFlags				srcStageMask
3993						VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,				// VkPipelineStageFlags				dstStageMask
3994						VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags					srcAccessMask
3995						VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,				// VkAccessFlags					dstAccessMask
3996						0u,													// VkDependencyFlags				dependencyFlags
3997					};
3998					subpassDependencies.push_back(storeSubpassDependency);
3999				}
4000			}
4001		}
4002
4003		const VkRenderPassCreateInfo renderPassParams =
4004		{
4005			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,					// VkStructureType					sType;
4006			DE_NULL,													// const void*						pNext;
4007			0u,															// VkRenderPassCreateFlags			flags;
4008			(deUint32)attachmentDescriptions.size(),					// deUint32							attachmentCount;
4009			&attachmentDescriptions[0],									// const VkAttachmentDescription*	pAttachments;
4010			(deUint32)subpassDescriptions.size(),						// deUint32							subpassCount;
4011			&subpassDescriptions[0],									// const VkSubpassDescription*		pSubpasses;
4012			(deUint32)subpassDependencies.size(),						// deUint32							dependencyCount;
4013			subpassDependencies.size() != 0 ? &subpassDependencies[0] : DE_NULL
4014		};
4015
4016		m_renderPass = RenderPassWrapper(m_pipelineConstructionType, vk, vkDevice, &renderPassParams);
4017	}
4018
4019	// Create framebuffer
4020	{
4021		std::vector<VkImage> images;
4022		std::vector<VkImageView> attachments;
4023		images.push_back(*m_colorImage);
4024		attachments.push_back(*m_colorAttachmentView);
4025		if (usesResolveImage)
4026		{
4027			images.push_back(*m_resolveImage);
4028			attachments.push_back(*m_resolveAttachmentView);
4029		}
4030		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
4031		{
4032			for (size_t i = 0; i < m_perSampleImages.size(); ++i)
4033			{
4034				images.push_back(*m_perSampleImages[i]->m_image);
4035				attachments.push_back(*m_perSampleImages[i]->m_attachmentView);
4036			}
4037		}
4038
4039		if (m_useDepth || m_useStencil)
4040		{
4041			images.push_back(*m_depthStencilImage);
4042			attachments.push_back(*m_depthStencilAttachmentView);
4043		}
4044
4045		const VkFramebufferCreateInfo framebufferParams =
4046		{
4047			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType					sType;
4048			DE_NULL,											// const void*						pNext;
4049			0u,													// VkFramebufferCreateFlags			flags;
4050			*m_renderPass,										// VkRenderPass						renderPass;
4051			(deUint32)attachments.size(),						// deUint32							attachmentCount;
4052			&attachments[0],									// const VkImageView*				pAttachments;
4053			(deUint32)m_renderSize.x(),							// deUint32							width;
4054			(deUint32)m_renderSize.y(),							// deUint32							height;
4055			1u													// deUint32							layers;
4056		};
4057
4058		m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, images);
4059	}
4060
4061	// Create pipeline layout
4062	{
4063		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
4064		{
4065			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
4066			DE_NULL,											// const void*						pNext;
4067			0u,													// VkPipelineLayoutCreateFlags		flags;
4068			0u,													// deUint32							setLayoutCount;
4069			DE_NULL,											// const VkDescriptorSetLayout*		pSetLayouts;
4070			0u,													// deUint32							pushConstantRangeCount;
4071			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
4072		};
4073
4074		m_pipelineLayout = PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
4075
4076		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
4077		{
4078
4079			// Create descriptor set layout
4080			const VkDescriptorSetLayoutBinding		layoutBinding					=
4081			{
4082				0u,															// deUint32								binding;
4083				VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,						// VkDescriptorType						descriptorType;
4084				1u,															// deUint32								descriptorCount;
4085				VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlags					stageFlags;
4086				DE_NULL,													// const VkSampler*						pImmutableSamplers;
4087			};
4088
4089			const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutParams		=
4090			{
4091				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,		// VkStructureType						sType
4092				DE_NULL,													// const void*							pNext
4093				0u,															// VkDescriptorSetLayoutCreateFlags		flags
4094				1u,															// deUint32								bindingCount
4095				&layoutBinding												// const VkDescriptorSetLayoutBinding*	pBindings
4096			};
4097			m_copySampleDesciptorLayout	= createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
4098
4099			// Create pipeline layout
4100
4101			const VkPushConstantRange				pushConstantRange				=
4102			{
4103				VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlags					stageFlags;
4104				0u,															// deUint32								offset;
4105				sizeof(deInt32)												// deUint32								size;
4106			};
4107			const VkPipelineLayoutCreateInfo		copySamplePipelineLayoutParams	=
4108			{
4109				VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,				// VkStructureType						sType;
4110				DE_NULL,													// const void*							pNext;
4111				0u,															// VkPipelineLayoutCreateFlags			flags;
4112				1u,															// deUint32								setLayoutCount;
4113				&m_copySampleDesciptorLayout.get(),							// const VkDescriptorSetLayout*			pSetLayouts;
4114				1u,															// deUint32								pushConstantRangeCount;
4115				&pushConstantRange											// const VkPushConstantRange*			pPushConstantRanges;
4116			};
4117			m_copySamplePipelineLayout		= PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &copySamplePipelineLayoutParams);
4118		}
4119	}
4120
4121	m_vertexShaderModule	= ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
4122	m_fragmentShaderModule	= ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
4123
4124	if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
4125	{
4126		m_copySampleVertexShaderModule		= ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("quad_vert"), 0);
4127		m_copySampleFragmentShaderModule	= ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("copy_sample_frag"), 0);
4128	}
4129
4130	// Create pipeline
4131	{
4132		const VkVertexInputBindingDescription	vertexInputBindingDescription =
4133		{
4134			0u,									// deUint32				binding;
4135			sizeof(Vertex4RGBA),				// deUint32				stride;
4136			VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputRate	inputRate;
4137		};
4138
4139		const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
4140		{
4141			{
4142				0u,									// deUint32	location;
4143				0u,									// deUint32	binding;
4144				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
4145				0u									// deUint32	offset;
4146			},
4147			{
4148				1u,									// deUint32	location;
4149				0u,									// deUint32	binding;
4150				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
4151				DE_OFFSET_OF(Vertex4RGBA, color),	// deUint32	offset;
4152			}
4153		};
4154
4155		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
4156		{
4157			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
4158			DE_NULL,														// const void*								pNext;
4159			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
4160			1u,																// deUint32									vertexBindingDescriptionCount;
4161			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
4162			2u,																// deUint32									vertexAttributeDescriptionCount;
4163			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
4164		};
4165
4166		const std::vector<VkViewport>	viewports		{ makeViewport(m_renderSize) };
4167		const std::vector<VkRect2D>		scissors		{ makeRect2D(m_renderSize) };
4168
4169		const deUint32					attachmentCount	= m_renderType == RENDER_TYPE_UNUSED_ATTACHMENT ? 2u : 1u;
4170
4171		std::vector<VkPipelineColorBlendAttachmentState> attachments;
4172
4173		for (deUint32 attachmentIdx = 0; attachmentIdx < attachmentCount; attachmentIdx++)
4174			attachments.push_back(m_colorBlendState);
4175
4176		VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
4177		{
4178			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
4179			DE_NULL,													// const void*									pNext;
4180			0u,															// VkPipelineColorBlendStateCreateFlags			flags;
4181			false,														// VkBool32										logicOpEnable;
4182			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
4183			attachmentCount,											// deUint32										attachmentCount;
4184			attachments.data(),											// const VkPipelineColorBlendAttachmentState*	pAttachments;
4185			{ 0.0f, 0.0f, 0.0f, 0.0f }									// float										blendConstants[4];
4186		};
4187
4188		const VkStencilOpState stencilOpState =
4189		{
4190			VK_STENCIL_OP_KEEP,						// VkStencilOp	failOp;
4191			VK_STENCIL_OP_REPLACE,					// VkStencilOp	passOp;
4192			VK_STENCIL_OP_KEEP,						// VkStencilOp	depthFailOp;
4193			VK_COMPARE_OP_GREATER,					// VkCompareOp	compareOp;
4194			1u,										// deUint32		compareMask;
4195			1u,										// deUint32		writeMask;
4196			1u,										// deUint32		reference;
4197		};
4198
4199		const VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
4200		{
4201			VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
4202			DE_NULL,													// const void*								pNext;
4203			0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
4204			m_useDepth,													// VkBool32									depthTestEnable;
4205			m_useDepth,													// VkBool32									depthWriteEnable;
4206			VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
4207			false,														// VkBool32									depthBoundsTestEnable;
4208			m_useStencil,												// VkBool32									stencilTestEnable;
4209			stencilOpState,												// VkStencilOpState							front;
4210			stencilOpState,												// VkStencilOpState							back;
4211			0.0f,														// float									minDepthBounds;
4212			1.0f,														// float									maxDepthBounds;
4213		};
4214
4215		const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo
4216		{
4217			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,						// VkStructureType								sType
4218			m_useConservative ? &m_rasterizationConservativeStateCreateInfo : DE_NULL,		// const void*									pNext
4219			0u,																				// VkPipelineRasterizationStateCreateFlags		flags
4220			VK_FALSE,																		// VkBool32										depthClampEnable
4221			VK_FALSE,																		// VkBool32										rasterizerDiscardEnable
4222			VK_POLYGON_MODE_FILL,															// VkPolygonMode								polygonMode
4223			VK_CULL_MODE_NONE,																// VkCullModeFlags								cullMode
4224			VK_FRONT_FACE_COUNTER_CLOCKWISE,												// VkFrontFace									frontFace
4225			VK_FALSE,																		// VkBool32										depthBiasEnable
4226			0.0f,																			// float										depthBiasConstantFactor
4227			0.0f,																			// float										depthBiasClamp
4228			0.0f,																			// float										depthBiasSlopeFactor
4229			1.0f																			// float										lineWidth
4230		};
4231
4232		VkPipelineFragmentShadingRateStateCreateInfoKHR shadingRateStateCreateInfo
4233		{
4234			VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR,								// VkStructureType						sType;
4235			DE_NULL,																							// const void*							pNext;
4236			{ 2, 2 },																							// VkExtent2D							fragmentSize;
4237			{ VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR, VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR },	// VkFragmentShadingRateCombinerOpKHR	combinerOps[2];
4238		};
4239
4240		const deUint32 numSubpasses = m_renderType == RENDER_TYPE_DEPTHSTENCIL_ONLY ? 2u : 1u;
4241
4242		m_graphicsPipelines.reserve(numSubpasses * numTopologies);
4243		for (deUint32 subpassIdx = 0; subpassIdx < numSubpasses; subpassIdx++)
4244		{
4245			if (m_renderType == RENDER_TYPE_DEPTHSTENCIL_ONLY)
4246			{
4247				if (subpassIdx == 0)
4248				{
4249					colorBlendStateParams.attachmentCount = 0;
4250				}
4251				else
4252				{
4253					colorBlendStateParams.attachmentCount = 1;
4254				}
4255			}
4256			for (deUint32 i = 0u; i < numTopologies; ++i)
4257			{
4258				m_graphicsPipelines.emplace_back(vki, vk, physicalDevice, vkDevice, context.getDeviceExtensions(), m_pipelineConstructionType);
4259				m_graphicsPipelines.back().setDefaultTopology(pTopology[i])
4260										  .setupVertexInputState(&vertexInputStateParams)
4261										  .setupPreRasterizationShaderState(viewports,
4262																			scissors,
4263																			m_pipelineLayout,
4264																			*m_renderPass,
4265																			subpassIdx,
4266																			m_vertexShaderModule,
4267																			&rasterizationStateCreateInfo,
4268																			ShaderWrapper(), ShaderWrapper(), ShaderWrapper(), DE_NULL,
4269																			(m_useFragmentShadingRate ? &shadingRateStateCreateInfo : nullptr))
4270										  .setupFragmentShaderState(m_pipelineLayout,
4271																	*m_renderPass,
4272																	subpassIdx,
4273																	m_fragmentShaderModule,
4274																	&depthStencilStateParams,
4275																	&m_multisampleStateParams)
4276										  .setupFragmentOutputState(*m_renderPass, subpassIdx, &colorBlendStateParams, &m_multisampleStateParams)
4277										  .setMonolithicPipelineLayout(m_pipelineLayout)
4278										  .buildPipeline();
4279			}
4280		}
4281	}
4282
4283	if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
4284	{
4285		// Create pipelines for copying samples to single sampled images
4286		{
4287			const VkPipelineVertexInputStateCreateInfo vertexInputStateParams
4288			{
4289				VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
4290				DE_NULL,														// const void*								pNext;
4291				0u,																// VkPipelineVertexInputStateCreateFlags	flags;
4292				0u,																// deUint32									vertexBindingDescriptionCount;
4293				DE_NULL,														// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
4294				0u,																// deUint32									vertexAttributeDescriptionCount;
4295				DE_NULL															// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
4296			};
4297
4298			const std::vector<VkViewport>	viewports	{ makeViewport(m_renderSize) };
4299			const std::vector<VkRect2D>		scissors	{ makeRect2D(m_renderSize) };
4300
4301			const VkPipelineColorBlendStateCreateInfo colorBlendStateParams
4302			{
4303				VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
4304				DE_NULL,													// const void*									pNext;
4305				0u,															// VkPipelineColorBlendStateCreateFlags			flags;
4306				false,														// VkBool32										logicOpEnable;
4307				VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
4308				1u,															// deUint32										attachmentCount;
4309				&m_colorBlendState,											// const VkPipelineColorBlendAttachmentState*	pAttachments;
4310				{ 0.0f, 0.0f, 0.0f, 0.0f }									// float										blendConstants[4];
4311			};
4312
4313			m_copySamplePipelines.reserve(m_perSampleImages.size());
4314			for (size_t i = 0; i < m_perSampleImages.size(); ++i)
4315			{
4316				// Pipeline is to be used in subpasses subsequent to sample-shading subpass
4317
4318				const deUint32 subpassIdx = 1u + (deUint32)i;
4319				m_copySamplePipelines.emplace_back(vki, vk, physicalDevice, vkDevice, m_context.getDeviceExtensions(), m_pipelineConstructionType);
4320				m_copySamplePipelines.back().setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
4321											.setDefaultRasterizationState()
4322											.setDefaultMultisampleState()
4323											.setDefaultDepthStencilState()
4324											.setupVertexInputState(&vertexInputStateParams)
4325											.setupPreRasterizationShaderState(viewports,
4326																			scissors,
4327																			m_copySamplePipelineLayout,
4328																			*m_renderPass,
4329																			subpassIdx,
4330																			m_copySampleVertexShaderModule)
4331											.setupFragmentShaderState(m_copySamplePipelineLayout,
4332																	*m_renderPass,
4333																	subpassIdx,
4334																	m_copySampleFragmentShaderModule)
4335											.setupFragmentOutputState(*m_renderPass, subpassIdx, &colorBlendStateParams)
4336											.setMonolithicPipelineLayout(m_copySamplePipelineLayout)
4337											.buildPipeline();
4338			}
4339		}
4340
4341		const VkDescriptorPoolSize			descriptorPoolSize
4342		{
4343			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,					// VkDescriptorType					type;
4344			1u														// deUint32							descriptorCount;
4345		};
4346
4347		const VkDescriptorPoolCreateInfo	descriptorPoolCreateInfo
4348		{
4349			VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,			// VkStructureType					sType
4350			DE_NULL,												// const void*						pNext
4351			VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,		// VkDescriptorPoolCreateFlags		flags
4352			1u,													// deUint32							maxSets
4353			1u,														// deUint32							poolSizeCount
4354			&descriptorPoolSize										// const VkDescriptorPoolSize*		pPoolSizes
4355		};
4356
4357		m_copySampleDesciptorPool = createDescriptorPool(vk, vkDevice, &descriptorPoolCreateInfo);
4358
4359		const VkDescriptorSetAllocateInfo	descriptorSetAllocateInfo
4360		{
4361			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,			// VkStructureType					sType
4362			DE_NULL,												// const void*						pNext
4363			*m_copySampleDesciptorPool,								// VkDescriptorPool					descriptorPool
4364			1u,														// deUint32							descriptorSetCount
4365			&m_copySampleDesciptorLayout.get(),						// const VkDescriptorSetLayout*		pSetLayouts
4366		};
4367
4368		m_copySampleDesciptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
4369
4370		const VkDescriptorImageInfo			imageInfo
4371		{
4372			DE_NULL,
4373			*m_colorAttachmentView,
4374			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
4375		};
4376		const VkWriteDescriptorSet			descriptorWrite
4377		{
4378			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,			// VkStructureType					sType;
4379			DE_NULL,										// const void*						pNext;
4380			*m_copySampleDesciptorSet,						// VkDescriptorSet					dstSet;
4381			0u,												// deUint32							dstBinding;
4382			0u,												// deUint32							dstArrayElement;
4383			1u,												// deUint32							descriptorCount;
4384			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,			// VkDescriptorType					descriptorType;
4385			&imageInfo,										// const VkDescriptorImageInfo*		pImageInfo;
4386			DE_NULL,										// const VkDescriptorBufferInfo*	pBufferInfo;
4387			DE_NULL,										// const VkBufferView*				pTexelBufferView;
4388		};
4389		vk.updateDescriptorSets(vkDevice, 1u, &descriptorWrite, 0u, DE_NULL);
4390	}
4391
4392	// Create vertex buffer
4393	{
4394		const VkBufferCreateInfo vertexBufferParams
4395		{
4396			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
4397			DE_NULL,									// const void*			pNext;
4398			0u,											// VkBufferCreateFlags	flags;
4399			1024u,										// VkDeviceSize			size;
4400			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
4401			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
4402			1u,											// deUint32				queueFamilyIndexCount;
4403			&queueFamilyIndices[0]						// const deUint32*		pQueueFamilyIndices;
4404		};
4405
4406		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
4407		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
4408
4409		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
4410
4411		// Load vertices into vertex buffer
4412		{
4413			Vertex4RGBA* pDst = static_cast<Vertex4RGBA*>(m_vertexBufferAlloc->getHostPtr());
4414
4415			if (m_renderType == RENDER_TYPE_DEPTHSTENCIL_ONLY)
4416			{
4417				DE_ASSERT(numTopologies == 1);
4418
4419				std::vector<Vertex4RGBA> vertices = pVertices[0];
4420
4421				// Set alpha to zero for the first draw. This should prevent depth writes because of zero coverage.
4422				for (size_t i = 0; i < vertices.size(); i++)
4423					vertices[i].color.w() = 0.0f;
4424
4425				deMemcpy(pDst, &vertices[0], vertices.size() * sizeof(Vertex4RGBA));
4426
4427				pDst += vertices.size();
4428
4429				// The second draw uses original vertices which are pure red.
4430				deMemcpy(pDst, &pVertices[0][0], pVertices[0].size() * sizeof(Vertex4RGBA));
4431			}
4432			else
4433			{
4434				for (deUint32 i = 0u; i < numTopologies; ++i)
4435				{
4436					deMemcpy(pDst, &pVertices[i][0], pVertices[i].size() * sizeof(Vertex4RGBA));
4437					pDst += pVertices[i].size();
4438				}
4439			}
4440		}
4441		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
4442	}
4443
4444	// Create command pool
4445	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndices[0]);
4446
4447	// Create command buffer
4448	{
4449		VkClearValue colorClearValue;
4450		if (m_renderType == RENDER_TYPE_DEPTHSTENCIL_ONLY)
4451		{
4452			colorClearValue.color.float32[0] = 0.25;
4453			colorClearValue.color.float32[1] = 0.25;
4454			colorClearValue.color.float32[2] = 0.25;
4455			colorClearValue.color.float32[3] = 1.0f;
4456		}
4457		else
4458		{
4459			colorClearValue.color.float32[0] = 0.0f;
4460			colorClearValue.color.float32[1] = 0.0f;
4461			colorClearValue.color.float32[2] = 0.0f;
4462			colorClearValue.color.float32[3] = 0.0f;
4463		}
4464
4465		VkClearValue depthStencilClearValue;
4466		depthStencilClearValue.depthStencil.depth = m_depthClearValue;
4467		depthStencilClearValue.depthStencil.stencil = 0u;
4468
4469		std::vector<VkClearValue> clearValues;
4470		clearValues.push_back(colorClearValue);
4471		if (usesResolveImage)
4472		{
4473			clearValues.push_back(colorClearValue);
4474		}
4475		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
4476		{
4477			for (size_t i = 0; i < m_perSampleImages.size(); ++i)
4478			{
4479				clearValues.push_back(colorClearValue);
4480			}
4481		}
4482		if (m_useDepth || m_useStencil)
4483		{
4484			clearValues.push_back(depthStencilClearValue);
4485		}
4486
4487		vk::VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
4488		std::vector<VkImageMemoryBarrier> imageLayoutBarriers;
4489
4490		{
4491			const VkImageMemoryBarrier colorImageBarrier =
4492			// color attachment image
4493			{
4494				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
4495				DE_NULL,										// const void*				pNext;
4496				0u,												// VkAccessFlags			srcAccessMask;
4497				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
4498				VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
4499				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			newLayout;
4500				VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
4501				VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
4502				*m_colorImage,									// VkImage					image;
4503				{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
4504			};
4505			imageLayoutBarriers.push_back(colorImageBarrier);
4506		}
4507		if (usesResolveImage)
4508		{
4509			const VkImageMemoryBarrier resolveImageBarrier =
4510			// resolve attachment image
4511			{
4512				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
4513				DE_NULL,										// const void*				pNext;
4514				0u,												// VkAccessFlags			srcAccessMask;
4515				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
4516				VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
4517				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			newLayout;
4518				VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
4519				VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
4520				*m_resolveImage,								// VkImage					image;
4521				{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
4522			};
4523			imageLayoutBarriers.push_back(resolveImageBarrier);
4524		}
4525		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
4526		{
4527			for (size_t i = 0; i < m_perSampleImages.size(); ++i)
4528			{
4529				const VkImageMemoryBarrier perSampleImageBarrier =
4530				// resolve attachment image
4531				{
4532					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
4533					DE_NULL,										// const void*				pNext;
4534					0u,												// VkAccessFlags			srcAccessMask;
4535					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
4536					VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
4537					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			newLayout;
4538					VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
4539					VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
4540					*m_perSampleImages[i]->m_image,					// VkImage					image;
4541					{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
4542				};
4543				imageLayoutBarriers.push_back(perSampleImageBarrier);
4544			}
4545		}
4546		if (m_useDepth || m_useStencil)
4547		{
4548			const VkImageMemoryBarrier depthStencilImageBarrier =
4549			// depth/stencil attachment image
4550			{
4551				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
4552				DE_NULL,											// const void*				pNext;
4553				0u,													// VkAccessFlags			srcAccessMask;
4554				VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			dstAccessMask;
4555				VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			oldLayout;
4556				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout			newLayout;
4557				VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
4558				VK_QUEUE_FAMILY_IGNORED,							// deUint32					dstQueueFamilyIndex;
4559				*m_depthStencilImage,								// VkImage					image;
4560				{ depthStencilAttachmentAspect, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
4561			};
4562			imageLayoutBarriers.push_back(depthStencilImageBarrier);
4563			dstStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
4564		}
4565
4566		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
4567
4568		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
4569
4570		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, dstStageMask, (VkDependencyFlags)0,
4571			0u, DE_NULL, 0u, DE_NULL, (deUint32)imageLayoutBarriers.size(), &imageLayoutBarriers[0]);
4572
4573		m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), (deUint32)clearValues.size(), &clearValues[0]);
4574
4575		VkDeviceSize vertexBufferOffset = 0u;
4576
4577		for (deUint32 i = 0u; i < numTopologies; ++i)
4578		{
4579			m_graphicsPipelines[i].bind(*m_cmdBuffer);
4580			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
4581			vk.cmdDraw(*m_cmdBuffer, (deUint32)pVertices[i].size(), 1, 0, 0);
4582
4583			vertexBufferOffset += static_cast<VkDeviceSize>(pVertices[i].size() * sizeof(Vertex4RGBA));
4584		}
4585
4586		if (m_renderType == RENDER_TYPE_DEPTHSTENCIL_ONLY)
4587		{
4588			// The first draw was without color buffer and zero coverage. The depth buffer is expected to still have the clear value.
4589			m_renderPass.nextSubpass(vk, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
4590			m_graphicsPipelines[1].bind(*m_cmdBuffer);
4591			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
4592			// The depth test should pass as the first draw didn't touch the depth buffer.
4593			vk.cmdDraw(*m_cmdBuffer, (deUint32)pVertices[0].size(), 1, 0, 0);
4594		}
4595		else if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
4596		{
4597			// Copy each sample id to single sampled image
4598			for (deInt32 sampleId = 0; sampleId < (deInt32)m_perSampleImages.size(); ++sampleId)
4599			{
4600				m_renderPass.nextSubpass(vk, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
4601				m_copySamplePipelines[sampleId].bind(*m_cmdBuffer);
4602				vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_copySamplePipelineLayout, 0u, 1u, &m_copySampleDesciptorSet.get(), 0u, DE_NULL);
4603				vk.cmdPushConstants(*m_cmdBuffer, *m_copySamplePipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(deInt32), &sampleId);
4604				vk.cmdDraw(*m_cmdBuffer, 4, 1, 0, 0);
4605			}
4606		}
4607
4608		m_renderPass.end(vk, *m_cmdBuffer);
4609
4610		endCommandBuffer(vk, *m_cmdBuffer);
4611	}
4612}
4613
4614MultisampleRenderer::~MultisampleRenderer (void)
4615{
4616}
4617
4618de::MovePtr<tcu::TextureLevel> MultisampleRenderer::render (void)
4619{
4620	const DeviceInterface&		vk					= m_context.getDeviceInterface();
4621	const VkDevice				vkDevice			= m_context.getDevice();
4622	const VkQueue				queue				= m_context.getUniversalQueue();
4623	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
4624
4625	if (m_backingMode == IMAGE_BACKING_MODE_SPARSE)
4626	{
4627		const VkPipelineStageFlags stageBits[] = { VK_PIPELINE_STAGE_TRANSFER_BIT };
4628		submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get(), false, 1u, 1u, &m_bindSemaphore.get(), stageBits);
4629	}
4630	else
4631	{
4632		submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
4633	}
4634
4635	if (m_renderType == RENDER_TYPE_RESOLVE || m_renderType == RENDER_TYPE_DEPTHSTENCIL_ONLY || m_renderType == RENDER_TYPE_UNUSED_ATTACHMENT)
4636	{
4637		return readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, m_context.getDefaultAllocator(), *m_resolveImage, m_colorFormat, m_renderSize.cast<deUint32>());
4638	}
4639	else if(m_renderType == RENDER_TYPE_SINGLE_SAMPLE)
4640	{
4641		return readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, m_context.getDefaultAllocator(), *m_colorImage, m_colorFormat, m_renderSize.cast<deUint32>());
4642	}
4643	else
4644	{
4645		return de::MovePtr<tcu::TextureLevel>();
4646	}
4647}
4648
4649de::MovePtr<tcu::TextureLevel> MultisampleRenderer::getSingleSampledImage (deUint32 sampleId)
4650{
4651	return readColorAttachment(m_context.getDeviceInterface(), m_context.getDevice(), m_context.getUniversalQueue(), m_context.getUniversalQueueFamilyIndex(), m_context.getDefaultAllocator(), *m_perSampleImages[sampleId]->m_image, m_colorFormat, m_renderSize.cast<deUint32>());
4652}
4653
4654de::MovePtr<tcu::TextureLevel> MultisampleRenderer::renderReusingDepth ()
4655{
4656	const auto ctx			= m_context.getContextCommonData();
4657	const auto renderSize	= m_renderSize.cast<uint32_t>();
4658	const auto scissor		= makeRect2D(renderSize);
4659	const auto fbExtent		= makeExtent3D(scissor.extent.width, scissor.extent.height, 1u);
4660	const auto colorUsage	= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
4661	const auto sampleCount	= m_multisampleStateParams.rasterizationSamples;
4662	const auto singleSample	= VK_SAMPLE_COUNT_1_BIT;
4663	const auto bindPoint	= VK_PIPELINE_BIND_POINT_GRAPHICS;
4664
4665	ImageWithBuffer secondColorBuffer	(ctx.vkd, ctx.device, ctx.allocator, fbExtent, m_colorFormat, colorUsage, VK_IMAGE_TYPE_2D, makeDefaultImageSubresourceRange(), 1u, sampleCount);
4666	ImageWithBuffer secondResolveBuffer	(ctx.vkd, ctx.device, ctx.allocator, fbExtent, m_colorFormat, colorUsage, VK_IMAGE_TYPE_2D, makeDefaultImageSubresourceRange(), 1u, singleSample);
4667
4668	const auto pcSize			= static_cast<uint32_t>(sizeof(float));
4669	const auto pcStages			= VK_SHADER_STAGE_VERTEX_BIT;
4670	const auto pcRange			= makePushConstantRange(pcStages, 0u, pcSize);
4671	const auto pipelineLayout	= makePipelineLayout(ctx.vkd, ctx.device, VK_NULL_HANDLE, &pcRange);
4672
4673	const std::vector<VkAttachmentDescription> attachmentDescriptions
4674	{
4675		{ // Color attachment.
4676			0u,											//	VkAttachmentDescriptionFlags	flags;
4677			m_colorFormat,								//	VkFormat						format;
4678			sampleCount,								//	VkSampleCountFlagBits			samples;
4679			VK_ATTACHMENT_LOAD_OP_CLEAR,				//	VkAttachmentLoadOp				loadOp;
4680			VK_ATTACHMENT_STORE_OP_DONT_CARE,			//	VkAttachmentStoreOp				storeOp;
4681			VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//	VkAttachmentLoadOp				stencilLoadOp;
4682			VK_ATTACHMENT_STORE_OP_DONT_CARE,			//	VkAttachmentStoreOp				stencilStoreOp;
4683			VK_IMAGE_LAYOUT_UNDEFINED,					//	VkImageLayout					initialLayout;
4684			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout					finalLayout;
4685		},
4686		{ // Depth/stencil attachment.
4687			0u,													//	VkAttachmentDescriptionFlags	flags;
4688			m_depthStencilFormat,								//	VkFormat						format;
4689			sampleCount,										//	VkSampleCountFlagBits			samples;
4690			VK_ATTACHMENT_LOAD_OP_LOAD,							//	VkAttachmentLoadOp				loadOp;
4691			VK_ATTACHMENT_STORE_OP_DONT_CARE,					//	VkAttachmentStoreOp				storeOp;
4692			VK_ATTACHMENT_LOAD_OP_DONT_CARE,					//	VkAttachmentLoadOp				stencilLoadOp;
4693			VK_ATTACHMENT_STORE_OP_DONT_CARE,					//	VkAttachmentStoreOp				stencilStoreOp;
4694			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	//	VkImageLayout					initialLayout;
4695			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	//	VkImageLayout					finalLayout;
4696		},
4697		{ // Resolve attachment.
4698			0u,											//	VkAttachmentDescriptionFlags	flags;
4699			m_colorFormat,								//	VkFormat						format;
4700			singleSample,								//	VkSampleCountFlagBits			samples;
4701			VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//	VkAttachmentLoadOp				loadOp;
4702			VK_ATTACHMENT_STORE_OP_STORE,				//	VkAttachmentStoreOp				storeOp;
4703			VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//	VkAttachmentLoadOp				stencilLoadOp;
4704			VK_ATTACHMENT_STORE_OP_DONT_CARE,			//	VkAttachmentStoreOp				stencilStoreOp;
4705			VK_IMAGE_LAYOUT_UNDEFINED,					//	VkImageLayout					initialLayout;
4706			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout					finalLayout;
4707		},
4708	};
4709
4710	const auto colorAttachmentReference		= makeAttachmentReference(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
4711	const auto dsAttachmentReference		= makeAttachmentReference(1u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
4712	const auto resolveAttachmentReference	= makeAttachmentReference(2u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
4713
4714	const VkSubpassDescription subpassDescription =
4715	{
4716		0u,								//	VkSubpassDescriptionFlags		flags;
4717		bindPoint,						//	VkPipelineBindPoint				pipelineBindPoint;
4718		0u,								//	uint32_t						inputAttachmentCount;
4719		nullptr,						//	const VkAttachmentReference*	pInputAttachments;
4720		1u,								//	uint32_t						colorAttachmentCount;
4721		&colorAttachmentReference,		//	const VkAttachmentReference*	pColorAttachments;
4722		&resolveAttachmentReference,	//	const VkAttachmentReference*	pResolveAttachments;
4723		&dsAttachmentReference,			//	const VkAttachmentReference*	pDepthStencilAttachment;
4724		0u,								//	uint32_t						preserveAttachmentCount;
4725		nullptr,						//	const uint32_t*					pPreserveAttachments;
4726	};
4727
4728	const VkRenderPassCreateInfo rpCreateInfo =
4729	{
4730		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	//	VkStructureType					sType;
4731		nullptr,									//	const void*						pNext;
4732		0u,											//	VkRenderPassCreateFlags			flags;
4733		de::sizeU32(attachmentDescriptions),		//	uint32_t						attachmentCount;
4734		de::dataOrNull(attachmentDescriptions),		//	const VkAttachmentDescription*	pAttachments;
4735		1u,											//	uint32_t						subpassCount;
4736		&subpassDescription,						//	const VkSubpassDescription*		pSubpasses;
4737		0u,											//	uint32_t						dependencyCount;
4738		nullptr,									//	const VkSubpassDependency*		pDependencies;
4739	};
4740	const auto renderPass = createRenderPass(ctx.vkd, ctx.device, &rpCreateInfo);
4741
4742	const std::vector<VkImageView> fbImageViews
4743	{
4744		secondColorBuffer.getImageView(),
4745		*m_depthStencilAttachmentView,
4746		secondResolveBuffer.getImageView(),
4747	};
4748	const auto framebuffer = makeFramebuffer(ctx.vkd, ctx.device, renderPass.get(), de::sizeU32(fbImageViews), de::dataOrNull(fbImageViews), fbExtent.width, fbExtent.height);
4749
4750	const std::vector<VkViewport>				viewports					(1u, makeViewport(fbExtent));
4751	const std::vector<VkRect2D>					scissors					(1u, scissor);
4752	const VkPipelineVertexInputStateCreateInfo	vertexInputStateCreateInfo	= initVulkanStructure();
4753	const auto									stencilOpState				= makeStencilOpState(VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_NEVER, 0u, 0u, 0u);
4754
4755	// This is the key to test the depth buffer contains the clear value and has not been written to:
4756	// The comparison op is EQUAL, so we will only draw if the depth buffer contains the expected value.
4757	const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo =
4758	{
4759		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,		//	VkStructureType							sType;
4760		nullptr,														//	const void*								pNext;
4761		0u,																//	VkPipelineDepthStencilStateCreateFlags	flags;
4762		VK_TRUE,														//	VkBool32								depthTestEnable;
4763		VK_FALSE,														//	VkBool32								depthWriteEnable;
4764		VK_COMPARE_OP_EQUAL,											//	VkCompareOp								depthCompareOp;
4765		VK_FALSE,														//	VkBool32								depthBoundsTestEnable;
4766		VK_FALSE,														//	VkBool32								stencilTestEnable;
4767		stencilOpState,													//	VkStencilOpState						front;
4768		stencilOpState,													//	VkStencilOpState						back;
4769		0.0f,															//	float									minDepthBounds;
4770		1.0f,															//	float									maxDepthBounds;
4771	};
4772
4773	const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo =
4774	{
4775		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	//	VkStructureType							sType;
4776		nullptr,													//	const void*								pNext;
4777		0u,															//	VkPipelineMultisampleStateCreateFlags	flags;
4778		sampleCount,												//	VkSampleCountFlagBits					rasterizationSamples;
4779		VK_FALSE,													//	VkBool32								sampleShadingEnable;
4780		1.0f,														//	float									minSampleShading;
4781		nullptr,													//	const VkSampleMask*						pSampleMask;
4782		VK_FALSE,													//	VkBool32								alphaToCoverageEnable;
4783		VK_FALSE,													//	VkBool32								alphaToOneEnable;
4784	};
4785
4786	const auto&	binaries	= m_context.getBinaryCollection();
4787	const auto	vertModule	= createShaderModule(ctx.vkd, ctx.device, binaries.get("checkDepth-vert"));
4788	const auto	fragModule	= createShaderModule(ctx.vkd, ctx.device, binaries.get("color_frag"));
4789	const auto	pipeline	= makeGraphicsPipeline(
4790		ctx.vkd, ctx.device, pipelineLayout.get(),
4791		vertModule.get(), VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, fragModule.get(), renderPass.get(),
4792		viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, 0u,
4793		&vertexInputStateCreateInfo, nullptr, &multisampleStateCreateInfo, &depthStencilStateCreateInfo);
4794
4795	const CommandPoolWithBuffer	cmd			(ctx.vkd, ctx.device, ctx.qfIndex);
4796	const auto					cmdBuffer	= cmd.cmdBuffer.get();
4797	const tcu::Vec4				clearColor	(0.0f, 0.0f, 0.0f, 1.0f);
4798
4799	beginCommandBuffer(ctx.vkd, cmdBuffer);
4800	{
4801		// Make sure the previous depth buffer writes have completed already.
4802		const auto depthBarrier	= makeMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT));
4803		const auto depthStages	= (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
4804		cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, depthStages, depthStages, &depthBarrier);
4805	}
4806	beginRenderPass(ctx.vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissor, clearColor);
4807	ctx.vkd.cmdBindPipeline(cmdBuffer, bindPoint, pipeline.get());
4808	ctx.vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), pcStages, 0u, pcSize, &m_depthClearValue);
4809	ctx.vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
4810	endRenderPass(ctx.vkd, cmdBuffer);
4811	endCommandBuffer(ctx.vkd, cmdBuffer);
4812	submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
4813
4814	return readColorAttachment(ctx.vkd, ctx.device, ctx.queue, ctx.qfIndex, ctx.allocator, secondResolveBuffer.getImage(), m_colorFormat, renderSize);
4815}
4816
4817// Multisample tests with subpasses using no attachments.
4818class VariableRateTestCase : public vkt::TestCase
4819{
4820public:
4821	using SampleCounts = std::vector<vk::VkSampleCountFlagBits>;
4822
4823	struct PushConstants
4824	{
4825		int width;
4826		int height;
4827		int samples;
4828	};
4829
4830	struct TestParams
4831	{
4832		PipelineConstructionType	pipelineConstructionType;	// The way pipeline is constructed.
4833		bool						nonEmptyFramebuffer;		// Empty framebuffer or not.
4834		vk::VkSampleCountFlagBits	fbCount;					// If not empty, framebuffer sample count.
4835		bool						unusedAttachment;			// If not empty, create unused attachment or not.
4836		SampleCounts				subpassCounts;				// Counts for the different subpasses.
4837		bool						useFragmentShadingRate;		// Use pipeline fragment shading rate.
4838	};
4839
4840	static const deInt32 kWidth		= 256u;
4841	static const deInt32 kHeight	= 256u;
4842
4843									VariableRateTestCase	(tcu::TestContext& testCtx, const std::string& name, const TestParams& params);
4844	virtual							~VariableRateTestCase	(void) {}
4845
4846	virtual void					initPrograms			(vk::SourceCollections& programCollection) const;
4847	virtual TestInstance*			createInstance			(Context& context) const;
4848	virtual void					checkSupport			(Context& context) const;
4849
4850	static constexpr vk::VkFormat	kColorFormat			= vk::VK_FORMAT_R8G8B8A8_UNORM;
4851
4852private:
4853	TestParams m_params;
4854};
4855
4856class VariableRateTestInstance : public vkt::TestInstance
4857{
4858public:
4859	using TestParams = VariableRateTestCase::TestParams;
4860
4861								VariableRateTestInstance	(Context& context, const TestParams& counts);
4862	virtual						~VariableRateTestInstance	(void) {}
4863
4864	virtual tcu::TestStatus		iterate						(void);
4865
4866private:
4867	TestParams m_params;
4868};
4869
4870VariableRateTestCase::VariableRateTestCase (tcu::TestContext& testCtx, const std::string& name, const TestParams& params)
4871	: vkt::TestCase	(testCtx, name)
4872	, m_params		(params)
4873{
4874}
4875
4876void VariableRateTestCase::initPrograms (vk::SourceCollections& programCollection) const
4877{
4878	std::stringstream vertSrc;
4879
4880	vertSrc	<< "#version 450\n"
4881			<< "\n"
4882			<< "layout(location=0) in vec2 inPos;\n"
4883			<< "\n"
4884			<< "void main() {\n"
4885			<< "    gl_Position = vec4(inPos, 0.0, 1.0);\n"
4886			<< "}\n"
4887			;
4888
4889	std::stringstream fragSrc;
4890
4891	fragSrc	<< "#version 450\n"
4892			<< "\n"
4893			<< "layout(set=0, binding=0, std430) buffer OutBuffer {\n"
4894			<< "    int coverage[];\n"
4895			<< "} out_buffer;\n"
4896			<< "\n"
4897			<< "layout(push_constant) uniform PushConstants {\n"
4898			<< "    int width;\n"
4899			<< "    int height;\n"
4900			<< "    int samples;\n"
4901			<< "} push_constants;\n"
4902			<< "\n"
4903			<< "void main() {\n"
4904			<< "   ivec2 coord = ivec2(floor(gl_FragCoord.xy));\n"
4905			<< "   int pos = ((coord.y * push_constants.width) + coord.x) * push_constants.samples + int(gl_SampleID);\n"
4906			<< "   out_buffer.coverage[pos] = 1;\n"
4907			<< "}\n"
4908			;
4909
4910	programCollection.glslSources.add("vert") << glu::VertexSource(vertSrc.str());
4911	programCollection.glslSources.add("frag") << glu::FragmentSource(fragSrc.str());
4912}
4913
4914TestInstance* VariableRateTestCase::createInstance (Context& context) const
4915{
4916	return new VariableRateTestInstance(context, m_params);
4917}
4918
4919void VariableRateTestCase::checkSupport (Context& context) const
4920{
4921	const auto&	vki				= context.getInstanceInterface();
4922	const auto	physicalDevice	= context.getPhysicalDevice();
4923
4924	// When using multiple subpasses, require variableMultisampleRate.
4925	if (m_params.subpassCounts.size() > 1)
4926	{
4927		if (!vk::getPhysicalDeviceFeatures(vki, physicalDevice).variableMultisampleRate)
4928			TCU_THROW(NotSupportedError, "Variable multisample rate not supported");
4929	}
4930
4931	// Check if sampleRateShading is supported.
4932	if(!vk::getPhysicalDeviceFeatures(vki, physicalDevice).sampleRateShading)
4933		TCU_THROW(NotSupportedError, "Sample rate shading is not supported");
4934
4935	// Make sure all subpass sample counts are supported.
4936	const auto	properties		= vk::getPhysicalDeviceProperties(vki, physicalDevice);
4937	const auto&	supportedCounts	= properties.limits.framebufferNoAttachmentsSampleCounts;
4938
4939	for (const auto count : m_params.subpassCounts)
4940	{
4941		if ((supportedCounts & count) == 0u)
4942			TCU_THROW(NotSupportedError, "Sample count combination not supported");
4943	}
4944
4945	if (m_params.nonEmptyFramebuffer)
4946	{
4947		// Check the framebuffer sample count is supported.
4948		const auto formatProperties = vk::getPhysicalDeviceImageFormatProperties(vki, physicalDevice, kColorFormat, vk::VK_IMAGE_TYPE_2D, vk::VK_IMAGE_TILING_OPTIMAL, vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0u);
4949		if ((formatProperties.sampleCounts & m_params.fbCount) == 0u)
4950			TCU_THROW(NotSupportedError, "Sample count of " + de::toString(m_params.fbCount) + " not supported for color attachment");
4951	}
4952
4953	if (m_params.useFragmentShadingRate && !checkFragmentShadingRateRequirements(context, m_params.fbCount))
4954		TCU_THROW(NotSupportedError, "Required FragmentShadingRate not supported");
4955
4956	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType);
4957}
4958
4959void zeroOutAndFlush(const vk::DeviceInterface& vkd, vk::VkDevice device, vk::BufferWithMemory& buffer, vk::VkDeviceSize size)
4960{
4961	auto& alloc = buffer.getAllocation();
4962	deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(size));
4963	vk::flushAlloc(vkd, device, alloc);
4964}
4965
4966VariableRateTestInstance::VariableRateTestInstance (Context& context, const TestParams& params)
4967	: vkt::TestInstance	(context)
4968	, m_params			(params)
4969{
4970}
4971
4972tcu::TestStatus VariableRateTestInstance::iterate (void)
4973{
4974	using PushConstants = VariableRateTestCase::PushConstants;
4975
4976	const auto&	vki			= m_context.getInstanceInterface();
4977	const auto&	vkd			= m_context.getDeviceInterface();
4978	const auto	physDevice	= m_context.getPhysicalDevice();
4979	const auto	device		= m_context.getDevice();
4980	auto&		allocator	= m_context.getDefaultAllocator();
4981	const auto&	queue		= m_context.getUniversalQueue();
4982	const auto	queueIndex	= m_context.getUniversalQueueFamilyIndex();
4983
4984	const vk::VkDeviceSize	kWidth			= static_cast<vk::VkDeviceSize>(VariableRateTestCase::kWidth);
4985	const vk::VkDeviceSize	kHeight			= static_cast<vk::VkDeviceSize>(VariableRateTestCase::kHeight);
4986	constexpr auto			kColorFormat	= VariableRateTestCase::kColorFormat;
4987
4988	const auto kWidth32		= static_cast<deUint32>(kWidth);
4989	const auto kHeight32	= static_cast<deUint32>(kHeight);
4990
4991	std::vector<std::unique_ptr<vk::BufferWithMemory>>	referenceBuffers;
4992	std::vector<std::unique_ptr<vk::BufferWithMemory>>	outputBuffers;
4993	std::vector<size_t>									bufferNumElements;
4994	std::vector<vk::VkDeviceSize>						bufferSizes;
4995
4996	// Create reference and output buffers.
4997	for (const auto count : m_params.subpassCounts)
4998	{
4999		bufferNumElements.push_back(static_cast<size_t>(kWidth * kHeight * count));
5000		bufferSizes.push_back(bufferNumElements.back() * sizeof(deInt32));
5001		const auto bufferCreateInfo = vk::makeBufferCreateInfo(bufferSizes.back(), vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
5002
5003		referenceBuffers.emplace_back	(new vk::BufferWithMemory{vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible});
5004		outputBuffers.emplace_back		(new vk::BufferWithMemory{vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible});
5005	}
5006
5007	// Descriptor set layout.
5008	vk::DescriptorSetLayoutBuilder builder;
5009	builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
5010	const auto descriptorSetLayout = builder.build(vkd, device);
5011
5012	// Pipeline layout.
5013	const vk::VkPushConstantRange pushConstantRange =
5014	{
5015		vk::VK_SHADER_STAGE_FRAGMENT_BIT,				//	VkShaderStageFlags	stageFlags;
5016		0u,												//	deUint32			offset;
5017		static_cast<deUint32>(sizeof(PushConstants)),	//	deUint32			size;
5018	};
5019
5020	const vk::VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
5021	{
5022		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	//	VkStructureType					sType;
5023		nullptr,											//	const void*						pNext;
5024		0u,													//	VkPipelineLayoutCreateFlags		flags;
5025		1u,													//	deUint32						setLayoutCount;
5026		&descriptorSetLayout.get(),							//	const VkDescriptorSetLayout*	pSetLayouts;
5027		1u,													//	deUint32						pushConstantRangeCount;
5028		&pushConstantRange,									//	const VkPushConstantRange*		pPushConstantRanges;
5029	};
5030	const vk::PipelineLayoutWrapper pipelineLayout (m_params.pipelineConstructionType, vkd, device, &pipelineLayoutCreateInfo);
5031
5032	// Subpass with no attachments.
5033	const vk::VkSubpassDescription emptySubpassDescription =
5034	{
5035		0u,										//	VkSubpassDescriptionFlags		flags;
5036		vk::VK_PIPELINE_BIND_POINT_GRAPHICS,	//	VkPipelineBindPoint				pipelineBindPoint;
5037		0u,										//	deUint32						inputAttachmentCount;
5038		nullptr,								//	const VkAttachmentReference*	pInputAttachments;
5039		0u,										//	deUint32						colorAttachmentCount;
5040		nullptr,								//	const VkAttachmentReference*	pColorAttachments;
5041		nullptr,								//	const VkAttachmentReference*	pResolveAttachments;
5042		nullptr,								//	const VkAttachmentReference*	pDepthStencilAttachment;
5043		0u,										//	deUint32						preserveAttachmentCount;
5044		nullptr,								//	const deUint32*					pPreserveAttachments;
5045	};
5046
5047	// Unused attachment reference.
5048	const vk::VkAttachmentReference unusedAttachmentReference =
5049	{
5050		VK_ATTACHMENT_UNUSED,							//	deUint32		attachment;
5051		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout	layout;
5052	};
5053
5054	// Subpass with unused attachment.
5055	const vk::VkSubpassDescription unusedAttachmentSubpassDescription =
5056	{
5057		0u,										//	VkSubpassDescriptionFlags		flags;
5058		vk::VK_PIPELINE_BIND_POINT_GRAPHICS,	//	VkPipelineBindPoint				pipelineBindPoint;
5059		0u,										//	deUint32						inputAttachmentCount;
5060		nullptr,								//	const VkAttachmentReference*	pInputAttachments;
5061		1u,										//	deUint32						colorAttachmentCount;
5062		&unusedAttachmentReference,				//	const VkAttachmentReference*	pColorAttachments;
5063		nullptr,								//	const VkAttachmentReference*	pResolveAttachments;
5064		nullptr,								//	const VkAttachmentReference*	pDepthStencilAttachment;
5065		0u,										//	deUint32						preserveAttachmentCount;
5066		nullptr,								//	const deUint32*					pPreserveAttachments;
5067	};
5068
5069	// Renderpass with multiple subpasses.
5070	vk::VkRenderPassCreateInfo renderPassCreateInfo =
5071	{
5072		vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	//	VkStructureType					sType;
5073		nullptr,										//	const void*						pNext;
5074		0u,												//	VkRenderPassCreateFlags			flags;
5075		0u,												//	deUint32						attachmentCount;
5076		nullptr,										//	const VkAttachmentDescription*	pAttachments;
5077		0u,												//	deUint32						subpassCount;
5078		nullptr,										//	const VkSubpassDescription*		pSubpasses;
5079		0u,												//	deUint32						dependencyCount;
5080		nullptr,										//	const VkSubpassDependency*		pDependencies;
5081	};
5082
5083	std::vector<vk::VkSubpassDescription> subpassesVector;
5084
5085	for (size_t i = 0; i < m_params.subpassCounts.size(); ++i)
5086		subpassesVector.push_back(emptySubpassDescription);
5087	renderPassCreateInfo.subpassCount	= static_cast<deUint32>(subpassesVector.size());
5088	renderPassCreateInfo.pSubpasses		= subpassesVector.data();
5089	RenderPassWrapper renderPassMultiplePasses (m_params.pipelineConstructionType, vkd, device, &renderPassCreateInfo);
5090
5091	// Render pass with single subpass.
5092	const vk::VkAttachmentDescription colorAttachmentDescription =
5093	{
5094		0u,												//	VkAttachmentDescriptionFlags	flags;
5095		kColorFormat,									//	VkFormat						format;
5096		m_params.fbCount,								//	VkSampleCountFlagBits			samples;
5097		vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//	VkAttachmentLoadOp				loadOp;
5098		vk::VK_ATTACHMENT_STORE_OP_STORE,				//	VkAttachmentStoreOp				storeOp;
5099		vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//	VkAttachmentLoadOp				stencilLoadOp;
5100		vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			//	VkAttachmentStoreOp				stencilStoreOp;
5101		vk::VK_IMAGE_LAYOUT_UNDEFINED,					//	VkImageLayout					initialLayout;
5102		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout					finalLayout;
5103	};
5104
5105	if (m_params.nonEmptyFramebuffer)
5106	{
5107		renderPassCreateInfo.attachmentCount = 1u;
5108		renderPassCreateInfo.pAttachments = &colorAttachmentDescription;
5109	}
5110	const bool unusedAttachmentSubpass			= (m_params.nonEmptyFramebuffer && m_params.unusedAttachment);
5111	renderPassCreateInfo.subpassCount			= 1u;
5112	renderPassCreateInfo.pSubpasses				= (unusedAttachmentSubpass ? &unusedAttachmentSubpassDescription : &emptySubpassDescription);
5113	RenderPassWrapper renderPassSingleSubpass	(m_params.pipelineConstructionType, vkd, device, &renderPassCreateInfo);
5114
5115	// Framebuffers.
5116	vk::VkFramebufferCreateInfo framebufferCreateInfo =
5117	{
5118		vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	//	VkStructureType				sType;
5119		nullptr,										//	const void*					pNext;
5120		0u,												//	VkFramebufferCreateFlags	flags;
5121		DE_NULL,										//	VkRenderPass				renderPass;
5122		0u,												//	deUint32					attachmentCount;
5123		nullptr,										//	const VkImageView*			pAttachments;
5124		kWidth32,										//	deUint32					width;
5125		kHeight32,										//	deUint32					height;
5126		1u,												//	deUint32					layers;
5127	};
5128
5129	// Framebuffer for multiple-subpasses render pass.
5130	framebufferCreateInfo.renderPass		= renderPassMultiplePasses.get();
5131	renderPassMultiplePasses.createFramebuffer(vkd, device, &framebufferCreateInfo, std::vector<VkImage>{});
5132
5133	// Framebuffer for single-subpass render pass.
5134	std::unique_ptr<vk::ImageWithMemory>	imagePtr;
5135	vk::Move<vk::VkImageView>				imageView;
5136	std::vector<vk::VkImage>				images;
5137
5138	if (m_params.nonEmptyFramebuffer)
5139	{
5140		const vk::VkImageCreateInfo imageCreateInfo =
5141		{
5142			vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
5143			nullptr,									//	const void*				pNext;
5144			0u,											//	VkImageCreateFlags		flags;
5145			vk::VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
5146			kColorFormat,								//	VkFormat				format;
5147			vk::makeExtent3D(kWidth32, kHeight32, 1u),	//	VkExtent3D				extent;
5148			1u,											//	deUint32				mipLevels;
5149			1u,											//	deUint32				arrayLayers;
5150			m_params.fbCount,							//	VkSampleCountFlagBits	samples;
5151			vk::VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
5152			vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,	//	VkImageUsageFlags		usage;
5153			vk::VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
5154			0u,											//	deUint32				queueFamilyIndexCount;
5155			nullptr,									//	const deUint32*			pQueueFamilyIndices;
5156			vk::VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
5157		};
5158		imagePtr.reset(new vk::ImageWithMemory{vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any});
5159
5160		const auto subresourceRange	= vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
5161		imageView					= vk::makeImageView(vkd, device, imagePtr->get(), vk::VK_IMAGE_VIEW_TYPE_2D, kColorFormat, subresourceRange);
5162
5163		framebufferCreateInfo.attachmentCount	= 1u;
5164		framebufferCreateInfo.pAttachments		= &imageView.get();
5165		images.push_back(**imagePtr);
5166	}
5167	framebufferCreateInfo.renderPass	= renderPassSingleSubpass.get();
5168	renderPassSingleSubpass.createFramebuffer(vkd, device, &framebufferCreateInfo, images);
5169
5170	// Shader modules and stages.
5171	const auto vertModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
5172	const auto fragModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
5173
5174	// Vertices, input state and assembly.
5175	const std::vector<tcu::Vec2> vertices =
5176	{
5177		{ -0.987f, -0.964f },
5178		{  0.982f, -0.977f },
5179		{  0.005f,  0.891f },
5180	};
5181
5182	const auto vertexBinding	= vk::makeVertexInputBindingDescription(0u, static_cast<deUint32>(sizeof(decltype(vertices)::value_type)), vk::VK_VERTEX_INPUT_RATE_VERTEX);
5183	const auto vertexAttribute	= vk::makeVertexInputAttributeDescription(0u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, 0u);
5184
5185	const vk::VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
5186	{
5187		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	//	VkStructureType								sType;
5188		nullptr,														//	const void*									pNext;
5189		0u,																//	VkPipelineVertexInputStateCreateFlags		flags;
5190		1u,																//	deUint32									vertexBindingDescriptionCount;
5191		&vertexBinding,													//	const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
5192		1u,																//	deUint32									vertexAttributeDescriptionCount;
5193		&vertexAttribute,												//	const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
5194	};
5195
5196	// Graphics pipelines to create output buffers.
5197	const std::vector<VkViewport>	viewport	{ vk::makeViewport(kWidth32, kHeight32) };
5198	const std::vector<VkRect2D>		scissor		{ vk::makeRect2D(kWidth32, kHeight32) };
5199
5200	const VkColorComponentFlags colorComponentFlags = (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
5201
5202	const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
5203	{
5204		VK_FALSE,				//	VkBool32				blendEnable;
5205		VK_BLEND_FACTOR_ZERO,	//	VkBlendFactor			srcColorBlendFactor;
5206		VK_BLEND_FACTOR_ZERO,	//	VkBlendFactor			dstColorBlendFactor;
5207		VK_BLEND_OP_ADD,		//	VkBlendOp				colorBlendOp;
5208		VK_BLEND_FACTOR_ZERO,	//	VkBlendFactor			srcAlphaBlendFactor;
5209		VK_BLEND_FACTOR_ZERO,	//	VkBlendFactor			dstAlphaBlendFactor;
5210		VK_BLEND_OP_ADD,		//	VkBlendOp				alphaBlendOp;
5211		colorComponentFlags,	//	VkColorComponentFlags	colorWriteMask;
5212	};
5213
5214	const vk::VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfoNoAttachments =
5215	{
5216		vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
5217		DE_NULL,														// const void*									pNext;
5218		0u,																// VkPipelineColorBlendStateCreateFlags			flags;
5219		VK_FALSE,														// VkBool32										logicOpEnable;
5220		vk::VK_LOGIC_OP_CLEAR,											// VkLogicOp									logicOp;
5221		0u,																// deUint32										attachmentCount;
5222		nullptr,														// const VkPipelineColorBlendAttachmentState*	pAttachments;
5223		{ 0.0f, 0.0f, 0.0f, 0.0f }										// float										blendConstants[4];
5224	};
5225
5226	const vk::VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfoOneAttachment =
5227	{
5228		vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
5229		DE_NULL,														// const void*									pNext;
5230		0u,																// VkPipelineColorBlendStateCreateFlags			flags;
5231		VK_FALSE,														// VkBool32										logicOpEnable;
5232		vk::VK_LOGIC_OP_CLEAR,											// VkLogicOp									logicOp;
5233		1u,																// deUint32										attachmentCount;
5234		&colorBlendAttachmentState,										// const VkPipelineColorBlendAttachmentState*	pAttachments;
5235		{ 0.0f, 0.0f, 0.0f, 0.0f }										// float										blendConstants[4];
5236	};
5237
5238	vk::VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo
5239	{
5240		vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	//	VkStructureType							sType;
5241		nullptr,														//	const void*								pNext;
5242		0u,																//	VkPipelineMultisampleStateCreateFlags	flags;
5243		vk::VK_SAMPLE_COUNT_1_BIT,										//	VkSampleCountFlagBits					rasterizationSamples;
5244		VK_FALSE,														//	VkBool32								sampleShadingEnable;
5245		0.0f,															//	float									minSampleShading;
5246		nullptr,														//	const VkSampleMask*						pSampleMask;
5247		VK_FALSE,														//	VkBool32								alphaToCoverageEnable;
5248		VK_FALSE,														//	VkBool32								alphaToOneEnable;
5249	};
5250
5251	std::vector<GraphicsPipelineWrapper> outputPipelines;
5252	outputPipelines.reserve(m_params.subpassCounts.size());
5253	for (const auto samples : m_params.subpassCounts)
5254	{
5255		const auto colorBlendStatePtr = (unusedAttachmentSubpass ? &colorBlendStateCreateInfoOneAttachment : &colorBlendStateCreateInfoNoAttachments);
5256
5257		multisampleStateCreateInfo.rasterizationSamples = samples;
5258
5259		outputPipelines.emplace_back(vki, vkd, physDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType);
5260		outputPipelines.back()
5261			.setDefaultDepthStencilState()
5262			.setDefaultRasterizationState()
5263			.setupVertexInputState(&vertexInputStateCreateInfo)
5264			.setupPreRasterizationShaderState(viewport,
5265				scissor,
5266				pipelineLayout,
5267				*renderPassSingleSubpass,
5268				0u,
5269				vertModule)
5270			.setupFragmentShaderState(pipelineLayout, *renderPassSingleSubpass, 0u, fragModule, DE_NULL, &multisampleStateCreateInfo)
5271			.setupFragmentOutputState(*renderPassSingleSubpass, 0u, colorBlendStatePtr, &multisampleStateCreateInfo)
5272			.setMonolithicPipelineLayout(pipelineLayout)
5273			.buildPipeline();
5274	}
5275
5276	// Graphics pipelines with variable rate but using several subpasses.
5277	std::vector<GraphicsPipelineWrapper> referencePipelines;
5278	referencePipelines.reserve(m_params.subpassCounts.size());
5279	for (size_t i = 0; i < m_params.subpassCounts.size(); ++i)
5280	{
5281		multisampleStateCreateInfo.rasterizationSamples = m_params.subpassCounts[i];
5282
5283		deUint32 subpass = static_cast<deUint32>(i);
5284		referencePipelines.emplace_back(vki, vkd, physDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType);
5285		referencePipelines.back()
5286			.setDefaultDepthStencilState()
5287			.setDefaultRasterizationState()
5288			.setupVertexInputState(&vertexInputStateCreateInfo)
5289			.setupPreRasterizationShaderState(viewport,
5290				scissor,
5291				pipelineLayout,
5292				*renderPassMultiplePasses,
5293				subpass,
5294				vertModule)
5295			.setupFragmentShaderState(pipelineLayout, *renderPassMultiplePasses, subpass, fragModule, DE_NULL, &multisampleStateCreateInfo)
5296			.setupFragmentOutputState(*renderPassMultiplePasses, subpass, &colorBlendStateCreateInfoNoAttachments, &multisampleStateCreateInfo)
5297			.setMonolithicPipelineLayout(pipelineLayout)
5298			.buildPipeline();
5299	}
5300
5301	// Prepare vertex, reference and output buffers.
5302	const auto				vertexBufferSize		= vertices.size() * sizeof(decltype(vertices)::value_type);
5303	const auto				vertexBufferCreateInfo	= vk::makeBufferCreateInfo(static_cast<VkDeviceSize>(vertexBufferSize), vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
5304	vk::BufferWithMemory	vertexBuffer			{vkd, device, allocator, vertexBufferCreateInfo, MemoryRequirement::HostVisible};
5305	auto&					vertexAlloc				= vertexBuffer.getAllocation();
5306
5307	deMemcpy(vertexAlloc.getHostPtr(), vertices.data(), vertexBufferSize);
5308	vk::flushAlloc(vkd, device, vertexAlloc);
5309
5310	for (size_t i = 0; i < referenceBuffers.size(); ++i)
5311	{
5312		zeroOutAndFlush(vkd, device, *referenceBuffers[i], bufferSizes[i]);
5313		zeroOutAndFlush(vkd, device, *outputBuffers[i], bufferSizes[i]);
5314	}
5315
5316	// Prepare descriptor sets.
5317	const deUint32				totalSets		= static_cast<deUint32>(referenceBuffers.size() * 2u);
5318	vk::DescriptorPoolBuilder	poolBuilder;
5319	poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, static_cast<deUint32>(referenceBuffers.size() * 2u));
5320	const auto descriptorPool = poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, totalSets);
5321
5322	std::vector<vk::Move<vk::VkDescriptorSet>> referenceSets	(referenceBuffers.size());
5323	std::vector<vk::Move<vk::VkDescriptorSet>> outputSets		(outputBuffers.size());
5324
5325	for (auto& set : referenceSets)
5326		set = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
5327	for (auto& set : outputSets)
5328		set = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
5329
5330	vk::DescriptorSetUpdateBuilder updateBuilder;
5331
5332	for (size_t i = 0; i < referenceSets.size(); ++i)
5333	{
5334		const auto descriptorBufferInfo = vk::makeDescriptorBufferInfo(referenceBuffers[i]->get(), 0u, bufferSizes[i]);
5335		updateBuilder.writeSingle(referenceSets[i].get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo);
5336	}
5337	for (size_t i = 0; i < outputSets.size(); ++i)
5338	{
5339		const auto descriptorBufferInfo = vk::makeDescriptorBufferInfo(outputBuffers[i]->get(), 0u, bufferSizes[i]);
5340		updateBuilder.writeSingle(outputSets[i].get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo);
5341	}
5342
5343	updateBuilder.update(vkd, device);
5344
5345	// Prepare command pool.
5346	const auto cmdPool		= vk::makeCommandPool(vkd, device, queueIndex);
5347	const auto cmdBufferPtr	= vk::allocateCommandBuffer(vkd , device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
5348	const auto cmdBuffer	= cmdBufferPtr.get();
5349
5350	vk::VkBufferMemoryBarrier storageBufferDevToHostBarrier =
5351	{
5352		vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	//	VkStructureType	sType;
5353		nullptr,										//	const void*		pNext;
5354		vk::VK_ACCESS_SHADER_WRITE_BIT,					//	VkAccessFlags	srcAccessMask;
5355		vk::VK_ACCESS_HOST_READ_BIT,					//	VkAccessFlags	dstAccessMask;
5356		VK_QUEUE_FAMILY_IGNORED,						//	deUint32		srcQueueFamilyIndex;
5357		VK_QUEUE_FAMILY_IGNORED,						//	deUint32		dstQueueFamilyIndex;
5358		DE_NULL,										//	VkBuffer		buffer;
5359		0u,												//	VkDeviceSize	offset;
5360		VK_WHOLE_SIZE,									//	VkDeviceSize	size;
5361	};
5362
5363	// Record command buffer.
5364	const vk::VkDeviceSize	vertexBufferOffset	= 0u;
5365	const auto				renderArea			= vk::makeRect2D(kWidth32, kHeight32);
5366	PushConstants			pushConstants		= { static_cast<int>(kWidth), static_cast<int>(kHeight), 0 };
5367
5368	vk::beginCommandBuffer(vkd, cmdBuffer);
5369
5370	// Render output buffers.
5371	renderPassSingleSubpass.begin(vkd, cmdBuffer, renderArea);
5372	for (size_t i = 0; i < outputBuffers.size(); ++i)
5373	{
5374		outputPipelines[i].bind(cmdBuffer);
5375		vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &outputSets[i].get(), 0u, nullptr);
5376		vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
5377		pushConstants.samples = static_cast<int>(m_params.subpassCounts[i]);
5378		vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), pushConstantRange.stageFlags, pushConstantRange.offset, pushConstantRange.size, &pushConstants);
5379		vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
5380	}
5381	renderPassSingleSubpass.end(vkd, cmdBuffer);
5382	for (size_t i = 0; i < outputBuffers.size(); ++i)
5383	{
5384		storageBufferDevToHostBarrier.buffer = outputBuffers[i]->get();
5385		vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, nullptr, 1u, &storageBufferDevToHostBarrier, 0u, nullptr);
5386	}
5387
5388	// Render reference buffers.
5389	renderPassMultiplePasses.begin(vkd, cmdBuffer, renderArea);
5390	for (size_t i = 0; i < referenceBuffers.size(); ++i)
5391	{
5392		if (i > 0)
5393			renderPassMultiplePasses.nextSubpass(vkd, cmdBuffer, vk::VK_SUBPASS_CONTENTS_INLINE);
5394		referencePipelines[i].bind(cmdBuffer);
5395		vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &referenceSets[i].get(), 0u, nullptr);
5396		vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
5397		pushConstants.samples = static_cast<int>(m_params.subpassCounts[i]);
5398		vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), pushConstantRange.stageFlags, pushConstantRange.offset, pushConstantRange.size, &pushConstants);
5399		vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
5400	}
5401	renderPassMultiplePasses.end(vkd, cmdBuffer);
5402	for (size_t i = 0; i < referenceBuffers.size(); ++i)
5403	{
5404		storageBufferDevToHostBarrier.buffer = referenceBuffers[i]->get();
5405		vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, nullptr, 1u, &storageBufferDevToHostBarrier, 0u, nullptr);
5406	}
5407
5408	vk::endCommandBuffer(vkd, cmdBuffer);
5409
5410	// Run all pipelines.
5411	vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
5412
5413	// Invalidate reference allocs.
5414#undef LOG_BUFFER_CONTENTS
5415#ifdef LOG_BUFFER_CONTENTS
5416	auto& log = m_context.getTestContext().getLog();
5417#endif
5418	for (size_t i = 0; i < referenceBuffers.size(); ++i)
5419	{
5420		auto& buffer	= referenceBuffers[i];
5421		auto& alloc		= buffer->getAllocation();
5422		vk::invalidateAlloc(vkd, device, alloc);
5423
5424#ifdef LOG_BUFFER_CONTENTS
5425		std::vector<deInt32> bufferValues(bufferNumElements[i]);
5426		deMemcpy(bufferValues.data(), alloc.getHostPtr(), bufferSizes[i]);
5427
5428		std::ostringstream msg;
5429		for (const auto value : bufferValues)
5430			msg << " " << value;
5431		log << tcu::TestLog::Message << "Reference buffer values with " << m_params[i] << " samples:" << msg.str() << tcu::TestLog::EndMessage;
5432#endif
5433	}
5434
5435	for (size_t i = 0; i < outputBuffers.size(); ++i)
5436	{
5437		auto& buffer	= outputBuffers[i];
5438		auto& alloc		= buffer->getAllocation();
5439		vk::invalidateAlloc(vkd, device, alloc);
5440
5441#ifdef LOG_BUFFER_CONTENTS
5442		std::vector<deInt32> bufferValues(bufferNumElements[i]);
5443		deMemcpy(bufferValues.data(), alloc.getHostPtr(), bufferSizes[i]);
5444
5445		std::ostringstream msg;
5446		for (const auto value : bufferValues)
5447			msg << " " << value;
5448		log << tcu::TestLog::Message << "Output buffer values with " << m_params[i] << " samples:" << msg.str() << tcu::TestLog::EndMessage;
5449#endif
5450
5451		if (deMemCmp(alloc.getHostPtr(), referenceBuffers[i]->getAllocation().getHostPtr(), static_cast<size_t>(bufferSizes[i])) != 0)
5452			return tcu::TestStatus::fail("Buffer mismatch in output buffer " + de::toString(i));
5453	}
5454
5455	return tcu::TestStatus::pass("Pass");
5456}
5457
5458using ElementsVector	= std::vector<vk::VkSampleCountFlagBits>;
5459using CombinationVector	= std::vector<ElementsVector>;
5460
5461void combinationsRecursive(const ElementsVector& elements, size_t requestedSize, CombinationVector& solutions, ElementsVector& partial)
5462{
5463	if (partial.size() == requestedSize)
5464		solutions.push_back(partial);
5465	else
5466	{
5467		for (const auto& elem : elements)
5468		{
5469			partial.push_back(elem);
5470			combinationsRecursive(elements, requestedSize, solutions, partial);
5471			partial.pop_back();
5472		}
5473	}
5474}
5475
5476CombinationVector combinations(const ElementsVector& elements, size_t requestedSize)
5477{
5478	CombinationVector solutions;
5479	ElementsVector partial;
5480
5481	combinationsRecursive(elements, requestedSize, solutions, partial);
5482	return solutions;
5483}
5484
5485/********
5486Z EXPORT TESTS
5487
5488The tests enable alpha to coverage statically or dynamically, and play with 3 other parameters, which we can be testing or not as
5489outputs from the frag shader.
5490
5491* Depth value
5492* Stencil reference value
5493* Sample mask
5494
5495Alpha values on the left side of the framebuffer will be 0.0. On the right side they will be 1.0. This means the left side should
5496not have coverage, and the right side should have.
5497
5498Depth value will be cleared to 1.0 and we expect to obtain 0.0 for covered pixels at the end. We will activate the depth test with a
5499depth compare op of "less".
5500
5501* If we are testing this, we will set 0.5 from the vertex shader and 0.0 from the frag shader.
5502* If we are not testing this, we will set 0.0 directly from the vertex shader.
5503
5504Stencil will be cleared to 0 and we expect to obtain 255 for covered pixels at the end. We will activate the stencil test with a
5505stencil op of "replace" for front-facing pixels, compare op "always", keep and "never" for back-facing pixels.
5506
5507* If we are testing this, the stencil ref value will be 128 in the pipeline, then 255 from the frag shader.
5508* If we are not testing this, the reference value will be set to 255 directly in the pipeline.
5509
5510Sample mask is a bit special: we'll always set it to 0xFF in the pipeline, and we normally expect all pixels to be covered.
5511
5512* If we are testing this, we'll set it to 0x00 on the lower half of the framebuffer.
5513* If we are not testing this, we'll leave it as it is.
5514
5515Expected result:
5516
5517* The left side of the framebuffer will have:
5518  - The clear color.
5519  - The clear depth value.
5520  - The clear stencil value.
5521
5522* The right side of the framebuffer will have:
5523  - The geometry color (typically blue).
5524  - The expected depth value.
5525  - The expected stencil value.
5526  - But, if we are testing the sample mask, the lower half of the right side will be like the left side.
5527
5528********/
5529enum ZExportTestBits
5530{
5531	ZEXP_DEPTH_BIT			= 0x1,
5532	ZEXP_STENCIL_BIT		= 0x2,	// Requires VK_EXT_shader_stencil_export
5533	ZEXP_SAMPLE_MASK_BIT	= 0x4,
5534};
5535
5536using ZExportFlags = uint32_t;
5537
5538struct ZExportParams
5539{
5540	const PipelineConstructionType	pipelineConstructionType;
5541	const ZExportFlags				testFlags;
5542	const bool						dynamicAlphaToCoverage;
5543
5544	ZExportParams (PipelineConstructionType pipelineConstructionType_, ZExportFlags testFlags_, bool dynamicAlphaToCoverage_)
5545		: pipelineConstructionType	(pipelineConstructionType_)
5546		, testFlags					(testFlags_)
5547		, dynamicAlphaToCoverage	(dynamicAlphaToCoverage_)
5548	{}
5549
5550	bool testDepth		(void) const	{ return hasFlag(ZEXP_DEPTH_BIT);		}
5551	bool testStencil	(void) const	{ return hasFlag(ZEXP_STENCIL_BIT);		}
5552	bool testSampleMask	(void) const	{ return hasFlag(ZEXP_SAMPLE_MASK_BIT);	}
5553
5554	static constexpr float		kClearDepth			= 1.0f;
5555	static constexpr float		kExpectedDepth		= 0.0f;
5556	static constexpr float		kBadDepth			= 0.5f;
5557
5558	static constexpr uint32_t	kClearStencil		= 0u;
5559	static constexpr uint32_t	kExpectedStencil	= 255u;
5560	static constexpr uint32_t	kBadStencil			= 128u;
5561
5562	static constexpr uint32_t	kWidth				= 4u;
5563	static constexpr uint32_t	kHeight				= 4u;
5564
5565private:
5566	bool hasFlag (ZExportTestBits bit) const
5567	{
5568		return ((testFlags & static_cast<ZExportFlags>(bit)) != 0u);
5569	}
5570};
5571
5572void ZExportCheckSupport (Context& context, const ZExportParams params)
5573{
5574	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), params.pipelineConstructionType);
5575
5576	context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
5577	context.requireDeviceFunctionality("VK_KHR_depth_stencil_resolve");
5578
5579	const auto& dsResolveProperties = context.getDepthStencilResolveProperties();
5580
5581	if ((dsResolveProperties.supportedDepthResolveModes & VK_RESOLVE_MODE_SAMPLE_ZERO_BIT) == 0u)
5582		TCU_THROW(NotSupportedError, "VK_RESOLVE_MODE_SAMPLE_ZERO_BIT not supported for depth");
5583
5584	if ((dsResolveProperties.supportedStencilResolveModes & VK_RESOLVE_MODE_SAMPLE_ZERO_BIT) == 0u)
5585		TCU_THROW(NotSupportedError, "VK_RESOLVE_MODE_SAMPLE_ZERO_BIT not supported for stencil");
5586
5587	if (params.testStencil())
5588		context.requireDeviceFunctionality("VK_EXT_shader_stencil_export");
5589
5590	if (params.dynamicAlphaToCoverage)
5591	{
5592#ifndef CTS_USES_VULKANSC
5593		const auto& eds3Features = context.getExtendedDynamicState3FeaturesEXT();
5594		if (!eds3Features.extendedDynamicState3AlphaToCoverageEnable)
5595			TCU_THROW(NotSupportedError, "extendedDynamicState3AlphaToCoverageEnable not supported");
5596#else
5597		DE_ASSERT(false);
5598#endif // CTS_USES_VULKANSC
5599	}
5600}
5601
5602void ZExportInitPrograms (SourceCollections& programCollection, const ZExportParams params)
5603{
5604	{
5605		const auto vertDepth = (params.testDepth() ? ZExportParams::kBadDepth : ZExportParams::kExpectedDepth);
5606
5607		std::ostringstream vert;
5608		vert
5609			<< "#version 460\n"
5610			<< "vec2 positions[3] = vec2[](\n"
5611			<< "    vec2(-1.0, -1.0),\n"
5612			<< "    vec2(-1.0, 3.0),\n"
5613			<< "    vec2(3.0, -1.0)\n"
5614			<< ");\n"
5615			<< "void main (void) {\n"
5616			<< "    gl_Position = vec4(positions[gl_VertexIndex % 3], " << vertDepth << ", 1.0);\n"
5617			<< "}\n"
5618			;
5619		programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
5620	}
5621
5622	{
5623		std::ostringstream frag;
5624		frag
5625			<< "#version 460\n"
5626			<< "layout (location=0) out vec4 outColor;\n"
5627			<< (params.testStencil() ? "#extension GL_ARB_shader_stencil_export: require\n" : "")
5628			<< "void main (void) {\n"
5629			<< "    const float alphaValue = ((int(gl_FragCoord.x) < " << (ZExportParams::kWidth / 2u) << ") ? 0.0 : 1.0);\n"
5630			<< "    outColor = vec4(0.0, 0.0, 1.0, alphaValue);\n"
5631			<< (params.testDepth() ? ("    gl_FragDepth = " + std::to_string(ZExportParams::kExpectedDepth) + ";\n") : "")
5632			<< (params.testStencil() ? ("    gl_FragStencilRefARB = " + std::to_string(ZExportParams::kExpectedStencil) + ";\n") : "")
5633			;
5634
5635		if (params.testSampleMask())
5636			frag << "    gl_SampleMask[0] = ((int(gl_FragCoord.y) >= " << (ZExportParams::kHeight / 2u) << ") ? 0 : 0xFF);\n";
5637
5638		frag << "}\n";
5639		programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
5640	}
5641}
5642
5643tcu::TestStatus ZExportIterate (Context& context, const ZExportParams params)
5644{
5645	const auto& ctx = context.getContextCommonData();
5646
5647	// Choose depth/stencil format.
5648	const auto dsFormat = findSupportedDepthStencilFormat(context, true, true);
5649	if (dsFormat == VK_FORMAT_UNDEFINED)
5650		TCU_FAIL("Unable to find supported depth/stencil format");
5651
5652	const auto fbExtent		= makeExtent3D(ZExportParams::kWidth, ZExportParams::kHeight, 1u);
5653	const auto colorFormat	= VK_FORMAT_R8G8B8A8_UNORM;
5654	const auto colorUsage	= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
5655	const auto dsUsage		= (VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
5656	const auto colorAspect	= VK_IMAGE_ASPECT_COLOR_BIT;
5657	const auto dsAspect		= (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
5658	const auto colorSRR		= makeImageSubresourceRange(colorAspect, 0u, 1u, 0u, 1u);
5659	const auto dsSRR		= makeImageSubresourceRange(dsAspect, 0u, 1u, 0u, 1u);
5660	const auto imageType	= VK_IMAGE_TYPE_2D;
5661	const auto viewType		= VK_IMAGE_VIEW_TYPE_2D;
5662	const auto sampleCount	= VK_SAMPLE_COUNT_4_BIT;
5663	const auto bindPoint	= VK_PIPELINE_BIND_POINT_GRAPHICS;
5664
5665	// Multisample color attachment.
5666	const VkImageCreateInfo colorAttachmentCreateInfo =
5667	{
5668		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
5669		nullptr,								//	const void*				pNext;
5670		0u,										//	VkImageCreateFlags		flags;
5671		imageType,								//	VkImageType				imageType;
5672		colorFormat,							//	VkFormat				format;
5673		fbExtent,								//	VkExtent3D				extent;
5674		1u,										//	uint32_t				mipLevels;
5675		1u,										//	uint32_t				arrayLayers;
5676		sampleCount,							//	VkSampleCountFlagBits	samples;
5677		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
5678		colorUsage,								//	VkImageUsageFlags		usage;
5679		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
5680		0u,										//	uint32_t				queueFamilyIndexCount;
5681		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
5682		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
5683	};
5684	ImageWithMemory colorAttachment (ctx.vkd, ctx.device, ctx.allocator, colorAttachmentCreateInfo, MemoryRequirement::Any);
5685	const auto colorAttachmentView = makeImageView(ctx.vkd, ctx.device, colorAttachment.get(), viewType, colorFormat, colorSRR);
5686
5687	// Multisample depth/stencil attachment.
5688	const VkImageCreateInfo dsAttachmentCreateInfo =
5689	{
5690		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
5691		nullptr,								//	const void*				pNext;
5692		0u,										//	VkImageCreateFlags		flags;
5693		imageType,								//	VkImageType				imageType;
5694		dsFormat,								//	VkFormat				format;
5695		fbExtent,								//	VkExtent3D				extent;
5696		1u,										//	uint32_t				mipLevels;
5697		1u,										//	uint32_t				arrayLayers;
5698		sampleCount,							//	VkSampleCountFlagBits	samples;
5699		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
5700		dsUsage,								//	VkImageUsageFlags		usage;
5701		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
5702		0u,										//	uint32_t				queueFamilyIndexCount;
5703		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
5704		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
5705	};
5706	ImageWithMemory dsAttachment (ctx.vkd, ctx.device, ctx.allocator, dsAttachmentCreateInfo, MemoryRequirement::Any);
5707	const auto dsAttachmentView = makeImageView(ctx.vkd, ctx.device, dsAttachment.get(), viewType, dsFormat, dsSRR);
5708
5709	// Resolve attachments.
5710	VkImageCreateInfo colorResolveAttachmentCreateInfo	= colorAttachmentCreateInfo;
5711	colorResolveAttachmentCreateInfo.samples			= VK_SAMPLE_COUNT_1_BIT;
5712	VkImageCreateInfo dsResolveAttachmentCreateInfo		= dsAttachmentCreateInfo;
5713	dsResolveAttachmentCreateInfo.samples				= VK_SAMPLE_COUNT_1_BIT;
5714
5715	ImageWithMemory colorResolveAttachment		(ctx.vkd, ctx.device, ctx.allocator, colorResolveAttachmentCreateInfo, MemoryRequirement::Any);
5716	ImageWithMemory dsResolveAttachment			(ctx.vkd, ctx.device, ctx.allocator, dsResolveAttachmentCreateInfo, MemoryRequirement::Any);
5717	const auto		colorResolveAttachmentView	= makeImageView(ctx.vkd, ctx.device, colorResolveAttachment.get(), viewType, colorFormat, colorSRR);
5718	const auto		dsResolveAttachmentView		= makeImageView(ctx.vkd, ctx.device, dsResolveAttachment.get(), viewType, dsFormat, dsSRR);
5719
5720	// Render pass and framebuffer.
5721	const VkAttachmentDescription2 colorAttachmentDesc =
5722	{
5723		VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
5724		nullptr,
5725		0u,													//	VkAttachmentDescriptionFlags	flags;
5726		colorFormat,										//	VkFormat						format;
5727		sampleCount,										//	VkSampleCountFlagBits			samples;
5728		VK_ATTACHMENT_LOAD_OP_CLEAR,						//	VkAttachmentLoadOp				loadOp;
5729		VK_ATTACHMENT_STORE_OP_DONT_CARE,					//	VkAttachmentStoreOp				storeOp;
5730		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					//	VkAttachmentLoadOp				stencilLoadOp;
5731		VK_ATTACHMENT_STORE_OP_DONT_CARE,					//	VkAttachmentStoreOp				stencilStoreOp;
5732		VK_IMAGE_LAYOUT_UNDEFINED,							//	VkImageLayout					initialLayout;
5733		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			//	VkImageLayout					finalLayout;
5734	};
5735	const VkAttachmentDescription2 dsAttachmentDesc =
5736	{
5737		VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
5738		nullptr,
5739		0u,													//	VkAttachmentDescriptionFlags	flags;
5740		dsFormat,											//	VkFormat						format;
5741		sampleCount,										//	VkSampleCountFlagBits			samples;
5742		VK_ATTACHMENT_LOAD_OP_CLEAR,						//	VkAttachmentLoadOp				loadOp;
5743		VK_ATTACHMENT_STORE_OP_DONT_CARE,					//	VkAttachmentStoreOp				storeOp;
5744		VK_ATTACHMENT_LOAD_OP_CLEAR,						//	VkAttachmentLoadOp				stencilLoadOp;
5745		VK_ATTACHMENT_STORE_OP_DONT_CARE,					//	VkAttachmentStoreOp				stencilStoreOp;
5746		VK_IMAGE_LAYOUT_UNDEFINED,							//	VkImageLayout					initialLayout;
5747		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	//	VkImageLayout					finalLayout;
5748	};
5749	const VkAttachmentDescription2 colorResolveAttachmentDesc =
5750	{
5751		VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
5752		nullptr,
5753		0u,													//	VkAttachmentDescriptionFlags	flags;
5754		colorFormat,										//	VkFormat						format;
5755		VK_SAMPLE_COUNT_1_BIT,								//	VkSampleCountFlagBits			samples;
5756		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					//	VkAttachmentLoadOp				loadOp;
5757		VK_ATTACHMENT_STORE_OP_STORE,						//	VkAttachmentStoreOp				storeOp;
5758		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					//	VkAttachmentLoadOp				stencilLoadOp;
5759		VK_ATTACHMENT_STORE_OP_DONT_CARE,					//	VkAttachmentStoreOp				stencilStoreOp;
5760		VK_IMAGE_LAYOUT_UNDEFINED,							//	VkImageLayout					initialLayout;
5761		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			//	VkImageLayout					finalLayout;
5762	};
5763	const VkAttachmentDescription2 dsResolveAttachmentDesc =
5764	{
5765		VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
5766		nullptr,
5767		0u,													//	VkAttachmentDescriptionFlags	flags;
5768		dsFormat,											//	VkFormat						format;
5769		VK_SAMPLE_COUNT_1_BIT,								//	VkSampleCountFlagBits			samples;
5770		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					//	VkAttachmentLoadOp				loadOp;
5771		VK_ATTACHMENT_STORE_OP_STORE,						//	VkAttachmentStoreOp				storeOp;
5772		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					//	VkAttachmentLoadOp				stencilLoadOp;
5773		VK_ATTACHMENT_STORE_OP_STORE,						//	VkAttachmentStoreOp				stencilStoreOp;
5774		VK_IMAGE_LAYOUT_UNDEFINED,							//	VkImageLayout					initialLayout;
5775		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	//	VkImageLayout					finalLayout;
5776	};
5777
5778	std::vector<VkAttachmentDescription2> attachmentDescriptions;
5779	attachmentDescriptions.reserve(4u);
5780	attachmentDescriptions.push_back(colorAttachmentDesc);
5781	attachmentDescriptions.push_back(dsAttachmentDesc);
5782	attachmentDescriptions.push_back(colorResolveAttachmentDesc);
5783	attachmentDescriptions.push_back(dsResolveAttachmentDesc);
5784
5785	const VkAttachmentReference2 colorAttachmentReference =
5786	{
5787		VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
5788		nullptr,
5789		0u,
5790		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
5791		colorAspect,
5792	};
5793	const VkAttachmentReference2 dsAttachmentReference =
5794	{
5795		VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
5796		nullptr,
5797		1u,
5798		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
5799		dsAspect,
5800	};
5801	const VkAttachmentReference2 colorResolveAttachmentReference =
5802	{
5803		VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
5804		nullptr,
5805		2u,
5806		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
5807		colorAspect,
5808	};
5809	const VkAttachmentReference2 dsResolveAttachmentReference =
5810	{
5811		VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
5812		nullptr,
5813		3u,
5814		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
5815		dsAspect,
5816	};
5817
5818	const VkSubpassDescriptionDepthStencilResolve dsResolveDescription =
5819	{
5820		VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE,	//	VkStructureType					sType;
5821		nullptr,														//	const void*						pNext;
5822		VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,								//	VkResolveModeFlagBits			depthResolveMode;
5823		VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,								//	VkResolveModeFlagBits			stencilResolveMode;
5824		&dsResolveAttachmentReference,									//	const VkAttachmentReference2*	pDepthStencilResolveAttachment;
5825	};
5826
5827	const VkSubpassDescription2 subpassDescription =
5828	{
5829		VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,
5830		&dsResolveDescription,
5831		0u,									//	VkSubpassDescriptionFlags		flags;
5832		bindPoint,							//	VkPipelineBindPoint				pipelineBindPoint;
5833		0u,									//	uint32_t						viewMask;
5834		0u,									//	uint32_t						inputAttachmentCount;
5835		nullptr,							//	const VkAttachmentReference*	pInputAttachments;
5836		1u,									//	uint32_t						colorAttachmentCount;
5837		&colorAttachmentReference,			//	const VkAttachmentReference*	pColorAttachments;
5838		&colorResolveAttachmentReference,	//	const VkAttachmentReference*	pResolveAttachments;
5839		&dsAttachmentReference,				//	const VkAttachmentReference*	pDepthStencilAttachment;
5840		0u,									//	uint32_t						preserveAttachmentCount;
5841		nullptr,							//	const uint32_t*					pPreserveAttachments;
5842	};
5843
5844	const VkRenderPassCreateInfo2 renderPassCreateInfo =
5845	{
5846		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,	//	VkStructureType					sType;
5847		nullptr,										//	const void*						pNext;
5848		0u,												//	VkRenderPassCreateFlags			flags;
5849		de::sizeU32(attachmentDescriptions),			//	uint32_t						attachmentCount;
5850		de::dataOrNull(attachmentDescriptions),			//	const VkAttachmentDescription*	pAttachments;
5851		1u,												//	uint32_t						subpassCount;
5852		&subpassDescription,							//	const VkSubpassDescription*		pSubpasses;
5853		0u,												//	uint32_t						dependencyCount;
5854		nullptr,										//	const VkSubpassDependency*		pDependencies;
5855		0u,												//	uint32_t						correlatedViewMaskCount;
5856		nullptr,										//	const uint32_t*					pCorrelatedViewMasks;
5857	};
5858
5859	const std::vector<VkImage>		images
5860	{
5861		*colorAttachment,
5862		*dsAttachment,
5863		*colorResolveAttachment,
5864		*dsResolveAttachment,
5865	};
5866
5867	const std::vector<VkImageView>	attachmentViews
5868	{
5869		colorAttachmentView.get(),
5870		dsAttachmentView.get(),
5871		colorResolveAttachmentView.get(),
5872		dsResolveAttachmentView.get(),
5873	};
5874
5875	RenderPassWrapper renderPass	(params.pipelineConstructionType, ctx.vkd, ctx.device, &renderPassCreateInfo);
5876	renderPass.createFramebuffer(ctx.vkd, ctx.device, de::sizeU32(attachmentViews), de::dataOrNull(images), de::dataOrNull(attachmentViews), fbExtent.width, fbExtent.height);
5877
5878	// Pipeline layout.
5879	const PipelineLayoutWrapper pipelineLayout (params.pipelineConstructionType, ctx.vkd, ctx.device);
5880
5881	// Shaders.
5882	const auto&	binaries	= context.getBinaryCollection();
5883	const auto	vertShader	= ShaderWrapper(ctx.vkd, ctx.device, binaries.get("vert"));
5884	const auto	fragShader	= ShaderWrapper(ctx.vkd, ctx.device, binaries.get("frag"));
5885
5886	// Viewports and scissors.
5887	const std::vector<VkViewport>	viewports	(1u, makeViewport(fbExtent));
5888	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(fbExtent));
5889
5890	const auto frontStencilRef = (params.testStencil() ? ZExportParams::kBadStencil : ZExportParams::kExpectedStencil);
5891	const VkStencilOpState frontStencilOpState
5892	{
5893		VK_STENCIL_OP_KEEP,												// VkStencilOp									failOp
5894		VK_STENCIL_OP_REPLACE,											// VkStencilOp									passOp
5895		VK_STENCIL_OP_KEEP,												// VkStencilOp									depthFailOp
5896		VK_COMPARE_OP_ALWAYS,											// VkCompareOp									compareOp
5897		0xFFu,															// deUint32										compareMask
5898		0xFFu,															// deUint32										writeMask
5899		frontStencilRef,												// deUint32										reference
5900	};
5901	const auto backStencilOpState = makeStencilOpState(VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_NEVER, 0xFFu, 0xFFu, 0u);
5902
5903	const VkPipelineDepthStencilStateCreateInfo dsStateInfo
5904	{
5905		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,		// VkStructureType								sType
5906		DE_NULL,														// const void*									pNext
5907		0u,																// VkPipelineDepthStencilStateCreateFlags		flags
5908		VK_TRUE,														// VkBool32										depthTestEnable
5909		VK_TRUE,														// VkBool32										depthWriteEnable
5910		VK_COMPARE_OP_LESS,												// VkCompareOp									depthCompareOp
5911		VK_FALSE,														// VkBool32										depthBoundsTestEnable
5912		VK_TRUE,														// VkBool32										stencilTestEnable
5913		frontStencilOpState,											// VkStencilOpState								front
5914		backStencilOpState,												// VkStencilOpState								back
5915		0.0f,															// float										minDepthBounds
5916		1.0f,															// float										maxDepthBounds
5917	};
5918
5919	// Multisample state, including alpha to coverage, which is key for these tests.
5920	const auto staticAlphaToCoverage = (params.dynamicAlphaToCoverage ? VK_FALSE : VK_TRUE);
5921	const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo
5922	{
5923		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType								sType
5924		nullptr,														// const void*									pNext
5925		0u,																// VkPipelineMultisampleStateCreateFlags		flags
5926		sampleCount,													// VkSampleCountFlagBits						rasterizationSamples
5927		VK_FALSE,														// VkBool32										sampleShadingEnable
5928		1.0f,															// float										minSampleShading
5929		nullptr,														// const VkSampleMask*							pSampleMask
5930		staticAlphaToCoverage,											// VkBool32										alphaToCoverageEnable
5931		VK_FALSE,														// VkBool32										alphaToOneEnable
5932	};
5933
5934	const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = initVulkanStructure();
5935
5936	std::vector<VkDynamicState> dynamicStates;
5937#ifndef CTS_USES_VULKANSC
5938	if (params.dynamicAlphaToCoverage)
5939		dynamicStates.push_back(VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT);
5940#else
5941	DE_ASSERT(false);
5942#endif // CTS_USES_VULKANSC
5943
5944	const VkPipelineDynamicStateCreateInfo dynamicStateInfo =
5945	{
5946		VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	//	VkStructureType						sType;
5947		nullptr,												//	const void*							pNext;
5948		0u,														//	VkPipelineDynamicStateCreateFlags	flags;
5949		de::sizeU32(dynamicStates),								//	uint32_t							dynamicStateCount;
5950		de::dataOrNull(dynamicStates),							//	const VkDynamicState*				pDynamicStates;
5951	};
5952
5953	GraphicsPipelineWrapper pipelineWrapper (ctx.vki, ctx.vkd, ctx.physicalDevice, ctx.device, context.getDeviceExtensions(), params.pipelineConstructionType);
5954	pipelineWrapper
5955			.setDefaultRasterizationState()
5956			.setDefaultColorBlendState()
5957			.setDynamicState(&dynamicStateInfo)
5958			.setupVertexInputState(&vertexInputStateCreateInfo)
5959			.setupPreRasterizationShaderState(viewports,
5960				scissors,
5961				pipelineLayout,
5962				*renderPass,
5963				0u,
5964				vertShader)
5965			.setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragShader, &dsStateInfo, &multisampleStateCreateInfo)
5966			.setupFragmentOutputState(*renderPass, 0u, nullptr, &multisampleStateCreateInfo)
5967			.setMonolithicPipelineLayout(pipelineLayout)
5968			.buildPipeline();
5969
5970	CommandPoolWithBuffer cmd (ctx.vkd, ctx.device, ctx.qfIndex);
5971	const auto cmdBuffer = *cmd.cmdBuffer;
5972
5973	const tcu::Vec4 clearColor		(0.0f, 0.0f, 0.0f, 0.0f);
5974	const tcu::Vec4 geometryColor	(0.0f, 0.0f, 1.0f, 1.0f); // For pixels with coverage. Must match frag shader.
5975
5976	const std::vector<VkClearValue> clearValues
5977	{
5978		makeClearValueColor(clearColor),
5979		makeClearValueDepthStencil(ZExportParams::kClearDepth, ZExportParams::kClearStencil),
5980	};
5981
5982	beginCommandBuffer(ctx.vkd, cmdBuffer);
5983	renderPass.begin(ctx.vkd, cmdBuffer, scissors.at(0u), de::sizeU32(clearValues), de::dataOrNull(clearValues));
5984	pipelineWrapper.bind(cmdBuffer);
5985#ifndef CTS_USES_VULKANSC
5986	if (params.dynamicAlphaToCoverage)
5987		ctx.vkd.cmdSetAlphaToCoverageEnableEXT(cmdBuffer, VK_TRUE);
5988#else
5989	DE_ASSERT(false);
5990#endif // CTS_USES_VULKANSC
5991	ctx.vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
5992	renderPass.end(ctx.vkd, cmdBuffer);
5993	endCommandBuffer(ctx.vkd, cmdBuffer);
5994	submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
5995
5996	const tcu::UVec2	renderSize		(fbExtent.width, fbExtent.height);
5997	const auto			colorLevel		= readColorAttachment(ctx.vkd, ctx.device, ctx.queue, ctx.qfIndex, ctx.allocator, colorResolveAttachment.get(), colorFormat, renderSize);
5998	const auto			depthLevel		= readDepthAttachment(ctx.vkd, ctx.device, ctx.queue, ctx.qfIndex, ctx.allocator, dsResolveAttachment.get(), dsFormat, renderSize);
5999	const auto			stencilLevel	= readStencilAttachment(ctx.vkd, ctx.device, ctx.queue, ctx.qfIndex, ctx.allocator, dsResolveAttachment.get(), dsFormat, renderSize, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
6000
6001	const auto			colorAccess		= colorLevel->getAccess();
6002	const auto			depthAccess		= depthLevel->getAccess();
6003	const auto			stencilAccess	= stencilLevel->getAccess();
6004
6005	const tcu::IVec3	iExtent		(static_cast<int>(fbExtent.width), static_cast<int>(fbExtent.height), static_cast<int>(fbExtent.depth));
6006	tcu::TextureLevel	refColor	(mapVkFormat(colorFormat), iExtent.x(), iExtent.y());
6007	tcu::TextureLevel	refDepth	(getDepthCopyFormat(dsFormat), iExtent.x(), iExtent.y());
6008	tcu::TextureLevel	refStencil	(getStencilCopyFormat(dsFormat), iExtent.x(), iExtent.y());
6009
6010	auto refColorAccess	= refColor.getAccess();
6011	auto refDepthAccess	= refDepth.getAccess();
6012	auto refStencilAccess	= refStencil.getAccess();
6013
6014	const auto halfWidth	= iExtent.x() / 2;
6015	const auto halfHeight	= iExtent.y() / 2;
6016
6017	const tcu::Vec4 geometryColorNoAlpha	(geometryColor.x(), geometryColor.y(), geometryColor.z(), 0.0f); // For pixels with coverage but alpha set to 0
6018
6019	// allow skipping alpha to coverage if sample mask output is used
6020	std::vector<bool> skipAlphaToCoverageBehaviors = (params.testSampleMask() ? std::vector<bool>({false, true}) : std::vector<bool>({false}));
6021
6022	for (bool skipAlphaToCoverage : skipAlphaToCoverageBehaviors)
6023	{
6024
6025		// Prepare color reference.
6026		{
6027			auto topLeft		= tcu::getSubregion(refColorAccess, 0,			0,			halfWidth, halfHeight);
6028			auto bottomLeft		= tcu::getSubregion(refColorAccess, 0,			halfHeight,	halfWidth, halfHeight);
6029			auto topRight		= tcu::getSubregion(refColorAccess, halfWidth,	0,			halfWidth, halfHeight);
6030			auto bottomRight	= tcu::getSubregion(refColorAccess, halfWidth,	halfHeight,	halfWidth, halfHeight);
6031
6032			tcu::clear(topLeft,		(skipAlphaToCoverage ? geometryColorNoAlpha												: clearColor));
6033			tcu::clear(bottomLeft,	(skipAlphaToCoverage ? (params.testSampleMask() ? clearColor	: geometryColorNoAlpha) : clearColor));
6034			tcu::clear(topRight, geometryColor);
6035			tcu::clear(bottomRight, (params.testSampleMask() ? clearColor : geometryColor));
6036		}
6037		// Prepare depth reference.
6038		{
6039			auto topLeft		= tcu::getSubregion(refDepthAccess, 0,			0,			halfWidth, halfHeight);
6040			auto bottomLeft		= tcu::getSubregion(refDepthAccess, 0,			halfHeight,	halfWidth, halfHeight);
6041			auto topRight		= tcu::getSubregion(refDepthAccess, halfWidth,	0,			halfWidth, halfHeight);
6042			auto bottomRight	= tcu::getSubregion(refDepthAccess, halfWidth,	halfHeight,	halfWidth, halfHeight);
6043
6044			tcu::clearDepth(topLeft,		(skipAlphaToCoverage ? ZExportParams::kExpectedDepth							: ZExportParams::kClearDepth));
6045			tcu::clearDepth(bottomLeft,		(skipAlphaToCoverage ? (params.testSampleMask() ? ZExportParams::kClearDepth	: ZExportParams::kExpectedDepth) : ZExportParams::kClearDepth));
6046			tcu::clearDepth(topRight,		ZExportParams::kExpectedDepth);
6047			tcu::clearDepth(bottomRight,	(params.testSampleMask() ? ZExportParams::kClearDepth : ZExportParams::kExpectedDepth));
6048		}
6049		// Prepare stencil reference.
6050		{
6051			const auto clearStencil		= static_cast<int>(ZExportParams::kClearStencil);
6052			const auto expectedStencil	= static_cast<int>(ZExportParams::kExpectedStencil);
6053
6054			auto topLeft		= tcu::getSubregion(refStencilAccess, 0,			0,			halfWidth, halfHeight);
6055			auto bottomLeft		= tcu::getSubregion(refStencilAccess, 0,			halfHeight,	halfWidth, halfHeight);
6056			auto topRight		= tcu::getSubregion(refStencilAccess, halfWidth,	0,			halfWidth, halfHeight);
6057			auto bottomRight	= tcu::getSubregion(refStencilAccess, halfWidth,	halfHeight,	halfWidth, halfHeight);
6058
6059			tcu::clearStencil(topLeft,		(skipAlphaToCoverage ? expectedStencil							: clearStencil));
6060			tcu::clearStencil(bottomLeft,	(skipAlphaToCoverage ? (params.testSampleMask() ? clearStencil	: expectedStencil) : clearStencil));
6061			tcu::clearStencil(topRight,		expectedStencil);
6062			tcu::clearStencil(bottomRight,	(params.testSampleMask() ? clearStencil : expectedStencil));
6063		}
6064
6065		// Compare results and references.
6066		auto& log = context.getTestContext().getLog();
6067		const auto colorOK		= tcu::floatThresholdCompare(log, "Color", "Color Result", refColorAccess, colorAccess, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::COMPARE_LOG_ON_ERROR);
6068		const auto depthOK		= tcu::dsThresholdCompare(log, "Depth", "Depth Result", refDepthAccess, depthAccess, 0.0f, tcu::COMPARE_LOG_ON_ERROR);
6069		const auto stencilOK	= tcu::dsThresholdCompare(log, "Stencil", "Stencil Result", refStencilAccess, stencilAccess, 0.0f, tcu::COMPARE_LOG_ON_ERROR);
6070
6071		if (colorOK && depthOK && stencilOK)
6072			return tcu::TestStatus::pass("Pass");
6073	}
6074
6075	return tcu::TestStatus::fail("Unexpected color, depth or stencil result; check log for details");
6076}
6077
6078} // anonymous
6079
6080tcu::TestCaseGroup* createMultisampleTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, bool useFragmentShadingRate)
6081{
6082	using TestCaseGroupPtr = de::MovePtr<tcu::TestCaseGroup>;
6083
6084	const VkSampleCountFlagBits samples[] =
6085	{
6086		VK_SAMPLE_COUNT_2_BIT,
6087		VK_SAMPLE_COUNT_4_BIT,
6088		VK_SAMPLE_COUNT_8_BIT,
6089		VK_SAMPLE_COUNT_16_BIT,
6090		VK_SAMPLE_COUNT_32_BIT,
6091		VK_SAMPLE_COUNT_64_BIT
6092	};
6093
6094	const char*			groupName[]			{ "multisample", "multisample_with_fragment_shading_rate" };
6095	TestCaseGroupPtr	multisampleTests	(new tcu::TestCaseGroup(testCtx, groupName[useFragmentShadingRate]));
6096
6097	// Rasterization samples tests
6098	{
6099		TestCaseGroupPtr rasterizationSamplesTests(new tcu::TestCaseGroup(testCtx, "raster_samples"));
6100
6101		for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
6102		{
6103			std::ostringstream caseName;
6104			caseName << "samples_" << samples[samplesNdx];
6105
6106			TestCaseGroupPtr samplesTests (new tcu::TestCaseGroup(testCtx, caseName.str().c_str()));
6107
6108			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_triangle",	pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_TRIANGLE, 1.0f, IMAGE_BACKING_MODE_REGULAR, 0u, useFragmentShadingRate));
6109			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_line",		pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_LINE, 1.0f, IMAGE_BACKING_MODE_REGULAR, 0u, useFragmentShadingRate));
6110			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_point_1px",	pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_POINT, 1.0f, IMAGE_BACKING_MODE_REGULAR, 0u, useFragmentShadingRate));
6111			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_point",		pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_POINT, 3.0f, IMAGE_BACKING_MODE_REGULAR, 0u, useFragmentShadingRate));
6112
6113			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "depth",			pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE, 1.0f, IMAGE_BACKING_MODE_REGULAR, TEST_MODE_DEPTH_BIT, useFragmentShadingRate));
6114			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "stencil",			pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE, 1.0f, IMAGE_BACKING_MODE_REGULAR, TEST_MODE_STENCIL_BIT, useFragmentShadingRate));
6115			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "depth_stencil",	pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE, 1.0f, IMAGE_BACKING_MODE_REGULAR, TEST_MODE_DEPTH_BIT | TEST_MODE_STENCIL_BIT, useFragmentShadingRate));
6116
6117#ifndef CTS_USES_VULKANSC
6118			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_triangle_sparse",	pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_TRIANGLE, 1.0f, IMAGE_BACKING_MODE_SPARSE, 0u, useFragmentShadingRate));
6119			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_line_sparse",		pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_LINE, 1.0f, IMAGE_BACKING_MODE_SPARSE, 0u, useFragmentShadingRate));
6120			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_point_1px_sparse",	pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_POINT, 1.0f, IMAGE_BACKING_MODE_SPARSE, 0u, useFragmentShadingRate));
6121			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "primitive_point_sparse",		pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_POINT, 3.0f, IMAGE_BACKING_MODE_SPARSE, 0u, useFragmentShadingRate));
6122
6123			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "depth_sparse",			pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE, 1.0f, IMAGE_BACKING_MODE_SPARSE, TEST_MODE_DEPTH_BIT, useFragmentShadingRate));
6124			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "stencil_sparse",			pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE, 1.0f, IMAGE_BACKING_MODE_SPARSE, TEST_MODE_STENCIL_BIT, useFragmentShadingRate));
6125			samplesTests->addChild(new RasterizationSamplesTest(testCtx, "depth_stencil_sparse",	pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_TRIANGLE, 1.0f, IMAGE_BACKING_MODE_SPARSE, TEST_MODE_DEPTH_BIT | TEST_MODE_STENCIL_BIT, useFragmentShadingRate));
6126#endif // CTS_USES_VULKANSC
6127			rasterizationSamplesTests->addChild(samplesTests.release());
6128		}
6129
6130		multisampleTests->addChild(rasterizationSamplesTests.release());
6131	}
6132
6133	// Raster samples consistency check
6134#ifndef CTS_USES_VULKANSC
6135	{
6136		TestCaseGroupPtr				rasterSamplesConsistencyTests	(new tcu::TestCaseGroup(testCtx, "raster_samples_consistency"));
6137		MultisampleTestParams			paramsRegular					= { pipelineConstructionType, GEOMETRY_TYPE_OPAQUE_TRIANGLE, 1.0f, IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate };
6138		MultisampleTestParams			paramsSparse					= { pipelineConstructionType, GEOMETRY_TYPE_OPAQUE_TRIANGLE, 1.0f, IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate };
6139
6140		addFunctionCaseWithPrograms(rasterSamplesConsistencyTests.get(),
6141									"unique_colors_check",
6142									checkSupport,
6143									initMultisamplePrograms,
6144									testRasterSamplesConsistency,
6145									paramsRegular);
6146		addFunctionCaseWithPrograms(rasterSamplesConsistencyTests.get(),
6147									"unique_colors_check_sparse",
6148									checkSupport,
6149									initMultisamplePrograms,
6150									testRasterSamplesConsistency,
6151									paramsSparse);
6152		multisampleTests->addChild(rasterSamplesConsistencyTests.release());
6153
6154	}
6155#endif // CTS_USES_VULKANSC
6156
6157	// minSampleShading tests
6158	{
6159		struct TestConfig
6160		{
6161			const char*	name;
6162			float		minSampleShading;
6163		};
6164
6165		const TestConfig testConfigs[] =
6166		{
6167			{ "min_0_0",	0.0f },
6168			{ "min_0_25",	0.25f },
6169			{ "min_0_5",	0.5f },
6170			{ "min_0_75",	0.75f },
6171			{ "min_1_0",	1.0f }
6172		};
6173
6174		// Input attachments are not supported with dynamic rendering and shader objects
6175		if (!isConstructionTypeShaderObject(pipelineConstructionType))
6176		{
6177			TestCaseGroupPtr minSampleShadingTests(new tcu::TestCaseGroup(testCtx, "min_sample_shading"));
6178			{
6179				for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testConfigs); configNdx++)
6180				{
6181					const TestConfig&	testConfig				= testConfigs[configNdx];
6182
6183					// minSampleShading is not supported by shader objects
6184					if (testConfig.minSampleShading != 1.0f && isConstructionTypeShaderObject(pipelineConstructionType))
6185						continue;
6186
6187					TestCaseGroupPtr	minShadingValueTests	(new tcu::TestCaseGroup(testCtx, testConfigs[configNdx].name));
6188
6189					for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
6190					{
6191						std::ostringstream caseName;
6192						caseName << "samples_" << samples[samplesNdx];
6193
6194						TestCaseGroupPtr samplesTests (new tcu::TestCaseGroup(testCtx, caseName.str().c_str()));
6195
6196						samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_triangle", pipelineConstructionType, samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_TRIANGLE, 1.0f, IMAGE_BACKING_MODE_REGULAR, true, useFragmentShadingRate));
6197						samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_line", pipelineConstructionType, samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_LINE, 1.0f, IMAGE_BACKING_MODE_REGULAR, true, useFragmentShadingRate));
6198						samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_point_1px", pipelineConstructionType, samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_POINT, 1.0f, IMAGE_BACKING_MODE_REGULAR, true, useFragmentShadingRate));
6199						samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_point", pipelineConstructionType, samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_POINT, 3.0f, IMAGE_BACKING_MODE_REGULAR, true, useFragmentShadingRate));
6200	#ifndef CTS_USES_VULKANSC
6201						samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_triangle_sparse", pipelineConstructionType, samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_TRIANGLE, 1.0f, IMAGE_BACKING_MODE_SPARSE, true, useFragmentShadingRate));
6202						samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_line_sparse", pipelineConstructionType, samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_LINE, 1.0f, IMAGE_BACKING_MODE_SPARSE, true, useFragmentShadingRate));
6203						samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_point_1px_sparse", pipelineConstructionType, samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_POINT, 1.0f, IMAGE_BACKING_MODE_SPARSE, true, useFragmentShadingRate));
6204						samplesTests->addChild(new MinSampleShadingTest(testCtx, "primitive_point_sparse", pipelineConstructionType, samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_POINT, 3.0f, IMAGE_BACKING_MODE_SPARSE, true, useFragmentShadingRate));
6205	#endif // CTS_USES_VULKANSC
6206
6207						minShadingValueTests->addChild(samplesTests.release());
6208					}
6209
6210					minSampleShadingTests->addChild(minShadingValueTests.release());
6211				}
6212
6213				multisampleTests->addChild(minSampleShadingTests.release());
6214			}
6215		}
6216
6217		// Input attachments are not supported with dynamic rendering and shader objects
6218		if (!isConstructionTypeShaderObject(pipelineConstructionType))
6219		{
6220			TestCaseGroupPtr minSampleShadingTests(new tcu::TestCaseGroup(testCtx, "min_sample_shading_enabled"));
6221
6222			for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testConfigs); configNdx++)
6223			{
6224				const TestConfig&	testConfig				= testConfigs[configNdx];
6225				TestCaseGroupPtr	minShadingValueTests	(new tcu::TestCaseGroup(testCtx, testConfigs[configNdx].name));
6226
6227				for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
6228				{
6229					std::ostringstream caseName;
6230					caseName << "samples_" << samples[samplesNdx];
6231
6232					TestCaseGroupPtr samplesTests (new tcu::TestCaseGroup(testCtx, caseName.str().c_str()));
6233
6234					samplesTests->addChild(new MinSampleShadingTest(testCtx, "quad", pipelineConstructionType, samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_QUAD, 1.0f, IMAGE_BACKING_MODE_REGULAR, true, useFragmentShadingRate));
6235
6236					minShadingValueTests->addChild(samplesTests.release());
6237				}
6238
6239				minSampleShadingTests->addChild(minShadingValueTests.release());
6240			}
6241
6242			multisampleTests->addChild(minSampleShadingTests.release());
6243		}
6244
6245		// Input attachments are not supported with dynamic rendering and shader objects
6246		if (!isConstructionTypeShaderObject(pipelineConstructionType))
6247		{
6248			TestCaseGroupPtr minSampleShadingTests(new tcu::TestCaseGroup(testCtx, "min_sample_shading_disabled"));
6249
6250			for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testConfigs); configNdx++)
6251			{
6252				const TestConfig&	testConfig				= testConfigs[configNdx];
6253				TestCaseGroupPtr	minShadingValueTests	(new tcu::TestCaseGroup(testCtx, testConfigs[configNdx].name));
6254
6255				for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
6256				{
6257					std::ostringstream caseName;
6258					caseName << "samples_" << samples[samplesNdx];
6259
6260					TestCaseGroupPtr samplesTests (new tcu::TestCaseGroup(testCtx, caseName.str().c_str()));
6261
6262					samplesTests->addChild(new MinSampleShadingTest(testCtx, "quad", pipelineConstructionType, samples[samplesNdx], testConfig.minSampleShading, GEOMETRY_TYPE_OPAQUE_QUAD, 1.0f, IMAGE_BACKING_MODE_REGULAR, false, useFragmentShadingRate));
6263
6264					minShadingValueTests->addChild(samplesTests.release());
6265				}
6266
6267				minSampleShadingTests->addChild(minShadingValueTests.release());
6268			}
6269
6270			multisampleTests->addChild(minSampleShadingTests.release());
6271		}
6272	}
6273
6274	// SampleMask tests
6275	{
6276		struct TestConfig
6277		{
6278			const char*		name;
6279			VkSampleMask	sampleMask;
6280		};
6281
6282		const TestConfig testConfigs[] =
6283		{
6284			// All mask bits are off
6285			{ "mask_all_on",0x0 },
6286			// All mask bits are on
6287			{ "mask_all_off",0xFFFFFFFF },
6288			// All mask elements are 0x1
6289			{ "mask_one",0x1},
6290			// All mask elements are 0xAAAAAAAA
6291			{ "mask_random",0xAAAAAAAA },
6292		};
6293
6294		TestCaseGroupPtr sampleMaskTests(new tcu::TestCaseGroup(testCtx, "sample_mask"));
6295
6296		for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testConfigs); configNdx++)
6297		{
6298			const TestConfig&	testConfig				= testConfigs[configNdx];
6299			TestCaseGroupPtr	sampleMaskValueTests	(new tcu::TestCaseGroup(testCtx, testConfig.name));
6300
6301			for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
6302			{
6303				std::ostringstream caseName;
6304				caseName << "samples_" << samples[samplesNdx];
6305
6306				const deUint32		sampleMaskCount	= samples[samplesNdx] / 32;
6307				TestCaseGroupPtr	samplesTests	(new tcu::TestCaseGroup(testCtx, caseName.str().c_str()));
6308
6309				std::vector<VkSampleMask> mask;
6310				for (deUint32 maskNdx = 0; maskNdx < sampleMaskCount; maskNdx++)
6311					mask.push_back(testConfig.sampleMask);
6312
6313				samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_triangle", pipelineConstructionType, samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_TRIANGLE, 1.0f, IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate));
6314				samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_line", pipelineConstructionType, samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_LINE, 1.0f, IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate));
6315				samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_point_1px", pipelineConstructionType, samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_POINT, 1.0f, IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate));
6316				samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_point", pipelineConstructionType, samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_POINT, 3.0f, IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate));
6317#ifndef CTS_USES_VULKANSC
6318				samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_triangle_sparse", pipelineConstructionType, samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_TRIANGLE, 1.0f, IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate));
6319				samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_line_sparse", pipelineConstructionType, samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_LINE, 1.0f, IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate));
6320				samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_point_1px_sparse", pipelineConstructionType, samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_POINT, 1.0f, IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate));
6321				samplesTests->addChild(new SampleMaskTest(testCtx, "primitive_point_sparse", pipelineConstructionType, samples[samplesNdx], mask, GEOMETRY_TYPE_OPAQUE_POINT, 3.0f, IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate));
6322#endif // CTS_USES_VULKANSC
6323
6324				sampleMaskValueTests->addChild(samplesTests.release());
6325			}
6326
6327			sampleMaskTests->addChild(sampleMaskValueTests.release());
6328		}
6329
6330		multisampleTests->addChild(sampleMaskTests.release());
6331
6332	}
6333
6334	// AlphaToOne tests
6335	{
6336		const VkSampleCountFlagBits samplesForAlphaToOne[] =
6337		{
6338			VK_SAMPLE_COUNT_1_BIT,
6339			VK_SAMPLE_COUNT_2_BIT,
6340			VK_SAMPLE_COUNT_4_BIT,
6341			VK_SAMPLE_COUNT_8_BIT,
6342			VK_SAMPLE_COUNT_16_BIT,
6343			VK_SAMPLE_COUNT_32_BIT,
6344			VK_SAMPLE_COUNT_64_BIT
6345		};
6346		TestCaseGroupPtr alphaToOneTests(new tcu::TestCaseGroup(testCtx, "alpha_to_one"));
6347
6348		for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samplesForAlphaToOne); samplesNdx++)
6349		{
6350			std::ostringstream caseName;
6351			caseName << "samples_" << samplesForAlphaToOne[samplesNdx];
6352
6353			alphaToOneTests->addChild(new AlphaToOneTest(testCtx, caseName.str(), pipelineConstructionType, samplesForAlphaToOne[samplesNdx], IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate));
6354#ifndef CTS_USES_VULKANSC
6355			caseName << "_sparse";
6356			alphaToOneTests->addChild(new AlphaToOneTest(testCtx, caseName.str(), pipelineConstructionType, samplesForAlphaToOne[samplesNdx], IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate));
6357#endif // CTS_USES_VULKANSC
6358		}
6359
6360		multisampleTests->addChild(alphaToOneTests.release());
6361	}
6362
6363	// AlphaToCoverageEnable tests
6364	{
6365		TestCaseGroupPtr alphaToCoverageTests (new tcu::TestCaseGroup(testCtx, "alpha_to_coverage"));
6366
6367		for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
6368		{
6369			std::ostringstream caseName;
6370			caseName << "samples_" << samples[samplesNdx];
6371
6372			TestCaseGroupPtr samplesTests (new tcu::TestCaseGroup(testCtx, caseName.str().c_str()));
6373
6374			samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_opaque", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_QUAD, IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate, false));
6375			samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_translucent", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_TRANSLUCENT_QUAD, IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate, false));
6376			samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_invisible", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_QUAD, IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate, false));
6377			samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_invisible_check_depth", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_QUAD, IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate, true));
6378#ifndef CTS_USES_VULKANSC
6379			samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_opaque_sparse", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_QUAD, IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate, false));
6380			samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_translucent_sparse", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_TRANSLUCENT_QUAD, IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate, false));
6381			samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_invisible_sparse", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_QUAD, IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate, false));
6382			samplesTests->addChild(new AlphaToCoverageTest(testCtx, "alpha_invisible_sparse_check_depth", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_QUAD, IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate, true));
6383#endif // CTS_USES_VULKANSC
6384
6385			alphaToCoverageTests->addChild(samplesTests.release());
6386		}
6387		multisampleTests->addChild(alphaToCoverageTests.release());
6388	}
6389
6390	// AlphaToCoverageEnable without color buffer tests
6391	{
6392		TestCaseGroupPtr alphaToCoverageNoColorAttachmentTests (new tcu::TestCaseGroup(testCtx, "alpha_to_coverage_no_color_attachment"));
6393
6394		for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
6395		{
6396			std::ostringstream caseName;
6397			caseName << "samples_" << samples[samplesNdx];
6398
6399			TestCaseGroupPtr samplesTests (new tcu::TestCaseGroup(testCtx, caseName.str().c_str()));
6400
6401			samplesTests->addChild(new AlphaToCoverageNoColorAttachmentTest(testCtx, "alpha_opaque", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_QUAD, IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate));
6402#ifndef CTS_USES_VULKANSC
6403			samplesTests->addChild(new AlphaToCoverageNoColorAttachmentTest(testCtx, "alpha_opaque_sparse", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_QUAD, IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate));
6404#endif // CTS_USES_VULKANSC
6405
6406			alphaToCoverageNoColorAttachmentTests->addChild(samplesTests.release());
6407		}
6408		multisampleTests->addChild(alphaToCoverageNoColorAttachmentTests.release());
6409	}
6410
6411	// AlphaToCoverageEnable with unused color attachment:
6412	// Set color output at location 0 as unused, but use the alpha write to control coverage for rendering to color buffer at location 1.
6413	{
6414		TestCaseGroupPtr alphaToCoverageColorUnusedAttachmentTests (new tcu::TestCaseGroup(testCtx, "alpha_to_coverage_unused_attachment"));
6415
6416		for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
6417		{
6418			std::ostringstream caseName;
6419			caseName << "samples_" << samples[samplesNdx];
6420
6421			TestCaseGroupPtr samplesTests (new tcu::TestCaseGroup(testCtx, caseName.str().c_str()));
6422
6423			samplesTests->addChild(new AlphaToCoverageColorUnusedAttachmentTest(testCtx, "alpha_opaque", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_QUAD, IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate));
6424#ifndef CTS_USES_VULKANSC
6425			samplesTests->addChild(new AlphaToCoverageColorUnusedAttachmentTest(testCtx, "alpha_opaque_sparse", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_OPAQUE_QUAD, IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate));
6426#endif // CTS_USES_VULKANSC
6427			samplesTests->addChild(new AlphaToCoverageColorUnusedAttachmentTest(testCtx, "alpha_invisible", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_QUAD, IMAGE_BACKING_MODE_REGULAR, useFragmentShadingRate));
6428#ifndef CTS_USES_VULKANSC
6429			samplesTests->addChild(new AlphaToCoverageColorUnusedAttachmentTest(testCtx, "alpha_invisible_sparse", pipelineConstructionType, samples[samplesNdx], GEOMETRY_TYPE_INVISIBLE_QUAD, IMAGE_BACKING_MODE_SPARSE, useFragmentShadingRate));
6430#endif // CTS_USES_VULKANSC
6431
6432			alphaToCoverageColorUnusedAttachmentTests->addChild(samplesTests.release());
6433		}
6434		multisampleTests->addChild(alphaToCoverageColorUnusedAttachmentTests.release());
6435	}
6436
6437#ifndef CTS_USES_VULKANSC
6438	// not all tests need to be repeated for FSR
6439	if (useFragmentShadingRate == false)
6440	{
6441		// Sampling from a multisampled image texture (texelFetch)
6442		multisampleTests->addChild(createMultisampleSampledImageTests(testCtx, pipelineConstructionType));
6443
6444		// Load/store on a multisampled rendered image (different kinds of access: color attachment write, storage image, etc.)
6445		multisampleTests->addChild(createMultisampleStorageImageTests(testCtx, pipelineConstructionType));
6446
6447		// Sampling from a multisampled image texture (texelFetch), checking supersample positions
6448		multisampleTests->addChild(createMultisampleStandardSamplePositionTests(testCtx, pipelineConstructionType));
6449
6450		// VK_AMD_shader_fragment_mask
6451		multisampleTests->addChild(createMultisampleShaderFragmentMaskTests(testCtx, pipelineConstructionType));
6452
6453		// Multisample resolve tests where a render area is less than an attachment size.
6454		multisampleTests->addChild(createMultisampleResolveRenderpassRenderAreaTests(testCtx, pipelineConstructionType));
6455
6456		// VK_EXT_multisampled_render_to_single_sampled
6457		{
6458			multisampleTests->addChild(createMultisampledRenderToSingleSampledTests(testCtx, pipelineConstructionType));
6459			// Take advantage of the code for this extension's tests to add some normal multisampling tests
6460			multisampleTests->addChild(createMultisampledMiscTests(testCtx, pipelineConstructionType));
6461		}
6462	}
6463
6464	// VK_EXT_sample_locations
6465	multisampleTests->addChild(createMultisampleSampleLocationsExtTests(testCtx, pipelineConstructionType, useFragmentShadingRate));
6466
6467	// VK_AMD_mixed_attachment
6468	multisampleTests->addChild(createMultisampleMixedAttachmentSamplesTests(testCtx, pipelineConstructionType, useFragmentShadingRate));
6469
6470	// Sample mask with and without vk_ext_post_depth_coverage
6471	{
6472		const vk::VkSampleCountFlagBits standardSamplesSet[] =
6473		{
6474			vk::VK_SAMPLE_COUNT_2_BIT,
6475			vk::VK_SAMPLE_COUNT_4_BIT,
6476			vk::VK_SAMPLE_COUNT_8_BIT,
6477			vk::VK_SAMPLE_COUNT_16_BIT
6478		};
6479
6480		TestCaseGroupPtr sampleMaskWithDepthTestGroup(new tcu::TestCaseGroup(testCtx, "sample_mask_with_depth_test"));
6481
6482		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(standardSamplesSet); ++ndx)
6483		{
6484			std::ostringstream caseName;
6485			caseName << "samples_" << standardSamplesSet[ndx];
6486
6487			sampleMaskWithDepthTestGroup->addChild(new SampleMaskWithDepthTestTest(testCtx, caseName.str(), pipelineConstructionType, standardSamplesSet[ndx], false, useFragmentShadingRate));
6488
6489			caseName << "_post_depth_coverage";
6490			sampleMaskWithDepthTestGroup->addChild(new SampleMaskWithDepthTestTest(testCtx, caseName.str(), pipelineConstructionType, standardSamplesSet[ndx], true, useFragmentShadingRate));
6491
6492		}
6493		multisampleTests->addChild(sampleMaskWithDepthTestGroup.release());
6494	}
6495#endif // CTS_USES_VULKANSC
6496
6497	// Input attachments are not supported with dynamic rendering and shader objects
6498	if (!isConstructionTypeShaderObject(pipelineConstructionType))
6499	{
6500		//Conservative rasterization test
6501		struct TestConfig
6502		{
6503			const char*		name;
6504			bool			enableMinSampleShading;
6505			const float		minSampleShading;
6506			const bool		enableSampleMask;
6507			VkSampleMask	sampleMask;
6508			bool			enablePostDepthCoverage;
6509		};
6510
6511		const TestConfig testConfigs[] =
6512		{
6513			// Only conservative rendering applied
6514			{ "plain_conservative",false,		0.0f,		false,		0x0,			false },
6515			// Post depth coverage enabled
6516			{ "post_depth_coverage",false,		0.0f,		false,		0x0,			true },
6517			// minSampleMask set to 0.25f
6518			{ "min_0_25",true,		0.25f,		false,		0x0,			false },
6519			// minSampleMask set to 0.5f
6520			{ "min_0_5",true,		0.5f,		false,		0x0,			false },
6521			// minSampleMask set to 0.75f
6522			{ "min_0_75",true,		0.75f,		false,		0x0,			false },
6523			// minSampleMask set to 1.0f
6524			{ "min_0_1_0",true,		1.0f,		false,		0x0,			false },
6525			// All mask bits are on
6526			{ "mask_all_off",false,		0.0f,		true,		0x0,			false },
6527			// All mask bits are off
6528			{ "mask_all_on",false,		0.0f,		true,		0xFFFFFFFF,		false },
6529			// All mask elements are 0xAAAAAAAA
6530			{ "mask_half_on",false,		0.0f,		true,		0xAAAAAAAA,		false },
6531		};
6532
6533		const vk::VkSampleCountFlagBits standardSamplesSet[] =
6534		{
6535			vk::VK_SAMPLE_COUNT_2_BIT,
6536			vk::VK_SAMPLE_COUNT_4_BIT,
6537			vk::VK_SAMPLE_COUNT_8_BIT,
6538			vk::VK_SAMPLE_COUNT_16_BIT
6539		};
6540
6541		enum vk::VkConservativeRasterizationModeEXT rasterizationMode[] =
6542		{
6543			vk::VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT,
6544			vk::VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT
6545		};
6546
6547		// Conservative rendering
6548		TestCaseGroupPtr conservativeGroup(new tcu::TestCaseGroup(testCtx, "conservative_with_full_coverage"));
6549
6550		for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(rasterizationMode); ++modeNdx)
6551		{
6552			const char*			modeName	= (modeNdx == 0 ? "overestimate" : "underestimate");
6553			TestCaseGroupPtr	modesGroup	(new tcu::TestCaseGroup(testCtx, modeName));
6554
6555			for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(standardSamplesSet); ++samplesNdx)
6556			{
6557				std::string caseName = "samples_" + std::to_string(standardSamplesSet[samplesNdx]) + "_";
6558
6559				for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testConfigs); configNdx++)
6560				{
6561					const TestConfig&				testConfig				= testConfigs[configNdx];
6562
6563					modesGroup->addChild(new SampleMaskWithConservativeTest(testCtx, caseName + testConfig.name, pipelineConstructionType, standardSamplesSet[samplesNdx],
6564																			rasterizationMode[modeNdx], testConfig.enableMinSampleShading, testConfig.minSampleShading, testConfig.enableSampleMask,
6565																			testConfig.sampleMask, testConfig.enablePostDepthCoverage, useFragmentShadingRate));
6566				}
6567
6568			}
6569
6570			conservativeGroup->addChild(modesGroup.release());
6571		}
6572
6573		multisampleTests->addChild(conservativeGroup.release());
6574	}
6575
6576	{
6577		static const std::vector<vk::VkSampleCountFlagBits> kSampleCounts =
6578		{
6579			vk::VK_SAMPLE_COUNT_1_BIT,
6580			vk::VK_SAMPLE_COUNT_2_BIT,
6581			vk::VK_SAMPLE_COUNT_4_BIT,
6582			vk::VK_SAMPLE_COUNT_8_BIT,
6583			vk::VK_SAMPLE_COUNT_16_BIT,
6584			vk::VK_SAMPLE_COUNT_32_BIT,
6585			vk::VK_SAMPLE_COUNT_64_BIT,
6586		};
6587
6588
6589		static const std::array<bool, 2> unusedAttachmentFlag = {{ false, true }};
6590
6591		{
6592			// Tests for multisample variable rate in subpasses
6593			TestCaseGroupPtr variableRateGroup(new tcu::TestCaseGroup(testCtx, "variable_rate"));
6594
6595			// 2 and 3 subpasses should be good enough.
6596			static const std::vector<size_t> combinationSizes = { 2, 3 };
6597
6598			// Basic cases.
6599			for (const auto size : combinationSizes)
6600			{
6601				const auto combs = combinations(kSampleCounts, size);
6602				for (const auto& comb : combs)
6603				{
6604					// Check sample counts actually vary between some of the subpasses.
6605					std::set<vk::VkSampleCountFlagBits> uniqueVals(begin(comb), end(comb));
6606					if (uniqueVals.size() < 2)
6607						continue;
6608
6609					std::ostringstream name;
6610
6611					bool first = true;
6612					for (const auto& count : comb)
6613					{
6614						name << (first ? "" : "_") << count;
6615						first = false;
6616					}
6617
6618					const VariableRateTestCase::TestParams params =
6619					{
6620						pipelineConstructionType,	//	PipelineConstructionType	pipelineConstructionType;
6621						false,						//	bool						nonEmptyFramebuffer;
6622						vk::VK_SAMPLE_COUNT_1_BIT,	//	vk::VkSampleCountFlagBits	fbCount;
6623						false,						//	bool						unusedAttachment;
6624						comb,						//	SampleCounts				subpassCounts;
6625						useFragmentShadingRate,		//	bool						useFragmentShadingRate;
6626					};
6627					variableRateGroup->addChild(new VariableRateTestCase(testCtx, name.str(), params));
6628				}
6629			}
6630
6631			// Cases with non-empty framebuffers: only 2 subpasses to avoid a large number of combinations.
6632			{
6633				// Use one more sample count for the framebuffer attachment. It will be taken from the last item.
6634				auto combs = combinations(kSampleCounts, 2 + 1);
6635				for (auto& comb : combs)
6636				{
6637					// Framebuffer sample count.
6638					const auto fbCount = comb.back();
6639					comb.pop_back();
6640
6641					// Check sample counts actually vary between some of the subpasses.
6642					std::set<vk::VkSampleCountFlagBits> uniqueVals(begin(comb), end(comb));
6643					if (uniqueVals.size() < 2)
6644						continue;
6645
6646					for (const auto flag : unusedAttachmentFlag)
6647					{
6648						std::ostringstream name;
6649
6650						bool first = true;
6651						for (const auto& count : comb)
6652						{
6653							name << (first ? "" : "_") << count;
6654							first = false;
6655						}
6656
6657						name << "_fb_" << fbCount;
6658
6659						if (flag)
6660						{
6661							name << "_unused";
6662						}
6663
6664						const VariableRateTestCase::TestParams params =
6665						{
6666							pipelineConstructionType,	//	PipelineConstructionType	pipelineConstructionType;
6667							true,						//	bool						nonEmptyFramebuffer;
6668							fbCount,					//	vk::VkSampleCountFlagBits	fbCount;
6669							flag,						//	bool						unusedAttachment;
6670							comb,						//	SampleCounts				subpassCounts;
6671							useFragmentShadingRate,		//	bool						useFragmentShadingRate;
6672						};
6673						variableRateGroup->addChild(new VariableRateTestCase(testCtx, name.str(), params));
6674					}
6675				}
6676			}
6677
6678			multisampleTests->addChild(variableRateGroup.release());
6679		}
6680
6681		{
6682			TestCaseGroupPtr mixedCountGroup(new tcu::TestCaseGroup(testCtx, "mixed_count", "Tests for mixed sample count in empty subpass and framebuffer"));
6683
6684			const auto combs = combinations(kSampleCounts, 2);
6685			for (const auto& comb : combs)
6686			{
6687				// Check different sample count.
6688				DE_ASSERT(comb.size() == 2u);
6689				const auto& fbCount		= comb[0];
6690				const auto& emptyCount	= comb[1];
6691
6692				if (fbCount == emptyCount)
6693					continue;
6694
6695				const std::string fbCountStr	= de::toString(fbCount);
6696				const std::string emptyCountStr	= de::toString(emptyCount);
6697
6698				for (const auto flag : unusedAttachmentFlag)
6699				{
6700					const std::string nameSuffix	= (flag ? "unused" : "");
6701					const std::string descSuffix	= (flag ? "one unused attachment reference" : "no attachment references");
6702					const std::string name			= fbCountStr + "_" + emptyCountStr + (nameSuffix.empty() ? "" : "_") + nameSuffix;
6703
6704					const VariableRateTestCase::TestParams params
6705					{
6706						pipelineConstructionType,							//	PipelineConstructionType	pipelineConstructionType;
6707						true,												//	bool						nonEmptyFramebuffer;
6708						fbCount,											//	vk::VkSampleCountFlagBits	fbCount;
6709						flag,												//	bool						unusedAttachment;
6710						VariableRateTestCase::SampleCounts(1u, emptyCount),	//	SampleCounts				subpassCounts;
6711						useFragmentShadingRate,								//	bool						useFragmentShadingRate;
6712					};
6713					mixedCountGroup->addChild(new VariableRateTestCase(testCtx, name, params));
6714				}
6715			}
6716
6717			multisampleTests->addChild(mixedCountGroup.release());
6718		}
6719
6720		if (!useFragmentShadingRate)
6721		{
6722			// Tests using alpha to coverage combined with depth/stencil/mask writes in the frag shader
6723			TestCaseGroupPtr zExportGroup (new tcu::TestCaseGroup(testCtx, "z_export"));
6724
6725			const struct
6726			{
6727				ZExportFlags		flags;
6728				const char*			name;
6729			} flagsCases[] =
6730			{
6731				{ (ZEXP_DEPTH_BIT),												"depth"			},
6732				{ (ZEXP_STENCIL_BIT),											"stencil"		},
6733				{ (ZEXP_SAMPLE_MASK_BIT),										"sample_mask"	},
6734				{ (ZEXP_DEPTH_BIT | ZEXP_STENCIL_BIT | ZEXP_SAMPLE_MASK_BIT),	"write_all"		},
6735			};
6736
6737			for (const auto& flagsCase : flagsCases)
6738			{
6739				for (int i = 0; i < 2; ++i)
6740				{
6741					const bool dynamicAlphaToCoverage = (i > 0);
6742
6743#ifdef CTS_USES_VULKANSC
6744					if (dynamicAlphaToCoverage)
6745						continue;
6746#endif // CTS_USES_VULKANSC
6747
6748					const auto			testName	= std::string(flagsCase.name) + "_" + (dynamicAlphaToCoverage ? "dynamic" : "static") + "_atc"; // atc = alpha to coverage
6749					const ZExportParams	params		(pipelineConstructionType, flagsCase.flags, dynamicAlphaToCoverage);
6750
6751					addFunctionCaseWithPrograms(zExportGroup.get(), testName, ZExportCheckSupport, ZExportInitPrograms, ZExportIterate, params);
6752				}
6753			}
6754
6755			multisampleTests->addChild(zExportGroup.release());
6756		}
6757	}
6758
6759	return multisampleTests.release();
6760}
6761
6762} // pipeline
6763} // vkt
6764