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