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