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