1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2021 The Khronos Group Inc.
6 * Copyright (c) 2023 LunarG, Inc.
7 * Copyright (c) 2023 Nintendo
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 Tests for VK_EXT_multisampled_render_to_single_sampled
24 *//*--------------------------------------------------------------------*/
25
26#include "vktPipelineMultisampledRenderToSingleSampledTests.hpp"
27#include "vktPipelineMakeUtil.hpp"
28#include "vktTestCase.hpp"
29#include "vktTestCaseUtil.hpp"
30#include "vktTestGroupUtil.hpp"
31
32#include "vkCmdUtil.hpp"
33#include "vkObjUtil.hpp"
34#include "vkPlatform.hpp"
35#include "vkMemUtil.hpp"
36#include "vkQueryUtil.hpp"
37#include "vkTypeUtil.hpp"
38#include "vkRefUtil.hpp"
39#include "vkBuilderUtil.hpp"
40#include "vkPrograms.hpp"
41#include "vkImageUtil.hpp"
42#include "vkPipelineConstructionUtil.hpp"
43
44#include "deUniquePtr.hpp"
45#include "deSharedPtr.hpp"
46#include "deRandom.hpp"
47#include "deMath.h"
48
49#include "tcuVector.hpp"
50#include "tcuTestLog.hpp"
51#include "tcuImageCompare.hpp"
52#include "tcuTextureUtil.hpp"
53#include "tcuRGBA.hpp"
54
55#include <string>
56#include <vector>
57
58
59// For testing, logs
60#define DEBUG_LOGS 0
61
62#if DEBUG_LOGS
63#define DBG(...) fprintf(stderr, __VA_ARGS__)
64#else
65#define DBG(...) ((void)0)
66#endif
67
68
69namespace vkt
70{
71namespace pipeline
72{
73namespace
74{
75using namespace vk;
76using de::UniquePtr;
77using de::MovePtr;
78using de::SharedPtr;
79using tcu::IVec2;
80using tcu::UVec2;
81using tcu::Vec2;
82using tcu::Vec4;
83using tcu::IVec4;
84using tcu::UVec4;
85
86VkImageAspectFlags getDepthStencilAspectFlags (const VkFormat format)
87{
88	const tcu::TextureFormat tcuFormat = mapVkFormat(format);
89
90	if      (tcuFormat.order == tcu::TextureFormat::DS)		return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
91	else if (tcuFormat.order == tcu::TextureFormat::D)		return VK_IMAGE_ASPECT_DEPTH_BIT;
92	else if (tcuFormat.order == tcu::TextureFormat::S)		return VK_IMAGE_ASPECT_STENCIL_BIT;
93
94	DE_ASSERT(false);
95	return 0u;
96}
97
98inline bool isDepthFormat (const VkFormat format)
99{
100	return (getDepthStencilAspectFlags(format) & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
101}
102
103inline bool isStencilFormat (const VkFormat format)
104{
105	return (getDepthStencilAspectFlags(format) & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
106}
107
108using PipelineSp = SharedPtr<Unique<VkPipeline>>;
109
110// How many regions to render to in multi-pass tests
111constexpr deUint32 RegionCount	= 4;
112
113struct DrawPushConstants
114{
115	Vec4 color1Data[2];
116	Vec4 color2Data[2];
117	IVec4 color3Data[2];
118	Vec2 depthData;
119};
120
121struct VerifyPushConstants
122{
123	Vec4 color1Data[2] = {Vec4(0, 0, 0, 0), Vec4(0, 0, 0, 0)};
124	Vec4 color2Data[2] = {Vec4(0, 0, 0, 0), Vec4(0, 0, 0, 0)};
125	IVec4 color3Data[2] = {IVec4(0, 0, 0, 0), IVec4(0, 0, 0, 0)};
126	float depthData = 0;
127	deUint32 stencilData = 0;
128};
129
130struct VerificationResults
131{
132	deUint32 color1Verification;
133	deUint32 color2Verification;
134	deUint32 color3Verification;
135	deUint32 depthVerification;
136	deUint32 stencilVerification;
137};
138
139struct VerifySingleFloatPushConstants
140{
141	UVec4 area;
142	Vec4 color;
143	deUint32 attachmentNdx;
144};
145
146struct VerifySingleIntPushConstants
147{
148	UVec4 area;
149	IVec4 color;
150	deUint32 attachmentNdx;
151};
152
153struct VerifySingleDepthPushConstants
154{
155	UVec4 area;
156	float depthData;
157};
158
159struct VerifySingleStencilPushConstants
160{
161	UVec4 area;
162	deUint32 stencilData;
163};
164
165//! The parameters that define a test case
166struct TestParams
167{
168	VkSampleCountFlagBits	numFloatColor1Samples;		//!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
169	VkSampleCountFlagBits	numFloatColor2Samples;		//!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
170	VkSampleCountFlagBits	numIntColorSamples;			//!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
171	VkSampleCountFlagBits	numDepthStencilSamples;		//!< VkAttachmentDescription::samples and VkImageCreateInfo::samples
172
173	VkFormat				floatColor1Format;			//!< Color attachment format
174	VkFormat				floatColor2Format;			//!< Color attachment format
175	VkFormat				intColorFormat;				//!< Color attachment format
176	VkFormat				depthStencilFormat;			//!< D/S attachment format. Will test both aspects if it's a mixed format
177
178	VkClearValue			clearValues[4];
179
180	VerifyPushConstants verifyConstants[RegionCount];
181
182	bool isMultisampledRenderToSingleSampled;			//!< Whether the test should use VK_EXT_multisampled_render_to_single_sampled or normal multisampling
183	bool clearBeforeRenderPass;							//!< Whether loadOp=CLEAR should be used, or clear is done before render pass and loadOp=LOAD is used
184	bool renderToWholeFramebuffer;						//!< Whether the test should render to the whole framebuffer.
185	bool testBlendsColors;								//!< Whether the test blends colors or overwrites them.  Tests don't adapt to this automatically, it's informative for shader generation.
186	bool dynamicRendering;								//!< Whether the test should use dynamic rendering.
187	bool useGarbageAttachment;							//!< Whether the test uese garbage attachments.
188
189	struct PerPass
190	{
191		VkSampleCountFlagBits	numSamples;				//!< Pipeline samples
192
193		deInt32 floatColor1Location;
194		deInt32 floatColor2Location;
195		deInt32 intColorLocation;
196		bool hasDepthStencil;
197
198		bool resolveFloatColor1;
199		bool resolveFloatColor2;
200		bool resolveIntColor;
201		bool resolveDepthStencil;
202
203		VkResolveModeFlagBits depthStencilResolveMode;
204
205		DrawPushConstants drawConstantsWithDepthWrite[RegionCount];
206		DrawPushConstants drawConstantsWithDepthTest[RegionCount];
207	};
208
209	std::vector<PerPass> perPass;
210
211	// Used to carry forward the rng seed from test generation to test run.
212	deUint32 rngSeed;
213
214	PipelineConstructionType pipelineConstructionType;
215
216	TestParams ()
217		: numFloatColor1Samples		{}
218		, numFloatColor2Samples		{}
219		, numIntColorSamples		{}
220		, numDepthStencilSamples	{}
221		, floatColor1Format			{}
222		, floatColor2Format			{}
223		, intColorFormat			{}
224		, depthStencilFormat		{}
225		, clearValues				{}
226	{
227	}
228
229	bool	usesColor1InPass		(const size_t passNdx) const	{ return perPass[passNdx].floatColor1Location >= 0; }
230	bool	usesColor2InPass		(const size_t passNdx) const	{ return perPass[passNdx].floatColor2Location >= 0; }
231	bool	usesColor3InPass		(const size_t passNdx) const	{ return perPass[passNdx].intColorLocation >= 0; }
232	bool	usesDepthStencilInPass	(const size_t passNdx) const	{ return perPass[passNdx].hasDepthStencil; }
233};
234
235struct Image
236{
237	Move<VkImage>				image;
238	MovePtr<Allocation>			alloc;
239	Move<VkImageView>			view;
240
241	void allocate(const DeviceInterface&		vk,
242				  const VkDevice				device,
243				  const MovePtr<Allocator>&		allocator,
244				  const VkFormat				format,
245				  const UVec2&					size,
246				  const VkSampleCountFlagBits	samples,
247				  const VkImageUsageFlags		usage,
248				  const VkImageAspectFlags		aspect,
249				  const deUint32				layerCount,
250				  const bool					usedForMSRTSS);
251	Move<VkImageView> makeView(const DeviceInterface&		vk,
252							   const VkDevice				device,
253							   const VkFormat				format,
254							   const VkImageAspectFlags		aspect,
255							   const deUint32				layerCount);
256};
257
258//! Common data used by the test
259struct WorkingData
260{
261	UVec2						framebufferSize;			//!< Size of the framebuffer
262	UVec4						renderArea;					//!< Render area
263
264	Move<VkBuffer>				vertexBuffer;				//!< Contains a fullscreen triangle
265	MovePtr<Allocation>			vertexBufferAlloc;			//!< Storage for vertexBuffer
266	Move<VkBuffer>				verificationBuffer;			//!< Buffer used for validation
267	MovePtr<Allocation>			verificationBufferAlloc;	//!< Storage for verificationBuffer
268	Move<VkBuffer>				singleVerificationBuffer;		//!< Buffer used for validation of attachments outside the render area
269	MovePtr<Allocation>			singleVerificationBufferAlloc;	//!< Storage for singleVerificationBuffer
270
271	//!< Color and depth/stencil attachments
272	Image						floatColor1;
273	Image						floatColor2;
274	Image						intColor;
275	Image						depthStencil;
276	Move<VkImageView>			depthOnlyImageView;
277	Move<VkImageView>			stencilOnlyImageView;
278
279	//!< Resolve attachments
280	Image						floatResolve1;
281	Image						floatResolve2;
282	Image						intResolve;
283	Image						depthStencilResolve;
284	Move<VkImageView>			depthOnlyResolveImageView;
285	Move<VkImageView>			stencilOnlyResolveImageView;
286
287	//!< Verification results for logging (an array of 5 to avoid hitting maxPerStageDescriptorStorageImages limit of 4.
288	Image						verify;
289
290	WorkingData (void) {}
291
292	Move<VkImage>&			getResolvedFloatColorImage1(const TestParams& params)
293	{
294		return params.numFloatColor1Samples != VK_SAMPLE_COUNT_1_BIT ? floatResolve1.image : floatColor1.image;
295	}
296	Move<VkImage>&			getResolvedFloatColorImage2(const TestParams& params)
297	{
298		return params.numFloatColor2Samples != VK_SAMPLE_COUNT_1_BIT ? floatResolve2.image : floatColor2.image;
299	}
300	Move<VkImage>&			getResolvedIntColorImage(const TestParams& params)
301	{
302		return params.numIntColorSamples != VK_SAMPLE_COUNT_1_BIT ? intResolve.image : intColor.image;
303	}
304	Move<VkImage>&			getResolvedDepthStencilImage(const TestParams& params)
305	{
306		return params.numDepthStencilSamples != VK_SAMPLE_COUNT_1_BIT ? depthStencilResolve.image : depthStencil.image;
307	}
308
309	Move<VkImageView>&			getResolvedFloatColorImage1View(const TestParams& params)
310	{
311		return params.numFloatColor1Samples != VK_SAMPLE_COUNT_1_BIT ? floatResolve1.view : floatColor1.view;
312	}
313	Move<VkImageView>&			getResolvedFloatColorImage2View(const TestParams& params)
314	{
315		return params.numFloatColor2Samples != VK_SAMPLE_COUNT_1_BIT ? floatResolve2.view : floatColor2.view;
316	}
317	Move<VkImageView>&			getResolvedIntColorImageView(const TestParams& params)
318	{
319		return params.numIntColorSamples != VK_SAMPLE_COUNT_1_BIT ? intResolve.view : intColor.view;
320	}
321	Move<VkImageView>&			getResolvedDepthOnlyImageView(const TestParams& params)
322	{
323		// If no depth aspect, return the stencil view just to have something bound in the desc set
324		if (!isDepthFormat(params.depthStencilFormat))
325			return getResolvedStencilOnlyImageView(params);
326		return params.numDepthStencilSamples != VK_SAMPLE_COUNT_1_BIT ? depthOnlyResolveImageView : depthOnlyImageView;
327	}
328	Move<VkImageView>&			getResolvedStencilOnlyImageView(const TestParams& params)
329	{
330		// If no stencil aspect, return the depth view just to have something bound in the desc set
331		if (!isStencilFormat(params.depthStencilFormat))
332			return getResolvedDepthOnlyImageView(params);
333		return params.numDepthStencilSamples != VK_SAMPLE_COUNT_1_BIT ? stencilOnlyResolveImageView : stencilOnlyImageView;
334	}
335};
336
337// Accumulate objects throughout the test to avoid them getting deleted before the command buffer is submitted and waited on.
338// Speeds up the test by avoiding making multiple submissions and waits.
339class TestObjects
340{
341public:
342	TestObjects(Context& contextIn);
343
344	void									beginCommandBuffer();
345	void									submitCommandsAndWait();
346
347	const Unique<VkCommandPool>							cmdPool;
348	const Unique<VkCommandBuffer>						cmdBuffer;
349	std::vector<PipelineSp>								computePipelines;
350	std::vector<MovePtr<GraphicsPipelineWrapper>>		graphicsPipelines;
351	std::vector<Move<VkDescriptorPool>>					descriptorPools;
352	std::vector<Move<VkDescriptorSet>>					descriptorSets;
353	std::vector<RenderPassWrapper>						renderPassFramebuffers;
354
355private:
356	Context&								context;
357};
358
359const VkImageUsageFlags	commonImageUsageFlags		= VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
360const VkImageUsageFlags	colorImageUsageFlags		= commonImageUsageFlags | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
361const VkImageUsageFlags depthStencilImageUsageFlags	= commonImageUsageFlags | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
362
363Move<VkImage> makeImage (const DeviceInterface&			vk,
364						 const VkDevice					device,
365						 const VkFormat					format,
366						 const UVec2&					size,
367						 const deUint32					layerCount,
368						 const VkSampleCountFlagBits	samples,
369						 const VkImageUsageFlags		usage,
370						 const bool						usedForMSRTSS)
371{
372	const VkImageCreateFlags createFlags = samples == VK_SAMPLE_COUNT_1_BIT && usedForMSRTSS ? VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT : 0;
373
374	const VkImageCreateInfo imageParams =
375	{
376		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
377		DE_NULL,										// const void*				pNext;
378		createFlags,									// VkImageCreateFlags		flags;
379		VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
380		format,											// VkFormat					format;
381		makeExtent3D(size.x(), size.y(), 1),			// VkExtent3D				extent;
382		1u,												// deUint32					mipLevels;
383		layerCount,										// deUint32					arrayLayers;
384		samples,										// VkSampleCountFlagBits	samples;
385		VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
386		usage,											// VkImageUsageFlags		usage;
387		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
388		0u,												// deUint32					queueFamilyIndexCount;
389		DE_NULL,										// const deUint32*			pQueueFamilyIndices;
390		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout;
391	};
392	return createImage(vk, device, &imageParams);
393}
394
395void Image::allocate (const DeviceInterface&		vk,
396					  const VkDevice				device,
397					  const MovePtr<Allocator>&		allocator,
398					  const VkFormat				format,
399					  const UVec2&					size,
400					  const VkSampleCountFlagBits	samples,
401					  const VkImageUsageFlags		usage,
402					  const VkImageAspectFlags		aspect,
403					  const deUint32				layerCount,
404					  const bool					usedForMSRTSS)
405{
406	image	= makeImage(vk, device, format, size, layerCount, samples, usage, usedForMSRTSS);
407	alloc	= bindImage(vk, device, *allocator, *image, MemoryRequirement::Any);
408	view	= makeView(vk, device, format, aspect, layerCount);
409}
410
411Move<VkImageView> Image::makeView(const DeviceInterface&	vk,
412								  const VkDevice			device,
413								  const VkFormat			format,
414								  const VkImageAspectFlags	aspect,
415								  const deUint32				layerCount)
416{
417	return makeImageView(vk, device, *image, layerCount > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D, format, makeImageSubresourceRange(aspect, 0u, 1u, 0u, layerCount));
418}
419
420//! Create a test-specific MSAA pipeline
421MovePtr<GraphicsPipelineWrapper> makeGraphicsPipeline (const InstanceInterface&					vki,
422													   const DeviceInterface&					vk,
423													   const VkPhysicalDevice					physicalDevice,
424													   const VkDevice							device,
425													   const std::vector<std::string>&			deviceExtensions,
426													   const PipelineConstructionType			pipelineConstructionType,
427													   const PipelineLayoutWrapper&				pipelineLayout,
428													   const VkRenderPass						renderPass,
429													   VkPipelineRenderingCreateInfoKHR*		pipelineRenderingCreateInfo,
430													   const ShaderWrapper						vertexModule,
431													   const ShaderWrapper						fragmentModule,
432													   const bool								enableBlend,
433													   const bool								enableDepthStencilWrite,
434													   const bool								enableDepthTest,
435													   const deUint32							intWriteMask,
436													   const deUint32							subpassNdx,
437													   const deInt32							integerAttachmentLocation,
438													   const UVec4&								viewportIn,
439													   const UVec4&								scissorIn,
440													   const VkSampleCountFlagBits				numSamples,
441													   const bool								garbageAttachment)
442{
443	std::vector<VkVertexInputBindingDescription>	vertexInputBindingDescriptions;
444	std::vector<VkVertexInputAttributeDescription>	vertexInputAttributeDescriptions;
445
446	// Vertex attributes: position
447	vertexInputBindingDescriptions.push_back  (makeVertexInputBindingDescription  (0u, sizeof(Vec4), VK_VERTEX_INPUT_RATE_VERTEX));
448	vertexInputAttributeDescriptions.push_back(makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u));
449
450	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
451	{
452		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
453		DE_NULL,														// const void*								pNext;
454		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags	flags;
455		static_cast<deUint32>(vertexInputBindingDescriptions.size()),	// uint32_t									vertexBindingDescriptionCount;
456		dataOrNullPtr(vertexInputBindingDescriptions),					// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
457		static_cast<deUint32>(vertexInputAttributeDescriptions.size()),	// uint32_t									vertexAttributeDescriptionCount;
458		dataOrNullPtr(vertexInputAttributeDescriptions),				// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
459	};
460
461	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
462	{
463		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
464		DE_NULL,														// const void*								pNext;
465		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags	flags;
466		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology						topology;
467		VK_FALSE,														// VkBool32									primitiveRestartEnable;
468	};
469
470	const std::vector<VkViewport> viewports
471	{{
472		static_cast<float>(viewportIn.x()), static_cast<float>(viewportIn.y()),		// x, y
473		static_cast<float>(viewportIn.z()), static_cast<float>(viewportIn.w()),		// width, height
474		0.0f, 1.0f																	// minDepth, maxDepth
475	}};
476
477	const std::vector<VkRect2D> scissors =
478	{{
479		makeOffset2D(scissorIn.x(), scissorIn.y()),
480		makeExtent2D(scissorIn.z(), scissorIn.w()),
481	}};
482
483	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
484	{
485		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	// VkStructureType							sType;
486		DE_NULL,													// const void*								pNext;
487		(VkPipelineRasterizationStateCreateFlags)0,					// VkPipelineRasterizationStateCreateFlags	flags;
488		VK_FALSE,													// VkBool32									depthClampEnable;
489		VK_FALSE,													// VkBool32									rasterizerDiscardEnable;
490		VK_POLYGON_MODE_FILL,										// VkPolygonMode							polygonMode;
491		VK_CULL_MODE_NONE,											// VkCullModeFlags							cullMode;
492		VK_FRONT_FACE_COUNTER_CLOCKWISE,							// VkFrontFace								frontFace;
493		VK_FALSE,													// VkBool32									depthBiasEnable;
494		0.0f,														// float									depthBiasConstantFactor;
495		0.0f,														// float									depthBiasClamp;
496		0.0f,														// float									depthBiasSlopeFactor;
497		1.0f,														// float									lineWidth;
498	};
499
500	VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
501	{
502		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
503		DE_NULL,													// const void*								pNext;
504		(VkPipelineMultisampleStateCreateFlags)0,					// VkPipelineMultisampleStateCreateFlags	flags;
505		numSamples,													// VkSampleCountFlagBits					rasterizationSamples;
506		VK_TRUE,													// VkBool32									sampleShadingEnable;
507		1.0f,														// float									minSampleShading;
508		DE_NULL,													// const VkSampleMask*						pSampleMask;
509		VK_FALSE,													// VkBool32									alphaToCoverageEnable;
510		VK_FALSE													// VkBool32									alphaToOneEnable;
511	};
512
513	// Simply increment the buffer
514	const VkStencilOpState stencilOpState = makeStencilOpState(
515		VK_STENCIL_OP_KEEP,						// stencil fail
516		VK_STENCIL_OP_INCREMENT_AND_CLAMP,		// depth & stencil pass
517		VK_STENCIL_OP_KEEP,						// depth only fail
518		VK_COMPARE_OP_ALWAYS,					// compare op
519		~0u,									// compare mask
520		~0u,									// write mask
521		0u);									// reference
522
523	// Enable depth write and test if needed
524	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
525	{
526		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,			// VkStructureType							sType;
527		DE_NULL,															// const void*								pNext;
528		(VkPipelineDepthStencilStateCreateFlags)0,							// VkPipelineDepthStencilStateCreateFlags	flags;
529		VK_TRUE,															// VkBool32									depthTestEnable;
530		enableDepthStencilWrite,											// VkBool32									depthWriteEnable;
531		enableDepthTest ? VK_COMPARE_OP_GREATER : VK_COMPARE_OP_ALWAYS,		// VkCompareOp								depthCompareOp;
532		VK_FALSE,															// VkBool32									depthBoundsTestEnable;
533		VK_TRUE,															// VkBool32									stencilTestEnable;
534		stencilOpState,														// VkStencilOpState							front;
535		stencilOpState,														// VkStencilOpState							back;
536		0.0f,																// float									minDepthBounds;
537		1.0f,																// float									maxDepthBounds;
538	};
539
540	// Always blend by addition.  This is used to verify the combination of multiple draw calls.
541	const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
542	VkPipelineColorBlendAttachmentState defaultBlendAttachmentState =
543	{
544		enableBlend
545			? VK_TRUE
546			: VK_FALSE,			// VkBool32					blendEnable;
547		VK_BLEND_FACTOR_ONE,	// VkBlendFactor			srcColorBlendFactor;
548		VK_BLEND_FACTOR_ONE,	// VkBlendFactor			dstColorBlendFactor;
549		VK_BLEND_OP_ADD,		// VkBlendOp				colorBlendOp;
550		VK_BLEND_FACTOR_ONE,	// VkBlendFactor			srcAlphaBlendFactor;
551		VK_BLEND_FACTOR_ONE,	// VkBlendFactor			dstAlphaBlendFactor;
552		VK_BLEND_OP_ADD,		// VkBlendOp				alphaBlendOp;
553		colorComponentsAll,		// VkColorComponentFlags	colorWriteMask;
554	};
555
556	VkPipelineColorBlendAttachmentState blendAttachmentStates[4] =
557	{
558		defaultBlendAttachmentState,
559		defaultBlendAttachmentState,
560		defaultBlendAttachmentState,
561		defaultBlendAttachmentState,
562	};
563
564	if (enableBlend && integerAttachmentLocation >= 0)
565	{
566		// Disable blend for the integer attachment unconditionally
567		blendAttachmentStates[integerAttachmentLocation].blendEnable = VK_FALSE;
568		// But emulate it by outputting to one channel only.
569		blendAttachmentStates[integerAttachmentLocation].colorWriteMask =
570			((intWriteMask & 1) != 0 ? VK_COLOR_COMPONENT_R_BIT : 0) |
571			((intWriteMask & 2) != 0 ? VK_COLOR_COMPONENT_G_BIT : 0) |
572			((intWriteMask & 4) != 0 ? VK_COLOR_COMPONENT_B_BIT : 0) |
573			((intWriteMask & 8) != 0 ? VK_COLOR_COMPONENT_A_BIT : 0);
574		DE_ASSERT(blendAttachmentStates[integerAttachmentLocation].colorWriteMask != 0);
575	}
576
577	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
578	{
579		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
580		DE_NULL,													// const void*									pNext;
581		(VkPipelineColorBlendStateCreateFlags)0,					// VkPipelineColorBlendStateCreateFlags			flags;
582		VK_FALSE,													// VkBool32										logicOpEnable;
583		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
584		4u,															// deUint32										attachmentCount;
585		blendAttachmentStates,										// const VkPipelineColorBlendAttachmentState*	pAttachments;
586		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConstants[4];
587	};
588
589	VkPipelineRenderingCreateInfo pipelineRenderingCreateInfoWithGarbage;
590	std::vector<VkFormat> garbageFormats;
591
592	if (garbageAttachment)
593	{
594		DE_ASSERT(pipelineRenderingCreateInfo);
595
596		for (int i = 0; i < 10; i++)
597			garbageFormats.push_back(VK_FORMAT_UNDEFINED);
598
599		pipelineRenderingCreateInfoWithGarbage = *pipelineRenderingCreateInfo;
600		// Just set a bunch of VK_FORMAT_UNDEFINED for garbage_color_attachment tests to make the validation happy.
601		pipelineRenderingCreateInfoWithGarbage.colorAttachmentCount		= static_cast<uint32_t>(garbageFormats.size());
602		pipelineRenderingCreateInfoWithGarbage.pColorAttachmentFormats  = garbageFormats.data();
603	}
604
605	MovePtr<GraphicsPipelineWrapper> graphicsPipeline = MovePtr<GraphicsPipelineWrapper>(new GraphicsPipelineWrapper(vki, vk, physicalDevice, device, deviceExtensions, pipelineConstructionType, 0u));
606	graphicsPipeline.get()->setMonolithicPipelineLayout(pipelineLayout)
607			.setupVertexInputState(&vertexInputStateInfo,
608								   &pipelineInputAssemblyStateInfo)
609			.setupPreRasterizationShaderState(viewports,
610											  scissors,
611											  pipelineLayout,
612											  renderPass,
613											  subpassNdx,
614											  vertexModule,
615											  &pipelineRasterizationStateInfo,
616											  ShaderWrapper(),
617											  ShaderWrapper(),
618											  ShaderWrapper(),
619											  DE_NULL,
620											  nullptr,
621											  garbageAttachment ? &pipelineRenderingCreateInfoWithGarbage : pipelineRenderingCreateInfo)
622			.setupFragmentShaderState(pipelineLayout,
623									  renderPass,
624									  subpassNdx,
625									  fragmentModule,
626									  &pipelineDepthStencilStateInfo,
627									  &pipelineMultisampleStateInfo)
628			.setRenderingColorAttachmentsInfo(pipelineRenderingCreateInfo)
629			.setupFragmentOutputState(renderPass,
630									  subpassNdx,
631									  &pipelineColorBlendStateInfo,
632									  &pipelineMultisampleStateInfo)
633			.buildPipeline();
634
635	return graphicsPipeline;
636}
637
638void logTestImages(Context&						context,
639				   const TestParams&			params,
640				   WorkingData&					wd,
641				   const bool					drawsToColor1,
642				   const bool					drawsToColor2,
643				   const bool					drawsToColor3,
644				   const bool					drawsToDepthStencil)
645{
646	const DeviceInterface&	vk				= context.getDeviceInterface();
647	const VkDevice			device			= context.getDevice();
648	MovePtr<Allocator>		allocator		= MovePtr<Allocator>(new SimpleAllocator(vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
649	tcu::TestLog&			log				= context.getTestContext().getLog();
650
651	const VkDeviceSize				bufferSize[4]	=
652	{
653		wd.framebufferSize.x() * wd.framebufferSize.y() * tcu::getPixelSize(mapVkFormat(params.floatColor1Format)),
654		wd.framebufferSize.x() * wd.framebufferSize.y() * tcu::getPixelSize(mapVkFormat(params.floatColor2Format)),
655		wd.framebufferSize.x() * wd.framebufferSize.y() * tcu::getPixelSize(mapVkFormat(params.intColorFormat)),
656		wd.framebufferSize.x() * wd.framebufferSize.y() * tcu::getPixelSize(mapVkFormat(params.depthStencilFormat)),
657	};
658	const Move<VkBuffer>			buffer[5]		=
659	{
660		makeBuffer(vk, device, bufferSize[0], VK_BUFFER_USAGE_TRANSFER_DST_BIT),
661		makeBuffer(vk, device, bufferSize[1], VK_BUFFER_USAGE_TRANSFER_DST_BIT),
662		makeBuffer(vk, device, bufferSize[2], VK_BUFFER_USAGE_TRANSFER_DST_BIT),
663		makeBuffer(vk, device, bufferSize[3], VK_BUFFER_USAGE_TRANSFER_DST_BIT),
664		makeBuffer(vk, device, bufferSize[3], VK_BUFFER_USAGE_TRANSFER_DST_BIT),
665	};
666	const MovePtr<Allocation>		bufferAlloc[5]	=
667	{
668		bindBuffer(vk, device, *allocator, *buffer[0], MemoryRequirement::HostVisible),
669		bindBuffer(vk, device, *allocator, *buffer[1], MemoryRequirement::HostVisible),
670		bindBuffer(vk, device, *allocator, *buffer[2], MemoryRequirement::HostVisible),
671		bindBuffer(vk, device, *allocator, *buffer[3], MemoryRequirement::HostVisible),
672		bindBuffer(vk, device, *allocator, *buffer[4], MemoryRequirement::HostVisible),
673	};
674
675	for (deUint32 bufferNdx = 0; bufferNdx < 5; ++bufferNdx)
676		invalidateAlloc(vk, device, *bufferAlloc[bufferNdx]);
677
678	const Unique<VkCommandPool>		cmdPool				(createCommandPool  (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
679	const Unique<VkCommandBuffer>	cmdBuffer			(makeCommandBuffer(vk, device, *cmdPool));
680
681	beginCommandBuffer(vk, *cmdBuffer);
682
683	const IVec2	size	(wd.framebufferSize.x(), wd.framebufferSize.y());
684	{
685		if (drawsToColor1)
686			copyImageToBuffer(vk, *cmdBuffer, *wd.getResolvedFloatColorImage1(params),	*buffer[0], size, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1);
687		if (drawsToColor2)
688			copyImageToBuffer(vk, *cmdBuffer, *wd.getResolvedFloatColorImage2(params),	*buffer[1], size, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1);
689		if (drawsToColor3)
690			copyImageToBuffer(vk, *cmdBuffer, *wd.getResolvedIntColorImage(params),		*buffer[2], size, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1);
691
692		VkImageLayout depthStencilLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
693		if (drawsToDepthStencil && isDepthFormat(params.depthStencilFormat))
694		{
695			copyImageToBuffer(vk, *cmdBuffer, *wd.getResolvedDepthStencilImage(params),	*buffer[3], size, VK_ACCESS_SHADER_WRITE_BIT, depthStencilLayout, 1,
696							  getDepthStencilAspectFlags(params.depthStencilFormat), VK_IMAGE_ASPECT_DEPTH_BIT);
697			depthStencilLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
698		}
699		if (drawsToDepthStencil && isStencilFormat(params.depthStencilFormat))
700		{
701			copyImageToBuffer(vk, *cmdBuffer, *wd.getResolvedDepthStencilImage(params),	*buffer[4], size, VK_ACCESS_SHADER_WRITE_BIT, depthStencilLayout, 1,
702							  getDepthStencilAspectFlags(params.depthStencilFormat), VK_IMAGE_ASPECT_STENCIL_BIT);
703		}
704	}
705
706	endCommandBuffer(vk, *cmdBuffer);
707	submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
708
709	// For the D32 depth formats, we specify the texture format directly as tcu::getEffectiveDepthStencilAccess assumes stencil data is interleaved.
710	// For the D24 format however, we have to use tcu::getEffectiveDepthStencilAccess to correctly account for the 8-bit padding.
711	const tcu::TextureFormat		copiedDepthFormat = tcu::TextureFormat(tcu::TextureFormat::D,
712																		   params.depthStencilFormat == VK_FORMAT_D16_UNORM	? tcu::TextureFormat::UNORM_INT16
713																															: tcu::TextureFormat::FLOAT);
714	const tcu::TextureFormat		copiedStencilFormat = tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
715
716	const tcu::ConstPixelBufferAccess	testImageData[5]	=
717	{
718		{ mapVkFormat(params.floatColor1Format),	size.x(), size.y(), 1, bufferAlloc[0]->getHostPtr() },
719		{ mapVkFormat(params.floatColor2Format),	size.x(), size.y(), 1, bufferAlloc[1]->getHostPtr() },
720		{ mapVkFormat(params.intColorFormat),		size.x(), size.y(), 1, bufferAlloc[2]->getHostPtr() },
721		{ copiedDepthFormat,						size.x(), size.y(), 1, bufferAlloc[3]->getHostPtr() },
722		{ copiedStencilFormat,						size.x(), size.y(), 1, bufferAlloc[4]->getHostPtr() },
723	};
724
725	const tcu::ConstPixelBufferAccess	testImageDataD24	= tcu::getEffectiveDepthStencilAccess(tcu::ConstPixelBufferAccess(mapVkFormat(params.depthStencilFormat),
726																															  size.x(), size.y(), 1, bufferAlloc[3]->getHostPtr()),
727																								  tcu::Sampler::MODE_DEPTH);
728
729	log << tcu::TestLog::ImageSet("attachments", "attachments");
730	if (drawsToColor1)
731		log << tcu::TestLog::Image("Color attachment 1",	"Color attachment 1",		testImageData[0]);
732	if (drawsToColor2)
733		log << tcu::TestLog::Image("Color attachment 2",	"Color attachment 2",		testImageData[1]);
734	if (drawsToColor3)
735		log << tcu::TestLog::Image("Color attachment 3",	"Color attachment 3",		testImageData[2]);
736	if (isDepthFormat(params.depthStencilFormat))
737		log << tcu::TestLog::Image("Depth attachment",		"Depth attachment",			params.depthStencilFormat == VK_FORMAT_D24_UNORM_S8_UINT ? testImageDataD24 : testImageData[3]);
738	if (isStencilFormat(params.depthStencilFormat))
739		log << tcu::TestLog::Image("Stencil attachment",	"Stencil attachment",		testImageData[4]);
740	log << tcu::TestLog::EndImageSet;
741}
742
743void logVerifyImages(Context&						context,
744					 const TestParams&				params,
745					 WorkingData&					wd,
746					 const bool						drawsToColor1,
747					 const bool						drawsToColor2,
748					 const bool						drawsToColor3,
749					 const bool						drawsToDepthStencil)
750{
751	const DeviceInterface&	vk				= context.getDeviceInterface();
752	const VkDevice			device			= context.getDevice();
753	MovePtr<Allocator>		allocator		= MovePtr<Allocator>(new SimpleAllocator(vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
754	tcu::TestLog&			log				= context.getTestContext().getLog();
755
756	const VkDeviceSize				bufferSize	= wd.framebufferSize.x() * wd.framebufferSize.y() * 5 * tcu::getPixelSize(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
757	const Move<VkBuffer>			buffer		= makeBuffer(vk, device, bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
758	const MovePtr<Allocation>		bufferAlloc	= bindBuffer(vk, device, *allocator, *buffer, MemoryRequirement::HostVisible);
759
760	invalidateAlloc(vk, device, *bufferAlloc);
761
762	const Unique<VkCommandPool>		cmdPool				(createCommandPool  (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
763	const Unique<VkCommandBuffer>	cmdBuffer			(makeCommandBuffer(vk, device, *cmdPool));
764
765	beginCommandBuffer(vk, *cmdBuffer);
766
767	copyImageToBuffer(vk, *cmdBuffer, *wd.verify.image, *buffer, IVec2(wd.framebufferSize.x(), wd.framebufferSize.y()), VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL, 5);
768
769	endCommandBuffer(vk, *cmdBuffer);
770	submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
771
772	const tcu::ConstPixelBufferAccess	verifyImageData	(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), wd.framebufferSize.x(), wd.framebufferSize.y(), 5, bufferAlloc->getHostPtr());
773
774	log << tcu::TestLog::ImageSet("attachment error mask", "attachment error mask");
775	if (drawsToColor1)
776		log << tcu::TestLog::Image("ErrorMask color attachment 1", "Error mask color attachment 1", tcu::getSubregion(verifyImageData, 0, 0, 0, wd.framebufferSize.x(), wd.framebufferSize.y(), 1));
777	if (drawsToColor2)
778		log << tcu::TestLog::Image("ErrorMask color attachment 2", "Error mask color attachment 2", tcu::getSubregion(verifyImageData, 0, 0, 1, wd.framebufferSize.x(), wd.framebufferSize.y(), 1));
779	if (drawsToColor3)
780		log << tcu::TestLog::Image("ErrorMask color attachment 3", "Error mask color attachment 3", tcu::getSubregion(verifyImageData, 0, 0, 2, wd.framebufferSize.x(), wd.framebufferSize.y(), 1));
781	if (drawsToDepthStencil && isDepthFormat(params.depthStencilFormat))
782		log << tcu::TestLog::Image("ErrorMask depth attachment", "Error mask depth attachment", tcu::getSubregion(verifyImageData, 0, 0, 3, wd.framebufferSize.x(), wd.framebufferSize.y(), 1));
783	if (drawsToDepthStencil && isStencilFormat(params.depthStencilFormat))
784		log << tcu::TestLog::Image("ErrorMask stencil attachment", "Error mask stencil attachment", tcu::getSubregion(verifyImageData, 0, 0, 4, wd.framebufferSize.x(), wd.framebufferSize.y(), 1));
785	log << tcu::TestLog::EndImageSet;
786}
787
788bool checkAndReportError (Context&						context,
789						  const deUint32				verifiedPixelCount,
790						  const deUint32				expectedPixelCount,
791						  const std::string&			attachment)
792{
793	tcu::TestLog&	log	= context.getTestContext().getLog();
794
795	bool passed = verifiedPixelCount == expectedPixelCount;
796
797	if (passed)
798		log << tcu::TestLog::Message << "Verification passed for " << attachment << tcu::TestLog::EndMessage;
799	else
800		log << tcu::TestLog::Message << "Verification failed for " << attachment << " for " << (expectedPixelCount - verifiedPixelCount) << " pixel(s)" << tcu::TestLog::EndMessage;
801
802	return passed;
803}
804
805void checkSampleRequirements (Context&						context,
806							  const VkSampleCountFlagBits	numSamples,
807							  const bool					checkColor,
808							  const bool					checkDepth,
809							  const bool					checkStencil)
810{
811	const VkPhysicalDeviceLimits& limits = context.getDeviceProperties().limits;
812
813	if (checkColor && (limits.framebufferColorSampleCounts & numSamples) == 0u)
814		TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported");
815
816	if (checkDepth && (limits.framebufferDepthSampleCounts & numSamples) == 0u)
817		TCU_THROW(NotSupportedError, "framebufferDepthSampleCounts: sample count not supported");
818
819	if (checkStencil && (limits.framebufferStencilSampleCounts & numSamples) == 0u)
820		TCU_THROW(NotSupportedError, "framebufferStencilSampleCounts: sample count not supported");
821}
822
823void checkImageRequirements (Context&						context,
824							 const VkFormat					format,
825							 const VkFormatFeatureFlags		requiredFeatureFlags,
826							 const VkImageUsageFlags		requiredUsageFlags,
827							 const VkSampleCountFlagBits	requiredSampleCount,
828							 VkImageFormatProperties&		imageProperties)
829{
830	const InstanceInterface&		vki				= context.getInstanceInterface();
831	const VkPhysicalDevice			physicalDevice	= context.getPhysicalDevice();
832
833	const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(vki, physicalDevice, format);
834
835	if ((formatProperties.optimalTilingFeatures & requiredFeatureFlags) != requiredFeatureFlags)
836		TCU_THROW(NotSupportedError, (de::toString(format) + ": format features not supported").c_str());
837
838	const VkImageCreateFlags createFlags = requiredSampleCount == VK_SAMPLE_COUNT_1_BIT ? VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT : 0;
839
840	const VkResult result = vki.getPhysicalDeviceImageFormatProperties(physicalDevice, format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, requiredUsageFlags, createFlags, &imageProperties);
841
842	if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
843		TCU_THROW(NotSupportedError, (de::toString(format) + ": format not supported").c_str());
844
845	if ((imageProperties.sampleCounts & requiredSampleCount) != requiredSampleCount)
846		TCU_THROW(NotSupportedError, (de::toString(format) + ": sample count not supported").c_str());
847}
848
849TestObjects::TestObjects(Context& contextIn)
850	: cmdPool(createCommandPool(contextIn.getDeviceInterface(), contextIn.getDevice(), VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, contextIn.getUniversalQueueFamilyIndex()))
851	, cmdBuffer(makeCommandBuffer(contextIn.getDeviceInterface(), contextIn.getDevice(), *cmdPool))
852	, context(contextIn)
853{
854}
855
856void TestObjects::beginCommandBuffer()
857{
858	const DeviceInterface&	vk				= context.getDeviceInterface();
859
860	vk::beginCommandBuffer(vk, *cmdBuffer);
861}
862
863void TestObjects::submitCommandsAndWait()
864{
865	const DeviceInterface&	vk				= context.getDeviceInterface();
866	const VkDevice			device			= context.getDevice();
867
868	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
869	vk::submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
870}
871
872void initializeAttachments(const TestParams& params, WorkingData& wd, std::vector<VkImage>& images, std::vector<VkImageView>& attachments, const size_t passNdx, deInt32 attachmentNdxes[8])
873{
874	const bool	includeAll	= passNdx >= params.perPass.size();
875	deInt32		currentNdx	= 0;
876
877	// Output attachments
878	if (includeAll || params.usesColor1InPass(passNdx))
879	{
880		images.push_back(wd.floatColor1.image.get());
881		attachments.push_back(wd.floatColor1.view.get());
882		attachmentNdxes[0] = currentNdx++;
883	}
884	if (includeAll || params.usesColor2InPass(passNdx))
885	{
886		images.push_back(wd.floatColor2.image.get());
887		attachments.push_back(wd.floatColor2.view.get());
888		attachmentNdxes[1] = currentNdx++;
889	}
890	if (includeAll || params.usesColor3InPass(passNdx))
891	{
892		images.push_back(wd.intColor.image.get());
893		attachments.push_back(wd.intColor.view.get());
894		attachmentNdxes[2] = currentNdx++;
895	}
896	if (includeAll || params.usesDepthStencilInPass(passNdx))
897	{
898		images.push_back(wd.depthStencil.image.get());
899		attachments.push_back(wd.depthStencil.view.get());
900		attachmentNdxes[3] = currentNdx++;
901	}
902
903	// Resolve attachments
904	if (params.numFloatColor1Samples != VK_SAMPLE_COUNT_1_BIT && (includeAll || params.usesColor1InPass(passNdx)))
905	{
906		images.push_back(wd.floatResolve1.image.get());
907		attachments.push_back(wd.floatResolve1.view.get());
908		attachmentNdxes[4] = currentNdx++;
909	}
910	if (params.numFloatColor2Samples != VK_SAMPLE_COUNT_1_BIT && (includeAll || params.usesColor2InPass(passNdx)))
911	{
912		images.push_back(wd.floatResolve2.image.get());
913		attachments.push_back(wd.floatResolve2.view.get());
914		attachmentNdxes[5] = currentNdx++;
915	}
916	if (params.numIntColorSamples != VK_SAMPLE_COUNT_1_BIT && (includeAll || params.usesColor3InPass(passNdx)))
917	{
918		images.push_back(wd.intResolve.image.get());
919		attachments.push_back(wd.intResolve.view.get());
920		attachmentNdxes[6] = currentNdx++;
921	}
922	if (params.numDepthStencilSamples != VK_SAMPLE_COUNT_1_BIT && (includeAll || params.usesDepthStencilInPass(passNdx)))
923	{
924		images.push_back(wd.depthStencilResolve.image.get());
925		attachments.push_back(wd.depthStencilResolve.view.get());
926		attachmentNdxes[7] = currentNdx++;
927	}
928}
929
930void initializeAttachmentDescriptions(const TestParams& params, std::vector<VkAttachmentDescription2>& descs,
931		const bool preCleared, const deInt32 attachmentNdxes[8], deUint32& attachmentUseMask)
932{
933	// The attachments are either cleared already or should be cleared now.  If an attachment was used in a previous render pass,
934	// it will override these values to always LOAD and use the SHADER_READ_ONLY layout.  It's SHADER_READ_ONLY because final layout
935	// is always that for simplicity.
936	const VkAttachmentLoadOp	loadOp			= preCleared ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR;
937	const VkImageLayout			initialLayout	= preCleared ? VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED;
938
939	// Output attachments
940	if (attachmentNdxes[0] >= 0)
941	{
942		descs.push_back(VkAttachmentDescription2{
943			VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,						// VkStructureType                  sType;
944			DE_NULL,														// const void*                      pNext;
945			(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFlags		flags;
946			params.floatColor1Format,										// VkFormat							format;
947			params.numFloatColor1Samples,									// VkSampleCountFlagBits			samples;
948			(attachmentUseMask & (1 << 0)) != 0
949				? VK_ATTACHMENT_LOAD_OP_LOAD
950				: loadOp,													// VkAttachmentLoadOp				loadOp;
951			VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp				storeOp;
952			VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp				stencilLoadOp;
953			VK_ATTACHMENT_STORE_OP_DONT_CARE,								// VkAttachmentStoreOp				stencilStoreOp;
954			(attachmentUseMask & (1 << 0)) != 0
955				? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
956				: initialLayout,											// VkImageLayout					initialLayout;
957			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL						// VkImageLayout					finalLayout;
958		});
959		attachmentUseMask |= 1 << 0;
960	}
961
962	if (attachmentNdxes[1] >= 0)
963	{
964		descs.push_back(VkAttachmentDescription2{
965			VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,						// VkStructureType                  sType;
966			DE_NULL,														// const void*                      pNext;
967			(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFlags		flags;
968			params.floatColor2Format,										// VkFormat							format;
969			params.numFloatColor2Samples,									// VkSampleCountFlagBits			samples;
970			(attachmentUseMask & (1 << 1)) != 0
971				? VK_ATTACHMENT_LOAD_OP_LOAD
972				: loadOp,													// VkAttachmentLoadOp				loadOp;
973			VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp				storeOp;
974			VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp				stencilLoadOp;
975			VK_ATTACHMENT_STORE_OP_DONT_CARE,								// VkAttachmentStoreOp				stencilStoreOp;
976			(attachmentUseMask & (1 << 1)) != 0
977				? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
978				: initialLayout,											// VkImageLayout					initialLayout;
979			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL						// VkImageLayout					finalLayout;
980		});
981		attachmentUseMask |= 1 << 1;
982	}
983
984	if (attachmentNdxes[2] >= 0)
985	{
986		descs.push_back(VkAttachmentDescription2{
987			VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,						// VkStructureType                  sType;
988			DE_NULL,														// const void*                      pNext;
989			(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFlags		flags;
990			params.intColorFormat,											// VkFormat							format;
991			params.numIntColorSamples,										// VkSampleCountFlagBits			samples;
992			(attachmentUseMask & (1 << 2)) != 0
993				? VK_ATTACHMENT_LOAD_OP_LOAD
994				: loadOp,													// VkAttachmentLoadOp				loadOp;
995			VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp				storeOp;
996			VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp				stencilLoadOp;
997			VK_ATTACHMENT_STORE_OP_DONT_CARE,								// VkAttachmentStoreOp				stencilStoreOp;
998			(attachmentUseMask & (1 << 2)) != 0
999				? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
1000				: initialLayout,											// VkImageLayout					initialLayout;
1001			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL						// VkImageLayout					finalLayout;
1002		});
1003		attachmentUseMask |= 1 << 2;
1004	}
1005
1006	if (attachmentNdxes[3] >= 0)
1007	{
1008		descs.push_back(VkAttachmentDescription2{
1009			VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,						// VkStructureType                  sType;
1010			DE_NULL,														// const void*                      pNext;
1011			(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFlags		flags;
1012			params.depthStencilFormat,										// VkFormat							format;
1013			params.numDepthStencilSamples,									// VkSampleCountFlagBits			samples;
1014			(attachmentUseMask & (1 << 3)) != 0
1015				? VK_ATTACHMENT_LOAD_OP_LOAD
1016				: loadOp,													// VkAttachmentLoadOp				loadOp;
1017			VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp				storeOp;
1018			(attachmentUseMask & (1 << 3)) != 0
1019				? VK_ATTACHMENT_LOAD_OP_LOAD
1020				: loadOp,													// VkAttachmentLoadOp				stencilLoadOp;
1021			VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp				stencilStoreOp;
1022			(attachmentUseMask & (1 << 3)) != 0
1023				? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
1024				: initialLayout,											// VkImageLayout					initialLayout;
1025			VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL					// VkImageLayout					finalLayout;
1026		});
1027		attachmentUseMask |= 1 << 3;
1028	}
1029
1030	// Resolve attachments
1031	if (attachmentNdxes[4] >= 0)
1032		descs.push_back(VkAttachmentDescription2{
1033			VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,						// VkStructureType                  sType;
1034			DE_NULL,														// const void*                      pNext;
1035			(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFlags		flags;
1036			params.floatColor1Format,										// VkFormat							format;
1037			VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits			samples;
1038			VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp				loadOp;
1039			VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp				storeOp;
1040			VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp				stencilLoadOp;
1041			VK_ATTACHMENT_STORE_OP_DONT_CARE,								// VkAttachmentStoreOp				stencilStoreOp;
1042			VK_IMAGE_LAYOUT_UNDEFINED,										// VkImageLayout					initialLayout;
1043			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL						// VkImageLayout					finalLayout;
1044		});
1045
1046	if (attachmentNdxes[5] >= 0)
1047		descs.push_back(VkAttachmentDescription2{
1048			VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,						// VkStructureType                  sType;
1049			DE_NULL,														// const void*                      pNext;
1050			(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFlags		flags;
1051			params.floatColor2Format,										// VkFormat							format;
1052			VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits			samples;
1053			VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp				loadOp;
1054			VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp				storeOp;
1055			VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp				stencilLoadOp;
1056			VK_ATTACHMENT_STORE_OP_DONT_CARE,								// VkAttachmentStoreOp				stencilStoreOp;
1057			VK_IMAGE_LAYOUT_UNDEFINED,										// VkImageLayout					initialLayout;
1058			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL						// VkImageLayout					finalLayout;
1059		});
1060
1061	if (attachmentNdxes[6] >= 0)
1062		descs.push_back(VkAttachmentDescription2{
1063			VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,						// VkStructureType                  sType;
1064			DE_NULL,														// const void*                      pNext;
1065			(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFlags		flags;
1066			params.intColorFormat,											// VkFormat							format;
1067			VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits			samples;
1068			VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp				loadOp;
1069			VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp				storeOp;
1070			VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp				stencilLoadOp;
1071			VK_ATTACHMENT_STORE_OP_DONT_CARE,								// VkAttachmentStoreOp				stencilStoreOp;
1072			VK_IMAGE_LAYOUT_UNDEFINED,										// VkImageLayout					initialLayout;
1073			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL						// VkImageLayout					finalLayout;
1074		});
1075
1076	if (attachmentNdxes[7] >= 0)
1077		descs.push_back(VkAttachmentDescription2{
1078			VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,						// VkStructureType                  sType;
1079			DE_NULL,														// const void*                      pNext;
1080			(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFlags		flags;
1081			params.depthStencilFormat,										// VkFormat							format;
1082			VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits			samples;
1083			VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp				loadOp;
1084			VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp				storeOp;
1085			VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp				stencilLoadOp;
1086			VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp				stencilStoreOp;
1087			VK_IMAGE_LAYOUT_UNDEFINED,										// VkImageLayout					initialLayout;
1088			VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL					// VkImageLayout					finalLayout;
1089		});
1090}
1091
1092void initializeRenderingAttachmentInfos (const TestParams&							params,
1093										 WorkingData&								wd,
1094										 std::vector<VkRenderingAttachmentInfo>&	colorAttachmentInfos,
1095										 VkRenderingAttachmentInfo&					depthStencilAttachmentInfo,
1096										 std::vector<VkFormat>&						colorAttachmentFormats,
1097										 const deInt32								attachmentNdxes[8],
1098										 deUint32&									attachmentUseMask,
1099										 deUint32									passNdx)
1100{
1101	// The attachments are either cleared already or should be cleared now. If an attachment was used in a previous render pass,
1102	// it will override these values to always LOAD and use the SHADER_READ_ONLY layout. It's SHADER_READ_ONLY because final layout
1103	// is always that for simplicity.
1104	const VkAttachmentLoadOp	loadOp			= params.clearBeforeRenderPass ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR;
1105	const TestParams::PerPass&	perPass			= params.perPass[passNdx];
1106
1107	const VkRenderingAttachmentInfo emptyRenderingAttachmentInfo = {
1108		VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,	// VkStructureType			sType
1109		DE_NULL,										// const void*				pNext
1110		DE_NULL,										// VkImageView				imageView
1111		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			imageLayout
1112		VK_RESOLVE_MODE_NONE,							// VkResolveModeFlagBits	resolveMode
1113		DE_NULL,										// VkImageView				resolveImageView
1114		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			resolveImageLayout
1115		VK_ATTACHMENT_LOAD_OP_DONT_CARE,				// VkAttachmentLoadOp		loadOp
1116		VK_ATTACHMENT_STORE_OP_DONT_CARE,				// VkAttachmentStoreOp		storeOp
1117		params.clearValues[0]							// VkClearValue				clearValue
1118	};
1119
1120	for (auto& colorAttachmentInfo : colorAttachmentInfos)
1121	{
1122		colorAttachmentInfo = emptyRenderingAttachmentInfo;
1123	}
1124
1125	// Output attachments
1126	if (attachmentNdxes[0] >= 0)
1127	{
1128		VkRenderingAttachmentInfo renderingAttachmentInfo = {
1129			VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,	// VkStructureType			sType
1130			DE_NULL,										// const void*				pNext
1131			wd.floatColor1.view.get(),						// VkImageView				imageView
1132			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			imageLayout
1133			VK_RESOLVE_MODE_NONE,							// VkResolveModeFlagBits	resolveMode
1134			DE_NULL,										// VkImageView				resolveImageView
1135			VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			resolveImageLayout
1136			(attachmentUseMask & (1 << 0)) != 0
1137				? VK_ATTACHMENT_LOAD_OP_LOAD
1138				: loadOp,									// VkAttachmentLoadOp		loadOp
1139			VK_ATTACHMENT_STORE_OP_STORE,					// VkAttachmentStoreOp		storeOp
1140			params.clearValues[0]							// VkClearValue				clearValue
1141		};
1142
1143		// Enable resolve image if it's used.
1144		if (attachmentNdxes[4] >= 0)
1145		{
1146			renderingAttachmentInfo.resolveMode			= VK_RESOLVE_MODE_AVERAGE_BIT;
1147			renderingAttachmentInfo.resolveImageView	= wd.floatResolve1.view.get();
1148			renderingAttachmentInfo.resolveImageLayout	= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1149		}
1150		else if (params.numFloatColor1Samples == VK_SAMPLE_COUNT_1_BIT)
1151		{
1152			renderingAttachmentInfo.resolveMode			= VK_RESOLVE_MODE_AVERAGE_BIT;
1153		}
1154
1155		colorAttachmentInfos[perPass.floatColor1Location]	= renderingAttachmentInfo;
1156		colorAttachmentFormats[perPass.floatColor1Location]	= params.floatColor1Format;
1157		attachmentUseMask |= 1 << 0;
1158	}
1159
1160	if (attachmentNdxes[1] >= 0)
1161	{
1162		VkRenderingAttachmentInfo renderingAttachmentInfo = {
1163			VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,	// VkStructureType			sType
1164			DE_NULL,										// const void*				pNext
1165			wd.floatColor2.view.get(),						// VkImageView				imageView
1166			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			imageLayout
1167			VK_RESOLVE_MODE_NONE,							// VkResolveModeFlagBits	resolveMode
1168			DE_NULL,										// VkImageView				resolveImageView
1169			VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			resolveImageLayout
1170			(attachmentUseMask & (1 << 1)) != 0
1171				? VK_ATTACHMENT_LOAD_OP_LOAD
1172				: loadOp,									// VkAttachmentLoadOp		loadOp
1173			VK_ATTACHMENT_STORE_OP_STORE,					// VkAttachmentStoreOp		storeOp
1174			params.clearValues[1]							// VkClearValue				clearValue
1175		};
1176
1177		if (attachmentNdxes[5] >= 0)
1178		{
1179			renderingAttachmentInfo.resolveMode			= VK_RESOLVE_MODE_AVERAGE_BIT;
1180			renderingAttachmentInfo.resolveImageView	= wd.floatResolve2.view.get();
1181			renderingAttachmentInfo.resolveImageLayout	= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1182		}
1183		else if (params.numFloatColor2Samples == VK_SAMPLE_COUNT_1_BIT)
1184		{
1185			renderingAttachmentInfo.resolveMode			= VK_RESOLVE_MODE_AVERAGE_BIT;
1186		}
1187
1188		colorAttachmentInfos[perPass.floatColor2Location] = renderingAttachmentInfo;
1189		colorAttachmentFormats[perPass.floatColor2Location] = params.floatColor2Format;
1190		attachmentUseMask |= 1 << 1;
1191	}
1192
1193	if (attachmentNdxes[2] >= 0)
1194	{
1195		VkRenderingAttachmentInfo renderingAttachmentInfo = {
1196			VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,	// VkStructureType			sType
1197			DE_NULL,										// const void*				pNext
1198			wd.intColor.view.get(),							// VkImageView				imageView
1199			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			imageLayout
1200			VK_RESOLVE_MODE_NONE,							// VkResolveModeFlagBits	resolveMode
1201			DE_NULL,										// VkImageView				resolveImageView
1202			VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			resolveImageLayout
1203			(attachmentUseMask & (1 << 2)) != 0
1204				? VK_ATTACHMENT_LOAD_OP_LOAD
1205				: loadOp,									// VkAttachmentLoadOp		loadOp
1206			VK_ATTACHMENT_STORE_OP_STORE,					// VkAttachmentStoreOp		storeOp
1207			params.clearValues[2]							// VkClearValue				clearValue
1208		};
1209
1210		if (attachmentNdxes[6] >= 0)
1211		{
1212			renderingAttachmentInfo.resolveMode			= VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
1213			renderingAttachmentInfo.resolveImageView	= wd.intResolve.view.get();
1214			renderingAttachmentInfo.resolveImageLayout	= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1215		}
1216		else if (params.numIntColorSamples == VK_SAMPLE_COUNT_1_BIT)
1217		{
1218			renderingAttachmentInfo.resolveMode			= VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
1219		}
1220
1221		colorAttachmentInfos[perPass.intColorLocation] = renderingAttachmentInfo;
1222		colorAttachmentFormats[perPass.intColorLocation] = params.intColorFormat;
1223		attachmentUseMask |= 1 << 2;
1224	}
1225
1226	if (attachmentNdxes[3] >= 0)
1227	{
1228
1229		VkRenderingAttachmentInfo renderingAttachmentInfo = {
1230			VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,		// VkStructureType			sType
1231			DE_NULL,											// const void*				pNext
1232			wd.depthStencil.view.get(),							// VkImageView				imageView
1233			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout			imageLayout
1234			VK_RESOLVE_MODE_NONE,								// VkResolveModeFlagBits	resolveMode
1235			DE_NULL,											// VkImageView				resolveImageView
1236			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			resolveImageLayout
1237			(attachmentUseMask & (1 << 3)) != 0
1238				? VK_ATTACHMENT_LOAD_OP_LOAD
1239				: loadOp,										// VkAttachmentLoadOp		loadOp
1240			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp		storeOp
1241			params.clearValues[3]								// VkClearValue				clearValue
1242		};
1243
1244		if (attachmentNdxes[7] >= 0)
1245		{
1246			renderingAttachmentInfo.resolveMode			= params.perPass[passNdx].depthStencilResolveMode;
1247			renderingAttachmentInfo.resolveImageView	= wd.depthStencilResolve.view.get();
1248			renderingAttachmentInfo.resolveImageLayout	= VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1249		}
1250		else if (params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT)
1251		{
1252			renderingAttachmentInfo.resolveMode			= params.perPass[passNdx].depthStencilResolveMode;
1253		}
1254
1255		depthStencilAttachmentInfo = renderingAttachmentInfo;
1256		attachmentUseMask |= 1 << 3;
1257	}
1258}
1259
1260void initResolveImageLayouts (Context&				context,
1261							  const TestParams&		params,
1262							  WorkingData&			wd,
1263							  TestObjects&			testObjects)
1264{
1265	const DeviceInterface&		vk						= context.getDeviceInterface();
1266	const VkImageMemoryBarrier	imageBarrierTemplate	=
1267	{
1268		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType			sType
1269		DE_NULL,																// const void*				pNext
1270		0,																		// VkAccessFlags			srcAccessMask
1271		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
1272			VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,						// VkAccessFlags			dstAccessMask
1273		VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout			oldLayout
1274		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,								// VkImageLayout			newLayout
1275		VK_QUEUE_FAMILY_IGNORED,												// uint32_t					srcQueueFamilyIndex
1276		VK_QUEUE_FAMILY_IGNORED,												// uint32_t					dstQueueFamilyIndex
1277		0,																		// VkImage					image
1278		makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u),	// VkImageSubresourceRange	subresourceRange
1279	};
1280
1281	std::vector<VkImageMemoryBarrier> barriers;
1282
1283	if (wd.floatResolve1.image)
1284	{
1285		barriers.push_back(imageBarrierTemplate);
1286		barriers.back().image = *wd.floatResolve1.image;
1287	}
1288
1289	if (wd.floatResolve2.image)
1290	{
1291		barriers.push_back(imageBarrierTemplate);
1292		barriers.back().image = *wd.floatResolve2.image;
1293	}
1294
1295	if (wd.intResolve.image)
1296	{
1297		barriers.push_back(imageBarrierTemplate);
1298		barriers.back().image = *wd.intResolve.image;
1299	}
1300
1301	if (wd.depthStencilResolve.image)
1302	{
1303		barriers.push_back(imageBarrierTemplate);
1304		barriers.back().image						= *wd.depthStencilResolve.image;
1305		barriers.back().newLayout					= VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1306		barriers.back().subresourceRange.aspectMask	= getDepthStencilAspectFlags(params.depthStencilFormat);
1307	}
1308
1309	if (!barriers.empty())
1310	{
1311		vk.cmdPipelineBarrier(*testObjects.cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0u,
1312				0u, DE_NULL, 0u, DE_NULL, static_cast<uint32_t>(barriers.size()), barriers.data());
1313	}
1314}
1315
1316void preRenderingImageLayoutTransition (Context&				context,
1317										const TestParams&		params,
1318										WorkingData&			wd,
1319										TestObjects&			testObjects)
1320{
1321	const DeviceInterface&		vk						= context.getDeviceInterface();
1322	const bool preCleared = params.clearBeforeRenderPass;
1323
1324	const VkImageMemoryBarrier	imageBarrierTemplate =
1325	{
1326		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType            sType;
1327		DE_NULL,																// const void*                pNext;
1328		preCleared ? VK_ACCESS_TRANSFER_WRITE_BIT : (VkAccessFlagBits)0,		// VkAccessFlags              srcAccessMask;
1329		VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
1330			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,								// VkAccessFlags              dstAccessMask;
1331		preCleared
1332			? VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
1333			: VK_IMAGE_LAYOUT_UNDEFINED,										// VkImageLayout              oldLayout;
1334		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,								// VkImageLayout              newLayout;
1335		VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   srcQueueFamilyIndex;
1336		VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   dstQueueFamilyIndex;
1337		0,																		// VkImage                    image;
1338		makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u),	// VkImageSubresourceRange    subresourceRange;
1339	};
1340
1341	VkImageMemoryBarrier	barriers[4]		= { imageBarrierTemplate, imageBarrierTemplate, imageBarrierTemplate, imageBarrierTemplate };
1342	barriers[0].image						= *wd.floatColor1.image;
1343	barriers[1].image						= *wd.floatColor2.image;
1344	barriers[2].image						= *wd.intColor.image;
1345	barriers[3].image						= *wd.depthStencil.image;
1346	barriers[3].dstAccessMask				= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
1347														VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
1348	barriers[3].newLayout					= VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1349	barriers[3].subresourceRange.aspectMask	= getDepthStencilAspectFlags(params.depthStencilFormat);
1350
1351	vk.cmdPipelineBarrier(*testObjects.cmdBuffer, preCleared ? VK_PIPELINE_STAGE_TRANSFER_BIT : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1352			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0u,
1353			0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1354}
1355
1356void postRenderingResolveImageLayoutTransition (Context&				context,
1357												const TestParams&		params,
1358												WorkingData&			wd,
1359												TestObjects&			testObjects)
1360{
1361	const DeviceInterface&		vk						= context.getDeviceInterface();
1362	const VkImageMemoryBarrier	imageBarrierTemplate	=
1363	{
1364		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType			sType
1365		DE_NULL,																// const void*				pNext
1366		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
1367			VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,						// VkAccessFlags			srcAccessMask
1368		VK_ACCESS_SHADER_READ_BIT,												// VkAccessFlags			dstAccessMask
1369		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,								// VkImageLayout			oldLayout
1370		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,								// VkImageLayout			newLayout
1371		VK_QUEUE_FAMILY_IGNORED,												// uint32_t					srcQueueFamilyIndex
1372		VK_QUEUE_FAMILY_IGNORED,												// uint32_t					dstQueueFamilyIndex
1373		0,																		// VkImage					image
1374		makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u),	// VkImageSubresourceRange	subresourceRange
1375	};
1376
1377	std::vector<VkImageMemoryBarrier> barriers;
1378
1379	if (wd.floatResolve1.image)
1380	{
1381		barriers.push_back(imageBarrierTemplate);
1382		barriers.back().image = *wd.floatResolve1.image;
1383	}
1384
1385	if (wd.floatResolve2.image)
1386	{
1387		barriers.push_back(imageBarrierTemplate);
1388		barriers.back().image = *wd.floatResolve2.image;
1389	}
1390
1391	if (wd.intResolve.image)
1392	{
1393		barriers.push_back(imageBarrierTemplate);
1394		barriers.back().image = *wd.intResolve.image;
1395	}
1396
1397	if (wd.depthStencilResolve.image)
1398	{
1399		barriers.push_back(imageBarrierTemplate);
1400		barriers.back().image						= *wd.depthStencilResolve.image;
1401		barriers.back().oldLayout					= VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1402		barriers.back().newLayout					= VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
1403		barriers.back().subresourceRange.aspectMask	= getDepthStencilAspectFlags(params.depthStencilFormat);
1404	}
1405
1406	if (!barriers.empty())
1407	{
1408		vk.cmdPipelineBarrier(*testObjects.cmdBuffer,
1409							  VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
1410							  VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT , 0u,
1411							  0u, DE_NULL, 0u, DE_NULL, static_cast<uint32_t>(barriers.size()), barriers.data());
1412	}
1413}
1414
1415void preinitializeAttachmentReferences(std::vector<VkAttachmentReference2>& references, const deUint32 count)
1416{
1417	references.resize(count, VkAttachmentReference2{
1418		VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,		// VkStructureType       sType;
1419		DE_NULL,										// const void*           pNext;
1420		VK_ATTACHMENT_UNUSED,							// uint32_t              attachment;
1421		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout         layout;
1422		0,												// VkImageAspectFlags    aspectMask;
1423	});
1424}
1425
1426void initializeAttachmentReference(VkAttachmentReference2& reference, deUint32 attachment, const VkFormat depthStencilFormat, const bool isInputAttachment)
1427{
1428	const bool isColor	= depthStencilFormat == VK_FORMAT_UNDEFINED;
1429
1430	reference.attachment	= attachment;
1431	reference.layout		= isInputAttachment
1432		? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
1433		: isColor
1434			? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
1435			: VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1436	reference.aspectMask	= isColor
1437		? VkImageAspectFlags(VK_IMAGE_ASPECT_COLOR_BIT)
1438		: getDepthStencilAspectFlags(depthStencilFormat);
1439}
1440
1441bool isInAttachmentReferences(const std::vector<VkAttachmentReference2>& references, const deInt32 attachment)
1442{
1443	for (const VkAttachmentReference2& reference: references)
1444		if (reference.attachment == static_cast<deUint32>(attachment))
1445			return true;
1446
1447	return false;
1448}
1449
1450void addSubpassDescription(const TestParams&										params,
1451						   const deUint32											passNdx,
1452						   std::vector<VkAttachmentReference2>&						attachmentReferences,
1453						   std::vector<VkAttachmentReference2>&						resolveAttachmentReferences,
1454						   VkSubpassDescriptionDepthStencilResolve&					depthStencilResolve,
1455						   std::vector<deUint32>*									preserveAttachments,
1456						   VkMultisampledRenderToSingleSampledInfoEXT&				msrtss,
1457						   std::vector<VkSubpassDescription2>&						subpasses,
1458						   const std::vector<VkAttachmentReference2>&				inputAttachmentReferences,
1459						   const deInt32											attachmentNdxes[8])
1460{
1461	const TestParams::PerPass&	perPass							= params.perPass[passNdx];
1462	bool						anySingleSampledAttachmentsUsed	= false;
1463
1464	// Maximum 4 attachment references for color and 1 for depth
1465	preinitializeAttachmentReferences(attachmentReferences, 5);
1466	preinitializeAttachmentReferences(resolveAttachmentReferences, 5);
1467
1468	if (perPass.floatColor1Location >= 0)
1469	{
1470		initializeAttachmentReference(attachmentReferences[perPass.floatColor1Location],
1471				attachmentNdxes[0], VK_FORMAT_UNDEFINED, false);
1472		anySingleSampledAttachmentsUsed	= anySingleSampledAttachmentsUsed || params.numFloatColor1Samples == VK_SAMPLE_COUNT_1_BIT;
1473	}
1474	else if (preserveAttachments && !isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[0]))
1475	{
1476		if (attachmentNdxes[0] != -1)
1477			preserveAttachments->push_back(attachmentNdxes[0]);
1478	}
1479	if (perPass.floatColor2Location >= 0)
1480	{
1481		initializeAttachmentReference(attachmentReferences[perPass.floatColor2Location],
1482				attachmentNdxes[1], VK_FORMAT_UNDEFINED, false);
1483		anySingleSampledAttachmentsUsed	= anySingleSampledAttachmentsUsed || params.numFloatColor2Samples == VK_SAMPLE_COUNT_1_BIT;
1484	}
1485	else if (preserveAttachments && !isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[1]))
1486	{
1487		if (attachmentNdxes[1] != -1)
1488			preserveAttachments->push_back(attachmentNdxes[1]);
1489	}
1490	if (perPass.intColorLocation >= 0)
1491	{
1492		initializeAttachmentReference(attachmentReferences[perPass.intColorLocation],
1493				attachmentNdxes[2], VK_FORMAT_UNDEFINED, false);
1494		anySingleSampledAttachmentsUsed	= anySingleSampledAttachmentsUsed || params.numIntColorSamples == VK_SAMPLE_COUNT_1_BIT;
1495	}
1496	else if (preserveAttachments && !isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[2]))
1497	{
1498		if (attachmentNdxes[2] != -1)
1499			preserveAttachments->push_back(attachmentNdxes[2]);
1500	}
1501	if (perPass.hasDepthStencil)
1502	{
1503		initializeAttachmentReference(attachmentReferences.back(),
1504				attachmentNdxes[3], params.depthStencilFormat, false);
1505		anySingleSampledAttachmentsUsed	= anySingleSampledAttachmentsUsed || params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT;
1506	}
1507	else if (preserveAttachments && !isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[3]))
1508	{
1509		if (attachmentNdxes[3] != -1)
1510			preserveAttachments->push_back(attachmentNdxes[3]);
1511	}
1512
1513	// Resolve attachments
1514	if (perPass.resolveFloatColor1)
1515	{
1516		initializeAttachmentReference(resolveAttachmentReferences[perPass.floatColor1Location],
1517				attachmentNdxes[4], VK_FORMAT_UNDEFINED, false);
1518	}
1519	else if (preserveAttachments && !isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[4]))
1520	{
1521		if (attachmentNdxes[4] != -1)
1522			preserveAttachments->push_back(attachmentNdxes[4]);
1523	}
1524	if (perPass.resolveFloatColor2)
1525	{
1526		initializeAttachmentReference(resolveAttachmentReferences[perPass.floatColor2Location],
1527				attachmentNdxes[5], VK_FORMAT_UNDEFINED, false);
1528	}
1529	else if (preserveAttachments && !isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[5]))
1530	{
1531		if (attachmentNdxes[5] != -1)
1532			preserveAttachments->push_back(attachmentNdxes[5]);
1533	}
1534	if (perPass.resolveIntColor)
1535	{
1536		initializeAttachmentReference(resolveAttachmentReferences[perPass.intColorLocation],
1537				attachmentNdxes[6], VK_FORMAT_UNDEFINED, false);
1538	}
1539	else if (preserveAttachments && !isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[6]))
1540	{
1541		if (attachmentNdxes[6] != -1)
1542			preserveAttachments->push_back(attachmentNdxes[6]);
1543	}
1544
1545	// Account for single-sampled attachments in input attachments as well.
1546	if (!inputAttachmentReferences.empty())
1547	{
1548		if (attachmentNdxes[0] >= 0 && isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[0]))
1549			anySingleSampledAttachmentsUsed	= anySingleSampledAttachmentsUsed || params.numFloatColor1Samples == VK_SAMPLE_COUNT_1_BIT;
1550		if (attachmentNdxes[1] >= 0 && isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[1]))
1551			anySingleSampledAttachmentsUsed	= anySingleSampledAttachmentsUsed || params.numFloatColor2Samples == VK_SAMPLE_COUNT_1_BIT;
1552		if (attachmentNdxes[2] >= 0 && isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[2]))
1553			anySingleSampledAttachmentsUsed	= anySingleSampledAttachmentsUsed || params.numIntColorSamples == VK_SAMPLE_COUNT_1_BIT;
1554		if (attachmentNdxes[3] >= 0 && isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[3]))
1555			anySingleSampledAttachmentsUsed	= anySingleSampledAttachmentsUsed || params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT;
1556	}
1557
1558	const bool needsMsrtss = anySingleSampledAttachmentsUsed && perPass.numSamples != VK_SAMPLE_COUNT_1_BIT;
1559	const bool needsDepthStencilResolve = perPass.resolveDepthStencil || (needsMsrtss && params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT && perPass.hasDepthStencil);
1560
1561	if (needsDepthStencilResolve)
1562	{
1563		if (perPass.resolveDepthStencil)
1564		{
1565			initializeAttachmentReference(resolveAttachmentReferences.back(),
1566					attachmentNdxes[7], params.depthStencilFormat, false);
1567		}
1568		depthStencilResolve = VkSubpassDescriptionDepthStencilResolve
1569		{
1570			VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE,	// VkStructureType                  sType;
1571			DE_NULL,														// const void*                      pNext;
1572			perPass.depthStencilResolveMode,								// VkResolveModeFlagBits            depthResolveMode;
1573			perPass.depthStencilResolveMode,								// VkResolveModeFlagBits            stencilResolveMode;
1574			perPass.resolveDepthStencil
1575				? &resolveAttachmentReferences.back()
1576				: nullptr,													// const VkAttachmentReference2*    pDepthStencilResolveAttachment;
1577		};
1578	}
1579	else if (preserveAttachments && !isInAttachmentReferences(inputAttachmentReferences, attachmentNdxes[7]))
1580	{
1581		if (attachmentNdxes[7] != -1)
1582			preserveAttachments->push_back(attachmentNdxes[7]);
1583	}
1584
1585	VkSubpassDescription2 subpassDescription =
1586	{
1587		VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,					// VkStructureType                 sType;
1588		needsDepthStencilResolve
1589			? &depthStencilResolve
1590			: DE_NULL,												// const void*                     pNext;
1591		(VkSubpassDescriptionFlags)0,								// VkSubpassDescriptionFlags       flags;
1592		VK_PIPELINE_BIND_POINT_GRAPHICS,							// VkPipelineBindPoint             pipelineBindPoint;
1593		0u,															// uint32_t                        viewMask;
1594		static_cast<deUint32>(inputAttachmentReferences.size()),	// uint32_t                        inputAttachmentCount;
1595		dataOrNullPtr(inputAttachmentReferences),					// const VkAttachmentReference2*   pInputAttachments;
1596		4u,															// uint32_t                        colorAttachmentCount;
1597		dataOrNullPtr(attachmentReferences),						// const VkAttachmentReference2*   pColorAttachments;
1598		dataOrNullPtr(resolveAttachmentReferences),					// const VkAttachmentReference2*   pResolveAttachments;
1599		perPass.hasDepthStencil
1600			? &attachmentReferences.back()
1601			: DE_NULL,												// const VkAttachmentReference2*   pDepthStencilAttachment;
1602		preserveAttachments
1603			? static_cast<deUint32>(preserveAttachments->size())
1604			: 0,													// uint32_t                        preserveAttachmentCount;
1605		preserveAttachments
1606			? dataOrNullPtr(*preserveAttachments)
1607			: nullptr,												// const uint32_t*                 pPreserveAttachments;
1608	};
1609
1610	// Append MSRTSS to subpass desc
1611	msrtss = VkMultisampledRenderToSingleSampledInfoEXT{
1612		VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT,	// VkStructureType			sType
1613		subpassDescription.pNext,											// const void*				pNext
1614		VK_TRUE,															// VkBool32					multisampledRenderToSingleSampledEnable
1615		perPass.numSamples,													// VkSampleCountFlagBits	rasterizationSamples
1616	};
1617	if (needsMsrtss)
1618		subpassDescription.pNext = &msrtss;
1619
1620	subpasses.push_back(subpassDescription);
1621}
1622
1623void addSubpassDependency(const deUint32 subpassNdx, std::vector<VkSubpassDependency2>& subpassDependencies)
1624{
1625	subpassDependencies.push_back(VkSubpassDependency2{
1626		VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,					// VkStructureType         sType;
1627		DE_NULL,												// const void*             pNext;
1628		subpassNdx - 1,											// uint32_t                srcSubpass;
1629		subpassNdx,												// uint32_t                dstSubpass;
1630
1631		VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
1632		VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,				// VkPipelineStageFlags    srcStageMask;
1633
1634		VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
1635		VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,				// VkPipelineStageFlags    dstStageMask;
1636
1637		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
1638		VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,			// VkAccessFlags           srcAccessMask;
1639
1640		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
1641		VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
1642		VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
1643		VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,			// VkAccessFlags           dstAccessMask;
1644
1645		VK_DEPENDENCY_BY_REGION_BIT,							// VkDependencyFlags       dependencyFlags;
1646		0,														// int32_t                 viewOffset;
1647	});
1648}
1649
1650void createRenderPassAndFramebuffer(Context&			context,
1651		WorkingData&									wd,
1652		TestObjects&									testObjects,
1653		const PipelineConstructionType					pipelineConstructionType,
1654	    const std::vector<VkImage>&						images,
1655		const std::vector<VkImageView>&					attachments,
1656		const std::vector<VkAttachmentDescription2>&	attachmentDescriptions,
1657		const std::vector<VkSubpassDescription2>&		subpasses,
1658		const std::vector<VkSubpassDependency2>&		subpassDependencies)
1659{
1660	const DeviceInterface&			vk			= context.getDeviceInterface();
1661	const VkDevice					device		= context.getDevice();
1662
1663	const VkRenderPassCreateInfo2 renderPassInfo =
1664	{
1665		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,			// VkStructureType					sType;
1666		DE_NULL,												// const void*						pNext;
1667		(VkRenderPassCreateFlags)0,								// VkRenderPassCreateFlags			flags;
1668		static_cast<deUint32>(attachmentDescriptions.size()),	// deUint32							attachmentCount;
1669		dataOrNullPtr(attachmentDescriptions),					// const VkAttachmentDescription2*	pAttachments;
1670		static_cast<deUint32>(subpasses.size()),				// deUint32							subpassCount;
1671		dataOrNullPtr(subpasses),								// const VkSubpassDescription2*		pSubpasses;
1672		static_cast<deUint32>(subpassDependencies.size()),		// deUint32							dependencyCount;
1673		dataOrNullPtr(subpassDependencies),						// const VkSubpassDependency2*		pDependencies;
1674		0u,														// uint32_t                         correlatedViewMaskCount;
1675		DE_NULL,												// const uint32_t*                  pCorrelatedViewMasks;
1676	};
1677
1678	testObjects.renderPassFramebuffers.emplace_back(RenderPassWrapper(pipelineConstructionType, vk, device, &renderPassInfo));
1679	testObjects.renderPassFramebuffers.back().createFramebuffer(vk, device, static_cast<deUint32>(attachments.size()), dataOrNullPtr(images), dataOrNullPtr(attachments), wd.framebufferSize.x(), wd.framebufferSize.y());
1680}
1681
1682void createWorkingData (Context& context, const TestParams& params, WorkingData& wd)
1683{
1684	const DeviceInterface&			vk			= context.getDeviceInterface();
1685	const VkDevice					device		= context.getDevice();
1686	MovePtr<Allocator>				allocator   = MovePtr<Allocator>(new SimpleAllocator(vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
1687
1688	// Create images
1689	{
1690		// TODO: change image types to be nonuniform, for example: mip 1 of 2D image, mip 2/level 3 of 2D array image, etc.
1691		wd.floatColor1.allocate	(vk, device, allocator, params.floatColor1Format,	wd.framebufferSize, params.numFloatColor1Samples,	colorImageUsageFlags,			VK_IMAGE_ASPECT_COLOR_BIT, 1, true);
1692		wd.floatColor2.allocate	(vk, device, allocator, params.floatColor2Format,	wd.framebufferSize, params.numFloatColor2Samples,	colorImageUsageFlags,			VK_IMAGE_ASPECT_COLOR_BIT, 1, true);
1693		wd.intColor.allocate	(vk, device, allocator, params.intColorFormat,		wd.framebufferSize, params.numIntColorSamples,		colorImageUsageFlags,			VK_IMAGE_ASPECT_COLOR_BIT, 1, true);
1694		wd.depthStencil.allocate(vk, device, allocator, params.depthStencilFormat,	wd.framebufferSize, params.numDepthStencilSamples,	depthStencilImageUsageFlags,	getDepthStencilAspectFlags(params.depthStencilFormat), 1, true);
1695
1696		if (isDepthFormat(params.depthStencilFormat))
1697			wd.depthOnlyImageView	= wd.depthStencil.makeView(vk, device, params.depthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT, 1);
1698
1699		if (isStencilFormat(params.depthStencilFormat))
1700			wd.stencilOnlyImageView	= wd.depthStencil.makeView(vk, device, params.depthStencilFormat, VK_IMAGE_ASPECT_STENCIL_BIT, 1);
1701
1702		if (params.numFloatColor1Samples != VK_SAMPLE_COUNT_1_BIT)
1703		{
1704			wd.floatResolve1.allocate(vk, device, allocator, params.floatColor1Format, wd.framebufferSize, VK_SAMPLE_COUNT_1_BIT, colorImageUsageFlags, VK_IMAGE_ASPECT_COLOR_BIT, 1, false);
1705		}
1706
1707		if (params.numFloatColor2Samples != VK_SAMPLE_COUNT_1_BIT)
1708		{
1709			wd.floatResolve2.allocate(vk, device, allocator, params.floatColor2Format, wd.framebufferSize, VK_SAMPLE_COUNT_1_BIT, colorImageUsageFlags, VK_IMAGE_ASPECT_COLOR_BIT, 1, false);
1710		}
1711
1712		if (params.numIntColorSamples != VK_SAMPLE_COUNT_1_BIT)
1713		{
1714			wd.intResolve.allocate(vk, device, allocator, params.intColorFormat, wd.framebufferSize, VK_SAMPLE_COUNT_1_BIT, colorImageUsageFlags, VK_IMAGE_ASPECT_COLOR_BIT, 1, false);
1715		}
1716
1717		if (params.numDepthStencilSamples != VK_SAMPLE_COUNT_1_BIT)
1718		{
1719			wd.depthStencilResolve.allocate(vk, device, allocator, params.depthStencilFormat, wd.framebufferSize, VK_SAMPLE_COUNT_1_BIT, depthStencilImageUsageFlags, getDepthStencilAspectFlags(params.depthStencilFormat), 1, false);
1720
1721			if (isDepthFormat(params.depthStencilFormat))
1722				wd.depthOnlyResolveImageView	= wd.depthStencilResolve.makeView(vk, device, params.depthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT, 1);
1723
1724			if (isStencilFormat(params.depthStencilFormat))
1725				wd.stencilOnlyResolveImageView	= wd.depthStencilResolve.makeView(vk, device, params.depthStencilFormat, VK_IMAGE_ASPECT_STENCIL_BIT, 1);
1726		}
1727
1728		wd.verify.allocate	(vk, device, allocator, VK_FORMAT_R8G8B8A8_UNORM, wd.framebufferSize, VK_SAMPLE_COUNT_1_BIT,
1729				VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_ASPECT_COLOR_BIT, 5, false);
1730	}
1731
1732	// Create vertex and verification buffers
1733	{
1734		// A fullscreen triangle
1735		const std::vector<Vec4> vertices =
1736		{
1737			Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
1738			Vec4( 3.0f, -1.0f, 0.0f, 1.0f),
1739			Vec4(-1.0f,  3.0f, 0.0f, 1.0f),
1740		};
1741
1742		const VkDeviceSize	vertexBufferSize = static_cast<VkDeviceSize>(sizeof(vertices[0]) * vertices.size());
1743		wd.vertexBuffer			= makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1744		wd.vertexBufferAlloc	= bindBuffer(vk, device, *allocator, *wd.vertexBuffer, MemoryRequirement::HostVisible);
1745
1746		deMemcpy(wd.vertexBufferAlloc->getHostPtr(), dataOrNullPtr(vertices), static_cast<std::size_t>(vertexBufferSize));
1747		flushMappedMemoryRange(vk, device, wd.vertexBufferAlloc->getMemory(), wd.vertexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1748
1749		// Initialize the verification data with 0.
1750		const VerificationResults results = {};
1751
1752		wd.verificationBuffer		= makeBuffer(vk, device, sizeof(results), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1753		wd.verificationBufferAlloc	= bindBuffer(vk, device, *allocator, *wd.verificationBuffer, MemoryRequirement::HostVisible);
1754
1755		deMemcpy(wd.verificationBufferAlloc->getHostPtr(), &results, sizeof(results));
1756		flushMappedMemoryRange(vk, device, wd.verificationBufferAlloc->getMemory(), wd.verificationBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1757
1758		wd.singleVerificationBuffer		= makeBuffer(vk, device, sizeof(results), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1759		wd.singleVerificationBufferAlloc	= bindBuffer(vk, device, *allocator, *wd.singleVerificationBuffer, MemoryRequirement::HostVisible);
1760
1761		deMemcpy(wd.singleVerificationBufferAlloc->getHostPtr(), &results, sizeof(results));
1762		flushMappedMemoryRange(vk, device, wd.singleVerificationBufferAlloc->getMemory(), wd.singleVerificationBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1763	}
1764}
1765
1766void checkRequirements (Context& context, TestParams params)
1767{
1768	const VkPhysicalDevice			physicalDevice		= context.getPhysicalDevice();
1769	const vk::InstanceInterface&	instanceInterface	= context.getInstanceInterface();
1770
1771	checkPipelineConstructionRequirements(instanceInterface, physicalDevice, params.pipelineConstructionType);
1772
1773	context.requireDeviceFunctionality("VK_KHR_depth_stencil_resolve");
1774	context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
1775
1776	if (params.dynamicRendering)
1777		context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
1778
1779	if (params.isMultisampledRenderToSingleSampled)
1780	{
1781		context.requireDeviceFunctionality("VK_EXT_multisampled_render_to_single_sampled");
1782
1783		// Check extension feature
1784		{
1785			VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT	msrtssFeatures =
1786			{
1787				VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT,
1788				DE_NULL,
1789				VK_FALSE,
1790			};
1791			VkPhysicalDeviceFeatures2						physicalDeviceFeatures =
1792			{
1793				VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
1794				&msrtssFeatures,
1795				{},
1796			};
1797
1798			instanceInterface.getPhysicalDeviceFeatures2(physicalDevice, &physicalDeviceFeatures);
1799
1800			if (msrtssFeatures.multisampledRenderToSingleSampled != VK_TRUE)
1801			{
1802				TCU_THROW(NotSupportedError, "multisampledRenderToSingleSampled not supported");
1803			}
1804		}
1805	}
1806
1807	// Check whether formats are supported with the requested usage and sample counts.
1808	{
1809		VkImageFormatProperties imageProperties;
1810		checkImageRequirements (context, params.floatColor1Format,
1811				VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,
1812				colorImageUsageFlags, params.numFloatColor1Samples, imageProperties);
1813		if (params.numFloatColor1Samples == VK_SAMPLE_COUNT_1_BIT)
1814			for (const TestParams::PerPass& perPass : params.perPass)
1815				if (perPass.floatColor1Location >= 0 && (imageProperties.sampleCounts & perPass.numSamples) != perPass.numSamples)
1816					TCU_THROW(NotSupportedError, (de::toString(params.floatColor1Format) + ": sample count not supported").c_str());
1817	}
1818	{
1819		VkImageFormatProperties imageProperties;
1820		checkImageRequirements (context, params.floatColor2Format,
1821				VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,
1822				colorImageUsageFlags, params.numFloatColor2Samples, imageProperties);
1823		if (params.numFloatColor1Samples == VK_SAMPLE_COUNT_1_BIT)
1824			for (const TestParams::PerPass& perPass : params.perPass)
1825				if (perPass.floatColor2Location >= 0 && (imageProperties.sampleCounts & perPass.numSamples) != perPass.numSamples)
1826					TCU_THROW(NotSupportedError, (de::toString(params.floatColor2Format) + ": sample count not supported").c_str());
1827	}
1828	{
1829		VkImageFormatProperties imageProperties;
1830		checkImageRequirements (context, params.intColorFormat,
1831				VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,
1832				colorImageUsageFlags, params.numIntColorSamples, imageProperties);
1833		if (params.numFloatColor1Samples == VK_SAMPLE_COUNT_1_BIT)
1834			for (const TestParams::PerPass& perPass : params.perPass)
1835				if (perPass.intColorLocation >= 0 && (imageProperties.sampleCounts & perPass.numSamples) != perPass.numSamples)
1836					TCU_THROW(NotSupportedError, (de::toString(params.intColorFormat) + ": sample count not supported").c_str());
1837	}
1838	{
1839		VkImageFormatProperties imageProperties;
1840		checkImageRequirements (context, params.depthStencilFormat,
1841				VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,
1842				depthStencilImageUsageFlags, params.numDepthStencilSamples, imageProperties);
1843		if (params.numFloatColor1Samples == VK_SAMPLE_COUNT_1_BIT)
1844			for (const TestParams::PerPass& perPass : params.perPass)
1845				if (perPass.hasDepthStencil && (imageProperties.sampleCounts & perPass.numSamples) != perPass.numSamples)
1846					TCU_THROW(NotSupportedError, (de::toString(params.depthStencilFormat) + ": sample count not supported").c_str());
1847	}
1848
1849	// Perform query to get supported depth/stencil resolve modes.
1850	VkPhysicalDeviceDepthStencilResolveProperties dsResolveProperties = {};
1851	dsResolveProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES;
1852
1853	VkPhysicalDeviceProperties2 deviceProperties = {};
1854	deviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1855	deviceProperties.pNext = &dsResolveProperties;
1856
1857	instanceInterface.getPhysicalDeviceProperties2(physicalDevice, &deviceProperties);
1858
1859	for (const TestParams::PerPass& perPass : params.perPass)
1860	{
1861		// Check whether sample counts used for rendering are acceptable
1862		const bool	checkColor		= perPass.floatColor1Location >= 0 || perPass.floatColor2Location >= 0 || perPass.intColorLocation >= 0;
1863		const bool	checkDepth		= perPass.hasDepthStencil && isDepthFormat(params.depthStencilFormat);
1864		const bool	checkStencil	= perPass.hasDepthStencil && isStencilFormat(params.depthStencilFormat);
1865		checkSampleRequirements(context, perPass.numSamples, checkColor, checkDepth, checkStencil);
1866
1867		// Check whether depth/stencil resolve mode is supported
1868		if (perPass.depthStencilResolveMode != VK_RESOLVE_MODE_NONE &&
1869			((dsResolveProperties.supportedDepthResolveModes & perPass.depthStencilResolveMode) == 0 ||
1870			 (dsResolveProperties.supportedStencilResolveModes & perPass.depthStencilResolveMode) == 0))
1871		{
1872			TCU_THROW(NotSupportedError, "Depth/stencil resolve mode not supported");
1873		}
1874	}
1875}
1876
1877void checkHasMsrtss (Context& context, VkFormat)
1878{
1879	context.requireDeviceFunctionality("VK_EXT_multisampled_render_to_single_sampled");
1880}
1881
1882void generateRandomClearValues(de::Random& rng, const TestParams& params, VkClearValue clearValues[4], bool smallValues)
1883{
1884	const bool		usesSignedIntFormat	= params.intColorFormat == VK_FORMAT_R16G16B16A16_SINT;
1885
1886	const float		minFloatValue		= 0.05f;
1887	const float		maxFloatValue		= smallValues ? 0.1f : 0.95f;
1888	const deUint32	minIntValue			= smallValues ? 20 : 5000;
1889	const deUint32	maxIntValue			= smallValues ? 100 : 10000;
1890	const float		minDepthValue		= 0.05f;
1891	const float		maxDepthValue		= smallValues ? 0.1f : 0.5f;
1892	const deUint32	minStencilValue		= 0x10;
1893	const deUint32	maxStencilValue		= 0x20;
1894
1895	clearValues[0].color.float32[0] = rng.getFloat(minFloatValue, maxFloatValue);
1896	clearValues[0].color.float32[1] = rng.getFloat(minFloatValue, maxFloatValue);
1897	clearValues[0].color.float32[2] = rng.getFloat(minFloatValue, maxFloatValue);
1898	clearValues[0].color.float32[3] = rng.getFloat(minFloatValue, maxFloatValue);
1899	clearValues[1].color.float32[0] = rng.getFloat(minFloatValue, maxFloatValue);
1900	clearValues[1].color.float32[1] = rng.getFloat(minFloatValue, maxFloatValue);
1901	clearValues[1].color.float32[2] = rng.getFloat(minFloatValue, maxFloatValue);
1902	clearValues[1].color.float32[3] = rng.getFloat(minFloatValue, maxFloatValue);
1903	clearValues[2].color.int32[0] = (usesSignedIntFormat ? -1 : 1) * rng.getInt(minIntValue, maxIntValue);
1904	clearValues[2].color.int32[1] = (usesSignedIntFormat ? -1 : 1) * rng.getInt(minIntValue, maxIntValue);
1905	clearValues[2].color.int32[2] = (usesSignedIntFormat ? -1 : 1) * rng.getInt(minIntValue, maxIntValue);
1906	clearValues[2].color.int32[3] = (usesSignedIntFormat ? -1 : 1) * rng.getInt(minIntValue, maxIntValue);
1907	clearValues[3].depthStencil.depth = rng.getFloat(minDepthValue, maxDepthValue);
1908	clearValues[3].depthStencil.stencil = rng.getInt(minStencilValue, maxStencilValue);
1909}
1910
1911void clearImagesBeforeDraw(Context& context, const TestParams& params, WorkingData& wd, TestObjects& testObjects)
1912{
1913	const DeviceInterface&	vk				= context.getDeviceInterface();
1914
1915	const VkImageMemoryBarrier	imageBarrierTemplate =
1916	{
1917		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType            sType;
1918		DE_NULL,																// const void*                pNext;
1919		0,																		// VkAccessFlags              srcAccessMask;
1920		VK_ACCESS_TRANSFER_WRITE_BIT,											// VkAccessFlags              dstAccessMask;
1921		VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout              oldLayout;
1922		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,									// VkImageLayout              newLayout;
1923		VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   srcQueueFamilyIndex;
1924		VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   dstQueueFamilyIndex;
1925		0,																		// VkImage                    image;
1926		makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u),	// VkImageSubresourceRange    subresourceRange;
1927	};
1928
1929	VkImageMemoryBarrier	preClearBarriers[4]		= { imageBarrierTemplate, imageBarrierTemplate, imageBarrierTemplate, imageBarrierTemplate };
1930	preClearBarriers[0].image						= *wd.floatColor1.image;
1931	preClearBarriers[1].image						= *wd.floatColor2.image;
1932	preClearBarriers[2].image						= *wd.intColor.image;
1933	preClearBarriers[3].image						= *wd.depthStencil.image;
1934	preClearBarriers[3].subresourceRange.aspectMask	= getDepthStencilAspectFlags(params.depthStencilFormat);
1935
1936	vk.cmdPipelineBarrier(*testObjects.cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1937			0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(preClearBarriers), preClearBarriers);
1938
1939	vk.cmdClearColorImage(*testObjects.cmdBuffer, *wd.floatColor1.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &params.clearValues[0].color, 1, &preClearBarriers[0].subresourceRange);
1940	vk.cmdClearColorImage(*testObjects.cmdBuffer, *wd.floatColor2.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &params.clearValues[1].color, 1, &preClearBarriers[1].subresourceRange);
1941	vk.cmdClearColorImage(*testObjects.cmdBuffer, *wd.intColor.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &params.clearValues[2].color, 1, &preClearBarriers[2].subresourceRange);
1942	vk.cmdClearDepthStencilImage(*testObjects.cmdBuffer, *wd.depthStencil.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &params.clearValues[3].depthStencil, 1, &preClearBarriers[3].subresourceRange);
1943
1944	const VkMemoryBarrier postClearBarrier =
1945	{
1946		VK_STRUCTURE_TYPE_MEMORY_BARRIER,										// VkStructureType    sType;
1947		DE_NULL,																// const void*        pNext;
1948		VK_ACCESS_TRANSFER_WRITE_BIT,											// VkAccessFlags      srcAccessMask;
1949		VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
1950			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
1951			VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
1952			VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,						// VkAccessFlags      dstAccessMask;
1953	};
1954
1955	vk.cmdPipelineBarrier(*testObjects.cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1956			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
1957			0u, 1u, &postClearBarrier, 0u, DE_NULL, 0u, DE_NULL);
1958}
1959
1960void getDrawRegions(WorkingData& wd, UVec4 regions[RegionCount])
1961{
1962	static_assert(RegionCount == 4, "Update this function to generate the correct number of regions");
1963
1964	UVec2 oneThirdRenderAreaSize(wd.renderArea.z() / 3, wd.renderArea.w() / 3);
1965	UVec2 twoThirdsRenderAreaSize(wd.renderArea.z() - oneThirdRenderAreaSize.x(), wd.renderArea.w() - oneThirdRenderAreaSize.y());
1966	UVec2 renderAreaSplit(wd.renderArea.x() + oneThirdRenderAreaSize.x(), wd.renderArea.y() + oneThirdRenderAreaSize.y());
1967
1968	regions[0] = UVec4(wd.renderArea.x(), wd.renderArea.y(), oneThirdRenderAreaSize.x(), oneThirdRenderAreaSize.y());
1969	regions[1] = UVec4(renderAreaSplit.x(), wd.renderArea.y(), twoThirdsRenderAreaSize.x(), oneThirdRenderAreaSize.y());
1970	regions[2] = UVec4(wd.renderArea.x(), renderAreaSplit.y(), oneThirdRenderAreaSize.x(), twoThirdsRenderAreaSize.y());
1971	regions[3] = UVec4(renderAreaSplit.x(), renderAreaSplit.y(), twoThirdsRenderAreaSize.x(), twoThirdsRenderAreaSize.y());
1972}
1973
1974void startRenderPass(Context& context, WorkingData&wd, TestObjects& testObjects, const deUint32 clearValueCount, const VkClearValue* clearValues)
1975{
1976	const DeviceInterface&	vk	= context.getDeviceInterface();
1977
1978	const VkRect2D renderArea =
1979	{
1980		{ static_cast<deInt32>(wd.renderArea.x()), static_cast<deInt32>(wd.renderArea.y()) },
1981		{ wd.renderArea.z(), wd.renderArea.w() }
1982	};
1983
1984	testObjects.renderPassFramebuffers.back().begin(vk, *testObjects.cmdBuffer, renderArea, clearValueCount, clearValues);
1985}
1986
1987void startRendering (Context&									context,
1988					 const TestParams&							params,
1989					 WorkingData&								wd,
1990					 TestObjects&								testObjects,
1991					 uint32_t									colorAttachmentCount,
1992					 std::vector<VkRenderingAttachmentInfo>&	colorAttachmentInfos,
1993					 VkRenderingAttachmentInfo&					depthStencilAttachmentInfo,
1994					 uint32_t									renderPassNdx)
1995{
1996	const DeviceInterface&		vk			= context.getDeviceInterface();
1997	const TestParams::PerPass&	perPass		= params.perPass[renderPassNdx];
1998
1999	bool anySingleSampledAttachmentsUsed = false;
2000	if (perPass.floatColor1Location >= 0)
2001	{
2002		anySingleSampledAttachmentsUsed	= anySingleSampledAttachmentsUsed || params.numFloatColor1Samples == VK_SAMPLE_COUNT_1_BIT;
2003	}
2004	if (perPass.floatColor2Location >= 0)
2005	{
2006		anySingleSampledAttachmentsUsed	= anySingleSampledAttachmentsUsed || params.numFloatColor2Samples == VK_SAMPLE_COUNT_1_BIT;
2007	}
2008	if (perPass.intColorLocation >= 0)
2009	{
2010		anySingleSampledAttachmentsUsed	= anySingleSampledAttachmentsUsed || params.numIntColorSamples == VK_SAMPLE_COUNT_1_BIT;
2011	}
2012	if (perPass.hasDepthStencil)
2013	{
2014		anySingleSampledAttachmentsUsed	= anySingleSampledAttachmentsUsed || params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT;
2015	}
2016
2017	// Append MSRTSS to subpass desc
2018	VkMultisampledRenderToSingleSampledInfoEXT msrtss =
2019	{
2020		VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT,	// VkStructureType			sType
2021		DE_NULL,															// const void*				pNext
2022		VK_TRUE,															// VkBool32					multisampledRenderToSingleSampledEnable
2023		perPass.numSamples													// VkSampleCountFlagBits	rasterizationSamples
2024	};
2025
2026	const VkRect2D renderArea =
2027	{
2028		{ static_cast<deInt32>(wd.renderArea.x()), static_cast<deInt32>(wd.renderArea.y()) },
2029		{ wd.renderArea.z(), wd.renderArea.w() }
2030	};
2031
2032	const bool useDepthStencil = params.usesDepthStencilInPass(renderPassNdx);
2033
2034	VkRenderingInfo renderingInfo =
2035	{
2036		VK_STRUCTURE_TYPE_RENDERING_INFO,									// VkStructureType						sType
2037		DE_NULL,															// const void*							pNext
2038		(VkRenderingFlags) 0,												// VkRenderingFlags						flags
2039		renderArea,															// VkRect2D								renderArea
2040		1u,																	// uint32_t								layerCount
2041		0u,																	// uint32_t								viewMask
2042		colorAttachmentCount,												// uint32_t								colorAttachmentCount
2043		colorAttachmentInfos.data(),										// const VkRenderingAttachmentInfo*		pColorAttachments
2044		useDepthStencil && isDepthFormat(params.depthStencilFormat) ?
2045			&depthStencilAttachmentInfo : DE_NULL,							// const VkRenderingAttachmentInfo*		pDepthAttachment
2046		useDepthStencil && isStencilFormat(params.depthStencilFormat) ?
2047			&depthStencilAttachmentInfo : DE_NULL							// const VkRenderingAttachmentInfo*		pStencilAttachment
2048	};
2049
2050	if (anySingleSampledAttachmentsUsed && perPass.numSamples != VK_SAMPLE_COUNT_1_BIT)
2051		renderingInfo.pNext = &msrtss;
2052
2053	vk.cmdBeginRendering(*testObjects.cmdBuffer, &renderingInfo);
2054}
2055
2056void postDrawBarrier(Context& context, TestObjects& testObjects)
2057{
2058	const DeviceInterface&	vk				= context.getDeviceInterface();
2059
2060	const VkMemoryBarrier barrier =
2061	{
2062		VK_STRUCTURE_TYPE_MEMORY_BARRIER,															// VkStructureType    sType;
2063		DE_NULL,																					// const void*        pNext;
2064		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,		// VkAccessFlags      srcAccessMask;
2065		VK_ACCESS_SHADER_READ_BIT,																	// VkAccessFlags      dstAccessMask;
2066	};
2067
2068	vk.cmdPipelineBarrier(*testObjects.cmdBuffer,
2069			VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
2070			VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 1u, &barrier, 0u, DE_NULL, 0u, DE_NULL);
2071}
2072
2073void setupVerifyDescriptorSetAndPipeline(Context& context, const TestParams& params, WorkingData& wd, TestObjects& testObjects, const VkPushConstantRange* pushConstantRange,
2074		Move<VkPipelineLayout>& verifyPipelineLayout)
2075{
2076	const DeviceInterface&	vk				= context.getDeviceInterface();
2077	const VkDevice			device			= context.getDevice();
2078
2079	const Unique<VkDescriptorSetLayout> descriptorSetLayout(
2080		DescriptorSetLayoutBuilder()
2081		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,	VK_SHADER_STAGE_COMPUTE_BIT)
2082		.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,		VK_SHADER_STAGE_COMPUTE_BIT)
2083		.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,		VK_SHADER_STAGE_COMPUTE_BIT)
2084		.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,		VK_SHADER_STAGE_COMPUTE_BIT)
2085		.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,		VK_SHADER_STAGE_COMPUTE_BIT)
2086		.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,		VK_SHADER_STAGE_COMPUTE_BIT)
2087		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,		VK_SHADER_STAGE_COMPUTE_BIT)
2088		.build(vk, device));
2089
2090	testObjects.descriptorPools.emplace_back(
2091		DescriptorPoolBuilder()
2092		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u)
2093		.addType(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 5u)
2094		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u)
2095		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
2096
2097	testObjects.descriptorSets.emplace_back(makeDescriptorSet(vk, device, *testObjects.descriptorPools.back(), *descriptorSetLayout));
2098
2099	const VkDescriptorBufferInfo	resultBufferInfo	= makeDescriptorBufferInfo(*wd.verificationBuffer, 0ull, sizeof(VerificationResults));
2100	const VkDescriptorImageInfo		color1ImageInfo		= makeDescriptorImageInfo(DE_NULL, *wd.getResolvedFloatColorImage1View(params), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2101	const VkDescriptorImageInfo		color2ImageInfo		= makeDescriptorImageInfo(DE_NULL, *wd.getResolvedFloatColorImage2View(params), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2102	const VkDescriptorImageInfo		color3ImageInfo		= makeDescriptorImageInfo(DE_NULL, *wd.getResolvedIntColorImageView(params), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2103	const VkDescriptorImageInfo		depthImageInfo		= makeDescriptorImageInfo(DE_NULL, *wd.getResolvedDepthOnlyImageView(params), VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL);
2104	const VkDescriptorImageInfo		stencilImageInfo	= makeDescriptorImageInfo(DE_NULL, *wd.getResolvedStencilOnlyImageView(params), VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL);
2105	const VkDescriptorImageInfo		verifyImageInfo		= makeDescriptorImageInfo(DE_NULL, *wd.verify.view, VK_IMAGE_LAYOUT_GENERAL);
2106
2107	DescriptorSetUpdateBuilder	builder;
2108
2109	builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferInfo);
2110	builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &color1ImageInfo);
2111	builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &color2ImageInfo);
2112	builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(3u), VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &color3ImageInfo);
2113	builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(4u), VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &depthImageInfo);
2114	builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(5u), VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &stencilImageInfo);
2115	builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(6u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &verifyImageInfo);
2116
2117	builder.update(vk, device);
2118
2119	const Unique<VkShaderModule>	verifyModule			(createShaderModule(vk, device, context.getBinaryCollection().get("comp"), 0u));
2120
2121	verifyPipelineLayout	= makePipelineLayout(vk, device, 1, &*descriptorSetLayout, 1, pushConstantRange);
2122
2123	testObjects.computePipelines.push_back(PipelineSp(new Unique<VkPipeline>(makeComputePipeline(vk, device, *verifyPipelineLayout, *verifyModule))));
2124
2125	vk.cmdBindPipeline(*testObjects.cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, **testObjects.computePipelines.back());
2126	vk.cmdBindDescriptorSets(*testObjects.cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *verifyPipelineLayout, 0u, 1u, &testObjects.descriptorSets.back().get(), 0u, DE_NULL);
2127}
2128
2129void postVerifyBarrier(Context& context, TestObjects& testObjects, const Move<VkBuffer>& verificationBuffer)
2130{
2131	const DeviceInterface&	vk				= context.getDeviceInterface();
2132
2133	const VkBufferMemoryBarrier barrier =
2134	{
2135		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// VkStructureType    sType;
2136		DE_NULL,										// const void*        pNext;
2137		VK_ACCESS_SHADER_WRITE_BIT,						// VkAccessFlags      srcAccessMask;
2138		VK_ACCESS_HOST_READ_BIT,						// VkAccessFlags      dstAccessMask;
2139		VK_QUEUE_FAMILY_IGNORED,						// uint32_t           srcQueueFamilyIndex;
2140		VK_QUEUE_FAMILY_IGNORED,						// uint32_t           dstQueueFamilyIndex;
2141		*verificationBuffer,							// VkBuffer           buffer;
2142		0ull,											// VkDeviceSize       offset;
2143		VK_WHOLE_SIZE,									// VkDeviceSize       size;
2144	};
2145
2146	vk.cmdPipelineBarrier(*testObjects.cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
2147			0u, DE_NULL, 1u, &barrier, 0u, DE_NULL);
2148}
2149
2150void dispatchVerifyConstantColor(Context&					context,
2151								 TestObjects&				testObjects,
2152								 const Move<VkImageView>&	imageView,
2153								 const VkImageLayout		layout,
2154								 const Move<VkImageView>&	verifyImageView,
2155								 const Move<VkBuffer>&		verificationBuffer,
2156								 const deUint32				pushConstantSize,
2157								 const void*				pushConstants,
2158								 const std::string&			shaderName)
2159{
2160	const DeviceInterface&	vk				= context.getDeviceInterface();
2161	const VkDevice			device			= context.getDevice();
2162
2163	// Set up descriptor set
2164	const Unique<VkDescriptorSetLayout> descriptorSetLayout(
2165		DescriptorSetLayoutBuilder()
2166		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,	VK_SHADER_STAGE_COMPUTE_BIT)
2167		.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,		VK_SHADER_STAGE_COMPUTE_BIT)
2168		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,		VK_SHADER_STAGE_COMPUTE_BIT)
2169		.build(vk, device));
2170
2171	testObjects.descriptorPools.emplace_back(
2172		DescriptorPoolBuilder()
2173		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u)
2174		.addType(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1u)
2175		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u)
2176		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
2177
2178	testObjects.descriptorSets.emplace_back(makeDescriptorSet(vk, device, *testObjects.descriptorPools.back(), *descriptorSetLayout));
2179
2180	const VkDescriptorBufferInfo	resultBufferInfo	= makeDescriptorBufferInfo(*verificationBuffer, 0ull, sizeof(VerificationResults));
2181	const VkDescriptorImageInfo		imageInfo			= makeDescriptorImageInfo(DE_NULL, *imageView, layout);
2182	const VkDescriptorImageInfo		verifyImageInfo		= makeDescriptorImageInfo(DE_NULL, *verifyImageView, VK_IMAGE_LAYOUT_GENERAL);
2183
2184	DescriptorSetUpdateBuilder	builder;
2185
2186	builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferInfo);
2187	builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfo);
2188	builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &verifyImageInfo);
2189
2190	builder.update(vk, device);
2191
2192	// Setup pipeline
2193	const VkPushConstantRange& verifyPushConstantRange =
2194	{
2195		VK_SHADER_STAGE_COMPUTE_BIT,	// VkShaderStageFlags    stageFlags;
2196		0,								// uint32_t              offset;
2197		pushConstantSize,				// uint32_t              size;
2198	};
2199
2200	const Unique<VkShaderModule>	verifyModule			(createShaderModule(vk, device, context.getBinaryCollection().get(shaderName), 0u));
2201	const Unique<VkPipelineLayout>	verifyPipelineLayout	(makePipelineLayout(vk, device, 1, &*descriptorSetLayout, 1, &verifyPushConstantRange));
2202
2203	testObjects.computePipelines.push_back(PipelineSp(new Unique<VkPipeline>(makeComputePipeline(vk, device, *verifyPipelineLayout, *verifyModule))));
2204
2205	vk.cmdBindPipeline(*testObjects.cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, **testObjects.computePipelines.back());
2206	vk.cmdBindDescriptorSets(*testObjects.cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *verifyPipelineLayout, 0u, 1u, &testObjects.descriptorSets.back().get(), 0u, DE_NULL);
2207
2208	const VkMemoryBarrier preVerifyBarrier =
2209	{
2210		VK_STRUCTURE_TYPE_MEMORY_BARRIER,		// VkStructureType    sType;
2211		DE_NULL,								// const void*        pNext;
2212		VK_ACCESS_SHADER_WRITE_BIT,				// VkAccessFlags      srcAccessMask;
2213		VK_ACCESS_SHADER_WRITE_BIT |
2214			VK_ACCESS_SHADER_READ_BIT,			// VkAccessFlags      dstAccessMask;
2215	};
2216
2217	vk.cmdPipelineBarrier(*testObjects.cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0,
2218			1u, &preVerifyBarrier, 0u, DE_NULL, 0u, DE_NULL);
2219
2220	// Area is always the first uvec4
2221	const UVec4* area = static_cast<const UVec4*>(pushConstants);
2222
2223	vk.cmdPushConstants(*testObjects.cmdBuffer, *verifyPipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, pushConstantSize, pushConstants);
2224	vk.cmdDispatch(*testObjects.cmdBuffer, (area->z() + 7) / 8, (area->w() + 7) / 8, 1);
2225
2226	postVerifyBarrier(context, testObjects, verificationBuffer);
2227}
2228
2229void testStart(Context& context, const TestParams& params, WorkingData& wd, TestObjects& testObjects)
2230{
2231	de::Random	rng(params.rngSeed);
2232
2233	wd.framebufferSize	= UVec2(rng.getInt(60, 80), rng.getInt(48, 64));
2234	wd.renderArea		= UVec4(0, 0, wd.framebufferSize.x(), wd.framebufferSize.y());
2235	if (!params.renderToWholeFramebuffer)
2236	{
2237		wd.renderArea.x() += rng.getInt(5, 15);
2238		wd.renderArea.y() += rng.getInt(5, 15);
2239		wd.renderArea.z() -= wd.renderArea.x() + rng.getInt(2, 12);
2240		wd.renderArea.w() -= wd.renderArea.y() + rng.getInt(2, 12);
2241	}
2242
2243	createWorkingData(context, params, wd);
2244
2245	testObjects.beginCommandBuffer();
2246
2247	const DeviceInterface&	vk				= context.getDeviceInterface();
2248
2249	// Clear verify image
2250	{
2251		VkImageMemoryBarrier	clearBarrier =
2252		{
2253			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType            sType;
2254			DE_NULL,																// const void*                pNext;
2255			0,																		// VkAccessFlags              srcAccessMask;
2256			VK_ACCESS_TRANSFER_WRITE_BIT,											// VkAccessFlags              dstAccessMask;
2257			VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout              oldLayout;
2258			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,									// VkImageLayout              newLayout;
2259			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   srcQueueFamilyIndex;
2260			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   dstQueueFamilyIndex;
2261			*wd.verify.image,														// VkImage                    image;
2262			makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 5u),	// VkImageSubresourceRange    subresourceRange;
2263		};
2264
2265		vk.cmdPipelineBarrier(*testObjects.cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
2266				0u, DE_NULL, 0u, DE_NULL, 1u, &clearBarrier);
2267
2268		VkClearColorValue clearToBlack;
2269		clearToBlack.float32[0] = 0;
2270		clearToBlack.float32[1] = 0;
2271		clearToBlack.float32[2] = 0;
2272		clearToBlack.float32[3] = 1.0;
2273		vk.cmdClearColorImage(*testObjects.cmdBuffer, *wd.verify.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearToBlack, 1, &clearBarrier.subresourceRange);
2274	}
2275
2276	// Transition it to GENERAL
2277	{
2278		VkImageMemoryBarrier	verifyBarrier =
2279		{
2280			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType            sType;
2281			DE_NULL,																// const void*                pNext;
2282			VK_ACCESS_TRANSFER_WRITE_BIT,											// VkAccessFlags              srcAccessMask;
2283			VK_ACCESS_SHADER_WRITE_BIT,												// VkAccessFlags              dstAccessMask;
2284			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,									// VkImageLayout              oldLayout;
2285			VK_IMAGE_LAYOUT_GENERAL,												// VkImageLayout              newLayout;
2286			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   srcQueueFamilyIndex;
2287			VK_QUEUE_FAMILY_IGNORED,												// uint32_t                   dstQueueFamilyIndex;
2288			*wd.verify.image,														// VkImage                    image;
2289			makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 5u),	// VkImageSubresourceRange    subresourceRange;
2290		};
2291
2292		vk.cmdPipelineBarrier(*testObjects.cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
2293				0u, DE_NULL, 0u, DE_NULL, 1u, &verifyBarrier);
2294	}
2295}
2296
2297void testEnd(Context& context, const TestParams& params, WorkingData& wd, TestObjects& testObjects)
2298{
2299	// If not rendering to the whole framebuffer and the images were cleared before the render pass, verify that the area outside the render pass is untouched.
2300	const bool	verifyOutsideRenderArea = params.clearBeforeRenderPass && !params.renderToWholeFramebuffer;
2301	if (verifyOutsideRenderArea)
2302	{
2303		const DeviceInterface&	vk				= context.getDeviceInterface();
2304		const VkDevice			device			= context.getDevice();
2305
2306		const UVec4 verifyAreas[] = {
2307			UVec4(0, 0, wd.framebufferSize.x(), wd.renderArea.y()),
2308			UVec4(0, wd.renderArea.y(), wd.renderArea.x(), wd.renderArea.w()),
2309			UVec4(wd.renderArea.x() + wd.renderArea.z(), wd.renderArea.y(), wd.framebufferSize.x() - wd.renderArea.x() - wd.renderArea.z(), wd.renderArea.w()),
2310			UVec4(0, wd.renderArea.y() + wd.renderArea.w(), wd.framebufferSize.x(), wd.framebufferSize.y() - wd.renderArea.y() - wd.renderArea.w()),
2311		};
2312
2313		for (deUint32 areaNdx = 0; areaNdx < DE_LENGTH_OF_ARRAY(verifyAreas); ++areaNdx)
2314		{
2315			if (params.numFloatColor1Samples == VK_SAMPLE_COUNT_1_BIT)
2316			{
2317				const VerifySingleFloatPushConstants	verifyColor1 =
2318				{
2319					verifyAreas[areaNdx],
2320					Vec4(params.clearValues[0].color.float32[0], params.clearValues[0].color.float32[1], params.clearValues[0].color.float32[2], params.clearValues[0].color.float32[3]),
2321					0,
2322				};
2323				dispatchVerifyConstantColor(context, testObjects, wd.getResolvedFloatColorImage1View(params), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, wd.verify.view, wd.singleVerificationBuffer,
2324						static_cast<deUint32>(sizeof(verifyColor1)), &verifyColor1, "comp_singleFloat");
2325			}
2326
2327			if (params.numFloatColor2Samples == VK_SAMPLE_COUNT_1_BIT)
2328			{
2329				const VerifySingleFloatPushConstants	verifyColor2 =
2330				{
2331					verifyAreas[areaNdx],
2332					Vec4(params.clearValues[1].color.float32[0], params.clearValues[1].color.float32[1], params.clearValues[1].color.float32[2], params.clearValues[1].color.float32[3]),
2333					1,
2334				};
2335				dispatchVerifyConstantColor(context, testObjects, wd.getResolvedFloatColorImage2View(params), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, wd.verify.view, wd.singleVerificationBuffer,
2336						static_cast<deUint32>(sizeof(verifyColor2)), &verifyColor2, "comp_singleFloat");
2337			}
2338
2339			if (params.numIntColorSamples == VK_SAMPLE_COUNT_1_BIT)
2340			{
2341				const VerifySingleIntPushConstants	verifyColor3 =
2342				{
2343					verifyAreas[areaNdx],
2344					IVec4(params.clearValues[2].color.int32[0], params.clearValues[2].color.int32[1], params.clearValues[2].color.int32[2], params.clearValues[2].color.int32[3]),
2345					2,
2346				};
2347				dispatchVerifyConstantColor(context, testObjects, wd.getResolvedIntColorImageView(params), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, wd.verify.view, wd.singleVerificationBuffer,
2348						static_cast<deUint32>(sizeof(verifyColor3)), &verifyColor3, "comp_singleInt");
2349			}
2350
2351			if (params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT && isDepthFormat(params.depthStencilFormat))
2352			{
2353				const VerifySingleDepthPushConstants	verifyDepth =
2354				{
2355					verifyAreas[areaNdx],
2356					params.clearValues[3].depthStencil.depth,
2357				};
2358				dispatchVerifyConstantColor(context, testObjects, wd.getResolvedDepthOnlyImageView(params), VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, wd.verify.view, wd.singleVerificationBuffer,
2359						static_cast<deUint32>(sizeof(verifyDepth)), &verifyDepth, "comp_singleDepth");
2360			}
2361
2362			if (params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT && isStencilFormat(params.depthStencilFormat))
2363			{
2364				const VerifySingleStencilPushConstants	verifyStencil =
2365				{
2366					verifyAreas[areaNdx],
2367					params.clearValues[3].depthStencil.stencil,
2368				};
2369				dispatchVerifyConstantColor(context, testObjects, wd.getResolvedStencilOnlyImageView(params), VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, wd.verify.view, wd.singleVerificationBuffer,
2370						static_cast<deUint32>(sizeof(verifyStencil)), &verifyStencil, "comp_singleStencil");
2371			}
2372		}
2373
2374		invalidateAlloc(vk, device, *wd.singleVerificationBufferAlloc);
2375	}
2376
2377	testObjects.submitCommandsAndWait();
2378}
2379
2380tcu::TestStatus verify(Context& context, const TestParams& params, WorkingData& wd)
2381{
2382	bool drawsToColor1			= false;
2383	bool drawsToColor2			= false;
2384	bool drawsToColor3			= false;
2385	bool drawsToDepthStencil	= false;
2386	for (const TestParams::PerPass& perPass : params.perPass)
2387	{
2388		if (perPass.floatColor1Location >= 0)
2389			drawsToColor1		= true;
2390		if (perPass.floatColor2Location >= 0)
2391			drawsToColor2		= true;
2392		if (perPass.intColorLocation >= 0)
2393			drawsToColor3		= true;
2394		if (perPass.hasDepthStencil)
2395			drawsToDepthStencil	= true;
2396	}
2397
2398	logTestImages(context, params, wd, drawsToColor1, drawsToColor2, drawsToColor3, drawsToDepthStencil);
2399
2400	// Verify draw call results
2401	{
2402		const VerificationResults*	const	results		= static_cast<const VerificationResults*>(wd.verificationBufferAlloc->getHostPtr());
2403		const deUint32						totalPixels	= wd.renderArea.z() * wd.renderArea.w();
2404		bool								allOk		= true;
2405		const char*							errorDelim	= "";
2406		std::string							errorMsg	= "Incorrect multisampled rendering for ";
2407
2408		if (drawsToColor1)
2409			if (!checkAndReportError(context, results->color1Verification, totalPixels, "color attachment 1"))
2410			{
2411				errorMsg	+= errorDelim;
2412				errorMsg	+= "color attachment 1";
2413				errorDelim	= ", ";
2414				allOk		= false;
2415			}
2416
2417		if (drawsToColor2)
2418			if (!checkAndReportError(context, results->color2Verification, totalPixels, "color attachment 2"))
2419			{
2420				errorMsg	+= errorDelim;
2421				errorMsg	+= "color attachment 2";
2422				errorDelim	= ", ";
2423				allOk		= false;
2424			}
2425
2426		if (drawsToColor3)
2427			if (!checkAndReportError(context, results->color3Verification, totalPixels, "color attachment 3"))
2428			{
2429				errorMsg	+= errorDelim;
2430				errorMsg	+= "color attachment 3";
2431				errorDelim	= ", ";
2432				allOk		= false;
2433			}
2434
2435		if (drawsToDepthStencil && isDepthFormat(params.depthStencilFormat))
2436			if (!checkAndReportError(context, results->depthVerification, totalPixels, "depth attachment"))
2437			{
2438				errorMsg	+= errorDelim;
2439				errorMsg	+= "depth attachment";
2440				errorDelim	= ", ";
2441				allOk		= false;
2442			}
2443
2444		if (drawsToDepthStencil && isStencilFormat(params.depthStencilFormat))
2445			if (!checkAndReportError(context, results->stencilVerification, totalPixels, "stencil attachment"))
2446			{
2447				errorMsg	+= errorDelim;
2448				errorMsg	+= "stencil attachment";
2449				errorDelim	= ", ";
2450				allOk		= false;
2451			}
2452
2453		if (!allOk)
2454		{
2455			logVerifyImages(context, params, wd, drawsToColor1, drawsToColor2, drawsToColor3, drawsToDepthStencil);
2456			return tcu::TestStatus::fail(errorMsg);
2457		}
2458	}
2459
2460	const bool	verifyOutsideRenderArea = params.clearBeforeRenderPass && !params.renderToWholeFramebuffer;
2461	if (verifyOutsideRenderArea)
2462	{
2463		const VerificationResults*	const	results		= static_cast<const VerificationResults*>(wd.singleVerificationBufferAlloc->getHostPtr());
2464		const deUint32						totalPixels	= wd.framebufferSize.x() * wd.framebufferSize.y() - wd.renderArea.z() * wd.renderArea.w();
2465		bool								allOk		= true;
2466
2467		if (params.numFloatColor1Samples == VK_SAMPLE_COUNT_1_BIT)
2468			allOk = checkAndReportError(context, results->color1Verification, totalPixels, "color attachment 1 (outside render area)") && allOk;
2469		if (params.numFloatColor2Samples == VK_SAMPLE_COUNT_1_BIT)
2470			allOk = checkAndReportError(context, results->color2Verification, totalPixels, "color attachment 2 (outside render area)") && allOk;
2471		if (params.numIntColorSamples == VK_SAMPLE_COUNT_1_BIT)
2472			allOk = checkAndReportError(context, results->color3Verification, totalPixels, "color attachment 3 (outside render area)") && allOk;
2473		if (params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT && isDepthFormat(params.depthStencilFormat))
2474			allOk = checkAndReportError(context, results->depthVerification, totalPixels, "depth attachment (outside render area)") && allOk;
2475		if (params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT && isStencilFormat(params.depthStencilFormat))
2476			allOk = checkAndReportError(context, results->stencilVerification, totalPixels, "stencil attachment (outside render area)") && allOk;
2477
2478		if (!allOk)
2479		{
2480			logVerifyImages(context, params, wd, drawsToColor1, drawsToColor2, drawsToColor3, drawsToDepthStencil);
2481			return tcu::TestStatus::fail("Detected corruption outside render area");
2482		}
2483	}
2484
2485	return tcu::TestStatus::pass("Pass");
2486}
2487
2488void initConstantColorVerifyPrograms (SourceCollections& programCollection, const TestParams params)
2489{
2490	const bool	usesSignedIntFormat		= params.intColorFormat == VK_FORMAT_R16G16B16A16_SINT;
2491
2492	// Compute shader - Verify outside render area is intact (float colors)
2493	{
2494		std::ostringstream src;
2495		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2496			<< "#extension GL_EXT_samplerless_texture_functions : require\n"
2497			<< "\n"
2498			<< "layout(push_constant) uniform PushConstants {\n"
2499			<< "    uvec4 area;\n"
2500			<< "    vec4 color;\n"
2501			<< "    uint attachmentNdx;\n"
2502			<< "} params;\n"
2503			<< "\n"
2504			<< "layout(local_size_x = 8, local_size_y = 8) in;\n"
2505			<< "layout(set = 0, binding = 0, std430) writeonly buffer Output {\n"
2506			<< "    uint colorVerification[3];\n"
2507			<< "    uint depthVerification;\n"
2508			<< "    uint stencilVerification;\n"
2509			<< "} sb_out;\n"
2510			<< "layout(set = 0, binding = 1) uniform texture2D colorImage;\n"
2511			<< "layout(set = 0, binding = 2, rgba8) uniform writeonly image2DArray verify;\n"
2512			<< "\n"
2513			<< "bool v4matches(vec4 a, vec4 b, float error)\n"
2514			<< "{\n"
2515			<< "    return all(lessThan(abs(a - b), vec4(error)));\n"
2516			<< "}\n"
2517			<< "\n"
2518			<< "void main (void)\n"
2519			<< "{\n"
2520			<< "    if (any(greaterThanEqual(gl_GlobalInvocationID.xy, params.area.zw)))\n"
2521			<< "        return;\n"
2522			<< "\n"
2523			<< "    uvec2 coords = params.area.xy + gl_GlobalInvocationID.xy;\n"
2524			<< "\n"
2525			<< "    vec4 result = vec4(1, 0, 0, 1);\n"
2526			<< "    vec4 color = texelFetch(colorImage, ivec2(coords), 0);\n"
2527			<< "    if (v4matches(color, params.color, 0.01))\n"
2528			<< "    {\n"
2529			<< "        atomicAdd(sb_out.colorVerification[params.attachmentNdx], 1);\n"
2530			<< "        result = vec4(0, 1, 0, 1);\n"
2531			<< "    }\n"
2532			<< "    imageStore(verify, ivec3(coords, params.attachmentNdx), result);\n"
2533			<< "}\n";
2534
2535		programCollection.glslSources.add("comp_singleFloat") << glu::ComputeSource(src.str());
2536	}
2537
2538	// Compute shader - Verify outside render area is intact (int colors)
2539	{
2540		std::ostringstream src;
2541		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2542			<< "#extension GL_EXT_samplerless_texture_functions : require\n"
2543			<< "\n"
2544			<< "layout(push_constant) uniform PushConstants {\n"
2545			<< "    uvec4 area;\n"
2546			<< "    ivec4 color;\n"
2547			<< "    uint attachmentNdx;\n"
2548			<< "} params;\n"
2549			<< "\n"
2550			<< "layout(local_size_x = 8, local_size_y = 8) in;\n"
2551			<< "layout(set = 0, binding = 0, std430) writeonly buffer Output {\n"
2552			<< "    uint colorVerification[3];\n"
2553			<< "    uint depthVerification;\n"
2554			<< "    uint stencilVerification;\n"
2555			<< "} sb_out;\n"
2556			<< "layout(set = 0, binding = 1) uniform " << (usesSignedIntFormat ? "i" : "u") << "texture2D colorImage;\n"
2557			<< "layout(set = 0, binding = 2, rgba8) uniform writeonly image2DArray verify;\n"
2558			<< "\n"
2559			<< "bool i4matches(ivec4 a, ivec4 b, int error)\n"
2560			<< "{\n"
2561			<< "    return all(lessThanEqual(abs(a - b), ivec4(error)));\n"
2562			<< "}\n"
2563			<< "\n"
2564			<< "void main (void)\n"
2565			<< "{\n"
2566			<< "    if (any(greaterThanEqual(gl_GlobalInvocationID.xy, params.area.zw)))\n"
2567			<< "        return;\n"
2568			<< "\n"
2569			<< "    uvec2 coords = params.area.xy + gl_GlobalInvocationID.xy;\n"
2570			<< "\n"
2571			<< "    vec4 result = vec4(1, 0, 0, 1);\n"
2572			<< "    ivec4 color = ivec4(texelFetch(colorImage, ivec2(coords), 0));\n"
2573			<< "    if (i4matches(color, params.color, 0))\n"
2574			<< "    {\n"
2575			<< "        atomicAdd(sb_out.colorVerification[params.attachmentNdx], 1);\n"
2576			<< "        result = vec4(0, 1, 0, 1);\n"
2577			<< "    }\n"
2578			<< "    imageStore(verify, ivec3(coords, params.attachmentNdx), result);\n"
2579			<< "}\n";
2580
2581		programCollection.glslSources.add("comp_singleInt") << glu::ComputeSource(src.str());
2582	}
2583
2584	// Compute shader - Verify outside render area is intact (depth)
2585	{
2586		std::ostringstream src;
2587		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2588			<< "#extension GL_EXT_samplerless_texture_functions : require\n"
2589			<< "\n"
2590			<< "layout(push_constant) uniform PushConstants {\n"
2591			<< "    uvec4 area;\n"
2592			<< "    float depthData;\n"
2593			<< "} params;\n"
2594			<< "\n"
2595			<< "layout(local_size_x = 8, local_size_y = 8) in;\n"
2596			<< "layout(set = 0, binding = 0, std430) writeonly buffer Output {\n"
2597			<< "    uint colorVerification[3];\n"
2598			<< "    uint depthVerification;\n"
2599			<< "    uint stencilVerification;\n"
2600			<< "} sb_out;\n"
2601			<< "layout(set = 0, binding = 1) uniform texture2D depthImage;\n"
2602			<< "layout(set = 0, binding = 2, rgba8) uniform writeonly image2DArray verify;\n"
2603			<< "\n"
2604			<< "bool fmatches(float a, float b, float error)\n"
2605			<< "{\n"
2606			<< "    return abs(a - b) < error;\n"
2607			<< "}\n"
2608			<< "\n"
2609			<< "void main (void)\n"
2610			<< "{\n"
2611			<< "    if (any(greaterThanEqual(gl_GlobalInvocationID.xy, params.area.zw)))\n"
2612			<< "        return;\n"
2613			<< "\n"
2614			<< "    uvec2 coords = params.area.xy + gl_GlobalInvocationID.xy;\n"
2615			<< "\n"
2616			<< "    vec4 result = vec4(1, 0, 0, 1);\n"
2617			<< "    float depth  = texelFetch(depthImage, ivec2(coords), 0).r;\n"
2618			<< "    if (fmatches(depth, params.depthData, 0.01))\n"
2619			<< "    {\n"
2620			<< "        atomicAdd(sb_out.depthVerification, 1);\n"
2621			<< "        result = vec4(0, 1, 0, 1);\n"
2622			<< "    }\n"
2623			<< "    imageStore(verify, ivec3(coords, 3), result);\n"
2624			<< "}\n";
2625
2626		programCollection.glslSources.add("comp_singleDepth") << glu::ComputeSource(src.str());
2627	}
2628
2629	// Compute shader - Verify outside render area is intact (stencil)
2630	{
2631		std::ostringstream src;
2632		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2633			<< "#extension GL_EXT_samplerless_texture_functions : require\n"
2634			<< "\n"
2635			<< "layout(push_constant) uniform PushConstants {\n"
2636			<< "    uvec4 area;\n"
2637			<< "    uint stencilData;\n"
2638			<< "} params;\n"
2639			<< "\n"
2640			<< "layout(local_size_x = 8, local_size_y = 8) in;\n"
2641			<< "layout(set = 0, binding = 0, std430) writeonly buffer Output {\n"
2642			<< "    uint colorVerification[3];\n"
2643			<< "    uint depthVerification;\n"
2644			<< "    uint stencilVerification;\n"
2645			<< "} sb_out;\n"
2646			<< "layout(set = 0, binding = 1) uniform utexture2D stencilImage;\n"
2647			<< "layout(set = 0, binding = 2, rgba8) uniform writeonly image2DArray verify;\n"
2648			<< "\n"
2649			<< "bool umatches(uint a, uint b, uint error)\n"
2650			<< "{\n"
2651			<< "    return abs(a - b) <= error;\n"
2652			<< "}\n"
2653			<< "\n"
2654			<< "void main (void)\n"
2655			<< "{\n"
2656			<< "    if (any(greaterThanEqual(gl_GlobalInvocationID.xy, params.area.zw)))\n"
2657			<< "        return;\n"
2658			<< "\n"
2659			<< "    uvec2 coords = params.area.xy + gl_GlobalInvocationID.xy;\n"
2660			<< "\n"
2661			<< "    vec4 result = vec4(1, 0, 0, 1);\n"
2662			<< "    uint stencil = texelFetch(stencilImage, ivec2(coords), 0).r;\n"
2663			<< "    if (umatches(stencil, params.stencilData, 0))\n"
2664			<< "    {\n"
2665			<< "        atomicAdd(sb_out.stencilVerification, 1);\n"
2666			<< "        result = vec4(0, 1, 0, 1);\n"
2667			<< "    }\n"
2668			<< "    imageStore(verify, ivec3(coords, 4), result);\n"
2669			<< "}\n";
2670
2671		programCollection.glslSources.add("comp_singleStencil") << glu::ComputeSource(src.str());
2672	}
2673}
2674
2675void initBasicPrograms (SourceCollections& programCollection, const TestParams params)
2676{
2677	// Vertex shader - position
2678	{
2679		std::ostringstream src;
2680		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2681			<< "\n"
2682			<< "layout(location = 0) in  vec4 in_position;\n"
2683			<< "\n"
2684			<< "out gl_PerVertex {\n"
2685			<< "    vec4 gl_Position;\n"
2686			<< "};\n"
2687			<< "\n"
2688			<< "void main(void)\n"
2689			<< "{\n"
2690			<< "    gl_Position = in_position;\n"
2691			<< "}\n";
2692
2693		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2694	}
2695
2696	const bool		usesSignedIntFormat	= params.intColorFormat == VK_FORMAT_R16G16B16A16_SINT;
2697	const char*     intTypePrefix		= usesSignedIntFormat ? "i" : "u";
2698
2699	// The framebuffer contains four attachments with the same number of samples.
2700	// The fragment shader outputs a different color per sample (in a gradient) to verify that the multisampled image actually has that many samples:
2701	//
2702	// - For samples [4s, 4s+3), the shader outputs:
2703	//
2704	//     Vec4(0, v, v, v),
2705	//     Vec4(v, 0, v, v),
2706	//     Vec4(v, v, 0, v),
2707	//     Vec4(v, v, v, 0),
2708	//
2709	//   for float attachments where v = 1-s*0.2. For sample s, it outputs:
2710	//
2711	//     UVec4(v, v + 1, v + 2, v + 3),
2712	//
2713	//   for the int attachment where v = (s+1)*(s+1)*10.
2714	//
2715	// Additionally, the fragment shader outputs depth based on the sample index as well.  For sample s, it outputs 1 - (s^1)/16.
2716	// Note that ^1 ensures VK_RESOLVE_MODE_SAMPLE_ZERO_BIT and VK_RESOLVE_MODE_MAX_BIT produce different values.
2717	{
2718		const TestParams::PerPass &perPass = params.perPass[0];
2719
2720		// The shader outputs up to 16 samples
2721		const deUint32	numSamples	= static_cast<deUint32>(perPass.numSamples);
2722
2723		DE_ASSERT(numSamples <= 16);
2724
2725		std::ostringstream src;
2726		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2727			<< "\n"
2728			<< "layout(location = " << perPass.floatColor1Location << ") out vec4 o_color1;\n"
2729			<< "layout(location = " << perPass.floatColor2Location << ") out vec4 o_color2;\n"
2730			<< "layout(location = " << perPass.intColorLocation << ") out " << intTypePrefix << "vec4 o_color3;\n"
2731			<< "\n"
2732			<< "layout(push_constant) uniform PushConstants {\n"
2733			<< "    uvec4 area;\n"
2734			<< "} params;\n"
2735			<< "\n"
2736			<< "void main(void)\n"
2737			<< "{\n"
2738			<< "    vec2 uv = (gl_FragCoord.xy - vec2(params.area.xy)) / vec2(params.area.zw);\n";
2739		for (deUint32 sampleID = 0; sampleID < numSamples; ++sampleID)
2740		{
2741			const char*	uvComponent	= sampleID % 2 == 0 ? "uv.x" : "uv.y";
2742
2743			const float		floatValue	= 1 - static_cast<float>(sampleID / 4) * 0.2f;
2744			const deUint32	intValue	= (sampleID + 1) * (sampleID + 1) * 10;
2745			const float		depthValue	= 1 - static_cast<float>(sampleID ^ 1) / 16.0f;
2746
2747			const Vec4		floatChannels(sampleID % 4 == 0 ? 0 : floatValue,
2748										  sampleID % 4 == 1 ? 0 : floatValue,
2749										  sampleID % 4 == 2 ? 0 : floatValue,
2750										  sampleID % 4 == 3 ? 0 : floatValue);
2751			const UVec4		intChannels(intValue, intValue + 1, intValue + 2, intValue + 3);
2752
2753			src << "    " << (sampleID == 0 ? "" : "else ") << "if (gl_SampleID == " << sampleID << ")\n"
2754				<< "    {\n"
2755				<< "        o_color1 = vec4(" << floatChannels.x() << ", " << floatChannels.y() << ", " << floatChannels.z() << ", " << floatChannels.w() << ") * " << uvComponent << ";\n"
2756				<< "        o_color2 = vec4(" << floatChannels.x() << ", " << floatChannels.y() << ", " << floatChannels.z() << ", " << floatChannels.w() << ") * " << uvComponent << ";\n"
2757				<< "        o_color3 = " << intTypePrefix << "vec4(vec4(" << intChannels.x() << ", " << intChannels.y() << ", " << intChannels.z() << ", " << intChannels.w() << ") * " << uvComponent << ");\n"
2758				<< "        gl_FragDepth = " << depthValue << ";\n"
2759				<< "    }\n";
2760		}
2761		src << "}\n";
2762
2763		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
2764	}
2765
2766	// Compute shader - verify the results of rendering
2767	//
2768	// Take the formulas used for the fragment shader.  Note the following:
2769	//
2770	//    n-1
2771	//    sum(1 - s*0.2)
2772	//     0                 n - (n*(n-1))/2 * 0.2
2773	//  ----------------- = ----------------------- = 1 - (n-1)*0.1
2774	//          n                    n
2775	//
2776	// When rendering is done to every sample and the attachment is resolved, we expect:
2777	//
2778	// - For float attachments, average of:
2779	//   * Horizontal gradient:
2780	//
2781	//       Vec4(0, 1, 1, 1)			if 2 samples
2782	//       Vec4(0.5v, v, 0.5v, v)		o.w. where v = 1 - (n - 1)*0.1 where n = floor(sampleCount / 4).
2783	//
2784	//   * Vertical gradient:
2785	//
2786	//       Vec4(1, 0, 1, 1)			if 2 samples
2787	//       Vec4(v, 0.5v, v, 0.5v)		o.w. where v = 1 - (n - 1)*0.1 where n = floor(sampleCount / 4).
2788	//
2789	// - For the int attachments, any of UVec4(v, v + 1, v + 2, v + 3) where v = (s+1)*(s+1)*10
2790	// - For the depth attachment, either 1 or 1-1/16 based on whether MAX or SAMPLE_ZERO resolve modes are selected respectively.
2791	// - For the stencil attachment, expect the clear value + 1.
2792	{
2793		const TestParams::PerPass &perPass = params.perPass[0];
2794
2795		// The shader outputs up to 16 samples
2796		const deUint32	numSamples	= static_cast<deUint32>(perPass.numSamples);
2797
2798		const float		floatValue	= 1 - static_cast<float>((numSamples / 4) - 1) * 0.1f;
2799
2800		const Vec4		floatExpectHorizontal	= numSamples == 2 ? Vec4(0, 1, 1, 1)
2801																  : Vec4(0.5f * floatValue, floatValue, 0.5f * floatValue, floatValue);
2802		const Vec4		floatExpectVertical		= numSamples == 2 ? Vec4(1, 0, 1, 1)
2803																  : Vec4(floatValue, 0.5f * floatValue, floatValue, 0.5f * floatValue);
2804
2805		std::ostringstream src;
2806		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2807			<< "#extension GL_EXT_samplerless_texture_functions : require\n"
2808			<< "\n"
2809			<< "layout(push_constant) uniform PushConstants {\n"
2810			<< "    uvec4 area;\n"
2811			<< "    uint stencilExpect;\n"
2812			<< "} params;\n"
2813			<< "\n"
2814			<< "layout(local_size_x = 8, local_size_y = 8) in;\n"
2815			<< "layout(set = 0, binding = 0, std430) writeonly buffer Output {\n"
2816			<< "    uint colorVerification[3];\n"
2817			<< "    uint depthVerification;\n"
2818			<< "    uint stencilVerification;\n"
2819			<< "} sb_out;\n"
2820			<< "layout(set = 0, binding = 1) uniform texture2D color1Image;\n"
2821			<< "layout(set = 0, binding = 2) uniform texture2D color2Image;\n"
2822			<< "layout(set = 0, binding = 3) uniform " << (usesSignedIntFormat ? "i" : "u") << "texture2D color3Image;\n";
2823		if (isDepthFormat(params.depthStencilFormat))
2824			src << "layout(set = 0, binding = 4) uniform texture2D depthImage;\n";
2825		if (isStencilFormat(params.depthStencilFormat))
2826			src << "layout(set = 0, binding = 5) uniform utexture2D stencilImage;\n";
2827		src << "layout(set = 0, binding = 6, rgba8) uniform writeonly image2DArray verify;\n"
2828			<< "\n"
2829			<< "bool fmatches(float a, float b, float error)\n"
2830			<< "{\n"
2831			<< "    return abs(a - b) < error;\n"
2832			<< "}\n"
2833			<< "bool umatches(uint a, uint b, uint error)\n"
2834			<< "{\n"
2835			<< "    return abs(a - b) <= error;\n"
2836			<< "}\n"
2837			<< "bool v4matches(vec4 a, vec4 b, vec4 error)\n"
2838			<< "{\n"
2839			<< "    return all(lessThan(abs(a - b), error));\n"
2840			<< "}\n"
2841			<< "bool i4matchesEither(ivec4 a, ivec4 b, ivec4 c, int errorB, int errorC)\n"
2842			<< "{\n"
2843			<< "    return all(lessThanEqual(abs(a - b), ivec4(errorB))) || all(lessThanEqual(abs(a - c), ivec4(errorC)));\n"
2844			<< "}\n"
2845			<< "\n"
2846			<< "void main (void)\n"
2847			<< "{\n"
2848			<< "    if (any(greaterThanEqual(gl_GlobalInvocationID.xy, params.area.zw)))\n"
2849			<< "        return;\n"
2850			<< "\n"
2851			<< "    uvec2 coords = params.area.xy + gl_GlobalInvocationID.xy;\n"
2852			<< "    vec2 uv = (vec2(gl_GlobalInvocationID.xy) + vec2(0.5)) / vec2(params.area.zw);\n"
2853			<< "\n"
2854			<< "    vec4 result1 = vec4(1, 0, 0, 1);\n"
2855			<< "    vec4 color1 = texelFetch(color1Image, ivec2(coords), 0);\n"
2856			<< "    vec4 expected1H = vec4(" << floatExpectHorizontal.x() << ", "
2857											 << floatExpectHorizontal.y() << ", "
2858											 << floatExpectHorizontal.z() << ", "
2859											 << floatExpectHorizontal.w() << ");\n"
2860			<< "    vec4 expected1V = vec4(" << floatExpectVertical.x() << ", "
2861											 << floatExpectVertical.y() << ", "
2862											 << floatExpectVertical.z() << ", "
2863											 << floatExpectVertical.w() << ");\n"
2864			<< "    vec4 expected1 = (expected1H * uv.x + expected1V * uv.y) / 2.0;\n"
2865			// Allow room for precision errors.  Rendering happens at sample locations while verification uv is in the middle of pixel.
2866			<< "    if (v4matches(color1, expected1, max(expected1H / float(params.area.z), expected1V / float(params.area.w)) + 2.0/255.0))\n"
2867			<< "    {\n"
2868			<< "        atomicAdd(sb_out.colorVerification[0], 1);\n"
2869			<< "        result1 = vec4(0, 1, 0, 1);\n"
2870			<< "    }\n"
2871			<< "    imageStore(verify, ivec3(coords, 0), result1);\n"
2872			<< "\n"
2873			<< "    vec4 result2 = vec4(1, 0, 0, 1);\n"
2874			<< "    vec4 color2 = texelFetch(color2Image, ivec2(coords), 0);\n"
2875			// Allow room for precision errors.  Rendering happens at sample locations while verification uv is in the middle of pixel.
2876			<< "    if (v4matches(color2, expected1, max(expected1H / float(params.area.z), expected1V / float(params.area.w)) + 2.0/1024.0))\n"
2877			<< "    {\n"
2878			<< "        atomicAdd(sb_out.colorVerification[1], 1);\n"
2879			<< "        result2 = vec4(0, 1, 0, 1);\n"
2880			<< "    }\n"
2881			<< "    imageStore(verify, ivec3(coords, 1), result2);\n"
2882			<< "\n"
2883			<< "    vec4 result3 = vec4(1, 0, 0, 1);\n"
2884			<< "    ivec4 color3 = ivec4(texelFetch(color3Image, ivec2(coords), 0));\n"
2885			<< "    if (";
2886		for (deUint32 sampleID = 0; sampleID < numSamples; ++sampleID)
2887		{
2888			const deUint32	intValue	= (sampleID + 1) * (sampleID + 1) * 10;
2889			const UVec4		intExpect(intValue, intValue + 1, intValue + 2, intValue + 3);
2890
2891			src << (sampleID == 0 ? "" : "        || ")
2892				<< "i4matchesEither(color3, ivec4(vec4(" << intExpect.x() << ", " << intExpect.y() << ", " << intExpect.z() << ", " << intExpect.w() << ") * uv.x), "
2893										<< "ivec4(vec4(" << intExpect.x() << ", " << intExpect.y() << ", " << intExpect.z() << ", " << intExpect.w() << ") * uv.y), "
2894										// Allow room for precision errors.  Rendering happens at sample locations while verification uv is in the middle of pixel.
2895										<< intValue << " / int(params.area.z) + 1, "
2896										<< intValue << " / int(params.area.w) + 1)" << (sampleID == numSamples - 1 ? ")" : "") << "\n";
2897		}
2898		src << "    {\n"
2899			<< "        atomicAdd(sb_out.colorVerification[2], 1);\n"
2900			<< "        result3 = vec4(0, 1, 0, 1);\n"
2901			<< "    }\n"
2902			<< "    imageStore(verify, ivec3(coords, 2), result3);\n"
2903			<< "\n";
2904		if (isDepthFormat(params.depthStencilFormat))
2905		{
2906			const float		expect	= perPass.depthStencilResolveMode == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT ? 1 - 1/16.0f : 1.0f;
2907
2908			src << "    vec4 resultDepth = vec4(1, 0, 0, 1);\n"
2909				<< "    float depth  = texelFetch(depthImage, ivec2(coords), 0).r;\n"
2910				<< "    if (fmatches(depth, " << expect << ", 0.01))\n"
2911				<< "    {\n"
2912				<< "        atomicAdd(sb_out.depthVerification, 1);\n"
2913				<< "        resultDepth = vec4(0, 1, 0, 1);\n"
2914				<< "    }\n"
2915				<< "    imageStore(verify, ivec3(coords, 3), resultDepth);\n";
2916		}
2917		if (isStencilFormat(params.depthStencilFormat))
2918		{
2919			src << "    vec4 resultStencil = vec4(1, 0, 0, 1);\n"
2920				<< "    uint stencil = texelFetch(stencilImage, ivec2(coords), 0).r;\n"
2921				<< "    if (umatches(stencil, params.stencilExpect, 0))\n"
2922				<< "    {\n"
2923				<< "        atomicAdd(sb_out.stencilVerification, 1);\n"
2924				<< "        resultStencil = vec4(0, 1, 0, 1);\n"
2925				<< "    }\n"
2926				<< "    imageStore(verify, ivec3(coords, 4), resultStencil);\n";
2927		}
2928		src << "}\n";
2929
2930		programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
2931	}
2932
2933	// Always generate constant-color checks as they are used by vkCmdClearAttachments tests
2934	initConstantColorVerifyPrograms(programCollection, params);
2935}
2936
2937void dispatchVerifyBasic(Context& context, const TestParams& params, WorkingData& wd, TestObjects& testObjects)
2938{
2939	const DeviceInterface&	vk				= context.getDeviceInterface();
2940	const VkDevice			device			= context.getDevice();
2941
2942	postDrawBarrier(context, testObjects);
2943
2944	const VkPushConstantRange& verifyPushConstantRange =
2945	{
2946		VK_SHADER_STAGE_COMPUTE_BIT,									// VkShaderStageFlags    stageFlags;
2947		0,																// uint32_t              offset;
2948		static_cast<deUint32>(sizeof(UVec4) + sizeof(deUint32)),		// uint32_t              size;
2949	};
2950
2951	Move<VkPipelineLayout> verifyPipelineLayout;
2952	setupVerifyDescriptorSetAndPipeline(context, params, wd, testObjects, &verifyPushConstantRange, verifyPipelineLayout);
2953
2954	const deUint32	stencilExpect	= params.clearValues[3].depthStencil.stencil + 1;
2955
2956	vk.cmdPushConstants(*testObjects.cmdBuffer, *verifyPipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(UVec4), &wd.renderArea);
2957	vk.cmdPushConstants(*testObjects.cmdBuffer, *verifyPipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, sizeof(UVec4), sizeof(deUint32), &stencilExpect);
2958	vk.cmdDispatch(*testObjects.cmdBuffer, (wd.renderArea.z() + 7) / 8, (wd.renderArea.w() + 7) / 8, 1);
2959
2960	postVerifyBarrier(context, testObjects, wd.verificationBuffer);
2961
2962	invalidateAlloc(vk, device, *wd.verificationBufferAlloc);
2963}
2964
2965void drawBasic (Context& context, const TestParams& params, WorkingData& wd, TestObjects& testObjects)
2966{
2967	const InstanceInterface&	vki				= context.getInstanceInterface();
2968	const DeviceInterface&		vk				= context.getDeviceInterface();
2969	const VkPhysicalDevice		physicalDevice	= context.getPhysicalDevice();
2970	const VkDevice				device			= context.getDevice();
2971	VkPipelineRenderingCreateInfo				pipelineRenderingCreateInfo;
2972	std::vector<VkFormat>						colorAttachmentFormats = { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED };
2973	std::vector<VkRenderingAttachmentInfo>		colorAttachmentInfos(4u);
2974	VkRenderingAttachmentInfo					depthStencilAttachmentInfo;
2975
2976	DE_ASSERT(params.perPass.size() == 1);
2977
2978	if (params.clearBeforeRenderPass)
2979	{
2980		clearImagesBeforeDraw(context, params, wd, testObjects);
2981	}
2982
2983	if (params.dynamicRendering)
2984	{
2985		preRenderingImageLayoutTransition(context, params, wd, testObjects);
2986		initResolveImageLayouts(context, params, wd, testObjects);
2987	}
2988
2989	// Create a render pass and a framebuffer
2990	{
2991		std::vector<VkSubpassDescription2>							subpasses;
2992		std::vector<VkImage>										images;
2993		std::vector<VkImageView>									attachments;
2994		std::vector<VkAttachmentDescription2>						attachmentDescriptions;
2995		std::vector<VkAttachmentReference2>							attachmentReferences;
2996		std::vector<VkAttachmentReference2>							resolveAttachmentReferences;
2997		VkMultisampledRenderToSingleSampledInfoEXT					msrtss;
2998		VkSubpassDescriptionDepthStencilResolve						depthStencilResolve;
2999		deInt32														attachmentNdxes[8]	= {-1, -1, -1, -1,
3000																						   -1, -1, -1, -1};
3001		deUint32													attachmentUseMask	= 0;
3002
3003		initializeAttachments(params, wd, images, attachments, 0, attachmentNdxes);
3004
3005		if (params.dynamicRendering)
3006		{
3007			initializeRenderingAttachmentInfos(params,
3008											   wd,
3009											   colorAttachmentInfos,
3010											   depthStencilAttachmentInfo,
3011											   colorAttachmentFormats,
3012											   attachmentNdxes,
3013											   attachmentUseMask,
3014											   0u);
3015
3016			pipelineRenderingCreateInfo = {
3017				VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,		// VkStructureType	sType
3018				DE_NULL,												// const void*		pNext
3019				0u,														// uint32_t			viewMask
3020				static_cast<uint32_t>(colorAttachmentFormats.size()),	// uint32_t			colorAttachmentCount
3021				colorAttachmentFormats.data(),							// const VkFormat*	pColorAttachmentFormats
3022				VK_FORMAT_UNDEFINED,									// VkFormat			depthAttachmentFormat
3023				VK_FORMAT_UNDEFINED										// VkFormat			stencilAttachmentFormat
3024			};
3025
3026			if (params.usesDepthStencilInPass(0))
3027			{
3028				if (isDepthFormat(params.depthStencilFormat))
3029					pipelineRenderingCreateInfo.depthAttachmentFormat = params.depthStencilFormat;
3030				if (isStencilFormat(params.depthStencilFormat))
3031					pipelineRenderingCreateInfo.stencilAttachmentFormat = params.depthStencilFormat;
3032			}
3033		}
3034		else
3035		{
3036			initializeAttachmentDescriptions(params, attachmentDescriptions, params.clearBeforeRenderPass, attachmentNdxes, attachmentUseMask);
3037
3038			addSubpassDescription(params,
3039								  0,
3040								  attachmentReferences,
3041								  resolveAttachmentReferences,
3042								  depthStencilResolve,
3043								  nullptr,
3044								  msrtss,
3045								  subpasses,
3046								  {},
3047								  attachmentNdxes);
3048
3049			createRenderPassAndFramebuffer(context, wd, testObjects, params.pipelineConstructionType, images, attachments, attachmentDescriptions, subpasses, {});
3050		}
3051	}
3052
3053	{
3054		const VkPushConstantRange& pushConstantRange =
3055		{
3056			VK_SHADER_STAGE_FRAGMENT_BIT,				// VkShaderStageFlags    stageFlags;
3057			0,											// uint32_t              offset;
3058			static_cast<deUint32>(sizeof(UVec4)),		// uint32_t              size;
3059		};
3060
3061		const ShaderWrapper				vertexModule	(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
3062		const ShaderWrapper				fragmentModule	(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag"), 0u));
3063		const PipelineLayoutWrapper		pipelineLayout	(params.pipelineConstructionType, vk, device, 0, DE_NULL, 1, &pushConstantRange);
3064
3065		testObjects.graphicsPipelines.push_back(
3066			pipeline::makeGraphicsPipeline(vki,
3067										   vk,
3068										   physicalDevice,
3069										   device,
3070										   context.getDeviceExtensions(),
3071										   params.pipelineConstructionType,
3072										   pipelineLayout,
3073										   params.dynamicRendering ? DE_NULL : *testObjects.renderPassFramebuffers.back(),
3074										   params.dynamicRendering ? &pipelineRenderingCreateInfo : DE_NULL,
3075										   vertexModule,
3076										   fragmentModule,
3077										   false,
3078										   true,
3079										   false,
3080										   0,
3081										   0,
3082										   params.perPass[0].intColorLocation,
3083										   wd.renderArea,
3084										   wd.renderArea,
3085										   params.perPass[0].numSamples,
3086										   params.useGarbageAttachment));
3087
3088		if (params.dynamicRendering)
3089		{
3090			startRendering(context, params, wd, testObjects, static_cast<uint32_t>(colorAttachmentFormats.size()), colorAttachmentInfos, depthStencilAttachmentInfo, 0u);
3091		}
3092		else
3093		{
3094			startRenderPass(context, wd, testObjects, DE_LENGTH_OF_ARRAY(params.clearValues), params.clearValues);
3095		}
3096
3097		const VkDeviceSize vertexBufferOffset = 0;
3098		vk.cmdBindVertexBuffers(*testObjects.cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset);
3099
3100		vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(UVec4), &wd.renderArea);
3101		(*testObjects.graphicsPipelines.back()).bind(*testObjects.cmdBuffer);
3102		vk.cmdDraw(*testObjects.cmdBuffer, 3, 1u, 0u, 0u);
3103
3104		if (params.dynamicRendering)
3105		{
3106			vk.cmdEndRendering(*testObjects.cmdBuffer);
3107		}
3108		else
3109		{
3110			testObjects.renderPassFramebuffers.back().end(vk, *testObjects.cmdBuffer);
3111		}
3112	}
3113
3114	if (params.dynamicRendering)
3115	{
3116		postRenderingResolveImageLayoutTransition(context, params, wd, testObjects);
3117	}
3118
3119	// Verify results
3120	dispatchVerifyBasic(context, params, wd, testObjects);
3121}
3122
3123//! Verify multisampled rendering is done with the exact number of samples.
3124tcu::TestStatus testBasic (Context& context, const TestParams params)
3125{
3126	WorkingData wd;
3127	TestObjects testObjects(context);
3128	testStart(context, params, wd, testObjects);
3129
3130	drawBasic (context, params, wd, testObjects);
3131
3132	testEnd(context, params, wd, testObjects);
3133	return verify(context, params, wd);
3134}
3135
3136void generateBasicTest (de::Random& rng, TestParams& params, const VkSampleCountFlagBits sampleCount, const VkResolveModeFlagBits resolveMode, const bool renderToWholeFramebuffer)
3137{
3138	params.perPass.resize(1);
3139
3140	TestParams::PerPass& perPass	= params.perPass[0];
3141
3142	// Set the sample count for attachments.
3143	if (params.isMultisampledRenderToSingleSampled)
3144	{
3145		params.numFloatColor1Samples	= VK_SAMPLE_COUNT_1_BIT;
3146		params.numFloatColor2Samples	= VK_SAMPLE_COUNT_1_BIT;
3147		params.numIntColorSamples		= VK_SAMPLE_COUNT_1_BIT;
3148		params.numDepthStencilSamples	= VK_SAMPLE_COUNT_1_BIT;
3149
3150		perPass.resolveFloatColor1		= false;
3151		perPass.resolveFloatColor2		= false;
3152		perPass.resolveIntColor			= false;
3153		perPass.resolveDepthStencil		= false;
3154	}
3155	else
3156	{
3157		params.numFloatColor1Samples	= sampleCount;
3158		params.numFloatColor2Samples	= sampleCount;
3159		params.numIntColorSamples		= sampleCount;
3160		params.numDepthStencilSamples	= sampleCount;
3161
3162		perPass.resolveFloatColor1		= true;
3163		perPass.resolveFloatColor2		= true;
3164		perPass.resolveIntColor			= true;
3165		perPass.resolveDepthStencil		= true;
3166	}
3167	perPass.depthStencilResolveMode	= resolveMode;
3168
3169	perPass.numSamples				= sampleCount;
3170
3171	// Set locations for the color attachments.
3172	perPass.floatColor1Location = 0;
3173	perPass.floatColor2Location = 1;
3174	perPass.intColorLocation = 2;
3175
3176	// Depth/stencil is always used
3177	perPass.hasDepthStencil = true;
3178
3179	// Always clear before render pass so outside render area can be verified.
3180	params.clearBeforeRenderPass	= true;
3181	params.renderToWholeFramebuffer	= renderToWholeFramebuffer;
3182	params.testBlendsColors			= false;
3183
3184	// Set random clear values.
3185	generateRandomClearValues(rng, params, params.clearValues, false);
3186
3187	params.rngSeed = rng.getUint32();
3188}
3189
3190void dispatchVerifyClearAttachments(Context& context, const TestParams& params, WorkingData& wd, TestObjects& testObjects, const UVec4 regions[RegionCount], const VkClearValue clearValues[RegionCount - 1][4])
3191{
3192	const DeviceInterface&	vk				= context.getDeviceInterface();
3193	const VkDevice			device			= context.getDevice();
3194
3195	postDrawBarrier(context, testObjects);
3196
3197	const VkPushConstantRange& verifyPushConstantRange =
3198	{
3199		VK_SHADER_STAGE_COMPUTE_BIT,									// VkShaderStageFlags    stageFlags;
3200		0,																// uint32_t              offset;
3201		static_cast<deUint32>(sizeof(UVec4) + sizeof(deUint32)),		// uint32_t              size;
3202	};
3203
3204	Move<VkPipelineLayout> verifyPipelineLayout;
3205	setupVerifyDescriptorSetAndPipeline(context, params, wd, testObjects, &verifyPushConstantRange, verifyPipelineLayout);
3206
3207	const deUint32	stencilExpect[2] =
3208	{
3209		// For region 0, there's a single draw that increments the cleared stencil
3210		params.clearValues[3].depthStencil.stencil + 1,
3211		// For region 1, there's a vkCmdClearAttachments followed by a draw that increments that stencil value
3212		clearValues[0][3].depthStencil.stencil + 1,
3213	};
3214
3215	// Verify regions 0 and 1 have gradient colors.
3216	for (deUint32 regionNdx = 0; regionNdx < 2; ++regionNdx)
3217	{
3218		vk.cmdPushConstants(*testObjects.cmdBuffer, *verifyPipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(UVec4), &regions[regionNdx]);
3219		vk.cmdPushConstants(*testObjects.cmdBuffer, *verifyPipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, sizeof(UVec4), sizeof(deUint32), &stencilExpect[regionNdx]);
3220		vk.cmdDispatch(*testObjects.cmdBuffer, (regions[regionNdx].z() + 7) / 8, (regions[regionNdx].w() + 7) / 8, 1);
3221
3222		postVerifyBarrier(context, testObjects, wd.verificationBuffer);
3223	}
3224
3225	// Verify the rest of the regions have clear values.  Note that clearValues[0] is unused as it's overriden with a draw call to region 1.
3226	for (deUint32 regionNdx = 2; regionNdx < RegionCount; ++regionNdx)
3227	{
3228		const VkClearValue*	regionClearValues	= clearValues[regionNdx - 1];
3229		const UVec4&		region				= regions[regionNdx];
3230
3231		{
3232			const VerifySingleFloatPushConstants	verifyColor1 =
3233			{
3234				region,
3235				Vec4(regionClearValues[0].color.float32[0], regionClearValues[0].color.float32[1], regionClearValues[0].color.float32[2], regionClearValues[0].color.float32[3]),
3236				0,
3237			};
3238			dispatchVerifyConstantColor(context, testObjects, wd.getResolvedFloatColorImage1View(params), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, wd.verify.view, wd.verificationBuffer,
3239					static_cast<deUint32>(sizeof(verifyColor1)), &verifyColor1, "comp_singleFloat");
3240		}
3241
3242		{
3243			const VerifySingleFloatPushConstants	verifyColor2 =
3244			{
3245				region,
3246				Vec4(regionClearValues[1].color.float32[0], regionClearValues[1].color.float32[1], regionClearValues[1].color.float32[2], regionClearValues[1].color.float32[3]),
3247				1,
3248			};
3249			dispatchVerifyConstantColor(context, testObjects, wd.getResolvedFloatColorImage2View(params), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, wd.verify.view, wd.verificationBuffer,
3250					static_cast<deUint32>(sizeof(verifyColor2)), &verifyColor2, "comp_singleFloat");
3251		}
3252
3253		{
3254			const VerifySingleIntPushConstants	verifyColor3 =
3255			{
3256				region,
3257				IVec4(regionClearValues[2].color.int32[0], regionClearValues[2].color.int32[1], regionClearValues[2].color.int32[2], regionClearValues[2].color.int32[3]),
3258				2,
3259			};
3260			dispatchVerifyConstantColor(context, testObjects, wd.getResolvedIntColorImageView(params), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, wd.verify.view, wd.verificationBuffer,
3261					static_cast<deUint32>(sizeof(verifyColor3)), &verifyColor3, "comp_singleInt");
3262		}
3263
3264		if (isDepthFormat(params.depthStencilFormat))
3265		{
3266			const VerifySingleDepthPushConstants	verifyDepth =
3267			{
3268				region,
3269				regionClearValues[3].depthStencil.depth,
3270			};
3271			dispatchVerifyConstantColor(context, testObjects, wd.getResolvedDepthOnlyImageView(params), VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, wd.verify.view, wd.verificationBuffer,
3272					static_cast<deUint32>(sizeof(verifyDepth)), &verifyDepth, "comp_singleDepth");
3273		}
3274
3275		if (isStencilFormat(params.depthStencilFormat))
3276		{
3277			const VerifySingleStencilPushConstants	verifyStencil =
3278			{
3279				region,
3280				regionClearValues[3].depthStencil.stencil,
3281			};
3282			dispatchVerifyConstantColor(context, testObjects, wd.getResolvedStencilOnlyImageView(params), VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, wd.verify.view, wd.verificationBuffer,
3283					static_cast<deUint32>(sizeof(verifyStencil)), &verifyStencil, "comp_singleStencil");
3284		}
3285	}
3286
3287	invalidateAlloc(vk, device, *wd.verificationBufferAlloc);
3288}
3289
3290void drawClearAttachments (Context& context, const TestParams& params, WorkingData& wd, TestObjects& testObjects)
3291{
3292	const InstanceInterface&	vki				= context.getInstanceInterface();
3293	const DeviceInterface&		vk				= context.getDeviceInterface();
3294	const VkPhysicalDevice		physicalDevice	= context.getPhysicalDevice();
3295	const VkDevice				device			= context.getDevice();
3296	VkPipelineRenderingCreateInfo				pipelineRenderingCreateInfo;
3297	std::vector<VkFormat>						colorAttachmentFormats = { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED };
3298	std::vector<VkRenderingAttachmentInfo>		colorAttachmentInfos(4u);
3299	VkRenderingAttachmentInfo					depthStencilAttachmentInfo;
3300
3301	DE_ASSERT(params.perPass.size() == 1);
3302
3303	if (params.clearBeforeRenderPass)
3304	{
3305		clearImagesBeforeDraw(context, params, wd, testObjects);
3306	}
3307
3308	if (params.dynamicRendering)
3309	{
3310		preRenderingImageLayoutTransition(context, params, wd, testObjects);
3311		initResolveImageLayouts(context, params, wd, testObjects);
3312	}
3313
3314	// Create a render pass and a framebuffer
3315	{
3316		std::vector<VkSubpassDescription2>							subpasses;
3317		std::vector<VkImage>										images;
3318		std::vector<VkImageView>									attachments;
3319		std::vector<VkAttachmentDescription2>						attachmentDescriptions;
3320		std::vector<VkAttachmentReference2>							attachmentReferences;
3321		std::vector<VkAttachmentReference2>							resolveAttachmentReferences;
3322		VkMultisampledRenderToSingleSampledInfoEXT					msrtss;
3323		VkSubpassDescriptionDepthStencilResolve						depthStencilResolve;
3324		deInt32														attachmentNdxes[8]	= {-1, -1, -1, -1,
3325																						   -1, -1, -1, -1};
3326		deUint32													attachmentUseMask	= 0;
3327
3328		initializeAttachments(params, wd, images, attachments, 0, attachmentNdxes);
3329
3330		if (params.dynamicRendering)
3331		{
3332			initializeRenderingAttachmentInfos(params,
3333											   wd,
3334											   colorAttachmentInfos,
3335											   depthStencilAttachmentInfo,
3336											   colorAttachmentFormats,
3337											   attachmentNdxes,
3338											   attachmentUseMask,
3339											   0u);
3340
3341			pipelineRenderingCreateInfo = {
3342				VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,		// VkStructureType	sType
3343				DE_NULL,												// const void*		pNext
3344				0u,														// uint32_t			viewMask
3345				static_cast<uint32_t>(colorAttachmentFormats.size()),	// uint32_t			colorAttachmentCount
3346				colorAttachmentFormats.data(),							// const VkFormat*	pColorAttachmentFormats
3347				VK_FORMAT_UNDEFINED,									// VkFormat			depthAttachmentFormat
3348				VK_FORMAT_UNDEFINED										// VkFormat			stencilAttachmentFormat
3349			};
3350
3351			if (params.usesDepthStencilInPass(0))
3352			{
3353				if (isDepthFormat(params.depthStencilFormat))
3354					pipelineRenderingCreateInfo.depthAttachmentFormat = params.depthStencilFormat;
3355				if (isStencilFormat(params.depthStencilFormat))
3356					pipelineRenderingCreateInfo.stencilAttachmentFormat = params.depthStencilFormat;
3357			}
3358		}
3359		else
3360		{
3361			initializeAttachmentDescriptions(params, attachmentDescriptions, params.clearBeforeRenderPass, attachmentNdxes, attachmentUseMask);
3362
3363			addSubpassDescription(params,
3364								  0,
3365								  attachmentReferences,
3366								  resolveAttachmentReferences,
3367								  depthStencilResolve,
3368								  nullptr,
3369								  msrtss,
3370								  subpasses,
3371								  {},
3372								  attachmentNdxes);
3373
3374			createRenderPassAndFramebuffer(context, wd, testObjects, params.pipelineConstructionType, images, attachments, attachmentDescriptions, subpasses, {});
3375		}
3376	}
3377
3378	UVec4	regions[RegionCount];
3379	getDrawRegions(wd, regions);
3380
3381	VkClearValue	clearValues[RegionCount - 1][4];
3382	de::Random		rng(params.rngSeed);
3383	for (deUint32 regionNdx = 0; regionNdx < RegionCount - 1; ++regionNdx)
3384		generateRandomClearValues(rng, params, clearValues[regionNdx], false);
3385
3386	{
3387		const VkPushConstantRange& pushConstantRange =
3388		{
3389			VK_SHADER_STAGE_FRAGMENT_BIT,				// VkShaderStageFlags    stageFlags;
3390			0,											// uint32_t              offset;
3391			static_cast<deUint32>(sizeof(UVec4)),		// uint32_t              size;
3392		};
3393
3394		const ShaderWrapper				vertexModule	(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
3395		const ShaderWrapper				fragmentModule	(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag"), 0u));
3396		const PipelineLayoutWrapper		pipelineLayout	(params.pipelineConstructionType, vk, device, 0, DE_NULL, 1, &pushConstantRange);
3397
3398		if (params.dynamicRendering)
3399		{
3400			startRendering(context, params, wd, testObjects, static_cast<uint32_t>(colorAttachmentFormats.size()), colorAttachmentInfos, depthStencilAttachmentInfo, 0u);
3401		}
3402		else
3403		{
3404			startRenderPass(context, wd, testObjects, DE_LENGTH_OF_ARRAY(params.clearValues), params.clearValues);
3405		}
3406
3407		// Draw to region[0]
3408		testObjects.graphicsPipelines.push_back(
3409			pipeline::makeGraphicsPipeline(vki,
3410										   vk,
3411										   physicalDevice,
3412										   device,
3413										   context.getDeviceExtensions(),
3414										   params.pipelineConstructionType,
3415										   pipelineLayout,
3416										   params.dynamicRendering ? DE_NULL : *testObjects.renderPassFramebuffers.back(),
3417										   params.dynamicRendering ? &pipelineRenderingCreateInfo : DE_NULL,
3418										   vertexModule,
3419										   fragmentModule,
3420										   false,
3421										   true,
3422										   false,
3423										   0,
3424										   0,
3425										   params.perPass[0].intColorLocation,
3426										   regions[0],
3427										   regions[0],
3428										   params.perPass[0].numSamples,
3429										   params.useGarbageAttachment));
3430
3431		const VkDeviceSize vertexBufferOffset = 0;
3432		vk.cmdBindVertexBuffers(*testObjects.cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset);
3433
3434		vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(UVec4), &regions[0]);
3435		(*testObjects.graphicsPipelines.back()).bind(*testObjects.cmdBuffer);
3436		vk.cmdDraw(*testObjects.cmdBuffer, 3, 1u, 0u, 0u);
3437
3438		// Clear all regions except region 0
3439		{
3440			for (deUint32 regionNdx = 0; regionNdx < RegionCount - 1; ++regionNdx)
3441			{
3442				const VkClearAttachment attachments[4] = {
3443					{ VK_IMAGE_ASPECT_COLOR_BIT,	static_cast<deUint32>(params.perPass[0].floatColor1Location),	clearValues[regionNdx][0], },
3444					{ VK_IMAGE_ASPECT_COLOR_BIT,	static_cast<deUint32>(params.perPass[0].floatColor2Location),	clearValues[regionNdx][1], },
3445					{ VK_IMAGE_ASPECT_COLOR_BIT,	static_cast<deUint32>(params.perPass[0].intColorLocation),		clearValues[regionNdx][2], },
3446					{ getDepthStencilAspectFlags(params.depthStencilFormat),	0,									clearValues[regionNdx][3], },
3447				};
3448				const UVec4& region = regions[regionNdx + 1];
3449				const VkClearRect clearRegions =
3450				{
3451					{
3452						{static_cast<deInt32>(region.x()), static_cast<deInt32>(region.y())},
3453						{region.z(), region.w()}
3454					}, 0, 1
3455				};
3456
3457				vk.cmdClearAttachments(*testObjects.cmdBuffer, 4, attachments, 1, &clearRegions);
3458			}
3459		}
3460
3461		// Draw to region[1], overriding the clear value
3462		testObjects.graphicsPipelines.push_back(
3463			makeGraphicsPipeline(vki,
3464								 vk,
3465								 physicalDevice,
3466								 device,
3467								 context.getDeviceExtensions(),
3468								 params.pipelineConstructionType,
3469								 pipelineLayout,
3470								 params.dynamicRendering ? DE_NULL : *testObjects.renderPassFramebuffers.back(),
3471								 params.dynamicRendering ? &pipelineRenderingCreateInfo : DE_NULL,
3472								 vertexModule,
3473								 fragmentModule,
3474								 false,
3475								 true,
3476								 false,
3477								 0,
3478								 0,
3479								 params.perPass[0].intColorLocation,
3480								 regions[1],
3481								 regions[1],
3482								 params.perPass[0].numSamples,
3483								 params.useGarbageAttachment));
3484
3485		vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(UVec4), &regions[1]);
3486		(*testObjects.graphicsPipelines.back()).bind(*testObjects.cmdBuffer);
3487		vk.cmdDraw(*testObjects.cmdBuffer, 3, 1u, 0u, 0u);
3488
3489		if (params.dynamicRendering)
3490		{
3491			vk.cmdEndRendering(*testObjects.cmdBuffer);
3492		}
3493		else
3494		{
3495			testObjects.renderPassFramebuffers.back().end(vk, *testObjects.cmdBuffer);
3496		}
3497	}
3498
3499	if (params.dynamicRendering)
3500	{
3501		postRenderingResolveImageLayoutTransition(context, params, wd, testObjects);
3502	}
3503
3504	// Verify results
3505	dispatchVerifyClearAttachments(context, params, wd, testObjects, regions, clearValues);
3506}
3507
3508//! Verify vkCmdClearAttachments works.
3509tcu::TestStatus testClearAttachments (Context& context, const TestParams params)
3510{
3511	WorkingData wd;
3512	TestObjects testObjects(context);
3513	testStart(context, params, wd, testObjects);
3514
3515	drawClearAttachments (context, params, wd, testObjects);
3516
3517	testEnd(context, params, wd, testObjects);
3518	return verify(context, params, wd);
3519}
3520
3521void drawOnePass(Context& context, const TestParams& params, WorkingData& wd, TestObjects& testObjects,
3522		const ShaderWrapper& vertexModule, const PipelineLayoutWrapper& pipelineLayout, const deUint32 passNdx,
3523		const deUint32 subpassNdx, UVec4 regions[RegionCount], VkPipelineRenderingCreateInfo* pipelineRenderingCreateInfo)
3524{
3525	const InstanceInterface&	vki				= context.getInstanceInterface();
3526	const DeviceInterface&		vk				= context.getDeviceInterface();
3527	const VkPhysicalDevice		physicalDevice	= context.getPhysicalDevice();
3528	const VkDevice				device			= context.getDevice();
3529
3530	const VkDeviceSize vertexBufferOffset = 0;
3531	vk.cmdBindVertexBuffers(*testObjects.cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset);
3532
3533	const TestParams::PerPass& perPass = params.perPass[passNdx];
3534
3535	// Each subpass performs 4 sets of one or two draw calls.  Two if there is depth/stencil and one if not.
3536	// When depth/stencil is present, the first draw call writes to depth, while the second draw call does a depth test.
3537	// The four sets are draw calls with scissors dividing the render area in four:
3538	//
3539	// +--------+---------------+
3540	// |        |               |
3541	// |   1    |       2       |
3542	// |        |               |
3543	// +--------+---------------+
3544	// |        |               |
3545	// |        |               |
3546	// |   3    |       4       |
3547	// |        |               |
3548	// |        |               |
3549	// +--------+---------------+
3550	//
3551
3552	std::ostringstream fragName;
3553	fragName << "frag_" << passNdx;
3554	const ShaderWrapper			fragmentModule	(ShaderWrapper(vk, device, context.getBinaryCollection().get(fragName.str().c_str()), 0u));
3555
3556	for (deUint32 regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
3557	{
3558		testObjects.graphicsPipelines.push_back(
3559			pipeline::makeGraphicsPipeline(vki,
3560										   vk,
3561										   physicalDevice,
3562										   device,
3563										   context.getDeviceExtensions(),
3564										   params.pipelineConstructionType,
3565										   pipelineLayout,
3566										   params.dynamicRendering ? DE_NULL : *testObjects.renderPassFramebuffers.back(),
3567										   params.dynamicRendering ? pipelineRenderingCreateInfo : DE_NULL,
3568										   vertexModule,
3569										   fragmentModule,
3570										   true,
3571										   true,
3572										   false,
3573										   1 << passNdx,
3574										   subpassNdx,
3575										   perPass.intColorLocation,
3576										   regions[regionNdx],
3577										   regions[regionNdx],
3578										   perPass.numSamples,
3579										   params.useGarbageAttachment));
3580
3581		vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(UVec4), &regions[regionNdx]);
3582		vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(UVec4), sizeof(perPass.drawConstantsWithDepthWrite[regionNdx]), &perPass.drawConstantsWithDepthWrite[regionNdx]);
3583		(*testObjects.graphicsPipelines.back()).bind(*testObjects.cmdBuffer);
3584		vk.cmdDraw(*testObjects.cmdBuffer, 3, 1u, 0u, 0u);
3585
3586		if (perPass.hasDepthStencil)
3587		{
3588			testObjects.graphicsPipelines.push_back(
3589				pipeline::makeGraphicsPipeline(vki,
3590											   vk,
3591											   physicalDevice,
3592											   device,
3593											   context.getDeviceExtensions(),
3594											   params.pipelineConstructionType,
3595											   pipelineLayout,
3596											   params.dynamicRendering ? DE_NULL : *testObjects.renderPassFramebuffers.back(),
3597											   params.dynamicRendering ? pipelineRenderingCreateInfo : DE_NULL,
3598											   vertexModule,
3599											   fragmentModule,
3600											   true,
3601											   false,
3602											   true,
3603											   1 << passNdx,
3604											   subpassNdx,
3605											   perPass.intColorLocation,
3606											   regions[regionNdx],
3607											   regions[regionNdx],
3608											   perPass.numSamples,
3609											   params.useGarbageAttachment));
3610
3611			vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(UVec4), &regions[regionNdx]);
3612			vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(UVec4), sizeof(perPass.drawConstantsWithDepthTest[regionNdx]), &perPass.drawConstantsWithDepthTest[regionNdx]);
3613			(*testObjects.graphicsPipelines.back()).bind(*testObjects.cmdBuffer);
3614			vk.cmdDraw(*testObjects.cmdBuffer, 3, 1u, 0u, 0u);
3615		}
3616	}
3617}
3618
3619void dispatchVerifyMultiPassRendering(Context& context, const TestParams& params, WorkingData& wd, TestObjects& testObjects, UVec4 regions[RegionCount])
3620{
3621	const DeviceInterface&	vk				= context.getDeviceInterface();
3622	const VkDevice			device			= context.getDevice();
3623
3624	postDrawBarrier(context, testObjects);
3625
3626	const VkPushConstantRange& verifyPushConstantRange =
3627	{
3628		VK_SHADER_STAGE_COMPUTE_BIT,											// VkShaderStageFlags    stageFlags;
3629		0,																		// uint32_t              offset;
3630		static_cast<deUint32>(sizeof(UVec4) + sizeof(VerifyPushConstants)),		// uint32_t              size;
3631	};
3632
3633	Move<VkPipelineLayout> verifyPipelineLayout;
3634	setupVerifyDescriptorSetAndPipeline(context, params, wd, testObjects, &verifyPushConstantRange, verifyPipelineLayout);
3635
3636	for (deUint32 regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
3637	{
3638		if (regionNdx != 0)
3639		{
3640			const VkMemoryBarrier preVerifyBarrier =
3641			{
3642				VK_STRUCTURE_TYPE_MEMORY_BARRIER,		// VkStructureType    sType;
3643				DE_NULL,								// const void*        pNext;
3644				VK_ACCESS_SHADER_WRITE_BIT,				// VkAccessFlags      srcAccessMask;
3645				VK_ACCESS_SHADER_WRITE_BIT |
3646					VK_ACCESS_SHADER_READ_BIT,			// VkAccessFlags      dstAccessMask;
3647			};
3648
3649			vk.cmdPipelineBarrier(*testObjects.cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0,
3650					1u, &preVerifyBarrier, 0u, DE_NULL, 0u, DE_NULL);
3651		}
3652
3653		vk.cmdPushConstants(*testObjects.cmdBuffer, *verifyPipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(UVec4), &regions[regionNdx]);
3654		vk.cmdPushConstants(*testObjects.cmdBuffer, *verifyPipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, sizeof(UVec4), sizeof(params.verifyConstants[regionNdx]), &params.verifyConstants[regionNdx]);
3655		vk.cmdDispatch(*testObjects.cmdBuffer, (regions[regionNdx].z() + 7) / 8, (regions[regionNdx].w() + 7) / 8, 1);
3656	}
3657
3658	postVerifyBarrier(context, testObjects, wd.verificationBuffer);
3659
3660	invalidateAlloc(vk, device, *wd.verificationBufferAlloc);
3661}
3662
3663void drawSingleRenderPass (Context& context, const TestParams& params, WorkingData& wd, TestObjects& testObjects)
3664{
3665	const DeviceInterface&	vk				= context.getDeviceInterface();
3666	const VkDevice			device			= context.getDevice();
3667	const deUint32			numSubpasses	= static_cast<deUint32>(params.perPass.size());
3668
3669	if (params.clearBeforeRenderPass)
3670	{
3671		clearImagesBeforeDraw(context, params, wd, testObjects);
3672	}
3673
3674	// Create a render pass and a framebuffer
3675	{
3676		std::vector<VkSubpassDescription2>							subpasses;
3677		std::vector<VkImage>										images;
3678		std::vector<VkImageView>									attachments;
3679		std::vector<VkAttachmentDescription2>						attachmentDescriptions;
3680		std::vector<std::vector<VkAttachmentReference2>>			attachmentReferences(numSubpasses);
3681		std::vector<std::vector<VkAttachmentReference2>>			resolveAttachmentReferences(numSubpasses);
3682		std::vector<std::vector<deUint32>>							preserveAttachments(numSubpasses);
3683		std::vector<VkSubpassDependency2>							subpassDependencies;
3684		std::vector<VkMultisampledRenderToSingleSampledInfoEXT>		msrtss(numSubpasses);
3685		std::vector<VkSubpassDescriptionDepthStencilResolve>	    depthStencilResolve(numSubpasses);
3686		deInt32														attachmentNdxes[8]	= {-1, -1, -1, -1,
3687																						   -1, -1, -1, -1};
3688		deUint32													attachmentUseMask	= 0;
3689
3690		initializeAttachments(params, wd, images, attachments, params.perPass.size(), attachmentNdxes);
3691		initializeAttachmentDescriptions(params, attachmentDescriptions, params.clearBeforeRenderPass, attachmentNdxes, attachmentUseMask);
3692
3693		for (deUint32 passNdx = 0; passNdx < numSubpasses; ++passNdx)
3694		{
3695			addSubpassDescription(params,
3696								  passNdx,
3697								  attachmentReferences[passNdx],
3698								  resolveAttachmentReferences[passNdx],
3699								  depthStencilResolve[passNdx],
3700								  &preserveAttachments[passNdx],
3701								  msrtss[passNdx],
3702								  subpasses,
3703								  {},
3704								  attachmentNdxes);
3705
3706			if (passNdx > 0)
3707				addSubpassDependency(passNdx, subpassDependencies);
3708		}
3709
3710		createRenderPassAndFramebuffer(context, wd, testObjects, params.pipelineConstructionType, images, attachments, attachmentDescriptions, subpasses, subpassDependencies);
3711	}
3712
3713	const VkPushConstantRange& pushConstantRange =
3714	{
3715		VK_SHADER_STAGE_FRAGMENT_BIT,											// VkShaderStageFlags    stageFlags;
3716		0,																		// uint32_t              offset;
3717		static_cast<deUint32>(sizeof(UVec4) + sizeof(DrawPushConstants)),		// uint32_t              size;
3718	};
3719
3720	const ShaderWrapper				vertexModule	(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
3721	const PipelineLayoutWrapper		pipelineLayout	(params.pipelineConstructionType, vk, device, 0, DE_NULL, 1, &pushConstantRange);
3722
3723	UVec4	regions[RegionCount];
3724	getDrawRegions(wd, regions);
3725
3726	startRenderPass(context, wd, testObjects, DE_LENGTH_OF_ARRAY(params.clearValues), params.clearValues);
3727
3728	for (deUint32 passNdx = 0; passNdx < numSubpasses; ++passNdx)
3729	{
3730		if (passNdx != 0)
3731			testObjects.renderPassFramebuffers.back().nextSubpass(vk, *testObjects.cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
3732
3733		drawOnePass(context, params, wd, testObjects, vertexModule, pipelineLayout, passNdx, passNdx, regions, DE_NULL);
3734	}
3735
3736	testObjects.renderPassFramebuffers.back().end(vk, *testObjects.cmdBuffer);
3737
3738	// Verify results
3739	dispatchVerifyMultiPassRendering(context, params, wd, testObjects, regions);
3740}
3741
3742//! Verify multisampled rendering in subpasses
3743tcu::TestStatus testSingleRenderPass (Context& context, const TestParams params)
3744{
3745	WorkingData wd;
3746	TestObjects testObjects(context);
3747	testStart(context, params, wd, testObjects);
3748
3749	drawSingleRenderPass (context, params, wd, testObjects);
3750
3751	testEnd(context, params, wd, testObjects);
3752	return verify(context, params, wd);
3753}
3754
3755void drawMultiRenderPass (Context& context, const TestParams& params, WorkingData& wd, TestObjects& testObjects)
3756{
3757	const DeviceInterface&	vk				= context.getDeviceInterface();
3758	const VkDevice			device			= context.getDevice();
3759	const deUint32			numRenderPasses	= static_cast<deUint32>(params.perPass.size());
3760
3761	if (params.clearBeforeRenderPass)
3762	{
3763		clearImagesBeforeDraw(context, params, wd, testObjects);
3764	}
3765
3766	if (params.dynamicRendering)
3767	{
3768		preRenderingImageLayoutTransition(context, params, wd, testObjects);
3769		initResolveImageLayouts(context, params, wd, testObjects);
3770	}
3771
3772	const VkPushConstantRange& pushConstantRange =
3773	{
3774		VK_SHADER_STAGE_FRAGMENT_BIT,											// VkShaderStageFlags    stageFlags;
3775		0,																		// uint32_t              offset;
3776		static_cast<deUint32>(sizeof(UVec4) + sizeof(DrawPushConstants)),		// uint32_t              size;
3777	};
3778
3779	const ShaderWrapper				vertexModule	(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
3780	const PipelineLayoutWrapper		pipelineLayout	(params.pipelineConstructionType, vk, device, 0, DE_NULL, 1, &pushConstantRange);
3781
3782	UVec4	regions[RegionCount];
3783	getDrawRegions(wd, regions);
3784
3785	deUint32						attachmentUseMask	= 0;
3786
3787	for (deUint32 renderPassNdx = 0; renderPassNdx < numRenderPasses; ++renderPassNdx)
3788	{
3789		// Create a render pass and a framebuffer
3790		std::vector<VkSubpassDescription2>				subpasses;
3791		std::vector<VkImage>							images;
3792		std::vector<VkImageView>						attachments;
3793		std::vector<VkAttachmentDescription2>			attachmentDescriptions;
3794		std::vector<VkAttachmentReference2>				attachmentReferences;
3795		std::vector<VkAttachmentReference2>				resolveAttachmentReferences;
3796		VkMultisampledRenderToSingleSampledInfoEXT		msrtss;
3797		VkSubpassDescriptionDepthStencilResolve			depthStencilResolve;
3798		deInt32											attachmentNdxes[8]	= {-1, -1, -1, -1,
3799																			   -1, -1, -1, -1};
3800		VkPipelineRenderingCreateInfo					pipelineRenderingCreateInfo;
3801		std::vector<VkFormat>							colorAttachmentFormats = { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED };
3802		std::vector<VkRenderingAttachmentInfo>			colorAttachmentInfos(4u);
3803		VkRenderingAttachmentInfo						depthStencilAttachmentInfo;
3804
3805		std::vector<VkClearValue>						clearValues;
3806
3807		initializeAttachments(params, wd, images, attachments, renderPassNdx, attachmentNdxes);
3808		if (params.dynamicRendering)
3809		{
3810			initializeRenderingAttachmentInfos(params,
3811											   wd,
3812											   colorAttachmentInfos,
3813											   depthStencilAttachmentInfo,
3814											   colorAttachmentFormats,
3815											   attachmentNdxes,
3816											   attachmentUseMask,
3817											   renderPassNdx);
3818
3819			pipelineRenderingCreateInfo = {
3820				VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,		// VkStructureType	sType
3821				DE_NULL,												// const void*		pNext
3822				0u,														// uint32_t			viewMask
3823				static_cast<uint32_t>(colorAttachmentFormats.size()),	// uint32_t			colorAttachmentCount
3824				colorAttachmentFormats.data(),							// const VkFormat*	pColorAttachmentFormats
3825				VK_FORMAT_UNDEFINED,									// VkFormat			depthAttachmentFormat
3826				VK_FORMAT_UNDEFINED										// VkFormat			stencilAttachmentFormat
3827			};
3828
3829			if (params.usesDepthStencilInPass(renderPassNdx))
3830			{
3831				if (isDepthFormat(params.depthStencilFormat))
3832					pipelineRenderingCreateInfo.depthAttachmentFormat = params.depthStencilFormat;
3833				if (isStencilFormat(params.depthStencilFormat))
3834					pipelineRenderingCreateInfo.stencilAttachmentFormat = params.depthStencilFormat;
3835			}
3836		}
3837		else
3838		{
3839			initializeAttachmentDescriptions(params, attachmentDescriptions, params.clearBeforeRenderPass, attachmentNdxes, attachmentUseMask);
3840
3841			addSubpassDescription(params,
3842								  renderPassNdx,
3843								  attachmentReferences,
3844								  resolveAttachmentReferences,
3845								  depthStencilResolve,
3846								  nullptr,
3847								  msrtss,
3848								  subpasses,
3849								  {},
3850								  attachmentNdxes);
3851
3852			createRenderPassAndFramebuffer(context, wd, testObjects, params.pipelineConstructionType, images, attachments, attachmentDescriptions, subpasses, {});
3853
3854			// Init clear values
3855			if (attachmentNdxes[0] >= 0)
3856				clearValues.push_back(params.clearValues[0]);
3857			if (attachmentNdxes[1] >= 0)
3858				clearValues.push_back(params.clearValues[1]);
3859			if (attachmentNdxes[2] >= 0)
3860				clearValues.push_back(params.clearValues[2]);
3861			if (attachmentNdxes[3] >= 0)
3862				clearValues.push_back(params.clearValues[3]);
3863		}
3864
3865		if (renderPassNdx > 0)
3866		{
3867			const VkMemoryBarrier interRenderPassBarrier =
3868			{
3869				VK_STRUCTURE_TYPE_MEMORY_BARRIER,										// VkStructureType    sType;
3870				DE_NULL,																// const void*        pNext;
3871				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
3872					VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,						// VkAccessFlags      srcAccessMask;
3873				VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
3874					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
3875					VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
3876					VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,						// VkAccessFlags      dstAccessMask;
3877			};
3878
3879			vk.cmdPipelineBarrier(*testObjects.cmdBuffer,
3880					VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT	| VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
3881															  VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
3882					0u, 1u, &interRenderPassBarrier, 0u, DE_NULL, 0u, DE_NULL);
3883		}
3884
3885		if (params.dynamicRendering)
3886		{
3887			startRendering(context, params, wd, testObjects, static_cast<uint32_t>(colorAttachmentFormats.size()), colorAttachmentInfos, depthStencilAttachmentInfo, renderPassNdx);
3888		}
3889		else
3890		{
3891			startRenderPass(context, wd, testObjects, static_cast<deUint32>(clearValues.size()), dataOrNullPtr(clearValues));
3892		}
3893
3894		drawOnePass(context, params, wd, testObjects, vertexModule, pipelineLayout, renderPassNdx, 0, regions, &pipelineRenderingCreateInfo);
3895
3896		if (params.dynamicRendering)
3897		{
3898			vk.cmdEndRendering(*testObjects.cmdBuffer);
3899		}
3900		else
3901		{
3902			testObjects.renderPassFramebuffers.back().end(vk, *testObjects.cmdBuffer);
3903		}
3904	}
3905
3906	if (params.dynamicRendering)
3907	{
3908		postRenderingResolveImageLayoutTransition(context, params, wd, testObjects);
3909	}
3910
3911	// Verify results
3912	dispatchVerifyMultiPassRendering(context, params, wd, testObjects, regions);
3913}
3914
3915//! Verify multisampled rendering in multiple render passes
3916tcu::TestStatus testMultiRenderPass (Context& context, const TestParams params)
3917{
3918	WorkingData wd;
3919	TestObjects testObjects(context);
3920	testStart(context, params, wd, testObjects);
3921
3922	drawMultiRenderPass (context, params, wd, testObjects);
3923
3924	testEnd(context, params, wd, testObjects);
3925	return verify(context, params, wd);
3926}
3927
3928void generateMultiPassTest (de::Random& rng, TestParams& params)
3929{
3930	const VkSampleCountFlagBits	sampleRange[] =
3931	{
3932		// 4x multisampling is always supported.  A higher chance is given to that to avoid too many tests being skipped.
3933		VK_SAMPLE_COUNT_2_BIT,
3934		VK_SAMPLE_COUNT_4_BIT,
3935		VK_SAMPLE_COUNT_4_BIT,
3936		VK_SAMPLE_COUNT_4_BIT,
3937		VK_SAMPLE_COUNT_8_BIT,
3938		VK_SAMPLE_COUNT_16_BIT,
3939	};
3940
3941	const VkResolveModeFlagBits	depthStencilResolveModeRange[] =
3942	{
3943		// SAMPLE_ZERO is always supported, while MAX may not be.  A higher chance is given to SAMPLE_ZERO to avoid too many tests being skipped.
3944		VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,
3945		VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,
3946		VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,
3947		VK_RESOLVE_MODE_MAX_BIT,
3948	};
3949
3950	// Generate a random number of passes (either subpass or render pass)
3951	const deUint32	passCount		= rng.getInt(1, 4);
3952
3953	params.perPass.resize(passCount);
3954
3955	std::vector<deUint32> passAttachments;
3956
3957	deUint32 usedAttachmentMask = 0;
3958	if (params.isMultisampledRenderToSingleSampled)
3959	{
3960		// Decide which attachments will be used in which pass.  This is a bit mask.
3961		for (deUint32 passNdx = 0; passNdx < passCount; ++passNdx)
3962		{
3963			passAttachments.push_back(rng.getInt(1, 15));
3964			usedAttachmentMask |= passAttachments.back();
3965		}
3966	}
3967	else
3968	{
3969		passAttachments.push_back(15);	// Make sure all attachments have the same sample count
3970		for (deUint32 passNdx = 1; passNdx < passCount; ++passNdx)
3971			passAttachments.push_back(rng.getInt(1, 15));
3972	}
3973
3974	// Decide which attachments will be single-sampled.  This is a bit mask.
3975	// Include any attachment that is not used in any subpass just to make all attachments valid.
3976	const deUint32	singleSampledAttachmentsMask	= params.isMultisampledRenderToSingleSampled ? rng.getInt(1, 15) | (~usedAttachmentMask & 0xF) : 0;
3977
3978	DBG("Generating test for %u passes\n", passCount);
3979
3980	// Set the sample count for attachments.  Multisampled attachments that are used in the same pass will get the same number of samples.
3981	if ((singleSampledAttachmentsMask & 1) != 0)
3982		params.numFloatColor1Samples = VK_SAMPLE_COUNT_1_BIT;
3983	if ((singleSampledAttachmentsMask & 2) != 0)
3984		params.numFloatColor2Samples = VK_SAMPLE_COUNT_1_BIT;
3985	if ((singleSampledAttachmentsMask & 4) != 0)
3986		params.numIntColorSamples = VK_SAMPLE_COUNT_1_BIT;
3987	if ((singleSampledAttachmentsMask & 8) != 0)
3988		params.numDepthStencilSamples = VK_SAMPLE_COUNT_1_BIT;
3989
3990	for (deUint32 passNdx = 0; passNdx < passCount; ++passNdx)
3991	{
3992		TestParams::PerPass& perPass = params.perPass[passNdx];
3993
3994		const deUint32				multisampledAttachments	= passAttachments[passNdx] & ~singleSampledAttachmentsMask;
3995		const VkSampleCountFlagBits	randomSampleCount		= sampleRange[rng.getInt(0, DE_LENGTH_OF_ARRAY(sampleRange) - 1)];
3996		DBG("  + random samples: %d, multisampled attachments: %#x\n", randomSampleCount, multisampledAttachments);
3997
3998		if (multisampledAttachments == 0)
3999		{
4000			// If all attachments are single-sampled, choose a random number of samples for the render pass.
4001			perPass.numSamples = randomSampleCount;
4002		}
4003		else
4004		{
4005			// Otherwise see if any of the attachments has already been decided what number of samples it has.
4006			VkSampleCountFlagBits	sampleCount = (multisampledAttachments & 1) != 0 && params.numFloatColor1Samples != 0 ?		params.numFloatColor1Samples
4007												: (multisampledAttachments & 2) != 0 && params.numFloatColor2Samples != 0 ?		params.numFloatColor2Samples
4008												: (multisampledAttachments & 4) != 0 && params.numIntColorSamples != 0 ?		params.numIntColorSamples
4009												: (multisampledAttachments & 8) != 0 && params.numDepthStencilSamples != 0 ?	params.numDepthStencilSamples
4010												// If none of the attachments already have a defined sample, generate a random sample count to use for all of them.
4011												: randomSampleCount;
4012			DBG("   + sample count from attachments or random: %d (already: %d %d %d %d)\n", sampleCount,
4013				params.numFloatColor1Samples, params.numFloatColor2Samples, params.numIntColorSamples, params.numDepthStencilSamples);
4014
4015			perPass.numSamples = sampleCount;
4016
4017			// Make all multisampled attachments used in the pass have the same number of samples.  Additionally, make all the multisampled attachments
4018			// used in conjunction with the these ones in future passes also have the same number of samples.
4019			for (deUint32 followingPassNdx = passNdx; followingPassNdx < passCount; ++followingPassNdx)
4020			{
4021				const deUint32				followingMultisampledAttachments	= passAttachments[followingPassNdx] & ~singleSampledAttachmentsMask;
4022
4023				if ((followingMultisampledAttachments & 1) != 0)
4024					params.numFloatColor1Samples = sampleCount;
4025				if ((followingMultisampledAttachments & 2) != 0)
4026					params.numFloatColor2Samples = sampleCount;
4027				if ((followingMultisampledAttachments & 4) != 0)
4028					params.numIntColorSamples = sampleCount;
4029				if ((followingMultisampledAttachments & 8) != 0)
4030					params.numDepthStencilSamples = sampleCount;
4031			}
4032		}
4033
4034		// Generate random locations for the color attachments.
4035		deInt32 locations[] = {0, 1, 2, 3};
4036		for (int i = 0; i < 3; ++i)
4037		{
4038			int j = rng.getInt(i, 3);
4039			std::swap(locations[i], locations[j]);
4040		}
4041		size_t nextLocation = 0;
4042		perPass.floatColor1Location = (passAttachments[passNdx] & 1) != 0 ? locations[nextLocation++] : -1;
4043		perPass.floatColor2Location = (passAttachments[passNdx] & 2) != 0 ? locations[nextLocation++] : -1;
4044		perPass.intColorLocation = (passAttachments[passNdx] & 4) != 0 ? locations[nextLocation++] : -1;
4045
4046		// Specify if depth/stencil is used
4047		perPass.hasDepthStencil = (passAttachments[passNdx] & 8) != 0;
4048
4049		perPass.resolveFloatColor1 = false;
4050		perPass.resolveFloatColor2 = false;
4051		perPass.resolveIntColor = false;
4052		perPass.resolveDepthStencil = false;
4053		perPass.depthStencilResolveMode = VK_RESOLVE_MODE_NONE;
4054
4055		DBG(" - %u samples, locations: %d %d %d has D/S? %d\n", perPass.numSamples,
4056			perPass.floatColor1Location, perPass.floatColor2Location, perPass.intColorLocation, perPass.hasDepthStencil);
4057	}
4058
4059	DBG(" Sample counts: %u %u %u %u\n", params.numFloatColor1Samples, params.numFloatColor2Samples, params.numIntColorSamples, params.numDepthStencilSamples);
4060
4061	// Assert that generated passes are valid
4062	for (deUint32 passNdx = 0; passNdx < passCount; ++passNdx)
4063	{
4064		const VkSampleCountFlagBits	sampleCounts[4]				= {params.numFloatColor1Samples, params.numFloatColor2Samples, params.numIntColorSamples, params.numDepthStencilSamples};
4065		VkSampleCountFlagBits		subpassSampleCount			= VK_SAMPLE_COUNT_1_BIT;
4066
4067		for (deUint32 attachmentNdx = 0; attachmentNdx < 4; ++attachmentNdx)
4068		{
4069			if ((passAttachments[passNdx] & (1 << attachmentNdx)) == 0)
4070				continue;
4071
4072			const VkSampleCountFlagBits attachmentSampleCount	= sampleCounts[attachmentNdx] == VK_SAMPLE_COUNT_1_BIT
4073																		? params.perPass[passNdx].numSamples
4074																		: sampleCounts[attachmentNdx];
4075
4076			if (subpassSampleCount == VK_SAMPLE_COUNT_1_BIT)
4077				subpassSampleCount = attachmentSampleCount;
4078
4079			DE_ASSERT(subpassSampleCount == attachmentSampleCount);
4080		}
4081	}
4082
4083	// Determine when multisampled attachments should resolve.
4084	deUint32	resolvedAttachmentsMask	= singleSampledAttachmentsMask;
4085	for (deUint32 passNdx = passCount; passNdx > 0; --passNdx)
4086	{
4087		TestParams::PerPass&	perPass		= params.perPass[passNdx - 1];
4088		const deUint32	unresolvedAttachments	= passAttachments[passNdx - 1] & ~resolvedAttachmentsMask;
4089
4090		// Make every multisampled attachment resolve in the last pass it's used.
4091		if ((unresolvedAttachments & 1) != 0)
4092			perPass.resolveFloatColor1 = true;
4093		if ((unresolvedAttachments & 2) != 0)
4094			perPass.resolveFloatColor2 = true;
4095		if ((unresolvedAttachments & 4) != 0)
4096			perPass.resolveIntColor = true;
4097		if ((unresolvedAttachments & 8) != 0)
4098			perPass.resolveDepthStencil = true;
4099
4100		if (perPass.resolveDepthStencil || params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT)
4101			perPass.depthStencilResolveMode	= depthStencilResolveModeRange[rng.getInt(0, DE_LENGTH_OF_ARRAY(depthStencilResolveModeRange) - 1)];
4102
4103		resolvedAttachmentsMask |= unresolvedAttachments;
4104
4105		DBG(" - Resolved 0x%x in pass %u\n", unresolvedAttachments, passNdx - 1);
4106	}
4107
4108	// Decide whether clear should be done as part of the render pass.  Tests loadOp=CLEAR vs loadOp=LOAD.
4109	params.clearBeforeRenderPass	= rng.getBool();
4110	// Decide whether should render to the whole framebuffer or a subarea.
4111	params.renderToWholeFramebuffer	= rng.getBool();
4112	// These tests blend color so they can verify the results all at once at the end.
4113	params.testBlendsColors			= true;
4114
4115	// Set random clear values.  Use small values as draw calls do additive blending.
4116	generateRandomClearValues(rng, params, params.clearValues, true);
4117
4118	// Decide DrawPushConstants
4119	for (deUint32 passNdx = 0; passNdx < passCount; ++passNdx)
4120	{
4121		TestParams::PerPass& perPass = params.perPass[passNdx];
4122
4123		for (deUint32 regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
4124		{
4125			perPass.drawConstantsWithDepthWrite[regionNdx]	= DrawPushConstants{
4126				{Vec4(rng.getFloat(0.05f, 0.1f), 0, rng.getFloat(0.05f, 0.1f), 0), Vec4(0, rng.getFloat(0.05f, 0.1f), 0, rng.getFloat(0.05f, 0.1f))},
4127				{Vec4(rng.getFloat(0.05f, 0.1f), rng.getFloat(0.05f, 0.1f), 0, 0), Vec4(0, 0, rng.getFloat(0.05f, 0.1f), rng.getFloat(0.05f, 0.1f))},
4128				{IVec4(0, 0, 0, 0), IVec4(0, 0, 0, 0)},
4129				// Use quantized values to avoid values that are too close and may cause precision issues
4130				Vec2(0.1f * static_cast<float>(rng.getInt(2, 9)), 0.1f * static_cast<float>(rng.getInt(2, 9))),
4131			};
4132
4133			perPass.drawConstantsWithDepthTest[regionNdx]	= DrawPushConstants{
4134				{Vec4(rng.getFloat(0.05f, 0.1f), 0, rng.getFloat(0.05f, 0.1f), 0), Vec4(0, rng.getFloat(0.05f, 0.1f), 0, rng.getFloat(0.05f, 0.1f))},
4135				{Vec4(rng.getFloat(0.05f, 0.1f), rng.getFloat(0.05f, 0.1f), 0, 0), Vec4(0, 0, rng.getFloat(0.05f, 0.1f), rng.getFloat(0.05f, 0.1f))},
4136				{IVec4(0, 0, 0, 0), IVec4(0, 0, 0, 0)},
4137				Vec2(0.1f * static_cast<float>(rng.getInt(2, 9)) + 0.05f, 0.1f * static_cast<float>(rng.getInt(2, 8)) + 0.05f),
4138			};
4139
4140			// Integer resolve may choose any sample, so we modify only one channel per pass (hence the maximum of 4 passes).  This way, the verification
4141			// shader can accept two values per channel.
4142			perPass.drawConstantsWithDepthWrite[regionNdx].color3Data[0][passNdx]	= rng.getInt(1000, 5000);
4143			perPass.drawConstantsWithDepthWrite[regionNdx].color3Data[1][passNdx]	= rng.getInt(1000, 5000);
4144			perPass.drawConstantsWithDepthTest[regionNdx].color3Data[0][passNdx]	= rng.getInt(1000, 5000);
4145			perPass.drawConstantsWithDepthTest[regionNdx].color3Data[1][passNdx]	= rng.getInt(1000, 5000);
4146		}
4147	}
4148
4149	// Calculate VerifyPushConstants.  Walk through the passes and emulate what the draw calls would produce.
4150	// Note: Color clear value is not applied and is added by the verification shader.  This is because the verification shader interpolates colors with black,
4151	// so the baseline (clear value) is added afterwards.
4152	Vec2 depthResult[RegionCount];
4153	UVec2 stencilResult[RegionCount];
4154	for (deUint32 regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
4155	{
4156		depthResult[regionNdx]		= Vec2(params.clearValues[3].depthStencil.depth, params.clearValues[3].depthStencil.depth);
4157		stencilResult[regionNdx]	= UVec2(params.clearValues[3].depthStencil.stencil, params.clearValues[3].depthStencil.stencil);
4158	}
4159
4160	for (deUint32 passNdx = 0; passNdx < passCount; ++passNdx)
4161	{
4162		TestParams::PerPass& perPass = params.perPass[passNdx];
4163
4164		for (deUint32 regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
4165		{
4166			// Apply the draw call output to enabled attachments.  Note that the tests always do additive blending, and when depth test succeeds, stencil is incremented.
4167
4168			// First draw call overwrites depth and always succeeds.
4169			// Second draw call overwrites only the samples that pass the depth test (which is GREATER).
4170			const bool	evenSamplesPassDepthTest	= perPass.hasDepthStencil &&
4171				(!isDepthFormat(params.depthStencilFormat) || perPass.drawConstantsWithDepthTest[regionNdx].depthData[0] > perPass.drawConstantsWithDepthWrite[regionNdx].depthData[0]);
4172			const bool	oddSamplesPassDepthTest		= perPass.hasDepthStencil &&
4173				(!isDepthFormat(params.depthStencilFormat) || perPass.drawConstantsWithDepthTest[regionNdx].depthData[1] > perPass.drawConstantsWithDepthWrite[regionNdx].depthData[1]);
4174
4175			if (perPass.floatColor1Location >= 0)
4176			{
4177				params.verifyConstants[regionNdx].color1Data[0] += perPass.drawConstantsWithDepthWrite[regionNdx].color1Data[0];
4178				params.verifyConstants[regionNdx].color1Data[1] += perPass.drawConstantsWithDepthWrite[regionNdx].color1Data[1];
4179				if (evenSamplesPassDepthTest)
4180					params.verifyConstants[regionNdx].color1Data[0] += perPass.drawConstantsWithDepthTest[regionNdx].color1Data[0];
4181				if (oddSamplesPassDepthTest)
4182					params.verifyConstants[regionNdx].color1Data[1] += perPass.drawConstantsWithDepthTest[regionNdx].color1Data[1];
4183			}
4184			if (perPass.floatColor2Location >= 0)
4185			{
4186				params.verifyConstants[regionNdx].color2Data[0] += perPass.drawConstantsWithDepthWrite[regionNdx].color2Data[0];
4187				params.verifyConstants[regionNdx].color2Data[1] += perPass.drawConstantsWithDepthWrite[regionNdx].color2Data[1];
4188				if (evenSamplesPassDepthTest)
4189					params.verifyConstants[regionNdx].color2Data[0] += perPass.drawConstantsWithDepthTest[regionNdx].color2Data[0];
4190				if (oddSamplesPassDepthTest)
4191					params.verifyConstants[regionNdx].color2Data[1] += perPass.drawConstantsWithDepthTest[regionNdx].color2Data[1];
4192			}
4193			if (perPass.intColorLocation >= 0)
4194			{
4195				// Note that integer formats don't blend, so always take the last value that's written.  Each pass writes to only one channel, and color mask is used
4196				// to emulate the effect of blending.
4197				if (evenSamplesPassDepthTest)
4198					params.verifyConstants[regionNdx].color3Data[0] += perPass.drawConstantsWithDepthTest[regionNdx].color3Data[0];
4199				else
4200					params.verifyConstants[regionNdx].color3Data[0] += perPass.drawConstantsWithDepthWrite[regionNdx].color3Data[0];
4201
4202				if (oddSamplesPassDepthTest)
4203					params.verifyConstants[regionNdx].color3Data[1] += perPass.drawConstantsWithDepthTest[regionNdx].color3Data[1];
4204				else
4205					params.verifyConstants[regionNdx].color3Data[1] += perPass.drawConstantsWithDepthWrite[regionNdx].color3Data[1];
4206			}
4207			if (perPass.hasDepthStencil)
4208			{
4209				depthResult[regionNdx] = perPass.drawConstantsWithDepthWrite[regionNdx].depthData;
4210				stencilResult[regionNdx] += UVec2(1);
4211
4212				if (evenSamplesPassDepthTest)
4213					++stencilResult[regionNdx][0];
4214				if (oddSamplesPassDepthTest)
4215					++stencilResult[regionNdx][1];
4216			}
4217
4218			// There is no need to resolve color attachments between passes.  For float formats, the additive nature of blend and resolve means we can continue adding to
4219			// the two color vectors and get the same result in the end, no matter when and how often resolve happens.  For the integer formats this is not true (because resolve
4220			// does not average), so the test makes sure every channel is written to in only one pass, which again means there's no need to perform a resolve in between passes.
4221			// Depth/stencil needs to resolve though, either if multisampled and requested or if it's single sampled.
4222			if (perPass.resolveDepthStencil || params.numDepthStencilSamples == VK_SAMPLE_COUNT_1_BIT)
4223			{
4224				DE_ASSERT(perPass.depthStencilResolveMode == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT || perPass.depthStencilResolveMode == VK_RESOLVE_MODE_MAX_BIT);
4225				if (perPass.depthStencilResolveMode == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT)
4226				{
4227					params.verifyConstants[regionNdx].depthData = depthResult[regionNdx][0];
4228					params.verifyConstants[regionNdx].stencilData = stencilResult[regionNdx][0];
4229				}
4230				else
4231				{
4232					params.verifyConstants[regionNdx].depthData = std::max(depthResult[regionNdx][0], depthResult[regionNdx][1]);
4233					params.verifyConstants[regionNdx].stencilData = std::max(stencilResult[regionNdx][0], stencilResult[regionNdx][1]);
4234				}
4235
4236				// If depth/stencil is single-sampled, prepare the data for the next pass.  If multisampled, it will no longer be used after the resolve.
4237				depthResult[regionNdx][0]	= depthResult[regionNdx][1]		= params.verifyConstants[regionNdx].depthData;
4238				stencilResult[regionNdx][0]	= stencilResult[regionNdx][1]	= params.verifyConstants[regionNdx].stencilData;
4239			}
4240		}
4241	}
4242
4243	params.rngSeed = rng.getUint32();
4244
4245	// Note: formats are decided outside this function
4246}
4247
4248void initMultipassPrograms (SourceCollections& programCollection, const TestParams params)
4249{
4250	// Vertex shader - position
4251	{
4252		std::ostringstream src;
4253		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4254			<< "\n"
4255			<< "layout(location = 0) in  vec4 in_position;\n"
4256			<< "\n"
4257			<< "out gl_PerVertex {\n"
4258			<< "    vec4 gl_Position;\n"
4259			<< "};\n"
4260			<< "\n"
4261			<< "void main(void)\n"
4262			<< "{\n"
4263			<< "    gl_Position = in_position;\n"
4264			<< "}\n";
4265
4266		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
4267	}
4268
4269	const bool		usesSignedIntFormat	= params.intColorFormat == VK_FORMAT_R16G16B16A16_SINT;
4270	const char*     intTypePrefix		= usesSignedIntFormat ? "i" : "u";
4271
4272	// Fragment shader - output color based on sample index and push constants
4273	for (size_t passNdx = 0; passNdx < params.perPass.size(); ++passNdx)
4274	{
4275		const TestParams::PerPass &perPass = params.perPass[passNdx];
4276
4277		// The framebuffer contains four attachments with a mixture of samples.  A subpass can only contain a mixture of 1x and Nx samples with the pipelines configured at Nx multisampled rendering.
4278		// The fragment shader is adjusted based on which of these attachments are used in the subpass.  The output of the fragment shader is determined by push constants
4279		// as such (2 colors specified per output in uniform data):
4280		//
4281		// - For even samples, output color is interpolation of color 0 and transparent black from left to right
4282		// - For odd samples, output color is interpolation of color 1 and transparent black from top to bottom
4283		//
4284		// Additionally, the fragment shader outputs depth based on the sample index as well.
4285		//
4286		std::ostringstream src;
4287		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4288			<< "\n";
4289
4290		if (perPass.floatColor1Location >= 0)
4291			src << "layout(location = " << perPass.floatColor1Location << ") out vec4 o_color1;\n";
4292		if (perPass.floatColor2Location >= 0)
4293			src << "layout(location = " << perPass.floatColor2Location << ") out vec4 o_color2;\n";
4294		if (perPass.intColorLocation >= 0)
4295			src << "layout(location = " << perPass.intColorLocation << ") out " << intTypePrefix << "vec4 o_color3;\n";
4296
4297		src << "\n"
4298			<< "layout(push_constant) uniform PushConstants {\n"
4299			<< "    uvec4 area;\n"
4300			<< "    vec4 color1Data[2];\n"
4301			<< "    vec4 color2Data[2];\n"
4302			<< "    ivec4 color3Data[2];\n"
4303			<< "    vec2 depthData;\n"
4304			<< "} params;\n"
4305			<< "\n"
4306			<< "void main(void)\n"
4307			<< "{\n"
4308			<< "    vec2 uv = (gl_FragCoord.xy - vec2(params.area.xy)) / vec2(params.area.zw);\n"
4309			<< "    if (gl_SampleID % 2 == 0)\n"
4310			<< "    {\n";
4311
4312		if (perPass.floatColor1Location >= 0)
4313			src << "        o_color1 = params.color1Data[0] * uv.x;\n";
4314		if (perPass.floatColor2Location >= 0)
4315			src << "        o_color2 = params.color2Data[0] * uv.x;\n";
4316		if (perPass.intColorLocation >= 0)
4317			src << "        o_color3 = " << intTypePrefix << "vec4(vec4(params.color3Data[0]) * uv.x);\n";
4318		if (perPass.hasDepthStencil)
4319			src << "        gl_FragDepth = params.depthData.x;\n";
4320
4321		src << "    }\n"
4322			<< "    else\n"
4323			<< "    {\n";
4324
4325		if (perPass.floatColor1Location >= 0)
4326			src << "        o_color1 = params.color1Data[1] * uv.y;\n";
4327		if (perPass.floatColor2Location >= 0)
4328			src << "        o_color2 = params.color2Data[1] * uv.y;\n";
4329		if (perPass.intColorLocation >= 0)
4330			src << "        o_color3 = " << intTypePrefix << "vec4(vec4(params.color3Data[1]) * uv.y);\n";
4331		if (perPass.hasDepthStencil)
4332			src << "        gl_FragDepth = params.depthData.y;\n";
4333
4334		src << "    }\n"
4335			<< "}\n";
4336
4337		std::ostringstream name;
4338		name << "frag_" << passNdx;
4339
4340		programCollection.glslSources.add(name.str()) << glu::FragmentSource(src.str());
4341	}
4342
4343	// Compute shader - verify the results of rendering
4344	{
4345		// The images are cleared and rendered to, possibly multiple times with blend, by blending between one color and black horizontally and another color and black vertically for every other sample.
4346		// Once resolved, the resulting image is verified by interpolating one color and black horizontally, another color and black vertically, averaging them and adding in the clear color.  For integer
4347		// formats, instead of averaging the two interpolated colors, either of the colors is accepted as integer resolves selects any sample.  A comparison threshold is used to avoid precision issues.
4348		// Each pixel that passes the test atomically increments an integer in the output buffer.  The test passes if the final number in the output buffer is the same as the number of pixels in the area being verified.
4349
4350		std::ostringstream src;
4351		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4352			<< "#extension GL_EXT_samplerless_texture_functions : require\n"
4353			<< "\n"
4354			<< "layout(push_constant) uniform PushConstants {\n"
4355			<< "    uvec4 area;\n"
4356			<< "    vec4 color1Data[2];\n"
4357			<< "    vec4 color2Data[2];\n"
4358			<< "    ivec4 color3Data[2];\n"
4359			<< "    float depthData;\n"
4360			<< "    uint stencilData;\n"
4361			<< "} params;\n"
4362			<< "\n"
4363			<< "layout(local_size_x = 8, local_size_y = 8) in;\n"
4364			<< "layout(set = 0, binding = 0, std430) writeonly buffer Output {\n"
4365			<< "    uint colorVerification[3];\n"
4366			<< "    uint depthVerification;\n"
4367			<< "    uint stencilVerification;\n"
4368			<< "} sb_out;\n"
4369			<< "layout(set = 0, binding = 1) uniform texture2D color1Image;\n"
4370			<< "layout(set = 0, binding = 2) uniform texture2D color2Image;\n"
4371			<< "layout(set = 0, binding = 3) uniform " << (usesSignedIntFormat ? "i" : "u") << "texture2D color3Image;\n";
4372		if (isDepthFormat(params.depthStencilFormat))
4373			src << "layout(set = 0, binding = 4) uniform texture2D depthImage;\n";
4374		if (isStencilFormat(params.depthStencilFormat))
4375			src << "layout(set = 0, binding = 5) uniform utexture2D stencilImage;\n";
4376		src << "layout(set = 0, binding = 6, rgba8) uniform writeonly image2DArray verify;\n"
4377			<< "\n"
4378			<< "bool fmatches(float a, float b, float error)\n"
4379			<< "{\n"
4380			<< "    return abs(a - b) < error;\n"
4381			<< "}\n"
4382			<< "bool umatches(uint a, uint b, uint error)\n"
4383			<< "{\n"
4384			<< "    return abs(a - b) <= error;\n"
4385			<< "}\n"
4386			<< "bool v4matches(vec4 a, vec4 b, vec4 error)\n"
4387			<< "{\n"
4388			<< "    return all(lessThan(abs(a - b), error));\n"
4389			<< "}\n"
4390			<< "bool i4matchesEither(ivec4 a, ivec4 b, ivec4 c, ivec4 errorB, ivec4 errorC)\n"
4391			<< "{\n"
4392			<< "    const bvec4 bMatches = lessThanEqual(abs(a - b), errorB);\n"
4393			<< "    const bvec4 cMatches = lessThanEqual(abs(a - c), errorC);\n"
4394			<< "    return all(bvec4(bMatches.x || cMatches.x, bMatches.y || cMatches.y, bMatches.z || cMatches.z, bMatches.w || cMatches.w));\n"
4395			<< "}\n"
4396			<< "\n"
4397			<< "void main (void)\n"
4398			<< "{\n"
4399			<< "    if (any(greaterThanEqual(gl_GlobalInvocationID.xy, params.area.zw)))\n"
4400			<< "        return;\n"
4401			<< "\n"
4402			<< "    uvec2 coords = params.area.xy + gl_GlobalInvocationID.xy;\n"
4403			<< "    vec2 uv = (vec2(gl_GlobalInvocationID.xy) + vec2(0.5)) / vec2(params.area.zw);\n"
4404			<< "\n"
4405			<< "    vec4 result1 = vec4(1, 0, 0, 1);\n"
4406			<< "    vec4 color1 = texelFetch(color1Image, ivec2(coords), 0);\n"
4407			<< "    vec4 expected1 = (params.color1Data[0] * uv.x + params.color1Data[1] * uv.y) / 2.0";
4408		if (params.testBlendsColors)
4409			src << " + vec4(" << params.clearValues[0].color.float32[0] << ", "
4410							  << params.clearValues[0].color.float32[1] << ", "
4411							  << params.clearValues[0].color.float32[2] << ", "
4412							  << params.clearValues[0].color.float32[3] << ")";
4413		src << ";\n"
4414			// Allow room for precision errors.  Rendering happens at sample locations while verification uv is in the middle of pixel.
4415			<< "    if (v4matches(color1, expected1, max(params.color1Data[0] / float(params.area.z), params.color1Data[1] / float(params.area.w)) + 2.0/255.0))\n"
4416			<< "    {\n"
4417			<< "        atomicAdd(sb_out.colorVerification[0], 1);\n"
4418			<< "        result1 = vec4(0, 1, 0, 1);\n"
4419			<< "    }\n"
4420			<< "    imageStore(verify, ivec3(coords, 0), result1);\n"
4421			<< "\n"
4422			<< "    vec4 result2 = vec4(1, 0, 0, 1);\n"
4423			<< "    vec4 color2 = texelFetch(color2Image, ivec2(coords), 0);\n"
4424			<< "    vec4 expected2 = (params.color2Data[0] * uv.x + params.color2Data[1] * uv.y) / 2.0";
4425		if (params.testBlendsColors)
4426			src << " + vec4(" << params.clearValues[1].color.float32[0] << ", "
4427							  << params.clearValues[1].color.float32[1] << ", "
4428							  << params.clearValues[1].color.float32[2] << ", "
4429							  << params.clearValues[1].color.float32[3] << ")";
4430		src << ";\n"
4431			// Allow room for precision errors.  Rendering happens at sample locations while verification uv is in the middle of pixel.
4432			<< "    if (v4matches(color2, expected2, max(params.color2Data[0] / float(params.area.z), params.color2Data[1] / float(params.area.w)) + 2.0/1024.0))\n"
4433			<< "    {\n"
4434			<< "        atomicAdd(sb_out.colorVerification[1], 1);\n"
4435			<< "        result2 = vec4(0, 1, 0, 1);\n"
4436			<< "    }\n"
4437			<< "    imageStore(verify, ivec3(coords, 1), result2);\n"
4438			<< "\n"
4439			<< "    vec4 result3 = vec4(1, 0, 0, 1);\n"
4440			<< "    ivec4 color3 = ivec4(texelFetch(color3Image, ivec2(coords), 0));\n";
4441			// Note that integer formats don't blend, so clear values are discarded, except for channels that are never written to.  Each pass
4442			// outputs only to one channel.
4443		if (params.testBlendsColors)
4444			src << "    ivec4 clearValue3 = ivec4(" << (params.perPass[0].intColorLocation < 0 ? params.clearValues[2].color.int32[0] : 0) << ", "
4445													<< (params.perPass.size() < 2 || params.perPass[1].intColorLocation < 0 ? params.clearValues[2].color.int32[1] : 0) << ", "
4446													<< (params.perPass.size() < 3 || params.perPass[2].intColorLocation < 0 ? params.clearValues[2].color.int32[2] : 0) << ", "
4447													<< (params.perPass.size() < 4 || params.perPass[3].intColorLocation < 0 ? params.clearValues[2].color.int32[3] : 0) << ")" << ";\n";
4448		else
4449			src << "    ivec4 clearValue3 = ivec4(0);\n";
4450		src << "    ivec4 expected3_0 = ivec4(params.color3Data[0] * uv.x) + clearValue3;\n"
4451			<< "    ivec4 expected3_1 = ivec4(params.color3Data[1] * uv.y) + clearValue3;\n"
4452			// Allow room for precision errors.  Rendering happens at sample locations while verification uv is in the middle of pixel.
4453			<< "    if (i4matchesEither(color3, expected3_0, expected3_1, params.color3Data[0] / int(params.area.z), params.color3Data[1] / int(params.area.w)))\n"
4454			<< "    {\n"
4455			<< "        atomicAdd(sb_out.colorVerification[2], 1);\n"
4456			<< "        result3 = vec4(0, 1, 0, 1);\n"
4457			<< "    }\n"
4458			<< "    imageStore(verify, ivec3(coords, 2), result3);\n"
4459			<< "\n";
4460		if (isDepthFormat(params.depthStencilFormat))
4461			src << "    vec4 resultDepth = vec4(1, 0, 0, 1);\n"
4462				<< "    float depth  = texelFetch(depthImage, ivec2(coords), 0).r;\n"
4463				<< "    if (fmatches(depth, params.depthData, 0.01))\n"
4464				<< "    {\n"
4465				<< "        atomicAdd(sb_out.depthVerification, 1);\n"
4466				<< "        resultDepth = vec4(0, 1, 0, 1);\n"
4467				<< "    }\n"
4468				<< "    imageStore(verify, ivec3(coords, 3), resultDepth);\n";
4469		if (isStencilFormat(params.depthStencilFormat))
4470			src << "    vec4 resultStencil = vec4(1, 0, 0, 1);\n"
4471				<< "    uint stencil = texelFetch(stencilImage, ivec2(coords), 0).r;\n"
4472				<< "    if (umatches(stencil, params.stencilData, 0))\n"
4473				<< "    {\n"
4474				<< "        atomicAdd(sb_out.stencilVerification, 1);\n"
4475				<< "        resultStencil = vec4(0, 1, 0, 1);\n"
4476				<< "    }\n"
4477				<< "    imageStore(verify, ivec3(coords, 4), resultStencil);\n";
4478		src << "}\n";
4479
4480		programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
4481	}
4482
4483	const bool	verifyOutsideRenderArea	= params.clearBeforeRenderPass && !params.renderToWholeFramebuffer;
4484	if (verifyOutsideRenderArea)
4485		initConstantColorVerifyPrograms(programCollection, params);
4486}
4487
4488void drawInputAttachments (Context& context, const TestParams& params, WorkingData& wd, TestObjects& testObjects)
4489{
4490	const InstanceInterface&	vki				= context.getInstanceInterface();
4491	const DeviceInterface&		vk				= context.getDeviceInterface();
4492	const VkPhysicalDevice		physicalDevice	= context.getPhysicalDevice();
4493	const VkDevice				device			= context.getDevice();
4494	const deUint32				numSubpasses	= static_cast<deUint32>(params.perPass.size());
4495
4496	if (params.clearBeforeRenderPass)
4497	{
4498		clearImagesBeforeDraw(context, params, wd, testObjects);
4499	}
4500
4501	// Create a render pass and a framebuffer
4502	{
4503		std::vector<VkSubpassDescription2>							subpasses;
4504		std::vector<VkImage>										images;
4505		std::vector<VkImageView>									attachments;
4506		std::vector<VkAttachmentDescription2>						attachmentDescriptions;
4507		std::vector<std::vector<VkAttachmentReference2>>			attachmentReferences(numSubpasses);
4508		std::vector<std::vector<VkAttachmentReference2>>			resolveAttachmentReferences(numSubpasses);
4509		std::vector<std::vector<deUint32>>							preserveAttachments(numSubpasses);
4510		std::vector<VkAttachmentReference2>							inputAttachmentReferences;
4511		std::vector<VkSubpassDependency2>							subpassDependencies;
4512		std::vector<VkMultisampledRenderToSingleSampledInfoEXT>		msrtss(numSubpasses);
4513		std::vector<VkSubpassDescriptionDepthStencilResolve>		depthStencilResolve(numSubpasses);
4514		deInt32														attachmentNdxes[8]	= {-1, -1, -1, -1,
4515																						   -1, -1, -1, -1};
4516		deUint32													attachmentUseMask	= 0;
4517
4518		initializeAttachments(params, wd, images, attachments, params.perPass.size(), attachmentNdxes);
4519		initializeAttachmentDescriptions(params, attachmentDescriptions, params.clearBeforeRenderPass, attachmentNdxes, attachmentUseMask);
4520
4521		DE_ASSERT(numSubpasses == 2);
4522		inputAttachmentReferences.resize(2, VkAttachmentReference2{
4523				VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,		// VkStructureType       sType;
4524				DE_NULL,										// const void*           pNext;
4525				VK_ATTACHMENT_UNUSED,							// uint32_t              attachment;
4526				VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout         layout;
4527				0,												// VkImageAspectFlags    aspectMask;
4528			});
4529		// Color attachment 1 and depth/stencil attachment are used as input attachments in subpass 1.
4530		initializeAttachmentReference(inputAttachmentReferences[0], attachmentNdxes[0], VK_FORMAT_UNDEFINED, true);
4531		initializeAttachmentReference(inputAttachmentReferences[1], attachmentNdxes[3], params.depthStencilFormat, true);
4532
4533		for (deUint32 passNdx = 0; passNdx < numSubpasses; ++passNdx)
4534		{
4535			const std::vector<VkAttachmentReference2> noInputAttachments;
4536
4537			addSubpassDescription(params,
4538								  passNdx,
4539								  attachmentReferences[passNdx],
4540								  resolveAttachmentReferences[passNdx],
4541								  depthStencilResolve[passNdx],
4542								  &preserveAttachments[passNdx],
4543								  msrtss[passNdx],
4544								  subpasses,
4545								  passNdx == 0 ? noInputAttachments : inputAttachmentReferences,
4546								  attachmentNdxes);
4547		}
4548
4549		subpassDependencies.push_back(VkSubpassDependency2{
4550			VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,					// VkStructureType         sType;
4551			DE_NULL,												// const void*             pNext;
4552			0,														// uint32_t                srcSubpass;
4553			1,														// uint32_t                dstSubpass;
4554
4555			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
4556			VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,				// VkPipelineStageFlags    srcStageMask;
4557
4558			VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,					// VkPipelineStageFlags    dstStageMask;
4559
4560			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
4561			VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,			// VkAccessFlags           srcAccessMask;
4562
4563			VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,					// VkAccessFlags           dstAccessMask;
4564
4565			VK_DEPENDENCY_BY_REGION_BIT,							// VkDependencyFlags       dependencyFlags;
4566			0,														// int32_t                 viewOffset;
4567		});
4568
4569		createRenderPassAndFramebuffer(context, wd, testObjects, params.pipelineConstructionType, images, attachments, attachmentDescriptions, subpasses, subpassDependencies);
4570	}
4571
4572	const VkPushConstantRange& pushConstantRange =
4573	{
4574		VK_SHADER_STAGE_FRAGMENT_BIT,											// VkShaderStageFlags    stageFlags;
4575		0,																		// uint32_t              offset;
4576		static_cast<deUint32>(sizeof(UVec4) + sizeof(DrawPushConstants)),		// uint32_t              size;
4577	};
4578
4579	const ShaderWrapper	vertexModule					(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
4580	const ShaderWrapper	fragmentModule0					(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag_0"), 0u));
4581	const ShaderWrapper	fragmentModule1					(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag_1"), 0u));
4582	const PipelineLayoutWrapper pipelineLayout			(params.pipelineConstructionType, vk, device, 0, DE_NULL, 1, &pushConstantRange);
4583
4584	// Descriptor set and layout for the draw call that uses input attachments
4585	const Unique<VkDescriptorSetLayout> descriptorSetLayout(
4586		DescriptorSetLayoutBuilder()
4587		.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,		VK_SHADER_STAGE_FRAGMENT_BIT)
4588		.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,		VK_SHADER_STAGE_FRAGMENT_BIT)
4589		.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,		VK_SHADER_STAGE_FRAGMENT_BIT)
4590		.build(vk, device));
4591
4592	testObjects.descriptorPools.emplace_back(
4593		DescriptorPoolBuilder()
4594		.addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u)
4595		.addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u)
4596		.addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u)
4597		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
4598
4599	testObjects.descriptorSets.emplace_back(makeDescriptorSet(vk, device, *testObjects.descriptorPools.back(), *descriptorSetLayout));
4600
4601	const VkDescriptorImageInfo		color1Info			= makeDescriptorImageInfo(DE_NULL, *wd.floatColor1.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
4602	const VkDescriptorImageInfo		depthInfo			= makeDescriptorImageInfo(DE_NULL, isDepthFormat(params.depthStencilFormat) ? *wd.depthOnlyImageView : *wd.stencilOnlyImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
4603	const VkDescriptorImageInfo		stencilInfo			= makeDescriptorImageInfo(DE_NULL, isStencilFormat(params.depthStencilFormat) ? *wd.stencilOnlyImageView : *wd.depthOnlyImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
4604
4605	DescriptorSetUpdateBuilder	builder;
4606
4607	builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &color1Info);
4608	builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &depthInfo);
4609	builder.writeSingle(*testObjects.descriptorSets.back(), DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &stencilInfo);
4610
4611	builder.update(vk, device);
4612
4613	const VkPushConstantRange& inputPushConstantRange =
4614	{
4615		VK_SHADER_STAGE_FRAGMENT_BIT,											// VkShaderStageFlags    stageFlags;
4616		0,																		// uint32_t              offset;
4617		static_cast<deUint32>(sizeof(UVec4)),									// uint32_t              size;
4618	};
4619
4620	const ShaderWrapper				fragmentModuleIn	(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag_in"), 0u));
4621	const PipelineLayoutWrapper		inputPipelineLayout	(params.pipelineConstructionType, vk, device, 1, &*descriptorSetLayout, 1, &inputPushConstantRange);
4622
4623	UVec4	regions[RegionCount];
4624	getDrawRegions(wd, regions);
4625
4626	startRenderPass(context, wd, testObjects, DE_LENGTH_OF_ARRAY(params.clearValues), params.clearValues);
4627
4628	{
4629		DE_ASSERT(numSubpasses == 2);
4630
4631		const VkDeviceSize vertexBufferOffset = 0;
4632		vk.cmdBindVertexBuffers(*testObjects.cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset);
4633
4634		// First draw call outputs to color attachment 1 and depth/stencil.  It doesn't blend with clear for simplicity of the verification code.
4635		for (deUint32 regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
4636		{
4637			testObjects.graphicsPipelines.push_back(
4638				pipeline::makeGraphicsPipeline(vki, vk, physicalDevice, device, context.getDeviceExtensions(), params.pipelineConstructionType, pipelineLayout, *testObjects.renderPassFramebuffers.back(), DE_NULL, vertexModule, fragmentModule0, false, true, false, 0, 0,
4639									 params.perPass[0].intColorLocation, regions[regionNdx], regions[regionNdx], params.perPass[0].numSamples, params.useGarbageAttachment));
4640
4641			vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(UVec4), &regions[regionNdx]);
4642			vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(UVec4), sizeof(params.perPass[0].drawConstantsWithDepthWrite[regionNdx]), &params.perPass[0].drawConstantsWithDepthWrite[regionNdx]);
4643			(*testObjects.graphicsPipelines.back()).bind(*testObjects.cmdBuffer);
4644			vk.cmdDraw(*testObjects.cmdBuffer, 3, 1u, 0u, 0u);
4645		}
4646
4647		// Next subpass initializes color attachments 2 and 3 from color attachment 1 and depth/stencil, then issues a draw call that modifies those attachments.
4648		testObjects.renderPassFramebuffers.back().nextSubpass(vk, *testObjects.cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
4649
4650		for (deUint32 regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
4651		{
4652			testObjects.graphicsPipelines.push_back(
4653				pipeline::makeGraphicsPipeline(vki, vk, physicalDevice, device, context.getDeviceExtensions(), params.pipelineConstructionType, inputPipelineLayout, *testObjects.renderPassFramebuffers.back(), DE_NULL, vertexModule, fragmentModuleIn, false, false, false, 0, 1,
4654									 params.perPass[1].intColorLocation, regions[regionNdx], regions[regionNdx], params.perPass[1].numSamples, params.useGarbageAttachment));
4655
4656			vk.cmdPushConstants(*testObjects.cmdBuffer, *inputPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(UVec4), &regions[regionNdx]);
4657			(*testObjects.graphicsPipelines.back()).bind(*testObjects.cmdBuffer);
4658			vk.cmdBindDescriptorSets(*testObjects.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *inputPipelineLayout, 0u, 1u, &testObjects.descriptorSets.back().get(), 0u, DE_NULL);
4659			vk.cmdDraw(*testObjects.cmdBuffer, 3, 1u, 0u, 0u);
4660		}
4661
4662		for (deUint32 regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
4663		{
4664			testObjects.graphicsPipelines.push_back(
4665				pipeline::makeGraphicsPipeline(vki, vk, physicalDevice, device, context.getDeviceExtensions(), params.pipelineConstructionType, pipelineLayout, *testObjects.renderPassFramebuffers.back(), DE_NULL, vertexModule, fragmentModule1, true, false, false, 0xC, 1,
4666									 params.perPass[1].intColorLocation, regions[regionNdx], regions[regionNdx], params.perPass[1].numSamples, params.useGarbageAttachment));
4667
4668			vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(UVec4), &regions[regionNdx]);
4669			vk.cmdPushConstants(*testObjects.cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(UVec4), sizeof(params.perPass[1].drawConstantsWithDepthWrite[regionNdx]), &params.perPass[1].drawConstantsWithDepthWrite[regionNdx]);
4670			(*testObjects.graphicsPipelines.back()).bind(*testObjects.cmdBuffer);
4671			vk.cmdDraw(*testObjects.cmdBuffer, 3, 1u, 0u, 0u);
4672		}
4673	}
4674
4675	testObjects.renderPassFramebuffers.back().end(vk, *testObjects.cmdBuffer);
4676
4677	// Verify results
4678	dispatchVerifyMultiPassRendering(context, params, wd, testObjects, regions);
4679}
4680
4681//! Verify input attachments and multisampled rendering interact correctly.
4682tcu::TestStatus testInputAttachments (Context& context, const TestParams params)
4683{
4684	WorkingData wd;
4685	TestObjects testObjects(context);
4686	testStart(context, params, wd, testObjects);
4687
4688	drawInputAttachments (context, params, wd, testObjects);
4689
4690	testEnd(context, params, wd, testObjects);
4691	return verify(context, params, wd);
4692}
4693
4694void generateInputAttachmentsTest (de::Random& rng, TestParams& params, const VkSampleCountFlagBits sampleCount, const VkResolveModeFlagBits resolveMode, const bool renderToWholeFramebuffer)
4695{
4696	params.perPass.resize(2);
4697
4698	// Set the sample count for attachments.
4699	if (params.isMultisampledRenderToSingleSampled)
4700	{
4701		params.numFloatColor1Samples				= VK_SAMPLE_COUNT_1_BIT;
4702		params.numFloatColor2Samples				= VK_SAMPLE_COUNT_1_BIT;
4703		params.numIntColorSamples					= VK_SAMPLE_COUNT_1_BIT;
4704		params.numDepthStencilSamples				= VK_SAMPLE_COUNT_1_BIT;
4705
4706		params.perPass[0].resolveFloatColor1		= false;
4707		params.perPass[0].resolveDepthStencil		= false;
4708
4709		params.perPass[1].resolveFloatColor2		= false;
4710		params.perPass[1].resolveIntColor			= false;
4711	}
4712	else
4713	{
4714		params.numFloatColor1Samples				= sampleCount;
4715		params.numFloatColor2Samples				= sampleCount;
4716		params.numIntColorSamples					= sampleCount;
4717		params.numDepthStencilSamples				= sampleCount;
4718
4719		params.perPass[0].resolveFloatColor1		= true;
4720		params.perPass[0].resolveDepthStencil		= true;
4721
4722		params.perPass[1].resolveFloatColor2		= true;
4723		params.perPass[1].resolveIntColor			= true;
4724	}
4725
4726	// Subpass 0 renders to color1 and depth/stencil only.  They are resolved at the end of the pass.
4727	params.perPass[0].resolveFloatColor2		= false;
4728	params.perPass[0].resolveIntColor			= false;
4729	params.perPass[0].depthStencilResolveMode	= resolveMode;
4730
4731	params.perPass[0].numSamples				= sampleCount;
4732
4733	params.perPass[0].floatColor1Location = 0;
4734	params.perPass[0].floatColor2Location = -1;
4735	params.perPass[0].intColorLocation = -1;
4736	params.perPass[0].hasDepthStencil = true;
4737
4738	// Subpass 1 uses color1 and depth/stencil as input attachments and outputs to color2 and color3.
4739	params.perPass[1].resolveFloatColor1		= false;
4740	params.perPass[1].resolveDepthStencil		= false;
4741
4742	params.perPass[1].numSamples				= params.isMultisampledRenderToSingleSampled ? VK_SAMPLE_COUNT_1_BIT : sampleCount;
4743
4744	params.perPass[1].floatColor1Location = -1;
4745	params.perPass[1].floatColor2Location = 3;
4746	params.perPass[1].intColorLocation = 2;
4747	params.perPass[1].hasDepthStencil = false;
4748
4749	// Always clear before render pass so outside render area can be verified.
4750	params.clearBeforeRenderPass	= true;
4751	params.renderToWholeFramebuffer	= renderToWholeFramebuffer;
4752	params.testBlendsColors			= false;
4753
4754	// Set random clear values.
4755	generateRandomClearValues(rng, params, params.clearValues, true);
4756
4757	// Decide DrawPushConstants
4758	for (deUint32 regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
4759	{
4760		// Subpass 0 writes to color 1, depth and stencil.
4761		params.perPass[0].drawConstantsWithDepthWrite[regionNdx]	= DrawPushConstants{
4762			{Vec4(rng.getFloat(0.2f, 0.4f), 0, rng.getFloat(0.2f, 0.4f), 0), Vec4(0, rng.getFloat(0.2f, 0.4f), 0, rng.getFloat(0.2f, 0.4f))},
4763			{Vec4(0, 0, 0, 0), Vec4(0, 0, 0, 0)},
4764			{IVec4(0, 0, 0, 0), IVec4(0, 0, 0, 0)},
4765			// Use quantized values to avoid values that are too close and may cause precision issues
4766			Vec2(0.025f * static_cast<float>(rng.getInt(2, 38)), 0.025f * static_cast<float>(rng.getInt(2, 38))),
4767		};
4768
4769		// Subpass 1 writes to color 2 and color 3.
4770		params.perPass[1].drawConstantsWithDepthWrite[regionNdx]	= DrawPushConstants{
4771			{Vec4(0, 0, 0, 0), Vec4(0, 0, 0, 0)},
4772			{Vec4(rng.getFloat(0.2f, 0.4f), rng.getFloat(0.2f, 0.4f), 0, 0), Vec4(0, 0, rng.getFloat(0.2f, 0.4f), rng.getFloat(0.2f, 0.4f))},
4773			{IVec4(0, 0, 0, 0), IVec4(0, 0, 0, 0)},
4774			// Use quantized values to avoid values that are too close and may cause precision issues
4775			Vec2(0, 0),
4776		};
4777
4778		// Integer resolve may choose any sample, so we modify only one channel.  This way, the verification
4779		// shader can accept two values per channel.
4780		params.perPass[0].drawConstantsWithDepthWrite[regionNdx].color3Data[0][0]	= rng.getInt(1000, 5000);
4781		params.perPass[0].drawConstantsWithDepthWrite[regionNdx].color3Data[1][1]	= rng.getInt(1000, 5000);
4782		params.perPass[1].drawConstantsWithDepthWrite[regionNdx].color3Data[0][2]	= rng.getInt(1000, 5000);
4783		params.perPass[1].drawConstantsWithDepthWrite[regionNdx].color3Data[1][3]	= rng.getInt(1000, 5000);
4784	}
4785
4786	// Calculate VerifyPushConstants.  Walk through the passes and emulate what the draw calls would produce.
4787	for (deUint32 regionNdx = 0; regionNdx < RegionCount; ++regionNdx)
4788	{
4789		// First, subpass[0]'s data is written to every sample of color1 and depth/stencil.
4790		params.verifyConstants[regionNdx].color1Data[0] = params.perPass[0].drawConstantsWithDepthWrite[regionNdx].color1Data[0];
4791		params.verifyConstants[regionNdx].color1Data[1] = params.perPass[0].drawConstantsWithDepthWrite[regionNdx].color1Data[1];
4792
4793		// Then depth/stencil is resolved
4794		DE_ASSERT(resolveMode == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT || resolveMode == VK_RESOLVE_MODE_MAX_BIT);
4795		if (resolveMode == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT)
4796		{
4797			params.verifyConstants[regionNdx].depthData	= params.perPass[0].drawConstantsWithDepthWrite[regionNdx].depthData[0];
4798		}
4799		else
4800		{
4801			params.verifyConstants[regionNdx].depthData	= std::max(params.perPass[0].drawConstantsWithDepthWrite[regionNdx].depthData[0], params.perPass[0].drawConstantsWithDepthWrite[regionNdx].depthData[1]);
4802		}
4803		params.verifyConstants[regionNdx].stencilData	= params.clearValues[3].depthStencil.stencil + 1;
4804
4805		// Then subpass 1 initializes color2 and color3 based on the previous subpass' color1 and depth/stencil values.
4806		params.verifyConstants[regionNdx].color2Data[0] = params.verifyConstants[regionNdx].color1Data[0];
4807		params.verifyConstants[regionNdx].color2Data[1] = params.verifyConstants[regionNdx].color1Data[1];
4808
4809		if (isDepthFormat(params.depthStencilFormat))
4810		{
4811			if (params.isMultisampledRenderToSingleSampled)
4812			{
4813				params.verifyConstants[regionNdx].color3Data[0][0]	= deInt32(10000 * params.verifyConstants[regionNdx].depthData);
4814				params.verifyConstants[regionNdx].color3Data[1][0]	= deInt32(10000 * params.verifyConstants[regionNdx].depthData);
4815			}
4816			else
4817			{
4818				params.verifyConstants[regionNdx].color3Data[0][0]	= deInt32(10000 * params.perPass[0].drawConstantsWithDepthWrite[regionNdx].depthData[0]);
4819				params.verifyConstants[regionNdx].color3Data[1][0]	= deInt32(10000 * params.perPass[0].drawConstantsWithDepthWrite[regionNdx].depthData[1]);
4820			}
4821		}
4822
4823		if (isStencilFormat(params.depthStencilFormat))
4824		{
4825			params.verifyConstants[regionNdx].color3Data[0][1]	= 100 * params.verifyConstants[regionNdx].stencilData;
4826			params.verifyConstants[regionNdx].color3Data[1][1]	= 100 * params.verifyConstants[regionNdx].stencilData;
4827		}
4828
4829		// Finally, a draw call in subpass 1 blends on top of those values.
4830		if (params.isMultisampledRenderToSingleSampled)
4831		{
4832			// If subpass 1 is single-sampled, there's only one sample to write to which is interpolated along X.  Additionally, there's no resolve.
4833			// The verification code expects the following:
4834			//
4835			//     color@uv = (color_even_samples*u + color_odd_samples*v) / 2
4836			//
4837			// In this case, we want color@uv to be color_even_samples*u.  We can have the verification shader arrive at this value
4838			// by providing color_even_samples twice what it should be and zero for color_odd_samples:
4839			//
4840			//     color@uv = (color_even_samples*2*u + 0*v) / 2 = color_even_samples*u
4841			params.verifyConstants[regionNdx].color2Data[0] += params.perPass[1].drawConstantsWithDepthWrite[regionNdx].color2Data[0] * Vec4(2, 2, 2, 2);
4842		}
4843		else
4844		{
4845			params.verifyConstants[regionNdx].color2Data[0] += params.perPass[1].drawConstantsWithDepthWrite[regionNdx].color2Data[0];
4846			params.verifyConstants[regionNdx].color2Data[1] += params.perPass[1].drawConstantsWithDepthWrite[regionNdx].color2Data[1];
4847		}
4848
4849		params.verifyConstants[regionNdx].color3Data[0] += params.perPass[1].drawConstantsWithDepthWrite[regionNdx].color3Data[0];
4850		params.verifyConstants[regionNdx].color3Data[1] += params.perPass[1].drawConstantsWithDepthWrite[regionNdx].color3Data[1];
4851	}
4852
4853	params.rngSeed = rng.getUint32();
4854}
4855
4856void initInputAttachmentsPrograms (SourceCollections& programCollection, const TestParams params)
4857{
4858	// This test reuses the same programs as the multipass tests for rendering and verification.
4859	initMultipassPrograms(programCollection, params);
4860
4861	const bool		usesSignedIntFormat	= params.intColorFormat == VK_FORMAT_R16G16B16A16_SINT;
4862	const char*     intTypePrefix		= usesSignedIntFormat ? "i" : "u";
4863	const char*		subpassInputSuffix	= params.perPass[1].numSamples == VK_SAMPLE_COUNT_1_BIT ? "" : "MS";
4864	const char*		subpassLoadParam	= params.perPass[1].numSamples == VK_SAMPLE_COUNT_1_BIT ? "" : ", gl_SampleID";
4865
4866	// Fragment shader - initialize color attachments 2 and 3 with data from color attachments 1 and depth/stencil
4867	{
4868		const TestParams::PerPass &perPass = params.perPass[1];
4869
4870		// Data from color attachment 1 is replicated in color attachment 2.  Data from the depth/stencil attachment is replicated in the red and green
4871		// channels of color attachment 3.  Depth is multiplied by 10000 and interpolated along x and stencil by 100 and interpolated along y.  This makes
4872		// the result look like the other draw calls that produce a gradient and simplifies the verification code.
4873		std::ostringstream src;
4874		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4875			<< "\n"
4876			<< "layout(location = " << perPass.floatColor2Location << ") out vec4 o_color2;\n"
4877			<< "layout(location = " << perPass.intColorLocation << ") out " << intTypePrefix << "vec4 o_color3;\n"
4878			<< "layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput" << subpassInputSuffix << " i_color1;\n";
4879		if (isDepthFormat(params.depthStencilFormat))
4880			src << "layout(input_attachment_index = 1, set = 0, binding = 1) uniform subpassInput" << subpassInputSuffix << " i_depth;\n";
4881		if (isStencilFormat(params.depthStencilFormat))
4882			src << "layout(input_attachment_index = 1, set = 0, binding = 2) uniform usubpassInput" << subpassInputSuffix << " i_stencil;\n";
4883		src << "\n"
4884			<< "layout(push_constant) uniform PushConstants {\n"
4885			<< "    uvec4 area;\n"
4886			<< "} params;\n"
4887			<< "\n"
4888			<< "void main(void)\n"
4889			<< "{\n"
4890			<< "    vec2 uv = (gl_FragCoord.xy - vec2(params.area.xy)) / vec2(params.area.zw);\n"
4891			<< "    o_color2 = subpassLoad(i_color1" << subpassLoadParam << ");\n"
4892			<< "    if (gl_SampleID % 2 != 0)\n"
4893			<< "        uv.xy = uv.yx;\n"
4894			<< "    uvec4 color3Value = uvec4(0);\n";
4895		if (isDepthFormat(params.depthStencilFormat))
4896			src << "    color3Value.x = uint(subpassLoad(i_depth" << subpassLoadParam << ").x * 10000 * uv.x);\n";
4897		if (isStencilFormat(params.depthStencilFormat))
4898			src << "    color3Value.y = uint(subpassLoad(i_stencil" << subpassLoadParam << ").x * 100 * uv.y);\n";
4899		src << "    o_color3 = " << intTypePrefix << "vec4(color3Value);\n"
4900			<< "}\n";
4901
4902		programCollection.glslSources.add("frag_in") << glu::FragmentSource(src.str());
4903	}
4904}
4905
4906//! Verify that subpass resolve perf query works.
4907tcu::TestStatus testPerfQuery (Context& context, VkFormat format)
4908{
4909	const InstanceInterface&			vki					= context.getInstanceInterface();
4910	const VkPhysicalDevice				physicalDevice		= context.getPhysicalDevice();
4911	VkFormatProperties2					formatProperties	= {};
4912	VkSubpassResolvePerformanceQueryEXT	perfQuery			= {};
4913
4914	perfQuery.sType = VK_STRUCTURE_TYPE_SUBPASS_RESOLVE_PERFORMANCE_QUERY_EXT;
4915	perfQuery.optimal = 0xDEADBEEF;
4916
4917	formatProperties.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
4918	formatProperties.pNext = &perfQuery;
4919
4920	vki.getPhysicalDeviceFormatProperties2(physicalDevice, format, &formatProperties);
4921
4922	// There is actually nothing to verify other than that the above query was successful.
4923	// Regardless of optimal resolve or not, the operations must succeed.  We'll just make sure
4924	// the driver did produce a valid response.
4925	if (perfQuery.optimal != VK_FALSE && perfQuery.optimal != VK_TRUE)
4926	{
4927		std::string errorMsg = "VkSubpassResolvePerformanceQueryEXT::optimal is not populated after query";
4928		return tcu::TestStatus::fail(errorMsg);
4929	}
4930
4931	return tcu::TestStatus::pass("Pass");
4932}
4933
4934std::string getFormatShortString (const VkFormat format)
4935{
4936	std::string s(de::toLower(getFormatName(format)));
4937	return s.substr(10);
4938}
4939
4940std::string getFormatCaseName (const VkFormat color1Format,
4941							   const VkFormat color2Format,
4942							   const VkFormat color3Format,
4943							   const VkFormat depthStencilFormat)
4944{
4945	std::ostringstream str;
4946	str << getFormatShortString(color1Format)
4947		<< "_" << getFormatShortString(color2Format)
4948		<< "_" << getFormatShortString(color3Format)
4949		<< "_" << getFormatShortString(depthStencilFormat);
4950	return str.str();
4951}
4952
4953std::string getSampleCountCaseName (const VkSampleCountFlagBits sampleCount)
4954{
4955	std::ostringstream str;
4956	str << sampleCount << "x";
4957	return str.str();
4958}
4959
4960std::string getResolveModeCaseName (const VkResolveModeFlagBits resolveMode)
4961{
4962	std::ostringstream str;
4963	if (resolveMode == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT)
4964		str << "ds_resolve_sample_zero";
4965	else if (resolveMode == VK_RESOLVE_MODE_MAX_BIT)
4966		str << "ds_resolve_max";
4967	else
4968		DE_ASSERT(false);
4969	return str.str();
4970}
4971
4972void createMultisampledTestsInGroup (tcu::TestCaseGroup*		rootGroup,
4973									 const bool					isMultisampledRenderToSingleSampled,
4974									 PipelineConstructionType	pipelineConstructionType,
4975									 const bool					dynamicRendering)
4976{
4977	// Color 1 is a float format
4978	const VkFormat	color1FormatRange[] =
4979	{
4980		VK_FORMAT_R8G8B8A8_UNORM,
4981	};
4982	constexpr deUint32	color1FormatCount = DE_LENGTH_OF_ARRAY(color1FormatRange);
4983
4984	// Color 2 is a float format
4985	const VkFormat	color2FormatRange[] =
4986	{
4987		VK_FORMAT_R16G16B16A16_SFLOAT,
4988	};
4989	constexpr deUint32	color2FormatCount = DE_LENGTH_OF_ARRAY(color2FormatRange);
4990
4991	// Color 3 is an integer format
4992	const VkFormat	color3FormatRange[] =
4993	{
4994		VK_FORMAT_R32G32B32A32_UINT,
4995		VK_FORMAT_R16G16B16A16_SINT,
4996	};
4997	constexpr deUint32	color3FormatCount = DE_LENGTH_OF_ARRAY(color3FormatRange);
4998
4999	// Test formats with only depth, only stencil or both
5000	const VkFormat	depthStencilFormatRange[] =
5001	{
5002		VK_FORMAT_D16_UNORM,				//!< Must be supported
5003		VK_FORMAT_S8_UINT,					//!< May not be supported
5004		VK_FORMAT_D24_UNORM_S8_UINT,		//!< Either this, or the next one must be supported
5005		VK_FORMAT_D32_SFLOAT_S8_UINT,
5006	};
5007	constexpr deUint32	depthStencilFormatCount = DE_LENGTH_OF_ARRAY(depthStencilFormatRange);
5008
5009	const VkSampleCountFlagBits	sampleRange[] =
5010	{
5011		VK_SAMPLE_COUNT_2_BIT,
5012		VK_SAMPLE_COUNT_4_BIT,
5013		VK_SAMPLE_COUNT_8_BIT,
5014		VK_SAMPLE_COUNT_16_BIT,
5015	};
5016
5017	const VkResolveModeFlagBits	depthStencilResolveModeRange[] =
5018	{
5019		VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,
5020		VK_RESOLVE_MODE_MAX_BIT,
5021	};
5022
5023	const bool boolRange[] = { false, true };
5024
5025	// Test 1: Simple tests that verify Nx multisampling actually uses N samples.
5026	{
5027		MovePtr<tcu::TestCaseGroup> group	(new tcu::TestCaseGroup(rootGroup->getTestContext(), "basic"));
5028
5029		de::Random	rng(0xDEADBEEF);
5030
5031		for (const VkFormat color1Format		: color1FormatRange)
5032		for (const VkFormat color2Format		: color2FormatRange)
5033		for (const VkFormat color3Format		: color3FormatRange)
5034		for (const VkFormat depthStencilFormat	: depthStencilFormatRange)
5035		{
5036			MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(
5037				rootGroup->getTestContext(), getFormatCaseName(color1Format, color2Format, color3Format, depthStencilFormat).c_str(), "Combination of framebuffer attachment formats"));
5038
5039			for (const VkSampleCountFlagBits sampleCount : sampleRange)
5040			{
5041				MovePtr<tcu::TestCaseGroup> sampleGroup(new tcu::TestCaseGroup(
5042					rootGroup->getTestContext(), getSampleCountCaseName(sampleCount).c_str(), "Sample count"));
5043
5044				for (const VkResolveModeFlagBits resolveMode : depthStencilResolveModeRange)
5045				{
5046					MovePtr<tcu::TestCaseGroup> resolveGroup(new tcu::TestCaseGroup(
5047						rootGroup->getTestContext(), getResolveModeCaseName(resolveMode).c_str(), "Depth/stencil resolve mode"));
5048
5049					for (const bool renderToWholeFramebuffer : boolRange)
5050					{
5051						TestParams testParams;
5052						deMemset(&testParams, 0, sizeof(testParams));
5053
5054						testParams.pipelineConstructionType				= pipelineConstructionType;
5055						testParams.isMultisampledRenderToSingleSampled	= isMultisampledRenderToSingleSampled;
5056						testParams.floatColor1Format					= color1Format;
5057						testParams.floatColor2Format					= color2Format;
5058						testParams.intColorFormat						= color3Format;
5059						testParams.depthStencilFormat					= depthStencilFormat;
5060						testParams.dynamicRendering						= dynamicRendering;
5061						testParams.useGarbageAttachment					= false;
5062
5063						generateBasicTest(rng, testParams, sampleCount, resolveMode, renderToWholeFramebuffer);
5064
5065						addFunctionCaseWithPrograms(
5066								resolveGroup.get(),
5067								renderToWholeFramebuffer ? "whole_framebuffer" : "sub_framebuffer",
5068								checkRequirements,
5069								initBasicPrograms,
5070								testBasic,
5071								testParams);
5072					}
5073
5074					sampleGroup->addChild(resolveGroup.release());
5075				}
5076				formatGroup->addChild(sampleGroup.release());
5077			}
5078			group->addChild(formatGroup.release());
5079		}
5080
5081		rootGroup->addChild(group.release());
5082	}
5083
5084	// Test 2: Test that vkCmdClearAttachments works.
5085	{
5086		MovePtr<tcu::TestCaseGroup> group	(new tcu::TestCaseGroup(rootGroup->getTestContext(), "clear_attachments"));
5087
5088		de::Random	rng(0x0FEDCBA9);
5089
5090		for (const VkFormat color1Format		: color1FormatRange)
5091		for (const VkFormat color2Format		: color2FormatRange)
5092		for (const VkFormat color3Format		: color3FormatRange)
5093		for (const VkFormat depthStencilFormat	: depthStencilFormatRange)
5094		{
5095			MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(
5096				rootGroup->getTestContext(), getFormatCaseName(color1Format, color2Format, color3Format, depthStencilFormat).c_str(), "Combination of framebuffer attachment formats"));
5097
5098			for (const VkSampleCountFlagBits sampleCount : sampleRange)
5099			{
5100				MovePtr<tcu::TestCaseGroup> sampleGroup(new tcu::TestCaseGroup(
5101					rootGroup->getTestContext(), getSampleCountCaseName(sampleCount).c_str(), "Sample count"));
5102
5103				for (const VkResolveModeFlagBits resolveMode : depthStencilResolveModeRange)
5104				{
5105					MovePtr<tcu::TestCaseGroup> resolveGroup(new tcu::TestCaseGroup(
5106						rootGroup->getTestContext(), getResolveModeCaseName(resolveMode).c_str(), "Depth/stencil resolve mode"));
5107
5108					for (const bool renderToWholeFramebuffer : boolRange)
5109					{
5110						TestParams testParams;
5111						deMemset(&testParams, 0, sizeof(testParams));
5112
5113						testParams.pipelineConstructionType				= pipelineConstructionType;
5114						testParams.isMultisampledRenderToSingleSampled	= isMultisampledRenderToSingleSampled;
5115						testParams.floatColor1Format					= color1Format;
5116						testParams.floatColor2Format					= color2Format;
5117						testParams.intColorFormat						= color3Format;
5118						testParams.depthStencilFormat					= depthStencilFormat;
5119						testParams.dynamicRendering						= dynamicRendering;
5120						testParams.useGarbageAttachment					= false;
5121
5122						generateBasicTest(rng, testParams, sampleCount, resolveMode, renderToWholeFramebuffer);
5123
5124						addFunctionCaseWithPrograms(
5125								resolveGroup.get(),
5126								renderToWholeFramebuffer ? "whole_framebuffer" : "sub_framebuffer",
5127								checkRequirements,
5128								initBasicPrograms,
5129								testClearAttachments,
5130								testParams);
5131					}
5132					sampleGroup->addChild(resolveGroup.release());
5133				}
5134				formatGroup->addChild(sampleGroup.release());
5135			}
5136			group->addChild(formatGroup.release());
5137		}
5138
5139		rootGroup->addChild(group.release());
5140	}
5141
5142	// Test 3: Tests with a single render pass, potentially with multiple subpasses.
5143	// Multiple subpasses can't be tested with dynamic rendering.
5144	if (!dynamicRendering)
5145	{
5146		// Single render pass with multiple subpasses
5147		MovePtr<tcu::TestCaseGroup> group	(new tcu::TestCaseGroup(rootGroup->getTestContext(), "multi_subpass"));
5148		MovePtr<tcu::TestCaseGroup> formatGroup[color1FormatCount][color2FormatCount][color3FormatCount][depthStencilFormatCount];
5149
5150		for (deUint32 color1FormatNdx = 0; color1FormatNdx < color1FormatCount; ++color1FormatNdx)
5151		for (deUint32 color2FormatNdx = 0; color2FormatNdx < color2FormatCount; ++color2FormatNdx)
5152		for (deUint32 color3FormatNdx = 0; color3FormatNdx < color3FormatCount; ++color3FormatNdx)
5153		for (deUint32 depthStencilFormatNdx = 0; depthStencilFormatNdx < depthStencilFormatCount; ++depthStencilFormatNdx)
5154		{
5155			formatGroup[color1FormatNdx][color2FormatNdx][color3FormatNdx][depthStencilFormatNdx] = MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(
5156					rootGroup->getTestContext(), getFormatCaseName(color1FormatRange[color1FormatNdx],
5157																   color2FormatRange[color2FormatNdx],
5158																   color3FormatRange[color3FormatNdx],
5159																   depthStencilFormatRange[depthStencilFormatNdx]).c_str(),
5160					"Combination of framebuffer attachment formats"));
5161		}
5162
5163		de::Random	rng(0x12345678);
5164
5165		for (deUint32 iteration = 0; iteration < (isMultisampledRenderToSingleSampled ? 1000 : 250); ++iteration)
5166		{
5167			TestParams testParams;
5168			deMemset(&testParams, 0, sizeof(testParams));
5169
5170			const deUint32 color1FormatNdx = iteration % color1FormatCount;
5171			const deUint32 color2FormatNdx = iteration % color2FormatCount;
5172			const deUint32 color3FormatNdx = iteration % color3FormatCount;
5173			const deUint32 depthStencilFormatNdx = iteration % depthStencilFormatCount;
5174
5175			testParams.pipelineConstructionType				= pipelineConstructionType;
5176			testParams.isMultisampledRenderToSingleSampled	= isMultisampledRenderToSingleSampled;
5177			testParams.floatColor1Format					= color1FormatRange[color1FormatNdx];
5178			testParams.floatColor2Format					= color2FormatRange[color2FormatNdx];
5179			testParams.intColorFormat						= color3FormatRange[color3FormatNdx];
5180			testParams.depthStencilFormat					= depthStencilFormatRange[depthStencilFormatNdx];
5181			testParams.dynamicRendering						= false;
5182			testParams.useGarbageAttachment					= false;
5183
5184			generateMultiPassTest(rng, testParams);
5185
5186			std::ostringstream name;
5187			name << "random_" << iteration;
5188
5189			addFunctionCaseWithPrograms(
5190				formatGroup[color1FormatNdx][color2FormatNdx][color3FormatNdx][depthStencilFormatNdx].get(),
5191				name.str().c_str(),
5192				checkRequirements,
5193				initMultipassPrograms,
5194				testSingleRenderPass,
5195				testParams);
5196		}
5197
5198		for (deUint32 color1FormatNdx = 0; color1FormatNdx < color1FormatCount; ++color1FormatNdx)
5199		for (deUint32 color2FormatNdx = 0; color2FormatNdx < color2FormatCount; ++color2FormatNdx)
5200		for (deUint32 color3FormatNdx = 0; color3FormatNdx < color3FormatCount; ++color3FormatNdx)
5201		for (deUint32 depthStencilFormatNdx = 0; depthStencilFormatNdx < depthStencilFormatCount; ++depthStencilFormatNdx)
5202		{
5203			group->addChild(formatGroup[color1FormatNdx][color2FormatNdx][color3FormatNdx][depthStencilFormatNdx].release());
5204		}
5205
5206		rootGroup->addChild(group.release());
5207	}
5208
5209	// Test 4: Tests with a multiple render passes, a single subpass each.
5210	{
5211		MovePtr<tcu::TestCaseGroup> group	(new tcu::TestCaseGroup(rootGroup->getTestContext(), "multi_renderpass"));
5212		MovePtr<tcu::TestCaseGroup> formatGroup[color1FormatCount][color2FormatCount][color3FormatCount][depthStencilFormatCount];
5213
5214		for (deUint32 color1FormatNdx = 0; color1FormatNdx < color1FormatCount; ++color1FormatNdx)
5215		for (deUint32 color2FormatNdx = 0; color2FormatNdx < color2FormatCount; ++color2FormatNdx)
5216		for (deUint32 color3FormatNdx = 0; color3FormatNdx < color3FormatCount; ++color3FormatNdx)
5217		for (deUint32 depthStencilFormatNdx = 0; depthStencilFormatNdx < depthStencilFormatCount; ++depthStencilFormatNdx)
5218		{
5219			formatGroup[color1FormatNdx][color2FormatNdx][color3FormatNdx][depthStencilFormatNdx] = MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(
5220					rootGroup->getTestContext(), getFormatCaseName(color1FormatRange[color1FormatNdx],
5221																   color2FormatRange[color2FormatNdx],
5222																   color3FormatRange[color3FormatNdx],
5223																   depthStencilFormatRange[depthStencilFormatNdx]).c_str(),
5224					"Combination of framebuffer attachment formats"));
5225		}
5226
5227		de::Random	rng(0x87654321);
5228
5229		for (deUint32 iteration = 0; iteration < (isMultisampledRenderToSingleSampled ? 1000 : 250); ++iteration)
5230		{
5231			TestParams testParams;
5232			deMemset(&testParams, 0, sizeof(testParams));
5233
5234			const deUint32 color1FormatNdx = iteration % color1FormatCount;
5235			const deUint32 color2FormatNdx = iteration % color2FormatCount;
5236			const deUint32 color3FormatNdx = iteration % color3FormatCount;
5237			const deUint32 depthStencilFormatNdx = iteration % depthStencilFormatCount;
5238
5239			testParams.pipelineConstructionType				= pipelineConstructionType;
5240			testParams.isMultisampledRenderToSingleSampled	= isMultisampledRenderToSingleSampled;
5241			testParams.floatColor1Format					= color1FormatRange[color1FormatNdx];
5242			testParams.floatColor2Format					= color2FormatRange[color2FormatNdx];
5243			testParams.intColorFormat						= color3FormatRange[color3FormatNdx];
5244			testParams.depthStencilFormat					= depthStencilFormatRange[depthStencilFormatNdx];
5245			testParams.dynamicRendering						= dynamicRendering;
5246			testParams.useGarbageAttachment					= false;
5247
5248			generateMultiPassTest(rng, testParams);
5249
5250			std::ostringstream name;
5251			name << "random_" << iteration;
5252
5253			addFunctionCaseWithPrograms(
5254				formatGroup[color1FormatNdx][color2FormatNdx][color3FormatNdx][depthStencilFormatNdx].get(),
5255				name.str().c_str(),
5256				checkRequirements,
5257				initMultipassPrograms,
5258				testMultiRenderPass,
5259				testParams);
5260		}
5261
5262		for (deUint32 color1FormatNdx = 0; color1FormatNdx < color1FormatCount; ++color1FormatNdx)
5263		for (deUint32 color2FormatNdx = 0; color2FormatNdx < color2FormatCount; ++color2FormatNdx)
5264		for (deUint32 color3FormatNdx = 0; color3FormatNdx < color3FormatCount; ++color3FormatNdx)
5265		for (deUint32 depthStencilFormatNdx = 0; depthStencilFormatNdx < depthStencilFormatCount; ++depthStencilFormatNdx)
5266		{
5267			group->addChild(formatGroup[color1FormatNdx][color2FormatNdx][color3FormatNdx][depthStencilFormatNdx].release());
5268		}
5269
5270		rootGroup->addChild(group.release());
5271	}
5272
5273	// Test 5: Tests multisampled rendering followed by use as input attachment.
5274	// These tests have two subpasses, so these can't be tested with dynamic rendering.
5275	if (!dynamicRendering && !vk::isConstructionTypeShaderObject(pipelineConstructionType))
5276	{
5277		MovePtr<tcu::TestCaseGroup> group	(new tcu::TestCaseGroup(rootGroup->getTestContext(), "input_attachments", "Tests that input attachment interaction with multisampled rendering works"));
5278
5279		de::Random	rng(0x18273645);
5280
5281		for (const VkFormat color1Format		: color1FormatRange)
5282		for (const VkFormat color2Format		: color2FormatRange)
5283		for (const VkFormat color3Format		: color3FormatRange)
5284		for (const VkFormat depthStencilFormat	: depthStencilFormatRange)
5285		{
5286			MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(
5287				rootGroup->getTestContext(), getFormatCaseName(color1Format, color2Format, color3Format, depthStencilFormat).c_str(), "Combination of framebuffer attachment formats"));
5288
5289			for (const VkSampleCountFlagBits sampleCount : sampleRange)
5290			{
5291				MovePtr<tcu::TestCaseGroup> sampleGroup(new tcu::TestCaseGroup(
5292					rootGroup->getTestContext(), getSampleCountCaseName(sampleCount).c_str(), "Sample count"));
5293
5294				for (const VkResolveModeFlagBits resolveMode : depthStencilResolveModeRange)
5295				{
5296					MovePtr<tcu::TestCaseGroup> resolveGroup(new tcu::TestCaseGroup(
5297						rootGroup->getTestContext(), getResolveModeCaseName(resolveMode).c_str(), "Depth/stencil resolve mode"));
5298
5299					for (const bool renderToWholeFramebuffer : boolRange)
5300					{
5301						TestParams testParams;
5302						deMemset(&testParams, 0, sizeof(testParams));
5303
5304						testParams.pipelineConstructionType				= pipelineConstructionType;
5305						testParams.isMultisampledRenderToSingleSampled	= isMultisampledRenderToSingleSampled;
5306						testParams.floatColor1Format					= color1Format;
5307						testParams.floatColor2Format					= color2Format;
5308						testParams.intColorFormat						= color3Format;
5309						testParams.depthStencilFormat					= depthStencilFormat;
5310						testParams.dynamicRendering						= false;
5311						testParams.useGarbageAttachment					= false;
5312
5313						generateInputAttachmentsTest(rng, testParams, sampleCount, resolveMode, renderToWholeFramebuffer);
5314
5315						addFunctionCaseWithPrograms(
5316								resolveGroup.get(),
5317								renderToWholeFramebuffer ? "whole_framebuffer" : "sub_framebuffer",
5318								checkRequirements,
5319								initInputAttachmentsPrograms,
5320								testInputAttachments,
5321								testParams);
5322					}
5323					sampleGroup->addChild(resolveGroup.release());
5324				}
5325				formatGroup->addChild(sampleGroup.release());
5326			}
5327			group->addChild(formatGroup.release());
5328		}
5329
5330		rootGroup->addChild(group.release());
5331	}
5332
5333
5334	// Test 6: Tests subpass resolve efficiency query.
5335	// Efficiency query tests don't need to be tested with different pipeline construction types and with dynamic rendering.
5336	if (isMultisampledRenderToSingleSampled && pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC && !dynamicRendering)
5337	{
5338		MovePtr<tcu::TestCaseGroup> group	(new tcu::TestCaseGroup(rootGroup->getTestContext(), "subpass_resolve_efficiency_query", "Tests that subpass resolve efficiency performance query works"));
5339
5340		for (const VkFormat format		: color1FormatRange)
5341		{
5342			addFunctionCase(
5343					group.get(),
5344					getFormatShortString(format),
5345					checkHasMsrtss,
5346					testPerfQuery,
5347					format);
5348		}
5349
5350		for (const VkFormat format		: color2FormatRange)
5351		{
5352			addFunctionCase(
5353					group.get(),
5354					getFormatShortString(format),
5355					checkHasMsrtss,
5356					testPerfQuery,
5357					format);
5358		}
5359
5360		for (const VkFormat format		: color3FormatRange)
5361		{
5362			addFunctionCase(
5363					group.get(),
5364					getFormatShortString(format),
5365					checkHasMsrtss,
5366					testPerfQuery,
5367					format);
5368		}
5369
5370		for (const VkFormat format	: depthStencilFormatRange)
5371		{
5372			addFunctionCase(
5373					group.get(),
5374					getFormatShortString(format),
5375					checkHasMsrtss,
5376					testPerfQuery,
5377					format);
5378		}
5379
5380		rootGroup->addChild(group.release());
5381	}
5382
5383	// Test 7: Test that work with garbage color attachments
5384	if (dynamicRendering && pipelineConstructionType != vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
5385	{
5386		MovePtr<tcu::TestCaseGroup> group	(new tcu::TestCaseGroup(rootGroup->getTestContext(), "garbage_color_attachment", "Tests that work with garbage color attachments"));
5387
5388		de::Random	rng(0x12348765);
5389
5390		for (const VkFormat color1Format		: color1FormatRange)
5391		for (const VkFormat color2Format		: color2FormatRange)
5392		for (const VkFormat color3Format		: color3FormatRange)
5393		for (const VkFormat depthStencilFormat	: depthStencilFormatRange)
5394		{
5395			TestParams testParams;
5396			deMemset(&testParams, 0, sizeof(testParams));
5397
5398			testParams.pipelineConstructionType				= pipelineConstructionType;
5399			testParams.isMultisampledRenderToSingleSampled	= isMultisampledRenderToSingleSampled;
5400			testParams.floatColor1Format					= color1Format;
5401			testParams.floatColor2Format					= color2Format;
5402			testParams.intColorFormat						= color3Format;
5403			testParams.depthStencilFormat					= depthStencilFormat;
5404			testParams.dynamicRendering						= dynamicRendering;
5405			testParams.useGarbageAttachment					= true;
5406
5407			generateBasicTest(rng, testParams, VK_SAMPLE_COUNT_2_BIT, VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, DE_TRUE);
5408
5409			// Combination of framebuffer attachment formats
5410			addFunctionCaseWithPrograms(
5411					group.get(),
5412					getFormatCaseName(color1Format, color2Format, color3Format, depthStencilFormat).c_str(),
5413					checkRequirements,
5414					initBasicPrograms,
5415					testBasic,
5416					testParams);
5417		}
5418
5419		rootGroup->addChild(group.release());
5420	}
5421}
5422
5423void createMultisampledRenderToSingleSampledTestsInGroup (tcu::TestCaseGroup* rootGroup, PipelineConstructionType pipelineConstructionType)
5424{
5425	createMultisampledTestsInGroup(rootGroup, true, pipelineConstructionType, false);
5426
5427	MovePtr<tcu::TestCaseGroup> dynamicRenderingGroup	(new tcu::TestCaseGroup(rootGroup->getTestContext(), "dynamic_rendering", "Multisampled rendering to single-sampled tests with dynamic rendering"));
5428	createMultisampledTestsInGroup(dynamicRenderingGroup.get(), true, pipelineConstructionType, true);
5429	rootGroup->addChild(dynamicRenderingGroup.release());
5430}
5431
5432void createMultisampledMiscTestsInGroup (tcu::TestCaseGroup* rootGroup, PipelineConstructionType pipelineConstructionType)
5433{
5434	createMultisampledTestsInGroup(rootGroup, false, pipelineConstructionType, false);
5435
5436	MovePtr<tcu::TestCaseGroup> dynamicRenderingGroup	(new tcu::TestCaseGroup(rootGroup->getTestContext(), "dynamic_rendering", "Miscellaneous multisampled rendering tests with dynamic rendering"));
5437	createMultisampledTestsInGroup(dynamicRenderingGroup.get(), false, pipelineConstructionType, true);
5438	rootGroup->addChild(dynamicRenderingGroup.release());
5439}
5440
5441} // anonymous ns
5442
5443tcu::TestCaseGroup* createMultisampledRenderToSingleSampledTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)
5444{
5445	// Test multisampled rendering to single-sampled framebuffer attachments
5446	return createTestGroup(testCtx, "multisampled_render_to_single_sampled", createMultisampledRenderToSingleSampledTestsInGroup, pipelineConstructionType);
5447}
5448
5449tcu::TestCaseGroup* createMultisampledMiscTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)
5450{
5451	return createTestGroup(testCtx, "misc", createMultisampledMiscTestsInGroup, pipelineConstructionType);
5452}
5453
5454} // pipeline
5455} // vkt
5456