1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 Google Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Tests for render pass multisample resolve
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRenderPassMultisampleResolveTests.hpp"
25 #include "vktRenderPassTestsUtil.hpp"
26 
27 #include "vktTestCaseUtil.hpp"
28 #include "vktTestGroupUtil.hpp"
29 
30 #include "vkDefs.hpp"
31 #include "vkDeviceUtil.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkPlatform.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkQueryUtil.hpp"
37 #include "vkRef.hpp"
38 #include "vkRefUtil.hpp"
39 #include "vkTypeUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkObjUtil.hpp"
42 
43 #include "tcuFloat.hpp"
44 #include "tcuImageCompare.hpp"
45 #include "tcuFormatUtil.hpp"
46 #include "tcuMaybe.hpp"
47 #include "tcuResultCollector.hpp"
48 #include "tcuTestLog.hpp"
49 #include "tcuTextureUtil.hpp"
50 #include "tcuVectorUtil.hpp"
51 #include "tcuStringTemplate.hpp"
52 
53 #include "deUniquePtr.hpp"
54 #include "deSharedPtr.hpp"
55 
56 using namespace vk;
57 
58 using tcu::BVec4;
59 using tcu::IVec2;
60 using tcu::IVec4;
61 using tcu::UVec2;
62 using tcu::UVec4;
63 using tcu::Vec2;
64 using tcu::Vec3;
65 using tcu::Vec4;
66 
67 using tcu::ConstPixelBufferAccess;
68 using tcu::PixelBufferAccess;
69 using tcu::TestLog;
70 
71 using std::vector;
72 
73 typedef de::SharedPtr<Allocation>							AllocationSp;
74 typedef de::SharedPtr<vk::Unique<VkImage> >					VkImageSp;
75 typedef de::SharedPtr<vk::Unique<VkImageView> >				VkImageViewSp;
76 typedef de::SharedPtr<vk::Unique<VkBuffer> >				VkBufferSp;
77 typedef de::SharedPtr<vk::Unique<VkSampler> >				VkSamplerSp;
78 typedef de::SharedPtr<vk::Unique<VkPipeline> >				VkPipelineSp;
79 typedef de::SharedPtr<vk::Unique<VkDescriptorSetLayout> >	VkDescriptorSetLayoutSp;
80 typedef de::SharedPtr<vk::Unique<VkDescriptorPool> >		VkDescriptorPoolSp;
81 typedef de::SharedPtr<vk::Unique<VkDescriptorSet> >			VkDescriptorSetSp;
82 
83 namespace vkt
84 {
85 namespace
86 {
87 
88 using namespace renderpass;
89 
90 template<typename T>
safeSharedPtr(T* ptr)91 de::SharedPtr<T> safeSharedPtr (T* ptr)
92 {
93 	try
94 	{
95 		return de::SharedPtr<T>(ptr);
96 	}
97 	catch (...)
98 	{
99 		delete ptr;
100 		throw;
101 	}
102 }
103 
104 enum TestType
105 {
106 	RESOLVE			= 0,
107 	MAX_ATTACHMENTS,
108 	COMPATIBILITY
109 };
110 
111 struct TestConfig
112 {
113 	TestType					testType;
114 	VkFormat					format;
115 	deUint32					sampleCount;
116 	deUint32					layerCount;
117 	deUint32					attachmentCount;
118 	deUint32					width;
119 	deUint32					height;
120 	const SharedGroupParams		groupParams;
121 };
122 
123 struct TestConfig2 : TestConfig
124 {
TestConfig2vkt::__anon29771::TestConfig2125 	TestConfig2(const TestConfig& src, deUint32 level)
126 		: TestConfig	(src)
127 		, resolveLevel	(level)
128 	{
129 	}
130 	deUint32		resolveLevel;
131 };
132 
133 // Render pass traits that groups render pass related types together and by that help
134 // to reduce number of template parrameters passed to number of functions in those tests
135 struct RenderPass1Trait
136 {
137 	typedef AttachmentDescription1	AttDesc;
138 	typedef AttachmentReference1	AttRef;
139 	typedef SubpassDescription1		SubpassDesc;
140 	typedef SubpassDependency1		SubpassDep;
141 	typedef RenderPassCreateInfo1	RenderPassCreateInfo;
142 };
143 struct RenderPass2Trait
144 {
145 	typedef AttachmentDescription2	AttDesc;
146 	typedef AttachmentReference2	AttRef;
147 	typedef SubpassDescription2		SubpassDesc;
148 	typedef SubpassDependency2		SubpassDep;
149 	typedef RenderPassCreateInfo2	RenderPassCreateInfo;
150 };
151 
152 class MultisampleRenderPassTestBase : public TestInstance
153 {
154 public:
155 	MultisampleRenderPassTestBase	(Context& context, TestConfig config);
156 	~MultisampleRenderPassTestBase	(void);
157 
158 protected:
159 
160 	Move<VkImage>			createImage			(VkSampleCountFlagBits		sampleCountBit,
161 												 VkImageUsageFlags			usage) const;
162 	Move<VkImage>			createImage			(VkSampleCountFlagBits		sampleCountBit,
163 												 VkImageUsageFlags			usage,
164 												 deUint32					width,
165 												 deUint32					height,
166 												 deUint32					mipLevels) const;
167 	vector<VkImageSp>		createImages		(VkSampleCountFlagBits		sampleCountBit,
168 												 VkImageUsageFlags			usage) const;
169 	vector<VkImageSp>		createImages		(VkSampleCountFlagBits		sampleCountBit,
170 												 VkImageUsageFlags			usage,
171 												 deUint32					width,
172 												 deUint32					height,
173 												 deUint32					mipLevels) const;
174 	vector<AllocationSp>	createImageMemory	(const vector<VkImageSp>&	images) const;
175 	vector<VkImageViewSp>	createImageViews	(const vector<VkImageSp>&	images,
176 												 deUint32					mipLevel = 0) const;
177 
178 	vector<VkBufferSp>		createBuffers		() const;
179 	vector<VkBufferSp>		createBuffers		(deUint32					width,
180 												 deUint32					height,
181 												 deUint32					mipLevels) const;
182 	vector<AllocationSp>	createBufferMemory	(const vector<VkBufferSp>& buffers) const;
183 
184 	Move<VkFramebuffer>		createFramebuffer	(const std::vector<VkImageViewSp>	multisampleImageViews,
185 												 const std::vector<VkImageViewSp>	singlesampleImageViews,
186 												 VkRenderPass						renderPass) const;
187 
188 	void					clearAttachments				(VkCommandBuffer commandBuffer) const;
189 	VkDeviceSize			getPixelSize					() const;
190 	tcu::Vec4				getFormatThreshold				() const;
191 	VkSampleCountFlagBits	sampleCountBitFromSampleCount	(deUint32 count) const;
192 	void					logImage						(const std::string& name,
193 															 const tcu::ConstPixelBufferAccess& image) const;
194 
195 protected:
196 
197 	const bool						m_testCompatibility;
198 	const SharedGroupParams			m_groupParams;
199 
200 	const VkFormat					m_format;
201 	const VkSampleCountFlagBits		m_sampleCount;
202 	const deUint32					m_layerCount;
203 	const deUint32					m_attachmentsCount;
204 	const deUint32					m_width;
205 	const deUint32					m_height;
206 };
207 
MultisampleRenderPassTestBase(Context& context, TestConfig config)208 MultisampleRenderPassTestBase::MultisampleRenderPassTestBase (Context& context, TestConfig config)
209 	: TestInstance				(context)
210 	, m_testCompatibility		(config.testType == COMPATIBILITY)
211 	, m_groupParams				(config.groupParams)
212 	, m_format					(config.format)
213 	, m_sampleCount				(sampleCountBitFromSampleCount(config.sampleCount))
214 	, m_layerCount				(config.layerCount)
215 	, m_attachmentsCount		(config.attachmentCount)
216 	, m_width					(config.width)
217 	, m_height					(config.height)
218 {
219 }
220 
~MultisampleRenderPassTestBase()221 MultisampleRenderPassTestBase::~MultisampleRenderPassTestBase ()
222 {
223 }
224 
createImage(VkSampleCountFlagBits sampleCountBit, VkImageUsageFlags usage) const225 Move<VkImage> MultisampleRenderPassTestBase::createImage (VkSampleCountFlagBits sampleCountBit, VkImageUsageFlags usage) const
226 {
227 	return createImage(sampleCountBit, usage, m_width, m_height, 1u);
228 }
229 
createImage(VkSampleCountFlagBits sampleCountBit, VkImageUsageFlags usage, deUint32 width, deUint32 height, deUint32 mipLevels) const230 Move<VkImage> MultisampleRenderPassTestBase::createImage (VkSampleCountFlagBits	sampleCountBit,
231 														  VkImageUsageFlags		usage,
232 														  deUint32				width,
233 														  deUint32				height,
234 														  deUint32				mipLevels) const
235 {
236 	const InstanceInterface&		vki						= m_context.getInstanceInterface();
237 	const DeviceInterface&			vkd						= m_context.getDeviceInterface();
238 	VkDevice						device					= m_context.getDevice();
239 	VkPhysicalDevice				physicalDevice			= m_context.getPhysicalDevice();
240 	const tcu::TextureFormat		format					(mapVkFormat(m_format));
241 	const VkImageType				imageType				(VK_IMAGE_TYPE_2D);
242 	const VkImageTiling				imageTiling				(VK_IMAGE_TILING_OPTIMAL);
243 	const VkFormatProperties		formatProperties		(getPhysicalDeviceFormatProperties(vki, physicalDevice, m_format));
244 	const VkExtent3D				imageExtent =
245 	{
246 		width,
247 		height,
248 		1u
249 	};
250 
251 	try
252 	{
253 		const VkImageFormatProperties	imageFormatProperties(getPhysicalDeviceImageFormatProperties(vki, physicalDevice, m_format, imageType, imageTiling, usage, 0u));
254 
255 		if ((tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
256 			&& (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)
257 			TCU_THROW(NotSupportedError, "Format can't be used as depth stencil attachment");
258 
259 		if (!(tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
260 			&& (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)
261 			TCU_THROW(NotSupportedError, "Format can't be used as color attachment");
262 
263 		if (imageFormatProperties.maxExtent.width < imageExtent.width
264 			|| imageFormatProperties.maxExtent.height < imageExtent.height
265 			|| ((imageFormatProperties.sampleCounts & m_sampleCount) == 0)
266 			|| imageFormatProperties.maxArrayLayers < m_layerCount)
267 		{
268 			TCU_THROW(NotSupportedError, "Image type not supported");
269 		}
270 
271 		const VkImageCreateInfo pCreateInfo =
272 		{
273 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
274 			DE_NULL,
275 			0u,
276 			imageType,
277 			m_format,
278 			imageExtent,
279 			mipLevels,
280 			m_layerCount,
281 			sampleCountBit,
282 			imageTiling,
283 			usage,
284 			VK_SHARING_MODE_EXCLUSIVE,
285 			0u,
286 			DE_NULL,
287 			VK_IMAGE_LAYOUT_UNDEFINED
288 		};
289 
290 		return ::createImage(vkd, device, &pCreateInfo);
291 	}
292 	catch (const vk::Error& error)
293 	{
294 		if (error.getError() == VK_ERROR_FORMAT_NOT_SUPPORTED)
295 			TCU_THROW(NotSupportedError, "Image format not supported");
296 
297 		throw;
298 	}
299 }
300 
createImages(VkSampleCountFlagBits sampleCountBit, VkImageUsageFlags usage) const301 vector<VkImageSp> MultisampleRenderPassTestBase::createImages (VkSampleCountFlagBits sampleCountBit, VkImageUsageFlags usage) const
302 {
303 	std::vector<VkImageSp> images (m_attachmentsCount);
304 	for (size_t imageNdx = 0; imageNdx < m_attachmentsCount; imageNdx++)
305 		images[imageNdx] = safeSharedPtr(new Unique<VkImage>(createImage(sampleCountBit, usage)));
306 	return images;
307 }
308 
createImages(VkSampleCountFlagBits sampleCountBit, VkImageUsageFlags usage, deUint32 width, deUint32 height, deUint32 mipLevels) const309 vector<VkImageSp> MultisampleRenderPassTestBase::createImages (VkSampleCountFlagBits	sampleCountBit,
310 															   VkImageUsageFlags		usage,
311 															   deUint32					width,
312 															   deUint32					height,
313 															   deUint32					mipLevels) const
314 {
315 	std::vector<VkImageSp> images (m_attachmentsCount);
316 	for (size_t imageNdx = 0; imageNdx < m_attachmentsCount; imageNdx++)
317 		images[imageNdx] = safeSharedPtr(new Unique<VkImage>(createImage(sampleCountBit, usage, width, height, mipLevels)));
318 	return images;
319 }
320 
createImageMemory(const vector<VkImageSp>& images) const321 vector<AllocationSp> MultisampleRenderPassTestBase::createImageMemory (const vector<VkImageSp>& images) const
322 {
323 	const DeviceInterface&		vkd			= m_context.getDeviceInterface();
324 	VkDevice					device		= m_context.getDevice();
325 	Allocator&					allocator	= m_context.getDefaultAllocator();
326 	std::vector<AllocationSp>	memory		(images.size());
327 
328 	for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
329 	{
330 		VkImage					image			= **images[memoryNdx];
331 		VkMemoryRequirements	requirements	= getImageMemoryRequirements(vkd, device, image);
332 
333 		de::MovePtr<Allocation>	allocation		(allocator.allocate(requirements, MemoryRequirement::Any));
334 		VK_CHECK(vkd.bindImageMemory(device, image, allocation->getMemory(), allocation->getOffset()));
335 		memory[memoryNdx] = safeSharedPtr(allocation.release());
336 	}
337 	return memory;
338 }
339 
createImageViews(const vector<VkImageSp>& images, deUint32 mipLevel) const340 vector<VkImageViewSp> MultisampleRenderPassTestBase::createImageViews (const vector<VkImageSp>& images, deUint32 mipLevel) const
341 {
342 	const DeviceInterface&			vkd		= m_context.getDeviceInterface();
343 	VkDevice						device	= m_context.getDevice();
344 	std::vector<VkImageViewSp>		views	(images.size());
345 	const VkImageSubresourceRange	range =
346 	{
347 		VK_IMAGE_ASPECT_COLOR_BIT,
348 		mipLevel,
349 		1u,
350 		0u,
351 		m_layerCount
352 	};
353 
354 	for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
355 	{
356 		const VkImageViewCreateInfo pCreateInfo =
357 		{
358 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
359 			DE_NULL,
360 			0u,
361 			**images[imageNdx],
362 			VK_IMAGE_VIEW_TYPE_2D_ARRAY,
363 			m_format,
364 			makeComponentMappingRGBA(),
365 			range,
366 		};
367 		views[imageNdx] = safeSharedPtr(new Unique<VkImageView>(createImageView(vkd, device, &pCreateInfo)));
368 	}
369 
370 	return views;
371 }
372 
createBuffers() const373 vector<VkBufferSp> MultisampleRenderPassTestBase::createBuffers () const
374 {
375 	return createBuffers(m_width, m_height, 1u);
376 }
377 
createBuffers(deUint32 width, deUint32 height, deUint32 mipLevels) const378 vector<VkBufferSp> MultisampleRenderPassTestBase::createBuffers (deUint32 width, deUint32 height, deUint32 mipLevels) const
379 {
380 	DE_ASSERT(mipLevels);
381 
382 	VkDeviceSize				size		= 0;
383 	for (deUint32 level = 0; level < mipLevels; ++level)
384 	{
385 		DE_ASSERT(width && height);
386 
387 		size += (width * height);
388 		height /= 2;
389 		width /=2;
390 	}
391 
392 	const DeviceInterface&		vkd			= m_context.getDeviceInterface();
393 	VkDevice					device		= m_context.getDevice();
394 	std::vector<VkBufferSp>		buffers		(m_attachmentsCount);
395 	const VkDeviceSize			pixelSize	(getPixelSize());
396 	const VkBufferCreateInfo	createInfo =
397 	{
398 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
399 		DE_NULL,
400 		0u,
401 
402 		size * m_layerCount * pixelSize,
403 		VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
404 
405 		VK_SHARING_MODE_EXCLUSIVE,
406 		0u,
407 		DE_NULL
408 	};
409 
410 	for (size_t bufferNdx = 0; bufferNdx < buffers.size(); bufferNdx++)
411 		buffers[bufferNdx] = safeSharedPtr(new Unique<VkBuffer>(createBuffer(vkd, device, &createInfo)));
412 
413 	return buffers;
414 }
415 
createBufferMemory(const vector<VkBufferSp>& buffers) const416 vector<AllocationSp> MultisampleRenderPassTestBase::createBufferMemory (const vector<VkBufferSp>& buffers) const
417 {
418 	const DeviceInterface&					vkd			= m_context.getDeviceInterface();
419 	VkDevice								device		= m_context.getDevice();
420 	Allocator&								allocator	= m_context.getDefaultAllocator();
421 	std::vector<de::SharedPtr<Allocation> >	memory		(buffers.size());
422 
423 	for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
424 	{
425 		VkBuffer				buffer			= **buffers[memoryNdx];
426 		VkMemoryRequirements	requirements	= getBufferMemoryRequirements(vkd, device, buffer);
427 		de::MovePtr<Allocation> allocation		(allocator.allocate(requirements, MemoryRequirement::HostVisible));
428 
429 		VK_CHECK(vkd.bindBufferMemory(device, buffer, allocation->getMemory(), allocation->getOffset()));
430 		memory[memoryNdx] = safeSharedPtr(allocation.release());
431 	}
432 	return memory;
433 }
434 
createFramebuffer(const std::vector<VkImageViewSp> multisampleImageViews, const std::vector<VkImageViewSp> singlesampleImageViews, VkRenderPass renderPass) const435 Move<VkFramebuffer> MultisampleRenderPassTestBase::createFramebuffer (const std::vector<VkImageViewSp>	multisampleImageViews,
436 																	  const std::vector<VkImageViewSp>	singlesampleImageViews,
437 																	  VkRenderPass						renderPass) const
438 {
439 	// when RenderPass was not created then we are testing dynamic rendering
440 	// and we can't create framebuffer without valid RenderPass object
441 	if (!renderPass)
442 		return Move<VkFramebuffer>();
443 
444 	const DeviceInterface&	vkd		= m_context.getDeviceInterface();
445 	VkDevice				device	= m_context.getDevice();
446 
447 	std::vector<VkImageView> attachments;
448 	attachments.reserve(multisampleImageViews.size() + singlesampleImageViews.size());
449 
450 	DE_ASSERT(multisampleImageViews.size() == singlesampleImageViews.size());
451 
452 	for (size_t ndx = 0; ndx < multisampleImageViews.size(); ndx++)
453 	{
454 		attachments.push_back(**multisampleImageViews[ndx]);
455 		attachments.push_back(**singlesampleImageViews[ndx]);
456 	}
457 
458 	const VkFramebufferCreateInfo createInfo =
459 	{
460 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
461 		DE_NULL,
462 		0u,
463 
464 		renderPass,
465 		(deUint32)attachments.size(),
466 		&attachments[0],
467 
468 		m_width,
469 		m_height,
470 		m_layerCount
471 	};
472 
473 	return ::createFramebuffer(vkd, device, &createInfo);
474 }
475 
clearAttachments(VkCommandBuffer commandBuffer) const476 void MultisampleRenderPassTestBase::clearAttachments (VkCommandBuffer commandBuffer) const
477 {
478 	const DeviceInterface&			vkd				= m_context.getDeviceInterface();
479 	const tcu::TextureFormat		format			(mapVkFormat(m_format));
480 	const tcu::TextureChannelClass	channelClass	(tcu::getTextureChannelClass(format.type));
481 	VkClearValue					value;
482 
483 	// Clear everything to black
484 	switch (channelClass)
485 	{
486 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
487 			value = makeClearValueColorF32(-1.0f, -1.0f, -1.0f, -1.0f);
488 			break;
489 
490 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
491 			value = makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f);
492 			break;
493 
494 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
495 			value = makeClearValueColorF32(-1.0f, -1.0f, -1.0f, -1.0f);
496 			break;
497 
498 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
499 			value = makeClearValueColorI32(-128, -128, -128, -128);
500 			break;
501 
502 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
503 			value = makeClearValueColorU32(0u, 0u, 0u, 0u);
504 			break;
505 
506 		default:
507 			DE_FATAL("Unknown channel class");
508 	}
509 	std::vector<VkClearAttachment> colors(m_attachmentsCount);
510 	for (deUint32 attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
511 	{
512 		colors[attachmentNdx].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
513 		colors[attachmentNdx].colorAttachment = attachmentNdx;
514 		colors[attachmentNdx].clearValue = value;
515 	}
516 	const VkClearRect rect =
517 	{
518 		{
519 			{ 0u, 0u },
520 			{ m_width, m_height }
521 		},
522 		0u,
523 		m_layerCount,
524 	};
525 	vkd.cmdClearAttachments(commandBuffer, deUint32(colors.size()), &colors[0], 1u, &rect);
526 }
527 
getPixelSize() const528 VkDeviceSize MultisampleRenderPassTestBase::getPixelSize () const
529 {
530 	const tcu::TextureFormat format(mapVkFormat(m_format));
531 	return format.getPixelSize();
532 }
533 
getFormatThreshold() const534 tcu::Vec4 MultisampleRenderPassTestBase::getFormatThreshold () const
535 {
536 	const tcu::TextureFormat	tcuFormat		(mapVkFormat(m_format));
537 	const deUint32				componentCount	(tcu::getNumUsedChannels(tcuFormat.order));
538 
539 	if (isSnormFormat(m_format))
540 	{
541 		return Vec4((componentCount >= 1) ? 1.5f * getRepresentableDiffSnorm(m_format, 0) : 0.0f,
542 					(componentCount >= 2) ? 1.5f * getRepresentableDiffSnorm(m_format, 1) : 0.0f,
543 					(componentCount >= 3) ? 1.5f * getRepresentableDiffSnorm(m_format, 2) : 0.0f,
544 					(componentCount == 4) ? 1.5f * getRepresentableDiffSnorm(m_format, 3) : 0.0f);
545 	}
546 	else if (isUnormFormat(m_format))
547 	{
548 		return Vec4((componentCount >= 1) ? 1.5f * getRepresentableDiffUnorm(m_format, 0) : 0.0f,
549 					(componentCount >= 2) ? 1.5f * getRepresentableDiffUnorm(m_format, 1) : 0.0f,
550 					(componentCount >= 3) ? 1.5f * getRepresentableDiffUnorm(m_format, 2) : 0.0f,
551 					(componentCount == 4) ? 1.5f * getRepresentableDiffUnorm(m_format, 3) : 0.0f);
552 	}
553 	else if (isFloatFormat(m_format))
554 	{
555 		return (tcuFormat.type == tcu::TextureFormat::HALF_FLOAT) ? tcu::Vec4(0.005f) : Vec4(0.00001f);
556 	}
557 	else
558 		return Vec4(0.001f);
559 }
560 
sampleCountBitFromSampleCount(deUint32 count) const561 VkSampleCountFlagBits MultisampleRenderPassTestBase::sampleCountBitFromSampleCount (deUint32 count) const
562 {
563 	switch (count)
564 	{
565 		case 1:  return VK_SAMPLE_COUNT_1_BIT;
566 		case 2:  return VK_SAMPLE_COUNT_2_BIT;
567 		case 4:  return VK_SAMPLE_COUNT_4_BIT;
568 		case 8:  return VK_SAMPLE_COUNT_8_BIT;
569 		case 16: return VK_SAMPLE_COUNT_16_BIT;
570 		case 32: return VK_SAMPLE_COUNT_32_BIT;
571 		case 64: return VK_SAMPLE_COUNT_64_BIT;
572 
573 		default:
574 			DE_FATAL("Invalid sample count");
575 			return (VkSampleCountFlagBits)0x0;
576 	}
577 }
578 
logImage(const std::string& name, const tcu::ConstPixelBufferAccess& image) const579 void MultisampleRenderPassTestBase::logImage (const std::string& name, const tcu::ConstPixelBufferAccess& image) const
580 {
581 	m_context.getTestContext().getLog() << tcu::LogImage(name.c_str(), name.c_str(), image);
582 
583 	for (deUint32 layerNdx = 0; layerNdx < m_layerCount; ++layerNdx)
584 	{
585 		const std::string			layerName	(name + " Layer:" + de::toString(layerNdx));
586 		tcu::ConstPixelBufferAccess	layerImage	(image.getFormat(), m_width, m_height, 1, image.getPixelPtr(0, 0, layerNdx));
587 
588 		m_context.getTestContext().getLog() << tcu::LogImage(layerName.c_str(), layerName.c_str(), layerImage);
589 	}
590 }
591 
592 class MultisampleRenderPassTestInstance : public MultisampleRenderPassTestBase
593 {
594 public:
595 	MultisampleRenderPassTestInstance	(Context& context, TestConfig config);
596 	~MultisampleRenderPassTestInstance	(void);
597 
598 	tcu::TestStatus			iterate		(void);
599 
600 private:
601 
602 	void					drawCommands				(VkCommandBuffer cmdBuffer, VkPipeline pipeline, VkPipelineLayout pipelineLayout) const;
603 
604 	template<typename RenderpassSubpass>
605 	void					submit						(void);
606 	void					submitDynamicRendering		(void);
607 	void					submitSwitch				(const SharedGroupParams groupParams);
608 	void					verify						(void);
609 
610 	template<typename RenderPassTrait>
611 	Move<VkRenderPass>		createRenderPass			(bool usedResolveAttachment);
612 	Move<VkRenderPass>		createRenderPassSwitch		(bool usedResolveAttachment);
613 	Move<VkRenderPass>		createRenderPassCompatible	(void);
614 	Move<VkPipelineLayout>	createRenderPipelineLayout	(void);
615 	Move<VkPipeline>		createRenderPipeline		(void);
616 
617 #ifndef CTS_USES_VULKANSC
618 	void					beginSecondaryCmdBuffer		(VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags = 0u) const;
619 #endif // CTS_USES_VULKANSC
620 
621 private:
622 
623 	const std::vector<VkImageSp>		m_multisampleImages;
624 	const std::vector<AllocationSp>		m_multisampleImageMemory;
625 	const std::vector<VkImageViewSp>	m_multisampleImageViews;
626 
627 	const std::vector<VkImageSp>		m_singlesampleImages;
628 	const std::vector<AllocationSp>		m_singlesampleImageMemory;
629 	const std::vector<VkImageViewSp>	m_singlesampleImageViews;
630 
631 	const Unique<VkRenderPass>			m_renderPass;
632 	const Unique<VkRenderPass>			m_renderPassCompatible;
633 	const Unique<VkFramebuffer>			m_framebuffer;
634 
635 	const Unique<VkPipelineLayout>		m_renderPipelineLayout;
636 	const Unique<VkPipeline>			m_renderPipeline;
637 
638 	const std::vector<VkBufferSp>		m_buffers;
639 	const std::vector<AllocationSp>		m_bufferMemory;
640 
641 	const Unique<VkCommandPool>			m_commandPool;
642 	tcu::TextureLevel					m_sum;
643 	tcu::TextureLevel					m_sumSrgb;
644 	deUint32							m_sampleMask;
645 	tcu::ResultCollector				m_resultCollector;
646 
647 protected:
648 	MultisampleRenderPassTestInstance	(Context& context, TestConfig config, deUint32 renderLevel);
649 
650 	const deUint32						m_renderLevel;
651 };
652 
MultisampleRenderPassTestInstance(Context& context, TestConfig config)653 MultisampleRenderPassTestInstance::MultisampleRenderPassTestInstance (Context& context, TestConfig config)
654 	: MultisampleRenderPassTestInstance (context, config, /*defaulf render level*/0u)
655 {
656 }
657 
MultisampleRenderPassTestInstance(Context& context, TestConfig config, deUint32 renderLevel)658 MultisampleRenderPassTestInstance::MultisampleRenderPassTestInstance (Context& context, TestConfig config, deUint32 renderLevel)
659 	: MultisampleRenderPassTestBase(context, config)
660 
661 	, m_multisampleImages		(createImages(m_sampleCount, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
662 	, m_multisampleImageMemory	(createImageMemory(m_multisampleImages))
663 	, m_multisampleImageViews	(createImageViews(m_multisampleImages))
664 
665 	, m_singlesampleImages		(createImages(VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, (1u << renderLevel)*m_width, (1u << renderLevel)*m_height, renderLevel+1 ))
666 	, m_singlesampleImageMemory	(createImageMemory(m_singlesampleImages))
667 	, m_singlesampleImageViews	(createImageViews(m_singlesampleImages, renderLevel))
668 
669 	// The "normal" render pass has an unused resolve attachment when testing compatibility.
670 	, m_renderPass				(createRenderPassSwitch(!m_testCompatibility))
671 	, m_renderPassCompatible	(createRenderPassCompatible())
672 	, m_framebuffer				(createFramebuffer(m_multisampleImageViews, m_singlesampleImageViews, *m_renderPass))
673 
674 	, m_renderPipelineLayout	(createRenderPipelineLayout())
675 	, m_renderPipeline			(createRenderPipeline())
676 
677 	, m_buffers					(createBuffers((1u << renderLevel)*m_width, (1u << renderLevel)*m_height, renderLevel+1 ))
678 	, m_bufferMemory			(createBufferMemory(m_buffers))
679 
680 	, m_commandPool				(createCommandPool(context.getDeviceInterface(), context.getDevice(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
681 	, m_sum						(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), m_width, m_height, m_layerCount)
682 	, m_sumSrgb					(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), m_width, m_height, m_layerCount)
683 	, m_sampleMask				(0x0u)
684 
685 	, m_renderLevel				(renderLevel)
686 {
687 	tcu::clear(m_sum.getAccess(), Vec4(0.0f, 0.0f, 0.0f, 0.0f));
688 	tcu::clear(m_sumSrgb.getAccess(), Vec4(0.0f, 0.0f, 0.0f, 0.0f));
689 }
690 
~MultisampleRenderPassTestInstance(void)691 MultisampleRenderPassTestInstance::~MultisampleRenderPassTestInstance (void)
692 {
693 }
694 
drawCommands(VkCommandBuffer cmdBuffer, VkPipeline pipeline, VkPipelineLayout pipelineLayout) const695 void MultisampleRenderPassTestInstance::drawCommands(VkCommandBuffer cmdBuffer, VkPipeline pipeline, VkPipelineLayout pipelineLayout) const
696 {
697 	const DeviceInterface& vkd = m_context.getDeviceInterface();
698 
699 	// Clear everything to black
700 	clearAttachments(cmdBuffer);
701 
702 	// Render black samples
703 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
704 	vkd.cmdPushConstants(cmdBuffer, pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(m_sampleMask), &m_sampleMask);
705 	vkd.cmdDraw(cmdBuffer, 6u, 1u, 0u, 0u);
706 }
707 
708 template<typename RenderpassSubpass>
submit(void)709 void MultisampleRenderPassTestInstance::submit (void)
710 {
711 	const DeviceInterface&			vkd				(m_context.getDeviceInterface());
712 	const VkDevice					device			(m_context.getDevice());
713 	const Unique<VkCommandBuffer>	commandBuffer	(allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
714 
715 	beginCommandBuffer(vkd, *commandBuffer);
716 
717 	// Memory barriers between previous copies and rendering
718 	{
719 		std::vector<VkImageMemoryBarrier> barriers;
720 
721 		for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
722 		{
723 			const VkImageMemoryBarrier barrier =
724 			{
725 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
726 				DE_NULL,
727 
728 				VK_ACCESS_TRANSFER_READ_BIT,
729 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
730 
731 				VK_IMAGE_LAYOUT_UNDEFINED,
732 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
733 
734 				VK_QUEUE_FAMILY_IGNORED,
735 				VK_QUEUE_FAMILY_IGNORED,
736 
737 				**m_singlesampleImages[dstNdx],
738 				{
739 					VK_IMAGE_ASPECT_COLOR_BIT,
740 					m_renderLevel,
741 					1u,
742 					0u,
743 					m_layerCount
744 				}
745 			};
746 
747 			barriers.push_back(barrier);
748 		}
749 
750 		vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0]);
751 	}
752 
753 	VkRect2D renderArea = makeRect2D(m_width, m_height);
754 	const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
755 	const VkRenderPassBeginInfo beginInfo =
756 	{
757 		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
758 		DE_NULL,
759 
760 		m_testCompatibility ? *m_renderPassCompatible : *m_renderPass,
761 		*m_framebuffer,
762 		renderArea,
763 
764 		0u,
765 		DE_NULL
766 	};
767 	RenderpassSubpass::cmdBeginRenderPass(vkd, *commandBuffer, &beginInfo, &subpassBeginInfo);
768 
769 	drawCommands(*commandBuffer, *m_renderPipeline, *m_renderPipelineLayout);
770 
771 	const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo(DE_NULL);
772 	RenderpassSubpass::cmdEndRenderPass(vkd, *commandBuffer, &subpassEndInfo);
773 
774 	for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
775 	{
776 		// assume that buffer(s) have enough memory to store desired amount of mipmaps
777 		copyImageToBuffer(vkd, *commandBuffer, **m_singlesampleImages[dstNdx], **m_buffers[dstNdx],
778 						  m_format, tcu::IVec2((1u << m_renderLevel)*m_width, (1u << m_renderLevel)*m_height), m_renderLevel,
779 						  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_layerCount);
780 	}
781 
782 	endCommandBuffer(vkd, *commandBuffer);
783 
784 	submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *commandBuffer);
785 
786 	for (size_t memoryBufferNdx = 0; memoryBufferNdx < m_bufferMemory.size(); memoryBufferNdx++)
787 		invalidateMappedMemoryRange(vkd, device, m_bufferMemory[memoryBufferNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
788 }
789 
submitDynamicRendering(void)790 void MultisampleRenderPassTestInstance::submitDynamicRendering (void)
791 {
792 #ifndef CTS_USES_VULKANSC
793 
794 	const DeviceInterface&			vkd				(m_context.getDeviceInterface());
795 	const VkDevice					device			(m_context.getDevice());
796 	const Unique<VkCommandBuffer>	cmdBuffer		(allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
797 	Move<VkCommandBuffer>			secCmdBuffer;
798 
799 	// Memory barriers between previous copies and rendering
800 	std::vector<VkImageMemoryBarrier> singlesampleImageBarriers(m_singlesampleImages.size(),
801 		{
802 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
803 			DE_NULL,
804 
805 			VK_ACCESS_TRANSFER_READ_BIT,
806 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
807 
808 			VK_IMAGE_LAYOUT_UNDEFINED,
809 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
810 
811 			VK_QUEUE_FAMILY_IGNORED,
812 			VK_QUEUE_FAMILY_IGNORED,
813 
814 			DE_NULL,
815 			{
816 				VK_IMAGE_ASPECT_COLOR_BIT,
817 				m_renderLevel,
818 				1u,
819 				0u,
820 				m_layerCount
821 			}
822 		});
823 	for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
824 		singlesampleImageBarriers[dstNdx].image = **m_singlesampleImages[dstNdx];
825 
826 	// Memory barriers to set multisample image layout to COLOR_ATTACHMENT_OPTIMAL
827 	std::vector<VkImageMemoryBarrier> multisampleImageBarriers(m_multisampleImages.size(),
828 		{
829 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
830 			DE_NULL,
831 
832 			0,
833 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
834 
835 			VK_IMAGE_LAYOUT_UNDEFINED,
836 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
837 
838 			VK_QUEUE_FAMILY_IGNORED,
839 			VK_QUEUE_FAMILY_IGNORED,
840 
841 			DE_NULL,
842 			{
843 				VK_IMAGE_ASPECT_COLOR_BIT,
844 				0u,
845 				1u,
846 				0u,
847 				m_layerCount
848 			}
849 		});
850 	for (size_t dstNdx = 0; dstNdx < m_multisampleImages.size(); dstNdx++)
851 		multisampleImageBarriers[dstNdx].image = **m_multisampleImages[dstNdx];
852 
853 	VkRect2D			renderArea = makeRect2D(m_width, m_height);
854 	const VkClearValue	clearValue = makeClearValueColor( { 0.0f, 0.0f, 0.0f, 1.0f } );
855 	std::vector<vk::VkRenderingAttachmentInfoKHR> colorAttachments(m_attachmentsCount,
856 		{
857 			vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,	// VkStructureType						sType;
858 			DE_NULL,												// const void*							pNext;
859 			DE_NULL,												// VkImageView							imageView;
860 			vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout						imageLayout;
861 			vk::VK_RESOLVE_MODE_NONE,								// VkResolveModeFlagBits				resolveMode;
862 			DE_NULL,												// VkImageView							resolveImageView;
863 			vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout						resolveImageLayout;
864 			vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp					loadOp;
865 			vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp					storeOp;
866 			clearValue												// VkClearValue							clearValue;
867 		});
868 
869 	for (deUint32 i = 0; i < m_attachmentsCount; ++i)
870 	{
871 		colorAttachments[i].imageView = **m_multisampleImageViews[i];
872 		colorAttachments[i].resolveImageView = **m_singlesampleImageViews[i];
873 		if (isIntFormat(m_format) || isUintFormat(m_format))
874 			colorAttachments[i].resolveMode = vk::VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
875 		else
876 			colorAttachments[i].resolveMode = vk::VK_RESOLVE_MODE_AVERAGE_BIT;
877 	}
878 
879 	vk::VkRenderingInfoKHR renderingInfo
880 	{
881 		vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
882 		DE_NULL,
883 		0,														// VkRenderingFlagsKHR					flags;
884 		renderArea,												// VkRect2D								renderArea;
885 		m_layerCount,											// deUint32								layerCount;
886 		0u,														// deUint32								viewMask;
887 		m_attachmentsCount,										// deUint32								colorAttachmentCount;
888 		colorAttachments.data(),								// const VkRenderingAttachmentInfoKHR*	pColorAttachments;
889 		DE_NULL,												// const VkRenderingAttachmentInfoKHR*	pDepthAttachment;
890 		DE_NULL,												// const VkRenderingAttachmentInfoKHR*	pStencilAttachment;
891 	};
892 
893 	if (m_groupParams->useSecondaryCmdBuffer)
894 	{
895 		secCmdBuffer = allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
896 
897 		// record secondary command buffer
898 		if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
899 		{
900 			beginSecondaryCmdBuffer(*secCmdBuffer, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
901 			vkd.cmdBeginRendering(*secCmdBuffer, &renderingInfo);
902 		}
903 		else
904 			beginSecondaryCmdBuffer(*secCmdBuffer);
905 
906 		drawCommands(*secCmdBuffer, *m_renderPipeline, *m_renderPipelineLayout);
907 
908 		if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
909 			vkd.cmdEndRendering(*secCmdBuffer);
910 
911 		endCommandBuffer(vkd, *secCmdBuffer);
912 
913 		// record primary command buffer
914 		beginCommandBuffer(vkd, *cmdBuffer);
915 
916 		vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)singlesampleImageBarriers.size(), &singlesampleImageBarriers[0]);
917 		vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)multisampleImageBarriers.size(), &multisampleImageBarriers[0]);
918 
919 		if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
920 		{
921 			renderingInfo.flags = vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
922 			vkd.cmdBeginRendering(*cmdBuffer, &renderingInfo);
923 		}
924 		vkd.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
925 
926 		if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
927 			vkd.cmdEndRendering(*cmdBuffer);
928 	}
929 	else
930 	{
931 		beginCommandBuffer(vkd, *cmdBuffer);
932 
933 		vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)singlesampleImageBarriers.size(), &singlesampleImageBarriers[0]);
934 		vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)multisampleImageBarriers.size(), &multisampleImageBarriers[0]);
935 
936 		vkd.cmdBeginRendering(*cmdBuffer, &renderingInfo);
937 		drawCommands(*cmdBuffer, *m_renderPipeline, *m_renderPipelineLayout);
938 		vkd.cmdEndRendering(*cmdBuffer);
939 	}
940 
941 	// Memory barriers to set single-sample image layout to TRANSFER_SRC_OPTIMAL
942 	{
943 		std::vector<VkImageMemoryBarrier> barriers;
944 
945 		for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
946 		{
947 			const VkImageMemoryBarrier barrier =
948 			{
949 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
950 				DE_NULL,
951 
952 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
953 				VK_ACCESS_TRANSFER_READ_BIT,
954 
955 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
956 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
957 
958 				VK_QUEUE_FAMILY_IGNORED,
959 				VK_QUEUE_FAMILY_IGNORED,
960 
961 				**m_singlesampleImages[dstNdx],
962 				{
963 					VK_IMAGE_ASPECT_COLOR_BIT,
964 					m_renderLevel,
965 					1u,
966 					0u,
967 					m_layerCount
968 				}
969 			};
970 
971 			barriers.push_back(barrier);
972 		}
973 
974 		vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0]);
975 	}
976 
977 	for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
978 	{
979 		// assume that buffer(s) have enough memory to store desired amount of mipmaps
980 		copyImageToBuffer(vkd, *cmdBuffer, **m_singlesampleImages[dstNdx], **m_buffers[dstNdx],
981 						  m_format, tcu::IVec2((1u << m_renderLevel)*m_width, (1u << m_renderLevel)*m_height), m_renderLevel,
982 						  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_layerCount);
983 	}
984 
985 	endCommandBuffer(vkd, *cmdBuffer);
986 
987 	submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *cmdBuffer);
988 
989 	for (size_t memoryBufferNdx = 0; memoryBufferNdx < m_bufferMemory.size(); memoryBufferNdx++)
990 		invalidateMappedMemoryRange(vkd, device, m_bufferMemory[memoryBufferNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
991 
992 #endif // CTS_USES_VULKANSC
993 }
994 
submitSwitch(const SharedGroupParams groupParams)995 void MultisampleRenderPassTestInstance::submitSwitch (const SharedGroupParams groupParams)
996 {
997 	switch (groupParams->renderingType)
998 	{
999 		case RENDERING_TYPE_RENDERPASS_LEGACY:
1000 			submit<RenderpassSubpass1>();
1001 			break;
1002 		case RENDERING_TYPE_RENDERPASS2:
1003 			submit<RenderpassSubpass2>();
1004 			break;
1005 		case RENDERING_TYPE_DYNAMIC_RENDERING:
1006 			submitDynamicRendering();
1007 			break;
1008 		default:
1009 			TCU_THROW(InternalError, "Impossible");
1010 	}
1011 }
1012 
verify(void)1013 void MultisampleRenderPassTestInstance::verify (void)
1014 {
1015 	const Vec4							errorColor		(1.0f, 0.0f, 0.0f, 1.0f);
1016 	const Vec4							okColor			(0.0f, 1.0f, 0.0f, 1.0f);
1017 	const tcu::TextureFormat			format			(mapVkFormat(m_format));
1018 	const tcu::TextureChannelClass		channelClass	(tcu::getTextureChannelClass(format.type));
1019 
1020 	deUint32							offset			(0u);
1021 	deUint32							width			((1u << m_renderLevel) * m_width);
1022 	deUint32							height			((1u << m_renderLevel) * m_height);
1023 	deUint32							pixelSize		(static_cast<deUint32>(getPixelSize()));
1024 	for (deUint32 level = 0; level < m_renderLevel; ++level)
1025 	{
1026 		offset += (width * height * pixelSize);
1027 		height /= 2;
1028 		width /= 2;
1029 	}
1030 
1031 	std::vector<tcu::ConstPixelBufferAccess> accesses;
1032 	for (deUint32 attachmentIdx = 0; attachmentIdx < m_attachmentsCount; ++attachmentIdx)
1033 	{
1034 		void* const ptr = static_cast<deUint8*>(m_bufferMemory[attachmentIdx]->getHostPtr()) + offset;
1035 		accesses.push_back(tcu::ConstPixelBufferAccess(format, m_width, m_height, m_layerCount, ptr));
1036 	}
1037 
1038 	tcu::TextureLevel					errorMask		(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width, m_height, m_layerCount);
1039 	tcu::TestLog&						log				(m_context.getTestContext().getLog());
1040 
1041 	switch (channelClass)
1042 	{
1043 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1044 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1045 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1046 		{
1047 			const int	componentCount	(tcu::getNumUsedChannels(format.order));
1048 			bool		isOk			= true;
1049 			float		clearValue;
1050 			float		renderValue;
1051 
1052 			switch (channelClass)
1053 			{
1054 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1055 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1056 					clearValue	= -1.0f;
1057 					renderValue	= 1.0f;
1058 					break;
1059 
1060 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1061 					clearValue	= 0.0f;
1062 					renderValue	= 1.0f;
1063 					break;
1064 
1065 				default:
1066 					clearValue	= 0.0f;
1067 					renderValue	= 0.0f;
1068 					DE_FATAL("Unknown channel class");
1069 			}
1070 
1071 			for (deUint32 z = 0; z < m_layerCount; z++)
1072 			for (deUint32 y = 0; y < m_height; y++)
1073 			for (deUint32 x = 0; x < m_width; x++)
1074 			{
1075 				// Color has to be black if no samples were covered, white if all samples were covered or same in every attachment
1076 				const Vec4	firstColor	(accesses[0].getPixel(x, y, z));
1077 				const Vec4	refColor	(m_sampleMask == 0x0u
1078 										? Vec4(clearValue,
1079 												componentCount > 1 ? clearValue : 0.0f,
1080 												componentCount > 2 ? clearValue : 0.0f,
1081 												componentCount > 3 ? clearValue : 1.0f)
1082 										: m_sampleMask == ((0x1u << m_sampleCount) - 1u)
1083 										? Vec4(renderValue,
1084 												componentCount > 1 ? renderValue : 0.0f,
1085 												componentCount > 2 ? renderValue : 0.0f,
1086 												componentCount > 3 ? renderValue : 1.0f)
1087 										: firstColor);
1088 
1089 				errorMask.getAccess().setPixel(okColor, x, y, z);
1090 
1091 				for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1092 				{
1093 					const Vec4 color (accesses[attachmentNdx].getPixel(x, y, z));
1094 
1095 					if (refColor != color)
1096 					{
1097 						isOk = false;
1098 						errorMask.getAccess().setPixel(errorColor, x, y, z);
1099 						break;
1100 					}
1101 				}
1102 
1103 				{
1104 					const Vec4 old = m_sum.getAccess().getPixel(x, y, z);
1105 					m_sum.getAccess().setPixel(old + (tcu::isSRGB(format) ? tcu::sRGBToLinear(firstColor) : firstColor), x, y, z);
1106 
1107 					const Vec4 oldSrgb = m_sumSrgb.getAccess().getPixel(x, y, z);
1108 					m_sumSrgb.getAccess().setPixel(oldSrgb + firstColor, x, y, z);
1109 				}
1110 			}
1111 
1112 			if (!isOk)
1113 			{
1114 				const std::string			sectionName	("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1115 				const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
1116 
1117 				for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1118 					logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1119 
1120 				logImage("ErrorMask", errorMask.getAccess());
1121 
1122 				if (m_sampleMask == 0x0u)
1123 				{
1124 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
1125 					m_resultCollector.fail("Empty sample mask didn't produce correct pixel values");
1126 				}
1127 				else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1128 				{
1129 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
1130 					m_resultCollector.fail("Full sample mask didn't produce correct pixel values");
1131 				}
1132 				else
1133 				{
1134 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve is inconsistent between attachments" << tcu::TestLog::EndMessage;
1135 					m_resultCollector.fail("Resolve is inconsistent between attachments");
1136 				}
1137 			}
1138 			break;
1139 		}
1140 
1141 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1142 		{
1143 			const int		componentCount			(tcu::getNumUsedChannels(format.order));
1144 			const UVec4		bitDepth				(tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1145 			const UVec4		renderValue				(tcu::select((UVec4(1u) << tcu::min(UVec4(8u), bitDepth)) - UVec4(1u),
1146 																  UVec4(0u, 0u, 0u, 1u),
1147 																  tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1148 			const UVec4		clearValue				(tcu::select(UVec4(0u),
1149 																 UVec4(0u, 0u, 0u, 1u),
1150 																 tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1151 			bool			unexpectedValues		= false;
1152 			bool			inconsistentComponents	= false;
1153 			bool			inconsistentAttachments	= false;
1154 
1155 			for (deUint32 z = 0; z < m_layerCount; z++)
1156 			for (deUint32 y = 0; y < m_height; y++)
1157 			for (deUint32 x = 0; x < m_width; x++)
1158 			{
1159 				// Color has to be all zeros if no samples were covered, all 255 if all samples were covered or consistent across all attachments
1160 				const UVec4 refColor	(m_sampleMask == 0x0u
1161 										? clearValue
1162 										: m_sampleMask == ((0x1u << m_sampleCount) - 1u)
1163 										? renderValue
1164 										: accesses[0].getPixelUint(x, y, z));
1165 				bool		isOk		= true;
1166 
1167 				// If reference value was taken from first attachment, check that it is valid value i.e. clear or render value
1168 				if (m_sampleMask != 0x0u && m_sampleMask != ((0x1u << m_sampleCount) - 1u))
1169 				{
1170 					// Each component must be resolved same way
1171 					const BVec4		isRenderValue			(refColor == renderValue);
1172 					const BVec4		isClearValue			(refColor == clearValue);
1173 					const bool		unexpectedValue			(tcu::anyNotEqual(tcu::logicalOr(isRenderValue, isClearValue), BVec4(true)));
1174 					const bool		inconsistentComponent	(!(tcu::allEqual(isRenderValue, BVec4(true)) || tcu::allEqual(isClearValue, BVec4(true))));
1175 
1176 					unexpectedValues		|= unexpectedValue;
1177 					inconsistentComponents	|= inconsistentComponent;
1178 
1179 					if (unexpectedValue || inconsistentComponent)
1180 						isOk = false;
1181 				}
1182 
1183 				for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1184 				{
1185 					const UVec4 color (accesses[attachmentNdx].getPixelUint(x, y, z));
1186 
1187 					if (refColor != color)
1188 					{
1189 						isOk = false;
1190 						inconsistentAttachments = true;
1191 						break;
1192 					}
1193 				}
1194 
1195 				errorMask.getAccess().setPixel((isOk ? okColor : errorColor), x, y, z);
1196 			}
1197 
1198 			if (unexpectedValues || inconsistentComponents || inconsistentAttachments)
1199 			{
1200 				const std::string			sectionName	("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1201 				const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
1202 
1203 				for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1204 					logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1205 
1206 				logImage("ErrorMask", errorMask.getAccess());
1207 
1208 				if (m_sampleMask == 0x0u)
1209 				{
1210 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
1211 					m_resultCollector.fail("Empty sample mask didn't produce correct pixels");
1212 				}
1213 				else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1214 				{
1215 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
1216 					m_resultCollector.fail("Full sample mask didn't produce correct pixels");
1217 				}
1218 				else
1219 				{
1220 					if (unexpectedValues)
1221 					{
1222 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve produced unexpected values i.e. not " << clearValue << " or " << renderValue << tcu::TestLog::EndMessage;
1223 						m_resultCollector.fail("Resolve produced unexpected values");
1224 					}
1225 
1226 					if (inconsistentComponents)
1227 					{
1228 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different components of attachment were resolved to different values." << tcu::TestLog::EndMessage;
1229 						m_resultCollector.fail("Different components of attachment were resolved to different values.");
1230 					}
1231 
1232 					if (inconsistentAttachments)
1233 					{
1234 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different attachments were resolved to different values." << tcu::TestLog::EndMessage;
1235 						m_resultCollector.fail("Different attachments were resolved to different values.");
1236 					}
1237 				}
1238 			}
1239 			break;
1240 		}
1241 
1242 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1243 		{
1244 			const int		componentCount			(tcu::getNumUsedChannels(format.order));
1245 			const IVec4		bitDepth				(tcu::getTextureFormatBitDepth(format));
1246 			const IVec4		renderValue				(tcu::select((IVec4(1) << (tcu::min(IVec4(8), bitDepth) - IVec4(1))) - IVec4(1),
1247 																  IVec4(0, 0, 0, 1),
1248 																  tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1249 			const IVec4		clearValue				(tcu::select(-(IVec4(1) << (tcu::min(IVec4(8), bitDepth) - IVec4(1))),
1250 																 IVec4(0, 0, 0, 1),
1251 																 tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1252 			bool			unexpectedValues		= false;
1253 			bool			inconsistentComponents	= false;
1254 			bool			inconsistentAttachments	= false;
1255 
1256 			for (deUint32 z = 0; z < m_layerCount; z++)
1257 			for (deUint32 y = 0; y < m_height; y++)
1258 			for (deUint32 x = 0; x < m_width; x++)
1259 			{
1260 				// Color has to be all zeros if no samples were covered, all 255 if all samples were covered or consistent across all attachments
1261 				const IVec4 refColor	(m_sampleMask == 0x0u
1262 										? clearValue
1263 										: m_sampleMask == ((0x1u << m_sampleCount) - 1u)
1264 										? renderValue
1265 										: accesses[0].getPixelInt(x, y, z));
1266 				bool		isOk		= true;
1267 
1268 				// If reference value was taken from first attachment, check that it is valid value i.e. clear or render value
1269 				if (m_sampleMask != 0x0u && m_sampleMask != ((0x1u << m_sampleCount) - 1u))
1270 				{
1271 					// Each component must be resolved same way
1272 					const BVec4		isRenderValue			(refColor == renderValue);
1273 					const BVec4		isClearValue			(refColor == clearValue);
1274 					const bool		unexpectedValue			(tcu::anyNotEqual(tcu::logicalOr(isRenderValue, isClearValue), BVec4(true)));
1275 					const bool		inconsistentComponent	(!(tcu::allEqual(isRenderValue, BVec4(true)) || tcu::allEqual(isClearValue, BVec4(true))));
1276 
1277 					unexpectedValues		|= unexpectedValue;
1278 					inconsistentComponents	|= inconsistentComponent;
1279 
1280 					if (unexpectedValue || inconsistentComponent)
1281 						isOk = false;
1282 				}
1283 
1284 				for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1285 				{
1286 					const IVec4 color (accesses[attachmentNdx].getPixelInt(x, y, z));
1287 
1288 					if (refColor != color)
1289 					{
1290 						isOk = false;
1291 						inconsistentAttachments = true;
1292 						break;
1293 					}
1294 				}
1295 
1296 				errorMask.getAccess().setPixel((isOk ? okColor : errorColor), x, y, z);
1297 			}
1298 
1299 			if (unexpectedValues || inconsistentComponents || inconsistentAttachments)
1300 			{
1301 				const std::string			sectionName	("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1302 				const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
1303 
1304 				for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1305 					logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1306 
1307 				logImage("ErrorMask", errorMask.getAccess());
1308 
1309 				if (m_sampleMask == 0x0u)
1310 				{
1311 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
1312 					m_resultCollector.fail("Empty sample mask didn't produce correct pixels");
1313 				}
1314 				else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1315 				{
1316 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
1317 					m_resultCollector.fail("Full sample mask didn't produce correct pixels");
1318 				}
1319 				else
1320 				{
1321 					if (unexpectedValues)
1322 					{
1323 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve produced unexpected values i.e. not " << clearValue << " or " << renderValue << tcu::TestLog::EndMessage;
1324 						m_resultCollector.fail("Resolve produced unexpected values");
1325 					}
1326 
1327 					if (inconsistentComponents)
1328 					{
1329 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different components of attachment were resolved to different values." << tcu::TestLog::EndMessage;
1330 						m_resultCollector.fail("Different components of attachment were resolved to different values.");
1331 					}
1332 
1333 					if (inconsistentAttachments)
1334 					{
1335 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different attachments were resolved to different values." << tcu::TestLog::EndMessage;
1336 						m_resultCollector.fail("Different attachments were resolved to different values.");
1337 					}
1338 				}
1339 			}
1340 			break;
1341 		}
1342 
1343 		default:
1344 			DE_FATAL("Unknown channel class");
1345 	}
1346 }
1347 
iterate(void)1348 tcu::TestStatus MultisampleRenderPassTestInstance::iterate (void)
1349 {
1350 	if (m_sampleMask == 0u)
1351 	{
1352 		const tcu::TextureFormat		format			(mapVkFormat(m_format));
1353 		const tcu::TextureChannelClass	channelClass	(tcu::getTextureChannelClass(format.type));
1354 		tcu::TestLog&					log				(m_context.getTestContext().getLog());
1355 
1356 		switch (channelClass)
1357 		{
1358 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1359 				log << TestLog::Message << "Clearing target to zero and rendering 255 pixels with every possible sample mask" << TestLog::EndMessage;
1360 				break;
1361 
1362 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1363 				log << TestLog::Message << "Clearing target to -128 and rendering 127 pixels with every possible sample mask" << TestLog::EndMessage;
1364 				break;
1365 
1366 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1367 			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1368 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1369 				log << TestLog::Message << "Clearing target to black and rendering white pixels with every possible sample mask" << TestLog::EndMessage;
1370 				break;
1371 
1372 			default:
1373 				DE_FATAL("Unknown channel class");
1374 		}
1375 	}
1376 
1377 	submitSwitch(m_groupParams);
1378 	verify();
1379 
1380 	if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1381 	{
1382 		const tcu::TextureFormat		format			(mapVkFormat(m_format));
1383 		const tcu::TextureChannelClass	channelClass	(tcu::getTextureChannelClass(format.type));
1384 		const Vec4						threshold		(getFormatThreshold());
1385 		tcu::TestLog&					log				(m_context.getTestContext().getLog());
1386 
1387 		if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT
1388 				|| channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT
1389 				|| channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
1390 		{
1391 			const int			componentCount	(tcu::getNumUsedChannels(format.order));
1392 			const Vec4			errorColor		(1.0f, 0.0f, 0.0f, 1.0f);
1393 			const Vec4			okColor			(0.0f, 1.0f, 0.0f, 1.0f);
1394 			tcu::TextureLevel	errorMask		(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width, m_height, m_layerCount);
1395 			bool				isOk			= true;
1396 			Vec4				maxDiff			(0.0f);
1397 			Vec4				expectedAverage;
1398 
1399 			switch (channelClass)
1400 			{
1401 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1402 				{
1403 					expectedAverage = Vec4(0.5f, componentCount > 1 ? 0.5f : 0.0f, componentCount > 2 ? 0.5f : 0.0f, componentCount > 3 ? 0.5f : 1.0f);
1404 					break;
1405 				}
1406 
1407 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1408 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1409 				{
1410 					expectedAverage = Vec4(0.0f, 0.0f, 0.0f, componentCount > 3 ? 0.0f : 1.0f);
1411 					break;
1412 				}
1413 
1414 				default:
1415 					DE_FATAL("Unknown channel class");
1416 			}
1417 
1418 			for (deUint32 z = 0; z < m_layerCount; z++)
1419 			for (deUint32 y = 0; y < m_height; y++)
1420 			for (deUint32 x = 0; x < m_width; x++)
1421 			{
1422 				const Vec4	sum		(m_sum.getAccess().getPixel(x, y, z));
1423 				const Vec4	average	(sum / Vec4((float)(0x1u << m_sampleCount)));
1424 				const Vec4	diff	(tcu::abs(average - expectedAverage));
1425 
1426 				m_sum.getAccess().setPixel(average, x, y, z);
1427 				errorMask.getAccess().setPixel(okColor, x, y, z);
1428 
1429 				bool failThreshold;
1430 
1431 				if (!tcu::isSRGB(format))
1432 				{
1433 					failThreshold = (diff[0] > threshold.x()
1434 										|| diff[1] > threshold.y()
1435 										|| diff[2] > threshold.z()
1436 										|| diff[3] > threshold.w());
1437 				}
1438 				else
1439 				{
1440 					const Vec4	sumSrgb(m_sumSrgb.getAccess().getPixel(x, y, z));
1441 					const Vec4	averageSrgb(sumSrgb / Vec4((float)(0x1u << m_sampleCount)));
1442 					const Vec4	diffSrgb(tcu::abs(averageSrgb - expectedAverage));
1443 
1444 					m_sumSrgb.getAccess().setPixel(averageSrgb, x, y, z);
1445 
1446 					// Spec doesn't restrict implementation to downsample in linear color space. So, comparing both non linear and
1447 					// linear diff's in case of srgb formats.
1448 					failThreshold = ((diff[0] > threshold.x()
1449 										|| diff[1] > threshold.y()
1450 										|| diff[2] > threshold.z()
1451 										|| diff[3] > threshold.w()) &&
1452 									(diffSrgb[0] > threshold.x()
1453 										|| diffSrgb[1] > threshold.y()
1454 										|| diffSrgb[2] > threshold.z()
1455 										|| diffSrgb[3] > threshold.w()));
1456 
1457 				}
1458 
1459 				if (failThreshold)
1460 				{
1461 					isOk	= false;
1462 					maxDiff	= tcu::max(maxDiff, diff);
1463 					errorMask.getAccess().setPixel(errorColor, x, y, z);
1464 				}
1465 			}
1466 
1467 			log << TestLog::Image("Average resolved values in attachment 0", "Average resolved values in attachment 0", m_sum);
1468 
1469 			if (!isOk)
1470 			{
1471 				std::stringstream	message;
1472 
1473 				m_context.getTestContext().getLog() << tcu::LogImage("ErrorMask", "ErrorMask", errorMask.getAccess());
1474 
1475 				message << "Average resolved values differ from expected average values by more than ";
1476 
1477 				switch (componentCount)
1478 				{
1479 					case 1:
1480 						message << threshold.x();
1481 						break;
1482 					case 2:
1483 						message << "vec2" << Vec2(threshold.x(), threshold.y());
1484 						break;
1485 					case 3:
1486 						message << "vec3" << Vec3(threshold.x(), threshold.y(), threshold.z());
1487 						break;
1488 					default:
1489 						message << "vec4" << threshold;
1490 				}
1491 
1492 				message << ". Max diff " << maxDiff;
1493 				log << TestLog::Message << message.str() << TestLog::EndMessage;
1494 
1495 				m_resultCollector.fail("Average resolved values differ from expected average values");
1496 			}
1497 		}
1498 
1499 		return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1500 	}
1501 	else
1502 	{
1503 		m_sampleMask++;
1504 		return tcu::TestStatus::incomplete();
1505 	}
1506 }
1507 
1508 template<typename RenderPassTrait>
createRenderPass(bool usedResolveAttachment)1509 Move<VkRenderPass> MultisampleRenderPassTestInstance::createRenderPass (bool usedResolveAttachment)
1510 {
1511 	// make name for RenderPass1Trait or RenderPass2Trait shorter
1512 	typedef RenderPassTrait RPT;
1513 	typedef typename RPT::AttDesc				AttDesc;
1514 	typedef typename RPT::AttRef				AttRef;
1515 	typedef typename RPT::SubpassDesc			SubpassDesc;
1516 	typedef typename RPT::RenderPassCreateInfo	RenderPassCreateInfo;
1517 
1518 	const DeviceInterface&	vkd						= m_context.getDeviceInterface();
1519 	VkDevice				device					= m_context.getDevice();
1520 	std::vector<AttDesc>	attachments;
1521 	std::vector<AttRef>		colorAttachmentRefs;
1522 	std::vector<AttRef>		resolveAttachmentRefs;
1523 
1524 	for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1525 	{
1526 		{
1527 			const AttDesc multisampleAttachment
1528 			(
1529 															// sType
1530 				DE_NULL,									// pNext
1531 				0u,											// flags
1532 				m_format,									// format
1533 				m_sampleCount,								// samples
1534 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// loadOp
1535 				VK_ATTACHMENT_STORE_OP_DONT_CARE,			// storeOp
1536 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// stencilLoadOp
1537 				VK_ATTACHMENT_STORE_OP_DONT_CARE,			// stencilStoreOp
1538 				VK_IMAGE_LAYOUT_UNDEFINED,					// initialLayout
1539 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// finalLayout
1540 			);
1541 			const AttRef attachmentRef
1542 			(
1543 															// sType
1544 				DE_NULL,									// pNext
1545 				(deUint32)attachments.size(),				// attachment
1546 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// layout
1547 				0u											// aspectMask
1548 			);
1549 			colorAttachmentRefs.push_back(attachmentRef);
1550 			attachments.push_back(multisampleAttachment);
1551 		}
1552 		{
1553 			const AttDesc singlesampleAttachment
1554 			(
1555 															// sType
1556 				DE_NULL,									// pNext
1557 				0u,											// flags
1558 				m_format,									// format
1559 				VK_SAMPLE_COUNT_1_BIT,						// samples
1560 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// loadOp
1561 				VK_ATTACHMENT_STORE_OP_STORE,				// storeOp
1562 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// stencilLoadOp
1563 				VK_ATTACHMENT_STORE_OP_DONT_CARE,			// stencilStoreOp
1564 				VK_IMAGE_LAYOUT_UNDEFINED,					// initialLayout
1565 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL		// finalLayout
1566 			);
1567 			const auto attachmentId = (usedResolveAttachment ? static_cast<deUint32>(attachments.size()) : VK_ATTACHMENT_UNUSED);
1568 			const AttRef attachmentRef
1569 			(
1570 															// sType
1571 				DE_NULL,									// pNext
1572 				attachmentId,								// attachment
1573 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// layout
1574 				0u											// aspectMask
1575 			);
1576 			resolveAttachmentRefs.push_back(attachmentRef);
1577 			attachments.push_back(singlesampleAttachment);
1578 		}
1579 	}
1580 
1581 	DE_ASSERT(colorAttachmentRefs.size() == resolveAttachmentRefs.size());
1582 	DE_ASSERT(attachments.size() == colorAttachmentRefs.size() + resolveAttachmentRefs.size());
1583 
1584 	const SubpassDesc subpass
1585 	(
1586 														// sType
1587 		DE_NULL,										// pNext
1588 		(VkSubpassDescriptionFlags)0,					// flags
1589 		VK_PIPELINE_BIND_POINT_GRAPHICS,				// pipelineBindPoint
1590 		0u,												// viewMask
1591 		0u,												// inputAttachmentCount
1592 		DE_NULL,										// pInputAttachments
1593 		(deUint32)colorAttachmentRefs.size(),			// colorAttachmentCount
1594 		&colorAttachmentRefs[0],						// pColorAttachments
1595 		&resolveAttachmentRefs[0],						// pResolveAttachments
1596 		DE_NULL,										// pDepthStencilAttachment
1597 		0u,												// preserveAttachmentCount
1598 		DE_NULL											// pPreserveAttachments
1599 	);
1600 	const RenderPassCreateInfo renderPassCreator
1601 	(
1602 														// sType
1603 		DE_NULL,										// pNext
1604 		(VkRenderPassCreateFlags)0u,					// flags
1605 		(deUint32)attachments.size(),					// attachmentCount
1606 		&attachments[0],								// pAttachments
1607 		1u,												// subpassCount
1608 		&subpass,										// pSubpasses
1609 		0u,												// dependencyCount
1610 		DE_NULL,										// pDependencies
1611 		0u,												// correlatedViewMaskCount
1612 		DE_NULL											// pCorrelatedViewMasks
1613 	);
1614 
1615 	return renderPassCreator.createRenderPass(vkd, device);
1616 }
1617 
createRenderPassSwitch(bool usedResolveAttachment)1618 Move<VkRenderPass> MultisampleRenderPassTestInstance::createRenderPassSwitch (bool usedResolveAttachment)
1619 {
1620 	switch (m_groupParams->renderingType)
1621 	{
1622 		case RENDERING_TYPE_RENDERPASS_LEGACY:
1623 			return createRenderPass<RenderPass1Trait>(usedResolveAttachment);
1624 		case RENDERING_TYPE_RENDERPASS2:
1625 			return createRenderPass<RenderPass2Trait>(usedResolveAttachment);
1626 		case RENDERING_TYPE_DYNAMIC_RENDERING:
1627 			return Move<VkRenderPass>();
1628 		default:
1629 			TCU_THROW(InternalError, "Impossible");
1630 	}
1631 }
1632 
createRenderPassCompatible(void)1633 Move<VkRenderPass> MultisampleRenderPassTestInstance::createRenderPassCompatible (void)
1634 {
1635 	if (m_testCompatibility)
1636 	{
1637 		// The compatible render pass is always created with a used resolve attachment.
1638 		return createRenderPassSwitch(true);
1639 	}
1640 	else
1641 	{
1642 		return {};
1643 	}
1644 }
1645 
createRenderPipelineLayout(void)1646 Move<VkPipelineLayout> MultisampleRenderPassTestInstance::createRenderPipelineLayout (void)
1647 {
1648 	const DeviceInterface&	vkd		= m_context.getDeviceInterface();
1649 	VkDevice				device	= m_context.getDevice();
1650 
1651 	const VkPushConstantRange pushConstant =
1652 	{
1653 		VK_SHADER_STAGE_FRAGMENT_BIT,
1654 		0u,
1655 		4u
1656 	};
1657 	const VkPipelineLayoutCreateInfo createInfo =
1658 	{
1659 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1660 		DE_NULL,
1661 		(vk::VkPipelineLayoutCreateFlags)0,
1662 
1663 		0u,
1664 		DE_NULL,
1665 
1666 		1u,
1667 		&pushConstant
1668 	};
1669 
1670 	return createPipelineLayout(vkd, device, &createInfo);
1671 }
1672 
createRenderPipeline(void)1673 Move<VkPipeline> MultisampleRenderPassTestInstance::createRenderPipeline (void)
1674 {
1675 	const DeviceInterface&			vkd						= m_context.getDeviceInterface();
1676 	VkDevice						device					= m_context.getDevice();
1677 	const vk::BinaryCollection&		binaryCollection		= m_context.getBinaryCollection();
1678 	const Unique<VkShaderModule>	vertexShaderModule		(createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
1679 	const Unique<VkShaderModule>	fragmentShaderModule	(createShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u));
1680 	const Move<VkShaderModule>		geometryShaderModule	(m_layerCount == 1 ? Move<VkShaderModule>() : createShaderModule(vkd, device, binaryCollection.get("geom"), 0u));
1681 	// Disable blending
1682 	const VkPipelineColorBlendAttachmentState attachmentBlendState =
1683 	{
1684 		VK_FALSE,
1685 		VK_BLEND_FACTOR_SRC_ALPHA,
1686 		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
1687 		VK_BLEND_OP_ADD,
1688 		VK_BLEND_FACTOR_ONE,
1689 		VK_BLEND_FACTOR_ONE,
1690 		VK_BLEND_OP_ADD,
1691 		VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
1692 	};
1693 	std::vector<VkPipelineColorBlendAttachmentState>	attachmentBlendStates(m_attachmentsCount, attachmentBlendState);
1694 	const VkPipelineVertexInputStateCreateInfo			vertexInputState =
1695 	{
1696 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
1697 		DE_NULL,
1698 		(VkPipelineVertexInputStateCreateFlags)0u,
1699 
1700 		0u,
1701 		DE_NULL,
1702 
1703 		0u,
1704 		DE_NULL
1705 	};
1706 	const tcu::UVec2				renderArea	(m_width, m_height);
1707 	const std::vector<VkViewport>	viewports	(1, makeViewport(renderArea));
1708 	const std::vector<VkRect2D>		scissors	(1, makeRect2D(renderArea));
1709 
1710 	const VkPipelineMultisampleStateCreateInfo multisampleState =
1711 	{
1712 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
1713 		DE_NULL,
1714 		(VkPipelineMultisampleStateCreateFlags)0u,
1715 
1716 		sampleCountBitFromSampleCount(m_sampleCount),
1717 		VK_FALSE,
1718 		0.0f,
1719 		DE_NULL,
1720 		VK_FALSE,
1721 		VK_FALSE,
1722 	};
1723 	const VkPipelineDepthStencilStateCreateInfo depthStencilState =
1724 	{
1725 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
1726 		DE_NULL,
1727 		(VkPipelineDepthStencilStateCreateFlags)0u,
1728 
1729 		VK_FALSE,
1730 		VK_TRUE,
1731 		VK_COMPARE_OP_ALWAYS,
1732 		VK_FALSE,
1733 		VK_TRUE,
1734 		{
1735 			VK_STENCIL_OP_KEEP,
1736 			VK_STENCIL_OP_INCREMENT_AND_WRAP,
1737 			VK_STENCIL_OP_KEEP,
1738 			VK_COMPARE_OP_ALWAYS,
1739 			~0u,
1740 			~0u,
1741 			0xFFu / (m_sampleCount + 1)
1742 		},
1743 		{
1744 			VK_STENCIL_OP_KEEP,
1745 			VK_STENCIL_OP_INCREMENT_AND_WRAP,
1746 			VK_STENCIL_OP_KEEP,
1747 			VK_COMPARE_OP_ALWAYS,
1748 			~0u,
1749 			~0u,
1750 			0xFFu / (m_sampleCount + 1)
1751 		},
1752 
1753 		0.0f,
1754 		1.0f
1755 	};
1756 	const VkPipelineColorBlendStateCreateInfo blendState =
1757 	{
1758 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
1759 		DE_NULL,
1760 		(VkPipelineColorBlendStateCreateFlags)0u,
1761 
1762 		VK_FALSE,
1763 		VK_LOGIC_OP_COPY,
1764 		deUint32(attachmentBlendStates.size()),
1765 		&attachmentBlendStates[0],
1766 		{ 0.0f, 0.0f, 0.0f, 0.0f }
1767 	};
1768 
1769 	void* pNext = DE_NULL;
1770 
1771 #ifndef CTS_USES_VULKANSC
1772 	std::vector<VkFormat> attachmentFormats(m_attachmentsCount, m_format);
1773 	VkPipelineRenderingCreateInfoKHR renderingCreateInfo
1774 	{
1775 		VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
1776 		DE_NULL,
1777 		0u,
1778 		m_attachmentsCount,
1779 		attachmentFormats.data(),
1780 		VK_FORMAT_UNDEFINED,
1781 		VK_FORMAT_UNDEFINED
1782 	};
1783 	if (m_groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
1784 		pNext = &renderingCreateInfo;
1785 #endif // CTS_USES_VULKANSC
1786 
1787 	return makeGraphicsPipeline(vkd,												// const DeviceInterface&                        vk
1788 								device,												// const VkDevice                                device
1789 								*m_renderPipelineLayout,							// const VkPipelineLayout                        pipelineLayout
1790 								*vertexShaderModule,								// const VkShaderModule                          vertexShaderModule
1791 								DE_NULL,											// const VkShaderModule                          tessellationControlShaderModule
1792 								DE_NULL,											// const VkShaderModule                          tessellationEvalShaderModule
1793 								m_layerCount != 1 ? *geometryShaderModule : DE_NULL,// const VkShaderModule                          geometryShaderModule
1794 								*fragmentShaderModule,								// const VkShaderModule                          fragmentShaderModule
1795 								*m_renderPass,										// const VkRenderPass                            renderPass
1796 								viewports,											// const std::vector<VkViewport>&                viewports
1797 								scissors,											// const std::vector<VkRect2D>&                  scissors
1798 								VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,				// const VkPrimitiveTopology                     topology
1799 								0u,													// const deUint32                                subpass
1800 								0u,													// const deUint32                                patchControlPoints
1801 								&vertexInputState,									// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
1802 								DE_NULL,											// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1803 								&multisampleState,									// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
1804 								&depthStencilState,									// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
1805 								&blendState,										// const VkPipelineColorBlendStateCreateInfo*    colorBlendStateCreateInfo
1806 								DE_NULL,											// const VkPipelineDynamicStateCreateInfo*       dynamicStateCreateInfo
1807 								pNext);												// const void*                                   pNext
1808 }
1809 
1810 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags) const1811 void MultisampleRenderPassTestInstance::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags) const
1812 {
1813 	const DeviceInterface& vkd = m_context.getDeviceInterface();
1814 	std::vector<VkFormat> formats(m_attachmentsCount, m_format);
1815 
1816 	VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
1817 	{
1818 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,		// VkStructureType					sType;
1819 		DE_NULL,																// const void*						pNext;
1820 		renderingFlags,															// VkRenderingFlagsKHR				flags;
1821 		0u,																		// uint32_t							viewMask;
1822 		m_attachmentsCount,														// uint32_t							colorAttachmentCount;
1823 		formats.data(),															// const VkFormat*					pColorAttachmentFormats;
1824 		VK_FORMAT_UNDEFINED,													// VkFormat							depthAttachmentFormat;
1825 		VK_FORMAT_UNDEFINED,													// VkFormat							stencilAttachmentFormat;
1826 		m_sampleCount,															// VkSampleCountFlagBits			rasterizationSamples;
1827 	};
1828 
1829 	const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
1830 	VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
1831 	if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1832 		usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
1833 
1834 	const VkCommandBufferBeginInfo commandBufBeginParams
1835 	{
1836 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,							// VkStructureType					sType;
1837 		DE_NULL,																// const void*						pNext;
1838 		usageFlags,																// VkCommandBufferUsageFlags		flags;
1839 		&bufferInheritanceInfo
1840 	};
1841 
1842 	VK_CHECK(vkd.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
1843 }
1844 #endif // CTS_USES_VULKANSC
1845 
1846 class MaxAttachmenstsRenderPassTestInstance : public MultisampleRenderPassTestBase
1847 {
1848 public:
1849 	MaxAttachmenstsRenderPassTestInstance	(Context& context, TestConfig config);
1850 	~MaxAttachmenstsRenderPassTestInstance	(void);
1851 
1852 	tcu::TestStatus			iterate			(void);
1853 
1854 private:
1855 
1856 	template<typename RenderpassSubpass>
1857 	void					submit						(void);
1858 	void					submitSwitch				(RenderingType renderingType);
1859 	void					verify						(void);
1860 
1861 	Move<VkDescriptorSetLayout>	createDescriptorSetLayout	(void);
1862 	Move<VkDescriptorPool>		createDescriptorPool		(void);
1863 	Move<VkDescriptorSet>		createDescriptorSet			(void);
1864 
1865 	template<typename RenderPassTrait>
1866 	Move<VkRenderPass>		createRenderPass			(void);
1867 	Move<VkRenderPass>		createRenderPassSwitch		(const RenderingType renderingType);
1868 	Move<VkPipelineLayout>	createRenderPipelineLayout	(bool secondSubpass);
1869 	Move<VkPipeline>		createRenderPipeline		(bool secondSubpass);
1870 
1871 private:
1872 
1873 	const std::vector<VkImageSp>			m_multisampleImages;
1874 	const std::vector<AllocationSp>			m_multisampleImageMemory;
1875 	const std::vector<VkImageViewSp>		m_multisampleImageViews;
1876 
1877 	const std::vector<VkImageSp>			m_singlesampleImages;
1878 	const std::vector<AllocationSp>			m_singlesampleImageMemory;
1879 	const std::vector<VkImageViewSp>		m_singlesampleImageViews;
1880 
1881 	const Unique<VkDescriptorSetLayout>		m_descriptorSetLayout;
1882 	const Unique<VkDescriptorPool>			m_descriptorPool;
1883 	const Unique<VkDescriptorSet>			m_descriptorSet;
1884 
1885 	const Unique<VkRenderPass>				m_renderPass;
1886 	const Unique<VkFramebuffer>				m_framebuffer;
1887 
1888 	const Unique<VkPipelineLayout>			m_pipelineLayoutPass0;
1889 	const Unique<VkPipeline>				m_pipelinePass0;
1890 	const Unique<VkPipelineLayout>			m_pipelineLayoutPass1;
1891 	const Unique<VkPipeline>				m_pipelinePass1;
1892 
1893 	const std::vector<VkBufferSp>			m_buffers;
1894 	const std::vector<AllocationSp>			m_bufferMemory;
1895 
1896 	const Unique<VkCommandPool>				m_commandPool;
1897 	tcu::ResultCollector					m_resultCollector;
1898 };
1899 
MaxAttachmenstsRenderPassTestInstance(Context& context, TestConfig config)1900 MaxAttachmenstsRenderPassTestInstance::MaxAttachmenstsRenderPassTestInstance (Context& context, TestConfig config)
1901 	: MultisampleRenderPassTestBase(context, config)
1902 
1903 	, m_multisampleImages		(createImages(m_sampleCount, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
1904 	, m_multisampleImageMemory	(createImageMemory(m_multisampleImages))
1905 	, m_multisampleImageViews	(createImageViews(m_multisampleImages))
1906 
1907 	, m_singlesampleImages		(createImages(VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT))
1908 	, m_singlesampleImageMemory	(createImageMemory(m_singlesampleImages))
1909 	, m_singlesampleImageViews	(createImageViews(m_singlesampleImages))
1910 
1911 	, m_descriptorSetLayout		(createDescriptorSetLayout())
1912 	, m_descriptorPool			(createDescriptorPool())
1913 	, m_descriptorSet			(createDescriptorSet())
1914 
1915 	, m_renderPass				(createRenderPassSwitch(config.groupParams->renderingType))
1916 	, m_framebuffer				(createFramebuffer(m_multisampleImageViews, m_singlesampleImageViews, *m_renderPass))
1917 
1918 	, m_pipelineLayoutPass0		(createRenderPipelineLayout(0))
1919 	, m_pipelinePass0			(createRenderPipeline(0))
1920 	, m_pipelineLayoutPass1		(createRenderPipelineLayout(1))
1921 	, m_pipelinePass1			(createRenderPipeline(1))
1922 
1923 	, m_buffers					(createBuffers())
1924 	, m_bufferMemory			(createBufferMemory(m_buffers))
1925 
1926 	, m_commandPool				(createCommandPool(context.getDeviceInterface(), context.getDevice(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
1927 {
1928 }
1929 
~MaxAttachmenstsRenderPassTestInstance(void)1930 MaxAttachmenstsRenderPassTestInstance::~MaxAttachmenstsRenderPassTestInstance (void)
1931 {
1932 }
1933 
1934 template<typename RenderpassSubpass>
submit(void)1935 void MaxAttachmenstsRenderPassTestInstance::submit (void)
1936 {
1937 	const DeviceInterface&								vkd					(m_context.getDeviceInterface());
1938 	const VkDevice										device				(m_context.getDevice());
1939 	const Unique<VkCommandBuffer>						commandBuffer		(allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1940 	const typename RenderpassSubpass::SubpassBeginInfo	subpassBeginInfo	(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
1941 	const typename RenderpassSubpass::SubpassEndInfo	subpassEndInfo		(DE_NULL);
1942 
1943 	beginCommandBuffer(vkd, *commandBuffer);
1944 
1945 	// Memory barriers between previous copies and rendering
1946 	{
1947 		std::vector<VkImageMemoryBarrier> barriers;
1948 
1949 		for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
1950 		{
1951 			const VkImageMemoryBarrier barrier =
1952 			{
1953 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
1954 				DE_NULL,
1955 
1956 				VK_ACCESS_TRANSFER_READ_BIT,
1957 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1958 
1959 				VK_IMAGE_LAYOUT_UNDEFINED,
1960 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1961 
1962 				VK_QUEUE_FAMILY_IGNORED,
1963 				VK_QUEUE_FAMILY_IGNORED,
1964 
1965 				**m_singlesampleImages[dstNdx],
1966 				{
1967 					VK_IMAGE_ASPECT_COLOR_BIT,
1968 					0u,
1969 					1u,
1970 					0u,
1971 					m_layerCount
1972 				}
1973 			};
1974 
1975 			barriers.push_back(barrier);
1976 		}
1977 
1978 		vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0]);
1979 	}
1980 
1981 	{
1982 		const VkRenderPassBeginInfo beginInfo =
1983 		{
1984 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
1985 			DE_NULL,
1986 
1987 			*m_renderPass,
1988 			*m_framebuffer,
1989 
1990 			{
1991 				{ 0u, 0u },
1992 				{ m_width, m_height }
1993 			},
1994 
1995 			0u,
1996 			DE_NULL
1997 		};
1998 		RenderpassSubpass::cmdBeginRenderPass(vkd, *commandBuffer, &beginInfo, &subpassBeginInfo);
1999 	}
2000 
2001 	// Clear everything to black
2002 	clearAttachments(*commandBuffer);
2003 
2004 	// First subpass - render black samples
2005 	{
2006 		vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelinePass0);
2007 		vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
2008 	}
2009 
2010 	// Second subpasss - merge attachments
2011 	{
2012 		RenderpassSubpass::cmdNextSubpass(vkd, *commandBuffer, &subpassBeginInfo, &subpassEndInfo);
2013 		vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelinePass1);
2014 		vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayoutPass1, 0, 1u, &*m_descriptorSet, 0, NULL);
2015 		vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
2016 	}
2017 
2018 	RenderpassSubpass::cmdEndRenderPass(vkd, *commandBuffer, &subpassEndInfo);
2019 
2020 	// Memory barriers between rendering and copies
2021 	{
2022 		std::vector<VkImageMemoryBarrier> barriers;
2023 
2024 		for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
2025 		{
2026 			const VkImageMemoryBarrier barrier =
2027 			{
2028 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2029 				DE_NULL,
2030 
2031 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
2032 				VK_ACCESS_TRANSFER_READ_BIT,
2033 
2034 				VK_IMAGE_LAYOUT_GENERAL,
2035 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2036 
2037 				VK_QUEUE_FAMILY_IGNORED,
2038 				VK_QUEUE_FAMILY_IGNORED,
2039 
2040 				**m_singlesampleImages[dstNdx],
2041 				{
2042 					VK_IMAGE_ASPECT_COLOR_BIT,
2043 					0u,
2044 					1u,
2045 					0u,
2046 					m_layerCount
2047 				}
2048 			};
2049 
2050 			barriers.push_back(barrier);
2051 		}
2052 
2053 		vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0]);
2054 	}
2055 
2056 	// Copy image memory to buffers
2057 	for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
2058 	{
2059 		const VkBufferImageCopy region =
2060 		{
2061 			0u,
2062 			0u,
2063 			0u,
2064 			{
2065 				VK_IMAGE_ASPECT_COLOR_BIT,
2066 				0u,
2067 				0u,
2068 				m_layerCount,
2069 			},
2070 			{ 0u, 0u, 0u },
2071 			{ m_width, m_height, 1u }
2072 		};
2073 
2074 		vkd.cmdCopyImageToBuffer(*commandBuffer, **m_singlesampleImages[dstNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_buffers[dstNdx], 1u, &region);
2075 	}
2076 
2077 	// Memory barriers between copies and host access
2078 	{
2079 		std::vector<VkBufferMemoryBarrier> barriers;
2080 
2081 		for (size_t dstNdx = 0; dstNdx < m_buffers.size(); dstNdx++)
2082 		{
2083 			const VkBufferMemoryBarrier barrier =
2084 			{
2085 				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2086 				DE_NULL,
2087 
2088 				VK_ACCESS_TRANSFER_WRITE_BIT,
2089 				VK_ACCESS_HOST_READ_BIT,
2090 
2091 				VK_QUEUE_FAMILY_IGNORED,
2092 				VK_QUEUE_FAMILY_IGNORED,
2093 
2094 				**m_buffers[dstNdx],
2095 				0u,
2096 				VK_WHOLE_SIZE
2097 			};
2098 
2099 			barriers.push_back(barrier);
2100 		}
2101 
2102 		vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0], 0u, DE_NULL);
2103 	}
2104 
2105 	endCommandBuffer(vkd, *commandBuffer);
2106 
2107 	submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *commandBuffer);
2108 
2109 	for (size_t memoryBufferNdx = 0; memoryBufferNdx < m_bufferMemory.size(); memoryBufferNdx++)
2110 		invalidateMappedMemoryRange(vkd, device, m_bufferMemory[memoryBufferNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
2111 }
2112 
submitSwitch(RenderingType renderingType)2113 void MaxAttachmenstsRenderPassTestInstance::submitSwitch (RenderingType renderingType)
2114 {
2115 	switch (renderingType)
2116 	{
2117 		case RENDERING_TYPE_RENDERPASS_LEGACY:
2118 			submit<RenderpassSubpass1>();
2119 			break;
2120 		case RENDERING_TYPE_RENDERPASS2:
2121 			submit<RenderpassSubpass2>();
2122 			break;
2123 		default:
2124 			TCU_THROW(InternalError, "Impossible");
2125 	}
2126 }
2127 
2128 template <typename VecType>
isValueAboveThreshold1(const VecType& vale, const VecType& threshold)2129 bool isValueAboveThreshold1 (const VecType& vale, const VecType& threshold)
2130 {
2131 	return (vale[0] > threshold[0]);
2132 }
2133 
2134 template <typename VecType>
isValueAboveThreshold2(const VecType& vale, const VecType& threshold)2135 bool isValueAboveThreshold2 (const VecType& vale, const VecType& threshold)
2136 {
2137 	return (vale[0] > threshold[0]) || (vale[1] > threshold[1]);
2138 }
2139 
2140 template <typename VecType>
isValueAboveThreshold3(const VecType& vale, const VecType& threshold)2141 bool isValueAboveThreshold3 (const VecType& vale, const VecType& threshold)
2142 {
2143 	return (vale[0] > threshold[0]) || (vale[1] > threshold[1]) || (vale[2] > threshold[2]);
2144 }
2145 
2146 template <typename VecType>
isValueAboveThreshold4(const VecType& vale, const VecType& threshold)2147 bool isValueAboveThreshold4 (const VecType& vale, const VecType& threshold)
2148 {
2149 	return (vale[0] > threshold[0]) || (vale[1] > threshold[1]) || (vale[2] > threshold[2]) || (vale[3] > threshold[3]);
2150 }
2151 
verify(void)2152 void MaxAttachmenstsRenderPassTestInstance::verify (void)
2153 {
2154 	const Vec4							errorColor		(1.0f, 0.0f, 0.0f, 1.0f);
2155 	const Vec4							okColor			(0.0f, 1.0f, 0.0f, 1.0f);
2156 	const tcu::TextureFormat			format			(mapVkFormat(m_format));
2157 	const tcu::TextureChannelClass		channelClass	(tcu::getTextureChannelClass(format.type));
2158 	const int							componentCount	(tcu::getNumUsedChannels(format.order));
2159 	const int							outputsCount	= m_attachmentsCount / 2;
2160 
2161 	DE_ASSERT((componentCount >= 0) && (componentCount < 5));
2162 
2163 	std::vector<tcu::ConstPixelBufferAccess> accesses;
2164 	for (int outputNdx = 0; outputNdx < outputsCount; ++outputNdx)
2165 	{
2166 		void* const ptr = m_bufferMemory[outputNdx]->getHostPtr();
2167 		accesses.push_back(tcu::ConstPixelBufferAccess(format, m_width, m_height, 1, ptr));
2168 	}
2169 
2170 	tcu::TextureLevel	errorMask	(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width, m_height, outputsCount);
2171 	tcu::TestLog&		log			(m_context.getTestContext().getLog());
2172 	bool				isOk		= true;
2173 
2174 	switch (channelClass)
2175 	{
2176 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2177 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2178 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2179 		{
2180 			const Vec4 refColor(0.0f, 0.3f, 0.6f, 0.75f);
2181 			const Vec4 threshold(getFormatThreshold());
2182 
2183 			typedef bool(*ValueAboveThresholdFn)(const Vec4&, const Vec4&);
2184 			ValueAboveThresholdFn componentToFnMap[4] =
2185 			{
2186 				isValueAboveThreshold1<Vec4>,
2187 				isValueAboveThreshold2<Vec4>,
2188 				isValueAboveThreshold3<Vec4>,
2189 				isValueAboveThreshold4<Vec4>
2190 			};
2191 			ValueAboveThresholdFn	isValueAboveThreshold	= componentToFnMap[componentCount - 1];
2192 			bool					isSRGBFormat			= tcu::isSRGB(format);
2193 
2194 			for (int outputNdx = 0; outputNdx < outputsCount; outputNdx++)
2195 			for (int y = 0; y < (int)m_height; y++)
2196 			for (int x = 0; x < (int)m_width; x++)
2197 			{
2198 				Vec4 color = accesses[outputNdx].getPixel(x, y);
2199 				if (isSRGBFormat)
2200 					color = tcu::sRGBToLinear(color);
2201 
2202 				const Vec4 diff(tcu::abs(color - refColor));
2203 
2204 				if (isValueAboveThreshold(diff, threshold))
2205 				{
2206 					isOk = false;
2207 					errorMask.getAccess().setPixel(errorColor, x, y, outputNdx);
2208 					break;
2209 				}
2210 				else
2211 					errorMask.getAccess().setPixel(okColor, x, y, outputNdx);
2212 			}
2213 			break;
2214 		}
2215 
2216 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2217 		{
2218 			const UVec4	refColor(0, 48, 144, 189);
2219 			UVec4		threshold(1, 1, 1, 1);
2220 
2221 			if (m_format == VK_FORMAT_A2B10G10R10_UINT_PACK32)
2222 				threshold[3] = 200;
2223 
2224 			typedef bool(*ValueAboveThresholdFn)(const UVec4&, const UVec4&);
2225 			ValueAboveThresholdFn componentToFnMap[4] =
2226 			{
2227 				isValueAboveThreshold1<UVec4>,
2228 				isValueAboveThreshold2<UVec4>,
2229 				isValueAboveThreshold3<UVec4>,
2230 				isValueAboveThreshold4<UVec4>
2231 			};
2232 			ValueAboveThresholdFn isValueAboveThreshold = componentToFnMap[componentCount - 1];
2233 
2234 			for (int outputNdx = 0; outputNdx < outputsCount; outputNdx++)
2235 			for (int y = 0; y < (int)m_height; y++)
2236 			for (int x = 0; x < (int)m_width; x++)
2237 			{
2238 				const UVec4 color	(accesses[outputNdx].getPixelUint(x, y));
2239 				const UVec4 diff	(std::abs(int(color.x()) - int(refColor.x())),
2240 									 std::abs(int(color.y()) - int(refColor.y())),
2241 									 std::abs(int(color.z()) - int(refColor.z())),
2242 									 std::abs(int(color.w()) - int(refColor.w())));
2243 
2244 				if (isValueAboveThreshold(diff, threshold))
2245 				{
2246 					isOk = false;
2247 					errorMask.getAccess().setPixel(errorColor, x, y, outputNdx);
2248 					break;
2249 				}
2250 				else
2251 					errorMask.getAccess().setPixel(okColor, x, y, outputNdx);
2252 			}
2253 			break;
2254 		}
2255 
2256 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2257 		{
2258 			const IVec4 refColor	(0, 24, 75, 93);
2259 			const IVec4 threshold	(1, 1, 1, 1);
2260 
2261 			typedef bool(*ValueAboveThresholdFn)(const IVec4&, const IVec4&);
2262 			ValueAboveThresholdFn componentToFnMap[4] =
2263 			{
2264 				isValueAboveThreshold1<IVec4>,
2265 				isValueAboveThreshold2<IVec4>,
2266 				isValueAboveThreshold3<IVec4>,
2267 				isValueAboveThreshold4<IVec4>
2268 			};
2269 			ValueAboveThresholdFn isValueAboveThreshold = componentToFnMap[componentCount - 1];
2270 
2271 			for (int outputNdx = 0; outputNdx < outputsCount; outputNdx++)
2272 			for (int y = 0; y < (int)m_height; y++)
2273 			for (int x = 0; x < (int)m_width; x++)
2274 			{
2275 				const IVec4 color	(accesses[outputNdx].getPixelInt(x, y));
2276 				const IVec4 diff	(std::abs(color.x() - refColor.x()),
2277 									 std::abs(color.y() - refColor.y()),
2278 									 std::abs(color.z() - refColor.z()),
2279 									 std::abs(color.w() - refColor.w()));
2280 
2281 				if (isValueAboveThreshold(diff, threshold))
2282 				{
2283 					isOk = false;
2284 					errorMask.getAccess().setPixel(errorColor, x, y, outputNdx);
2285 					break;
2286 				}
2287 				else
2288 					errorMask.getAccess().setPixel(okColor, x, y, outputNdx);
2289 			}
2290 			break;
2291 		}
2292 
2293 		default:
2294 			DE_FATAL("Unknown channel class");
2295 	}
2296 
2297 	if (!isOk)
2298 	{
2299 		const std::string			sectionName	("MaxAttachmentsVerify");
2300 		const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
2301 
2302 		logImage("ErrorMask", errorMask.getAccess());
2303 		m_resultCollector.fail("Fail");
2304 	}
2305 }
2306 
iterate(void)2307 tcu::TestStatus MaxAttachmenstsRenderPassTestInstance::iterate(void)
2308 {
2309 	submitSwitch(m_groupParams->renderingType);
2310 	verify();
2311 
2312 	return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
2313 }
2314 
createDescriptorSetLayout()2315 Move<VkDescriptorSetLayout> MaxAttachmenstsRenderPassTestInstance::createDescriptorSetLayout()
2316 {
2317 	const VkDescriptorSetLayoutBinding bindingTemplate =
2318 	{
2319 		0,														// binding
2320 		VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,					// descriptorType
2321 		1u,														// descriptorCount
2322 		VK_SHADER_STAGE_FRAGMENT_BIT,							// stageFlags
2323 		DE_NULL													// pImmutableSamplers
2324 	};
2325 
2326 	std::vector<VkDescriptorSetLayoutBinding> bindings(m_attachmentsCount, bindingTemplate);
2327 	for (deUint32 idx = 0; idx < m_attachmentsCount; ++idx)
2328 		bindings[idx].binding = idx;
2329 
2330 	const VkDescriptorSetLayoutCreateInfo createInfo =
2331 	{
2332 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// sType
2333 		DE_NULL,												// pNext
2334 		0u,														// flags
2335 		m_attachmentsCount,										// bindingCount
2336 		&bindings[0]											// pBindings
2337 	};
2338 
2339 	return ::createDescriptorSetLayout(m_context.getDeviceInterface(), m_context.getDevice(), &createInfo);
2340 }
2341 
createDescriptorPool()2342 Move<VkDescriptorPool> MaxAttachmenstsRenderPassTestInstance::createDescriptorPool()
2343 {
2344 	const VkDescriptorPoolSize size =
2345 	{
2346 		VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,					// type
2347 		m_attachmentsCount										// descriptorCount
2348 	};
2349 
2350 	const VkDescriptorPoolCreateInfo createInfo =
2351 	{
2352 		VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,			// sType
2353 		DE_NULL,												// pNext
2354 		VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,		// flags
2355 		1u,														// maxSets
2356 		1u,														// poolSizeCount
2357 		&size													// pPoolSizes
2358 	};
2359 
2360 	return ::createDescriptorPool(m_context.getDeviceInterface(), m_context.getDevice(), &createInfo);
2361 }
2362 
createDescriptorSet()2363 Move<VkDescriptorSet> MaxAttachmenstsRenderPassTestInstance::createDescriptorSet()
2364 {
2365 	const VkDescriptorSetAllocateInfo allocateInfo =
2366 	{
2367 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,			// sType
2368 		DE_NULL,												// pNext
2369 		*m_descriptorPool,										// descriptorPool
2370 		1u,														// descriptorSetCount
2371 		&*m_descriptorSetLayout									// pSetLayouts
2372 	};
2373 
2374 	const vk::DeviceInterface&		vkd					= m_context.getDeviceInterface();
2375 	vk::VkDevice					device				= m_context.getDevice();
2376 	Move<VkDescriptorSet>			descriptorSet		= allocateDescriptorSet(vkd, device, &allocateInfo);
2377 	vector<VkDescriptorImageInfo>	descriptorImageInfo	(m_attachmentsCount);
2378 	vector<VkWriteDescriptorSet>	descriptorWrites	(m_attachmentsCount);
2379 
2380 	for (deUint32 idx = 0; idx < m_attachmentsCount; ++idx)
2381 	{
2382 		const VkDescriptorImageInfo imageInfo =
2383 		{
2384 			DE_NULL,									// VkSampler		sampler
2385 			**m_singlesampleImageViews[idx],			// VkImageView		imageView
2386 			VK_IMAGE_LAYOUT_GENERAL						// VkImageLayout	imageLayout
2387 		};
2388 		descriptorImageInfo[idx] = imageInfo;
2389 
2390 		const VkWriteDescriptorSet	write =
2391 		{
2392 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,		// VkStructureType					sType
2393 			DE_NULL,									// const void*						pNext
2394 			*descriptorSet,								// VkDescriptorSet					dstSet
2395 			(deUint32)idx,								// uint32_t							dstBinding
2396 			0u,											// uint32_t							dstArrayElement
2397 			1u,											// uint32_t							descriptorCount
2398 			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,		// VkDescriptorType					descriptorType
2399 			&descriptorImageInfo[idx],					// const VkDescriptorImageInfo*		pImageInfo
2400 			DE_NULL,									// const VkDescriptorBufferInfo*	pBufferInfo
2401 			DE_NULL										// const VkBufferView*				pTexelBufferView
2402 		};
2403 
2404 		descriptorWrites[idx] = write;
2405 	}
2406 
2407 	vkd.updateDescriptorSets(device, (deUint32)descriptorWrites.size(), &descriptorWrites[0], 0u, DE_NULL);
2408 	return descriptorSet;
2409 }
2410 
2411 template<typename RenderPassTrait>
createRenderPass(void)2412 Move<VkRenderPass> MaxAttachmenstsRenderPassTestInstance::createRenderPass(void)
2413 {
2414 	// make name for RenderPass1Trait or RenderPass2Trait shorter
2415 	typedef RenderPassTrait RPT;
2416 
2417 	typedef typename RPT::AttDesc				AttDesc;
2418 	typedef typename RPT::AttRef				AttRef;
2419 	typedef typename RPT::SubpassDep			SubpassDep;
2420 	typedef typename RPT::SubpassDesc			SubpassDesc;
2421 	typedef typename RPT::RenderPassCreateInfo	RenderPassCreateInfo;
2422 
2423 	const DeviceInterface&	vkd		= m_context.getDeviceInterface();
2424 	VkDevice				device	= m_context.getDevice();
2425 	std::vector<AttDesc>	attachments;
2426 	std::vector<AttRef>		sp0colorAttachmentRefs;
2427 	std::vector<AttRef>		sp0resolveAttachmentRefs;
2428 	std::vector<AttRef>		sp1inAttachmentRefs;
2429 	std::vector<AttRef>		sp1colorAttachmentRefs;
2430 
2431 	for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
2432 	{
2433 		// define first subpass outputs
2434 		{
2435 			const AttDesc multisampleAttachment
2436 			(
2437 				DE_NULL,									// pNext
2438 				0u,											// flags
2439 				m_format,									// format
2440 				m_sampleCount,								// samples
2441 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// loadOp
2442 				VK_ATTACHMENT_STORE_OP_STORE,				// storeOp
2443 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// stencilLoadOp
2444 				VK_ATTACHMENT_STORE_OP_DONT_CARE,			// stencilStoreOp
2445 				VK_IMAGE_LAYOUT_UNDEFINED,					// initialLayout
2446 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// finalLayout
2447 			);
2448 			const AttRef attachmentRef
2449 			(
2450 				DE_NULL,
2451 				(deUint32)attachments.size(),				// attachment
2452 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// layout
2453 				0u											// aspectMask
2454 			);
2455 			sp0colorAttachmentRefs.push_back(attachmentRef);
2456 			attachments.push_back(multisampleAttachment);
2457 		}
2458 		// define first subpass resolve attachments
2459 		{
2460 			const AttDesc singlesampleAttachment
2461 			(
2462 				DE_NULL,									// pNext
2463 				0u,											// flags
2464 				m_format,									// format
2465 				VK_SAMPLE_COUNT_1_BIT,						// samples
2466 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// loadOp
2467 				VK_ATTACHMENT_STORE_OP_STORE,				// storeOp
2468 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// stencilLoadOp
2469 				VK_ATTACHMENT_STORE_OP_DONT_CARE,			// stencilStoreOp
2470 				VK_IMAGE_LAYOUT_UNDEFINED,					// initialLayout
2471 				VK_IMAGE_LAYOUT_GENERAL						// finalLayout
2472 			);
2473 			const AttRef attachmentRef
2474 			(
2475 				DE_NULL,									// pNext
2476 				(deUint32)attachments.size(),				// attachment
2477 				VK_IMAGE_LAYOUT_GENERAL,					// layout
2478 				0u											// aspectMask
2479 			);
2480 			sp0resolveAttachmentRefs.push_back(attachmentRef);
2481 			attachments.push_back(singlesampleAttachment);
2482 		}
2483 		// define second subpass inputs
2484 		{
2485 			const AttRef attachmentRef
2486 			(
2487 				DE_NULL,									// pNext
2488 				(deUint32)attachments.size() - 1,			// attachment
2489 				VK_IMAGE_LAYOUT_GENERAL,					// layout
2490 				VK_IMAGE_ASPECT_COLOR_BIT					// aspectMask
2491 			);
2492 			sp1inAttachmentRefs.push_back(attachmentRef);
2493 		}
2494 		// define second subpass outputs - it merges pairs of
2495 		// results that were produced by the first subpass
2496 		if (attachmentNdx < (m_attachmentsCount / 2))
2497 		{
2498 			const AttRef colorAttachmentRef
2499 			(
2500 				DE_NULL,									// pNext
2501 				(deUint32)attachments.size() - 1,			// attachment
2502 				VK_IMAGE_LAYOUT_GENERAL,					// layout
2503 				0u											// aspectMask
2504 			);
2505 			sp1colorAttachmentRefs.push_back(colorAttachmentRef);
2506 		}
2507 	}
2508 
2509 	DE_ASSERT(sp0colorAttachmentRefs.size() == sp0resolveAttachmentRefs.size());
2510 	DE_ASSERT(attachments.size() == sp0colorAttachmentRefs.size() + sp0resolveAttachmentRefs.size());
2511 
2512 	{
2513 		const SubpassDesc subpass0
2514 		(
2515 															// sType
2516 			DE_NULL,										// pNext
2517 			(VkSubpassDescriptionFlags)0,					// flags
2518 			VK_PIPELINE_BIND_POINT_GRAPHICS,				// pipelineBindPoint
2519 			0u,												// viewMask
2520 			0u,												// inputAttachmentCount
2521 			DE_NULL,										// pInputAttachments
2522 			(deUint32)sp0colorAttachmentRefs.size(),		// colorAttachmentCount
2523 			&sp0colorAttachmentRefs[0],						// pColorAttachments
2524 			&sp0resolveAttachmentRefs[0],					// pResolveAttachments
2525 			DE_NULL,										// pDepthStencilAttachment
2526 			0u,												// preserveAttachmentCount
2527 			DE_NULL											// pPreserveAttachments
2528 		);
2529 		const SubpassDesc subpass1
2530 		(
2531 															// sType
2532 			DE_NULL,										// pNext
2533 			(VkSubpassDescriptionFlags)0,					// flags
2534 			VK_PIPELINE_BIND_POINT_GRAPHICS,				// pipelineBindPoint
2535 			0u,												// viewMask
2536 			(deUint32)sp1inAttachmentRefs.size(),			// inputAttachmentCount
2537 			&sp1inAttachmentRefs[0],						// pInputAttachments
2538 			(deUint32)sp1colorAttachmentRefs.size(),		// colorAttachmentCount
2539 			&sp1colorAttachmentRefs[0],						// pColorAttachments
2540 			DE_NULL,										// pResolveAttachments
2541 			DE_NULL,										// pDepthStencilAttachment
2542 			0u,												// preserveAttachmentCount
2543 			DE_NULL											// pPreserveAttachments
2544 		);
2545 		SubpassDesc subpasses[] =
2546 		{
2547 			subpass0,
2548 			subpass1
2549 		};
2550 		const SubpassDep subpassDependency
2551 		(
2552 			DE_NULL,										// pNext
2553 			0u,												// srcSubpass
2554 			1u,												// dstSubpass
2555 			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,	// srcStageMask
2556 			VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,			// dstStageMask
2557 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// srcAccessMask
2558 			VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,			// dstAccessMask
2559 			0u,												// dependencyFlags
2560 			0u												// viewOffset
2561 		);
2562 		const RenderPassCreateInfo renderPassCreator
2563 		(
2564 															// sType
2565 			DE_NULL,										// pNext
2566 			(VkRenderPassCreateFlags)0u,					// flags
2567 			(deUint32)attachments.size(),					// attachmentCount
2568 			&attachments[0],								// pAttachments
2569 			2u,												// subpassCount
2570 			subpasses,										// pSubpasses
2571 			1u,												// dependencyCount
2572 			&subpassDependency,								// pDependencies
2573 			0u,												// correlatedViewMaskCount
2574 			DE_NULL											// pCorrelatedViewMasks
2575 		);
2576 
2577 		return renderPassCreator.createRenderPass(vkd, device);
2578 	}
2579 }
2580 
createRenderPassSwitch(const RenderingType renderingType)2581 Move<VkRenderPass> MaxAttachmenstsRenderPassTestInstance::createRenderPassSwitch(const RenderingType renderingType)
2582 {
2583 	switch (renderingType)
2584 	{
2585 		case RENDERING_TYPE_RENDERPASS_LEGACY:
2586 			return createRenderPass<RenderPass1Trait>();
2587 		case RENDERING_TYPE_RENDERPASS2:
2588 			return createRenderPass<RenderPass2Trait>();
2589 		default:
2590 			TCU_THROW(InternalError, "Impossible");
2591 	}
2592 }
2593 
createRenderPipelineLayout(bool secondSubpass)2594 Move<VkPipelineLayout> MaxAttachmenstsRenderPassTestInstance::createRenderPipelineLayout(bool secondSubpass)
2595 {
2596 	const DeviceInterface&	vkd		= m_context.getDeviceInterface();
2597 	VkDevice				device	= m_context.getDevice();
2598 
2599 	const VkPipelineLayoutCreateInfo createInfo =
2600 	{
2601 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
2602 		DE_NULL,
2603 		(vk::VkPipelineLayoutCreateFlags)0,
2604 
2605 		secondSubpass ? 1u : 0u,
2606 		secondSubpass ? &*m_descriptorSetLayout : DE_NULL,
2607 
2608 		0u,
2609 		DE_NULL
2610 	};
2611 
2612 	return createPipelineLayout(vkd, device, &createInfo);
2613 }
2614 
createRenderPipeline(bool secondSubpass)2615 Move<VkPipeline> MaxAttachmenstsRenderPassTestInstance::createRenderPipeline(bool secondSubpass)
2616 {
2617 	const DeviceInterface&			vkd						= m_context.getDeviceInterface();
2618 	VkDevice						device					= m_context.getDevice();
2619 	const vk::BinaryCollection&		binaryCollection		= m_context.getBinaryCollection();
2620 	VkSampleCountFlagBits			sampleCount				= sampleCountBitFromSampleCount(m_sampleCount);
2621 	deUint32						blendStatesCount		= m_attachmentsCount;
2622 	std::string						fragShaderNameBase		= "quad-frag-sp0-";
2623 
2624 	if (secondSubpass)
2625 	{
2626 		sampleCount			= VK_SAMPLE_COUNT_1_BIT;
2627 		blendStatesCount	/= 2;
2628 		fragShaderNameBase	= "quad-frag-sp1-";
2629 	}
2630 
2631 	std::string						fragShaderName			= fragShaderNameBase + de::toString(m_attachmentsCount);
2632 	const Unique<VkShaderModule>	vertexShaderModule		(createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
2633 	const Unique<VkShaderModule>	fragmentShaderModule	(createShaderModule(vkd, device, binaryCollection.get(fragShaderName), 0u));
2634 	const Move<VkShaderModule>		geometryShaderModule	(m_layerCount == 1 ? Move<VkShaderModule>() : createShaderModule(vkd, device, binaryCollection.get("geom"), 0u));
2635 
2636 	// Disable blending
2637 	const VkPipelineColorBlendAttachmentState attachmentBlendState =
2638 	{
2639 		VK_FALSE,
2640 		VK_BLEND_FACTOR_SRC_ALPHA,
2641 		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
2642 		VK_BLEND_OP_ADD,
2643 		VK_BLEND_FACTOR_ONE,
2644 		VK_BLEND_FACTOR_ONE,
2645 		VK_BLEND_OP_ADD,
2646 		VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
2647 	};
2648 	std::vector<VkPipelineColorBlendAttachmentState>	attachmentBlendStates(blendStatesCount, attachmentBlendState);
2649 	const VkPipelineVertexInputStateCreateInfo			vertexInputState =
2650 	{
2651 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
2652 		DE_NULL,
2653 		(VkPipelineVertexInputStateCreateFlags)0u,
2654 
2655 		0u,
2656 		DE_NULL,
2657 
2658 		0u,
2659 		DE_NULL
2660 	};
2661 	const tcu::UVec2				renderArea	(m_width, m_height);
2662 	const std::vector<VkViewport>	viewports	(1, makeViewport(renderArea));
2663 	const std::vector<VkRect2D>		scissors	(1, makeRect2D(renderArea));
2664 
2665 	const VkPipelineMultisampleStateCreateInfo multisampleState =
2666 	{
2667 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
2668 		DE_NULL,
2669 		(VkPipelineMultisampleStateCreateFlags)0u,
2670 
2671 		sampleCount,
2672 		VK_FALSE,
2673 		0.0f,
2674 		DE_NULL,
2675 		VK_FALSE,
2676 		VK_FALSE,
2677 	};
2678 	const VkPipelineDepthStencilStateCreateInfo depthStencilState =
2679 	{
2680 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
2681 		DE_NULL,
2682 		(VkPipelineDepthStencilStateCreateFlags)0u,
2683 
2684 		VK_FALSE,
2685 		VK_TRUE,
2686 		VK_COMPARE_OP_ALWAYS,
2687 		VK_FALSE,
2688 		VK_TRUE,
2689 		{
2690 			VK_STENCIL_OP_KEEP,
2691 			VK_STENCIL_OP_INCREMENT_AND_WRAP,
2692 			VK_STENCIL_OP_KEEP,
2693 			VK_COMPARE_OP_ALWAYS,
2694 			~0u,
2695 			~0u,
2696 			0xFFu / (m_sampleCount + 1)
2697 		},
2698 		{
2699 			VK_STENCIL_OP_KEEP,
2700 			VK_STENCIL_OP_INCREMENT_AND_WRAP,
2701 			VK_STENCIL_OP_KEEP,
2702 			VK_COMPARE_OP_ALWAYS,
2703 			~0u,
2704 			~0u,
2705 			0xFFu / (m_sampleCount + 1)
2706 		},
2707 
2708 		0.0f,
2709 		1.0f
2710 	};
2711 	const VkPipelineColorBlendStateCreateInfo blendState =
2712 	{
2713 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
2714 		DE_NULL,
2715 		(VkPipelineColorBlendStateCreateFlags)0u,
2716 
2717 		VK_FALSE,
2718 		VK_LOGIC_OP_COPY,
2719 		deUint32(attachmentBlendStates.size()),
2720 		&attachmentBlendStates[0],
2721 		{ 0.0f, 0.0f, 0.0f, 0.0f }
2722 	};
2723 
2724 	return makeGraphicsPipeline(vkd,																// vk
2725 								device,																// device
2726 								secondSubpass ? *m_pipelineLayoutPass1 : *m_pipelineLayoutPass0,	// pipelineLayout
2727 								*vertexShaderModule,												// vertexShaderModule
2728 								DE_NULL,															// tessellationControlShaderModule
2729 								DE_NULL,															// tessellationEvalShaderModule
2730 								m_layerCount != 1 ? *geometryShaderModule : DE_NULL,				// geometryShaderModule
2731 								*fragmentShaderModule,												// fragmentShaderModule
2732 								*m_renderPass,														// renderPass
2733 								viewports,															// viewports
2734 								scissors,															// scissors
2735 								VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,								// topology
2736 								secondSubpass,														// subpass
2737 								0u,																	// patchControlPoints
2738 								&vertexInputState,													// vertexInputStateCreateInfo
2739 								DE_NULL,															// rasterizationStateCreateInfo
2740 								&multisampleState,													// multisampleStateCreateInfo
2741 								&depthStencilState,													// depthStencilStateCreateInfo
2742 								&blendState);														// colorBlendStateCreateInfo
2743 }
2744 
2745 class MultisampleRenderPassResolveLevelTestInstance : public MultisampleRenderPassTestInstance
2746 {
2747 public:
2748 	MultisampleRenderPassResolveLevelTestInstance	(Context& context, TestConfig2 config);
2749 	~MultisampleRenderPassResolveLevelTestInstance	(void) = default;
2750 };
2751 
MultisampleRenderPassResolveLevelTestInstance(Context& context, TestConfig2 config)2752 MultisampleRenderPassResolveLevelTestInstance::MultisampleRenderPassResolveLevelTestInstance (Context& context, TestConfig2 config)
2753 	: MultisampleRenderPassTestInstance(context, config, config.resolveLevel)
2754 {
2755 }
2756 
2757 struct Programs
2758 {
initvkt::__anon29771::Programs2759 	void init(vk::SourceCollections& dst, TestConfig config) const
2760 	{
2761 		const tcu::TextureFormat		format			(mapVkFormat(config.format));
2762 		const tcu::TextureChannelClass	channelClass	(tcu::getTextureChannelClass(format.type));
2763 
2764 		dst.glslSources.add("quad-vert") << glu::VertexSource(
2765 			"#version 450\n"
2766 			"out gl_PerVertex {\n"
2767 			"\tvec4 gl_Position;\n"
2768 			"};\n"
2769 			"highp float;\n"
2770 			"void main (void) {\n"
2771 			"\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
2772 			"\t                   ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
2773 			"}\n");
2774 
2775 		if (config.layerCount > 1)
2776 		{
2777 			std::ostringstream src;
2778 
2779 			src << "#version 450\n"
2780 				<< "highp float;\n"
2781 				<< "\n"
2782 				<< "layout(triangles) in;\n"
2783 				<< "layout(triangle_strip, max_vertices = " << 3 * 2 * config.layerCount << ") out;\n"
2784 				<< "\n"
2785 				<< "in gl_PerVertex {\n"
2786 				<< "    vec4 gl_Position;\n"
2787 				<< "} gl_in[];\n"
2788 				<< "\n"
2789 				<< "out gl_PerVertex {\n"
2790 				<< "    vec4 gl_Position;\n"
2791 				<< "};\n"
2792 				<< "\n"
2793 				<< "void main (void) {\n"
2794 				<< "    for (int layerNdx = 0; layerNdx < " << config.layerCount << "; ++layerNdx) {\n"
2795 				<< "        for(int vertexNdx = 0; vertexNdx < gl_in.length(); vertexNdx++) {\n"
2796 				<< "            gl_Position = gl_in[vertexNdx].gl_Position;\n"
2797 				<< "            gl_Layer    = layerNdx;\n"
2798 				<< "            EmitVertex();\n"
2799 				<< "        };\n"
2800 				<< "        EndPrimitive();\n"
2801 				<< "    };\n"
2802 				<< "}\n";
2803 
2804 			dst.glslSources.add("geom") << glu::GeometrySource(src.str());
2805 		}
2806 
2807 		const tcu::StringTemplate genericLayoutTemplate("layout(location = ${INDEX}) out ${TYPE_PREFIX}vec4 o_color${INDEX};\n");
2808 		const tcu::StringTemplate genericBodyTemplate("\to_color${INDEX} = ${TYPE_PREFIX}vec4(${COLOR_VAL});\n");
2809 
2810 		if (config.testType == RESOLVE || config.testType == COMPATIBILITY)
2811 		{
2812 			const tcu::StringTemplate fragTemplate("#version 450\n"
2813 												   "layout(push_constant) uniform PushConstant {\n"
2814 												   "\thighp uint sampleMask;\n"
2815 												   "} pushConstants;\n"
2816 												   "${LAYOUT}"
2817 												   "void main (void)\n"
2818 												   "{\n"
2819 												   "${BODY}"
2820 												   "}\n");
2821 
2822 			std::map<std::string, std::string> parameters;
2823 			switch (channelClass)
2824 			{
2825 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2826 					parameters["TYPE_PREFIX"] = "u";
2827 					parameters["COLOR_VAL"] = "255";
2828 					break;
2829 
2830 				case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2831 					parameters["TYPE_PREFIX"] = "i";
2832 					parameters["COLOR_VAL"] = "127";
2833 					break;
2834 
2835 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2836 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2837 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2838 					parameters["TYPE_PREFIX"] = "";
2839 					parameters["COLOR_VAL"] = "1.0";
2840 					break;
2841 
2842 				default:
2843 					DE_FATAL("Unknown channel class");
2844 			}
2845 
2846 			std::string layoutDefinitions = "";
2847 			std::string shaderBody = "\tgl_SampleMask[0] = int(pushConstants.sampleMask);\n";
2848 
2849 			for (deUint32 attIdx = 0; attIdx < config.attachmentCount; ++attIdx)
2850 			{
2851 				parameters["INDEX"]	= de::toString(attIdx);
2852 				layoutDefinitions	+= genericLayoutTemplate.specialize(parameters);
2853 				shaderBody			+= genericBodyTemplate.specialize(parameters);
2854 			}
2855 
2856 			parameters["LAYOUT"]	= layoutDefinitions;
2857 			parameters["BODY"]		= shaderBody;
2858 			dst.glslSources.add("quad-frag") << glu::FragmentSource(fragTemplate.specialize(parameters));
2859 		}
2860 		else	// MAX_ATTACMENTS
2861 		{
2862 			const tcu::StringTemplate fragTemplate("#version 450\n"
2863 												   "${LAYOUT}"
2864 												   "void main (void)\n"
2865 												   "{\n"
2866 												   "${BODY}"
2867 												   "}\n");
2868 
2869 			std::map<std::string, std::string> parameters;
2870 			switch (channelClass)
2871 			{
2872 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2873 					parameters["TYPE_PREFIX"] = "u";
2874 					parameters["COLOR_VAL"] = "0, 64, 192, 252";
2875 					break;
2876 
2877 				case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2878 					parameters["TYPE_PREFIX"] = "i";
2879 					parameters["COLOR_VAL"] = "0, 32, 100, 124";
2880 					break;
2881 
2882 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2883 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2884 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2885 					parameters["TYPE_PREFIX"] = "";
2886 					parameters["COLOR_VAL"] = "0.0, 0.4, 0.8, 1.0";
2887 					break;
2888 
2889 				default:
2890 					DE_FATAL("Unknown channel class");
2891 			}
2892 
2893 			// parts of fragment shader for second subpass - Vulkan introduced a new uniform type and syntax to glsl for input attachments
2894 			const tcu::StringTemplate subpassLayoutTemplate("layout (input_attachment_index = ${INDEX}, set = 0, binding = ${INDEX}) uniform ${TYPE_PREFIX}subpassInput i_color${INDEX};\n");
2895 			const tcu::StringTemplate subpassFBodyTemplate("\to_color${INDEX} = subpassLoad(i_color${INDEX})*0.5 + subpassLoad(i_color${MIX_INDEX})*0.25;\n");
2896 			const tcu::StringTemplate subpassIBodyTemplate("\to_color${INDEX} = subpassLoad(i_color${INDEX}) / 2 + subpassLoad(i_color${MIX_INDEX}) / 4;\n");
2897 
2898 			bool selectIBody = isIntFormat(config.format) || isUintFormat(config.format);
2899 			const tcu::StringTemplate& subpassBodyTemplate = selectIBody ? subpassIBodyTemplate : subpassFBodyTemplate;
2900 
2901 			std::string sp0layoutDefinitions	= "";
2902 			std::string sp0shaderBody			= "";
2903 			std::string sp1inLayoutDefinitions	= "";
2904 			std::string sp1outLayoutDefinitions	= "";
2905 			std::string sp1shaderBody			= "";
2906 
2907 			deUint32 halfAttachments = config.attachmentCount / 2;
2908 			for (deUint32 attIdx = 0; attIdx < config.attachmentCount; ++attIdx)
2909 			{
2910 				parameters["INDEX"] = de::toString(attIdx);
2911 
2912 				sp0layoutDefinitions	+= genericLayoutTemplate.specialize(parameters);
2913 				sp0shaderBody			+= genericBodyTemplate.specialize(parameters);
2914 
2915 				sp1inLayoutDefinitions += subpassLayoutTemplate.specialize(parameters);
2916 				if (attIdx < halfAttachments)
2917 				{
2918 					// we are combining pairs of input attachments to produce half the number of outputs
2919 					parameters["MIX_INDEX"]	= de::toString(halfAttachments + attIdx);
2920 					sp1outLayoutDefinitions	+= genericLayoutTemplate.specialize(parameters);
2921 					sp1shaderBody			+= subpassBodyTemplate.specialize(parameters);
2922 				}
2923 			}
2924 
2925 			// construct fragment shaders for subpass1 and subpass2; note that there
2926 			// is different shader definition depending on number of attachments
2927 			std::string nameBase	= "quad-frag-sp";
2928 			std::string namePostfix	= de::toString(config.attachmentCount);
2929 			parameters["LAYOUT"]	= sp0layoutDefinitions;
2930 			parameters["BODY"]		= sp0shaderBody;
2931 			dst.glslSources.add(nameBase + "0-" + namePostfix) << glu::FragmentSource(fragTemplate.specialize(parameters));
2932 			parameters["LAYOUT"]	= sp1inLayoutDefinitions + sp1outLayoutDefinitions;
2933 			parameters["BODY"]		= sp1shaderBody;
2934 			dst.glslSources.add(nameBase + "1-" + namePostfix) << glu::FragmentSource(fragTemplate.specialize(parameters));
2935 		}
2936 	}
2937 };
2938 
2939 template<class TestConfigType>
checkSupport(Context& context, TestConfigType config)2940 void checkSupport(Context& context, TestConfigType config)
2941 {
2942 	if (config.layerCount > 1)
2943 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
2944 
2945 	if (config.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
2946 		context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
2947 
2948 	if (config.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
2949 		context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
2950 
2951 #ifndef CTS_USES_VULKANSC
2952 	if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
2953 		!context.getPortabilitySubsetFeatures().multisampleArrayImage &&
2954 		(config.sampleCount != VK_SAMPLE_COUNT_1_BIT) && (config.layerCount != 1))
2955 	{
2956 		TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Implementation does not support image array with multiple samples per texel");
2957 	}
2958 #endif // CTS_USES_VULKANSC
2959 
2960 	const InstanceInterface&				vki				= context.getInstanceInterface();
2961 	vk::VkPhysicalDevice					physicalDevice	= context.getPhysicalDevice();
2962 	const vk::VkPhysicalDeviceProperties	properties		= vk::getPhysicalDeviceProperties(vki, physicalDevice);
2963 
2964 	if (config.attachmentCount > properties.limits.maxColorAttachments)
2965 		TCU_THROW(NotSupportedError, "Required number of color attachments not supported.");
2966 }
2967 
formatToName(VkFormat format)2968 std::string formatToName (VkFormat format)
2969 {
2970 	const std::string	formatStr	= de::toString(format);
2971 	const std::string	prefix		= "VK_FORMAT_";
2972 
2973 	DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
2974 
2975 	return de::toLower(formatStr.substr(prefix.length()));
2976 }
2977 
initTests(tcu::TestCaseGroup* group, const SharedGroupParams groupParams)2978 void initTests (tcu::TestCaseGroup* group, const SharedGroupParams groupParams)
2979 {
2980 	static const VkFormat	formats[] =
2981 	{
2982 		VK_FORMAT_R5G6B5_UNORM_PACK16,
2983 		VK_FORMAT_R8_UNORM,
2984 		VK_FORMAT_R8_SNORM,
2985 		VK_FORMAT_R8_UINT,
2986 		VK_FORMAT_R8_SINT,
2987 		VK_FORMAT_R8G8_UNORM,
2988 		VK_FORMAT_R8G8_SNORM,
2989 		VK_FORMAT_R8G8_UINT,
2990 		VK_FORMAT_R8G8_SINT,
2991 		VK_FORMAT_R8G8B8A8_UNORM,
2992 		VK_FORMAT_R8G8B8A8_SNORM,
2993 		VK_FORMAT_R8G8B8A8_UINT,
2994 		VK_FORMAT_R8G8B8A8_SINT,
2995 		VK_FORMAT_R8G8B8A8_SRGB,
2996 		VK_FORMAT_A8B8G8R8_UNORM_PACK32,
2997 		VK_FORMAT_A8B8G8R8_SNORM_PACK32,
2998 		VK_FORMAT_A8B8G8R8_UINT_PACK32,
2999 		VK_FORMAT_A8B8G8R8_SINT_PACK32,
3000 		VK_FORMAT_A8B8G8R8_SRGB_PACK32,
3001 		VK_FORMAT_B8G8R8A8_UNORM,
3002 		VK_FORMAT_B8G8R8A8_SRGB,
3003 		VK_FORMAT_A2R10G10B10_UNORM_PACK32,
3004 		VK_FORMAT_A2B10G10R10_UNORM_PACK32,
3005 		VK_FORMAT_A2B10G10R10_UINT_PACK32,
3006 		VK_FORMAT_R16_UNORM,
3007 		VK_FORMAT_R16_SNORM,
3008 		VK_FORMAT_R16_UINT,
3009 		VK_FORMAT_R16_SINT,
3010 		VK_FORMAT_R16_SFLOAT,
3011 		VK_FORMAT_R16G16_UNORM,
3012 		VK_FORMAT_R16G16_SNORM,
3013 		VK_FORMAT_R16G16_UINT,
3014 		VK_FORMAT_R16G16_SINT,
3015 		VK_FORMAT_R16G16_SFLOAT,
3016 		VK_FORMAT_R16G16B16A16_UNORM,
3017 		VK_FORMAT_R16G16B16A16_SNORM,
3018 		VK_FORMAT_R16G16B16A16_UINT,
3019 		VK_FORMAT_R16G16B16A16_SINT,
3020 		VK_FORMAT_R16G16B16A16_SFLOAT,
3021 		VK_FORMAT_R32_UINT,
3022 		VK_FORMAT_R32_SINT,
3023 		VK_FORMAT_R32_SFLOAT,
3024 		VK_FORMAT_R32G32_UINT,
3025 		VK_FORMAT_R32G32_SINT,
3026 		VK_FORMAT_R32G32_SFLOAT,
3027 		VK_FORMAT_R32G32B32A32_UINT,
3028 		VK_FORMAT_R32G32B32A32_SINT,
3029 		VK_FORMAT_R32G32B32A32_SFLOAT,
3030 		VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
3031 	};
3032 	const deUint32			sampleCounts[] =
3033 	{
3034 		2u, 4u, 8u
3035 	};
3036 	const deUint32			layerCounts[] =
3037 	{
3038 		1u, 3u, 6u
3039 	};
3040 	const deUint32			resolveLevels[] =
3041 	{
3042 		2u, 3u, 4u
3043 	};
3044 	tcu::TestContext&		testCtx	(group->getTestContext());
3045 
3046 	for (size_t layerCountNdx = 0; layerCountNdx < DE_LENGTH_OF_ARRAY(layerCounts); layerCountNdx++)
3047 	{
3048 		const deUint32					layerCount		(layerCounts[layerCountNdx]);
3049 		const std::string				layerGroupName	("layers_" + de::toString(layerCount));
3050 		de::MovePtr<tcu::TestCaseGroup>	layerGroup		(new tcu::TestCaseGroup(testCtx, layerGroupName.c_str(), layerGroupName.c_str()));
3051 
3052 		for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
3053 		{
3054 			const VkFormat					format		(formats[formatNdx]);
3055 			const std::string				formatName	(formatToName(format));
3056 			de::MovePtr<tcu::TestCaseGroup>	formatGroup	(new tcu::TestCaseGroup(testCtx, formatName.c_str(), formatName.c_str()));
3057 
3058 			for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++)
3059 			{
3060 				const deUint32	sampleCount(sampleCounts[sampleCountNdx]);
3061 
3062 				// Skip this test as it is rather slow
3063 				if (layerCount == 6 && sampleCount == 8)
3064 					continue;
3065 
3066 				// Reduce number of tests for dynamic rendering cases where secondary command buffer is used
3067 				if (groupParams->useSecondaryCmdBuffer && ( (sampleCount > 2u) || (layerCount > 3u) ))
3068 					continue;
3069 
3070 				std::string			testName	("samples_" + de::toString(sampleCount));
3071 				const TestConfig	testConfig
3072 				{
3073 					RESOLVE,
3074 					format,
3075 					sampleCount,
3076 					layerCount,
3077 					4u,
3078 					32u,
3079 					32u,
3080 					groupParams
3081 				};
3082 
3083 				formatGroup->addChild(new InstanceFactory1WithSupport<MultisampleRenderPassTestInstance, TestConfig, FunctionSupport1<TestConfig>, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, testName.c_str(), testName.c_str(), testConfig, typename FunctionSupport1<TestConfig>::Args(checkSupport, testConfig)));
3084 
3085 				for (deUint32 resolveLevel : resolveLevels)
3086 				{
3087 					const TestConfig2 testConfig2(testConfig, resolveLevel);
3088 					std::string resolveLevelTestNameStr(testName + "_resolve_level_" + de::toString(resolveLevel));
3089 					const char* resolveLevelTestName = resolveLevelTestNameStr.c_str();
3090 
3091 					formatGroup->addChild(new InstanceFactory1WithSupport<MultisampleRenderPassResolveLevelTestInstance, TestConfig2, FunctionSupport1<TestConfig2>, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, resolveLevelTestName, resolveLevelTestName, testConfig2, typename FunctionSupport1<TestConfig2>::Args(checkSupport, testConfig2)));
3092 
3093 					// Reduce number of tests for dynamic rendering cases where secondary command buffer is used
3094 					if (groupParams->useSecondaryCmdBuffer)
3095 						break;
3096 				}
3097 
3098 				// MaxAttachmenstsRenderPassTest is ment to test extreme cases where applications might consume all available on-chip
3099 				// memory. This is achieved by using maxColorAttachments attachments and two subpasses, but during test creation we
3100 				// dont know what is the maximal number of attachments (spirv tools are not available on all platforms) so we cant
3101 				// construct shaders during test execution. To be able to test this we need to execute tests for all available
3102 				// numbers of attachments despite the fact that we are only interested in the maximal number; test construction code
3103 				// assumes that the number of attachments is power of two
3104 				if ((groupParams->renderingType != RENDERING_TYPE_DYNAMIC_RENDERING) && (layerCount == 1))
3105 				{
3106 					for (deUint32 power = 2; power < 5; ++power)
3107 					{
3108 						deUint32	attachmentCount					= 1 << power;
3109 						std::string	maxAttName						= "max_attachments_" + de::toString(attachmentCount) + "_" + testName;
3110 
3111 						TestConfig	maxAttachmentsTestConfig		= testConfig;
3112 						maxAttachmentsTestConfig.testType			= MAX_ATTACHMENTS;
3113 						maxAttachmentsTestConfig.attachmentCount	= attachmentCount;
3114 
3115 						formatGroup->addChild(new InstanceFactory1WithSupport<MaxAttachmenstsRenderPassTestInstance, TestConfig, FunctionSupport1<TestConfig>, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, maxAttName.c_str(), maxAttName.c_str(), maxAttachmentsTestConfig, typename FunctionSupport1<TestConfig>::Args(checkSupport, maxAttachmentsTestConfig)));
3116 					}
3117 
3118 					{
3119 						std::string	compatibilityTestName			= "compatibility_" + testName;
3120 
3121 						TestConfig	compatibilityTestConfig			= testConfig;
3122 						compatibilityTestConfig.testType			= COMPATIBILITY;
3123 						compatibilityTestConfig.attachmentCount		= 1;
3124 
3125 						formatGroup->addChild(new InstanceFactory1WithSupport<MultisampleRenderPassTestInstance, TestConfig, FunctionSupport1<TestConfig>, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, compatibilityTestName.c_str(), compatibilityTestName.c_str(), compatibilityTestConfig, typename FunctionSupport1<TestConfig>::Args(checkSupport, compatibilityTestConfig)));
3126 					}
3127 				}
3128 			}
3129 
3130 			if (layerCount == 1)
3131 				group->addChild(formatGroup.release());
3132 			else
3133 				layerGroup->addChild(formatGroup.release());
3134 		}
3135 
3136 		if (layerCount != 1)
3137 			group->addChild(layerGroup.release());
3138 	}
3139 }
3140 
3141 } // anonymous
3142 
createRenderPassMultisampleResolveTests(tcu::TestContext& testCtx, const renderpass::SharedGroupParams groupParams)3143 tcu::TestCaseGroup* createRenderPassMultisampleResolveTests (tcu::TestContext& testCtx, const renderpass::SharedGroupParams groupParams)
3144 {
3145 	return createTestGroup(testCtx, "multisample_resolve", "Multisample render pass resolve tests", initTests, groupParams);
3146 }
3147 
createRenderPass2MultisampleResolveTests(tcu::TestContext& testCtx, const renderpass::SharedGroupParams groupParams)3148 tcu::TestCaseGroup* createRenderPass2MultisampleResolveTests (tcu::TestContext& testCtx, const renderpass::SharedGroupParams groupParams)
3149 {
3150 	return createTestGroup(testCtx, "multisample_resolve", "Multisample render pass resolve tests", initTests, groupParams);
3151 }
3152 
createDynamicRenderingMultisampleResolveTests(tcu::TestContext& testCtx, const renderpass::SharedGroupParams groupParams)3153 tcu::TestCaseGroup* createDynamicRenderingMultisampleResolveTests (tcu::TestContext& testCtx, const renderpass::SharedGroupParams groupParams)
3154 {
3155 	return createTestGroup(testCtx, "multisample_resolve", "Multisample dynamic rendering resolve tests", initTests, groupParams);
3156 }
3157 
3158 } // vkt
3159