• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 	RenderingType	renderingType;
121 };
122 
123 struct TestConfig2 : TestConfig
124 {
TestConfig2vkt::__anon687a28300111::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 RenderingType				m_renderingType;
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_renderingType			(config.renderingType)
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 	template<typename RenderpassSubpass>
603 	void					submit						(void);
604 	void					submitSwitch				(RenderingType renderingType);
605 	void					verify						(void);
606 
607 	template<typename RenderPassTrait>
608 	Move<VkRenderPass>		createRenderPass			(bool usedResolveAttachment);
609 	Move<VkRenderPass>		createRenderPassSwitch		(bool usedResolveAttachment);
610 	Move<VkRenderPass>		createRenderPassCompatible	(void);
611 	Move<VkPipelineLayout>	createRenderPipelineLayout	(void);
612 	Move<VkPipeline>		createRenderPipeline		(void);
613 
614 private:
615 
616 	const std::vector<VkImageSp>		m_multisampleImages;
617 	const std::vector<AllocationSp>		m_multisampleImageMemory;
618 	const std::vector<VkImageViewSp>	m_multisampleImageViews;
619 
620 	const std::vector<VkImageSp>		m_singlesampleImages;
621 	const std::vector<AllocationSp>		m_singlesampleImageMemory;
622 	const std::vector<VkImageViewSp>	m_singlesampleImageViews;
623 
624 	const Unique<VkRenderPass>			m_renderPass;
625 	const Unique<VkRenderPass>			m_renderPassCompatible;
626 	const Unique<VkFramebuffer>			m_framebuffer;
627 
628 	const Unique<VkPipelineLayout>		m_renderPipelineLayout;
629 	const Unique<VkPipeline>			m_renderPipeline;
630 
631 	const std::vector<VkBufferSp>		m_buffers;
632 	const std::vector<AllocationSp>		m_bufferMemory;
633 
634 	const Unique<VkCommandPool>			m_commandPool;
635 	tcu::TextureLevel					m_sum;
636 	tcu::TextureLevel					m_sumSrgb;
637 	deUint32							m_sampleMask;
638 	tcu::ResultCollector				m_resultCollector;
639 
640 protected:
641 	MultisampleRenderPassTestInstance	(Context& context, TestConfig config, deUint32 renderLevel);
642 
643 	const deUint32						m_renderLevel;
644 };
645 
MultisampleRenderPassTestInstance(Context & context,TestConfig config)646 MultisampleRenderPassTestInstance::MultisampleRenderPassTestInstance (Context& context, TestConfig config)
647 	: MultisampleRenderPassTestInstance (context, config, /*defaulf render level*/0u)
648 {
649 }
650 
MultisampleRenderPassTestInstance(Context & context,TestConfig config,deUint32 renderLevel)651 MultisampleRenderPassTestInstance::MultisampleRenderPassTestInstance (Context& context, TestConfig config, deUint32 renderLevel)
652 	: MultisampleRenderPassTestBase(context, config)
653 
654 	, m_multisampleImages		(createImages(m_sampleCount, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
655 	, m_multisampleImageMemory	(createImageMemory(m_multisampleImages))
656 	, m_multisampleImageViews	(createImageViews(m_multisampleImages))
657 
658 	, 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 ))
659 	, m_singlesampleImageMemory	(createImageMemory(m_singlesampleImages))
660 	, m_singlesampleImageViews	(createImageViews(m_singlesampleImages, renderLevel))
661 
662 	// The "normal" render pass has an unused resolve attachment when testing compatibility.
663 	, m_renderPass				(createRenderPassSwitch(!m_testCompatibility))
664 	, m_renderPassCompatible	(createRenderPassCompatible())
665 	, m_framebuffer				(createFramebuffer(m_multisampleImageViews, m_singlesampleImageViews, *m_renderPass))
666 
667 	, m_renderPipelineLayout	(createRenderPipelineLayout())
668 	, m_renderPipeline			(createRenderPipeline())
669 
670 	, m_buffers					(createBuffers((1u << renderLevel)*m_width, (1u << renderLevel)*m_height, renderLevel+1 ))
671 	, m_bufferMemory			(createBufferMemory(m_buffers))
672 
673 	, m_commandPool				(createCommandPool(context.getDeviceInterface(), context.getDevice(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
674 	, m_sum						(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), m_width, m_height, m_layerCount)
675 	, m_sumSrgb					(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), m_width, m_height, m_layerCount)
676 	, m_sampleMask				(0x0u)
677 
678 	, m_renderLevel				(renderLevel)
679 {
680 	tcu::clear(m_sum.getAccess(), Vec4(0.0f, 0.0f, 0.0f, 0.0f));
681 	tcu::clear(m_sumSrgb.getAccess(), Vec4(0.0f, 0.0f, 0.0f, 0.0f));
682 }
683 
~MultisampleRenderPassTestInstance(void)684 MultisampleRenderPassTestInstance::~MultisampleRenderPassTestInstance (void)
685 {
686 }
687 
688 template<typename RenderpassSubpass>
submit(void)689 void MultisampleRenderPassTestInstance::submit (void)
690 {
691 	const DeviceInterface&			vkd				(m_context.getDeviceInterface());
692 	const VkDevice					device			(m_context.getDevice());
693 	const Unique<VkCommandBuffer>	commandBuffer	(allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
694 
695 	beginCommandBuffer(vkd, *commandBuffer);
696 
697 	// Memory barriers between previous copies and rendering
698 	{
699 		std::vector<VkImageMemoryBarrier> barriers;
700 
701 		for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
702 		{
703 			const VkImageMemoryBarrier barrier =
704 			{
705 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
706 				DE_NULL,
707 
708 				VK_ACCESS_TRANSFER_READ_BIT,
709 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
710 
711 				VK_IMAGE_LAYOUT_UNDEFINED,
712 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
713 
714 				VK_QUEUE_FAMILY_IGNORED,
715 				VK_QUEUE_FAMILY_IGNORED,
716 
717 				**m_singlesampleImages[dstNdx],
718 				{
719 					VK_IMAGE_ASPECT_COLOR_BIT,
720 					0u,
721 					1u,
722 					0u,
723 					m_layerCount
724 				}
725 			};
726 
727 			barriers.push_back(barrier);
728 		}
729 
730 		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]);
731 	}
732 
733 	// Memory barriers to set multisample image layout to COLOR_ATTACHMENT_OPTIMAL
734 	if (m_renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
735 	{
736 		std::vector<VkImageMemoryBarrier> barriers;
737 
738 		for (size_t dstNdx = 0; dstNdx < m_multisampleImages.size(); dstNdx++)
739 		{
740 			const VkImageMemoryBarrier barrier =
741 			{
742 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
743 				DE_NULL,
744 
745 				0,
746 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
747 
748 				VK_IMAGE_LAYOUT_UNDEFINED,
749 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
750 
751 				VK_QUEUE_FAMILY_IGNORED,
752 				VK_QUEUE_FAMILY_IGNORED,
753 
754 				**m_multisampleImages[dstNdx],
755 				{
756 					VK_IMAGE_ASPECT_COLOR_BIT,
757 					0u,
758 					1u,
759 					0u,
760 					m_layerCount
761 				}
762 			};
763 
764 			barriers.push_back(barrier);
765 		}
766 
767 		vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0]);
768 	}
769 
770 	VkRect2D renderArea = makeRect2D(m_width, m_height);
771 	if (m_renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
772 	{
773 		const VkClearValue clearValue = makeClearValueColor( { 0.0f, 0.0f, 0.0f, 1.0f } );
774 		std::vector<vk::VkRenderingAttachmentInfoKHR> colorAttachments(m_attachmentsCount,
775 			{
776 				vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,	// VkStructureType						sType;
777 				DE_NULL,												// const void*							pNext;
778 				DE_NULL,												// VkImageView							imageView;
779 				vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout						imageLayout;
780 				vk::VK_RESOLVE_MODE_AVERAGE_BIT,						// VkResolveModeFlagBits				resolveMode;
781 				DE_NULL,												// VkImageView							resolveImageView;
782 				vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout						resolveImageLayout;
783 				vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp					loadOp;
784 				vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp					storeOp;
785 				clearValue												// VkClearValue							clearValue;
786 			});
787 
788 		for (deUint32 i = 0; i < m_attachmentsCount; ++i)
789 		{
790 			colorAttachments[i].imageView = **m_multisampleImageViews[i];
791 			colorAttachments[i].resolveImageView = **m_singlesampleImageViews[i];
792 		}
793 
794 		vk::VkRenderingInfoKHR renderingInfo
795 		{
796 			vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
797 			DE_NULL,
798 			0,														// VkRenderingFlagsKHR					flags;
799 			renderArea,												// VkRect2D								renderArea;
800 			m_layerCount,											// deUint32								layerCount;
801 			0u,														// deUint32								viewMask;
802 			m_attachmentsCount,										// deUint32								colorAttachmentCount;
803 			colorAttachments.data(),								// const VkRenderingAttachmentInfoKHR*	pColorAttachments;
804 			DE_NULL,												// const VkRenderingAttachmentInfoKHR*	pDepthAttachment;
805 			DE_NULL,												// const VkRenderingAttachmentInfoKHR*	pStencilAttachment;
806 		};
807 
808 		vkd.cmdBeginRenderingKHR(*commandBuffer, &renderingInfo);
809 	}
810 	else
811 	{
812 		const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
813 		const VkRenderPassBeginInfo beginInfo =
814 		{
815 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
816 			DE_NULL,
817 
818 			m_testCompatibility ? *m_renderPassCompatible : *m_renderPass,
819 			*m_framebuffer,
820 			renderArea,
821 
822 			0u,
823 			DE_NULL
824 		};
825 		RenderpassSubpass::cmdBeginRenderPass(vkd, *commandBuffer, &beginInfo, &subpassBeginInfo);
826 	}
827 
828 	// Clear everything to black
829 	clearAttachments(*commandBuffer);
830 
831 	// Render black samples
832 	{
833 		vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
834 		vkd.cmdPushConstants(*commandBuffer, *m_renderPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(m_sampleMask), &m_sampleMask);
835 		vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
836 	}
837 
838 	if (m_renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
839 		vkd.cmdEndRenderingKHR(*commandBuffer);
840 	else
841 	{
842 		const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo(DE_NULL);
843 		RenderpassSubpass::cmdEndRenderPass(vkd, *commandBuffer, &subpassEndInfo);
844 	}
845 
846 	// Memory barriers to set single-sample image layout to TRANSFER_SRC_OPTIMAL
847 	if (m_renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
848 	{
849 		std::vector<VkImageMemoryBarrier> barriers;
850 
851 		for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
852 		{
853 			const VkImageMemoryBarrier barrier =
854 			{
855 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
856 				DE_NULL,
857 
858 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
859 				VK_ACCESS_TRANSFER_READ_BIT,
860 
861 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
862 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
863 
864 				VK_QUEUE_FAMILY_IGNORED,
865 				VK_QUEUE_FAMILY_IGNORED,
866 
867 				**m_singlesampleImages[dstNdx],
868 				{
869 					VK_IMAGE_ASPECT_COLOR_BIT,
870 					0u,
871 					1u,
872 					0u,
873 					m_layerCount
874 				}
875 			};
876 
877 			barriers.push_back(barrier);
878 		}
879 
880 		vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0]);
881 	}
882 
883 	for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
884 	{
885 		// assume that buffer(s) have enough memory to store desired amount of mipmaps
886 		copyImageToBuffer(vkd, *commandBuffer, **m_singlesampleImages[dstNdx], **m_buffers[dstNdx],
887 						  m_format, tcu::IVec2((1u << m_renderLevel)*m_width, (1u << m_renderLevel)*m_height), m_renderLevel,
888 						  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_layerCount);
889 	}
890 
891 	endCommandBuffer(vkd, *commandBuffer);
892 
893 	submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *commandBuffer);
894 
895 	for (size_t memoryBufferNdx = 0; memoryBufferNdx < m_bufferMemory.size(); memoryBufferNdx++)
896 		invalidateMappedMemoryRange(vkd, device, m_bufferMemory[memoryBufferNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
897 }
898 
submitSwitch(RenderingType renderingType)899 void MultisampleRenderPassTestInstance::submitSwitch (RenderingType renderingType)
900 {
901 	switch (renderingType)
902 	{
903 		case RENDERING_TYPE_RENDERPASS_LEGACY:
904 			submit<RenderpassSubpass1>();
905 			break;
906 		case RENDERING_TYPE_RENDERPASS2:
907 		case RENDERING_TYPE_DYNAMIC_RENDERING:
908 			submit<RenderpassSubpass2>();
909 			break;
910 		default:
911 			TCU_THROW(InternalError, "Impossible");
912 	}
913 }
914 
verify(void)915 void MultisampleRenderPassTestInstance::verify (void)
916 {
917 	const Vec4							errorColor		(1.0f, 0.0f, 0.0f, 1.0f);
918 	const Vec4							okColor			(0.0f, 1.0f, 0.0f, 1.0f);
919 	const tcu::TextureFormat			format			(mapVkFormat(m_format));
920 	const tcu::TextureChannelClass		channelClass	(tcu::getTextureChannelClass(format.type));
921 
922 	deUint32							offset			(0u);
923 	deUint32							width			((1u << m_renderLevel) * m_width);
924 	deUint32							height			((1u << m_renderLevel) * m_height);
925 	deUint32							pixelSize		(static_cast<deUint32>(getPixelSize()));
926 	for (deUint32 level = 0; level < m_renderLevel; ++level)
927 	{
928 		offset += (width * height * pixelSize);
929 		height /= 2;
930 		width /= 2;
931 	}
932 
933 	std::vector<tcu::ConstPixelBufferAccess> accesses;
934 	for (deUint32 attachmentIdx = 0; attachmentIdx < m_attachmentsCount; ++attachmentIdx)
935 	{
936 		void* const ptr = static_cast<deUint8*>(m_bufferMemory[attachmentIdx]->getHostPtr()) + offset;
937 		accesses.push_back(tcu::ConstPixelBufferAccess(format, m_width, m_height, m_layerCount, ptr));
938 	}
939 
940 	tcu::TextureLevel					errorMask		(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width, m_height, m_layerCount);
941 	tcu::TestLog&						log				(m_context.getTestContext().getLog());
942 
943 	switch (channelClass)
944 	{
945 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
946 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
947 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
948 		{
949 			const int	componentCount	(tcu::getNumUsedChannels(format.order));
950 			bool		isOk			= true;
951 			float		clearValue;
952 			float		renderValue;
953 
954 			switch (channelClass)
955 			{
956 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
957 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
958 					clearValue	= -1.0f;
959 					renderValue	= 1.0f;
960 					break;
961 
962 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
963 					clearValue	= 0.0f;
964 					renderValue	= 1.0f;
965 					break;
966 
967 				default:
968 					clearValue	= 0.0f;
969 					renderValue	= 0.0f;
970 					DE_FATAL("Unknown channel class");
971 			}
972 
973 			for (deUint32 z = 0; z < m_layerCount; z++)
974 			for (deUint32 y = 0; y < m_height; y++)
975 			for (deUint32 x = 0; x < m_width; x++)
976 			{
977 				// Color has to be black if no samples were covered, white if all samples were covered or same in every attachment
978 				const Vec4	firstColor	(accesses[0].getPixel(x, y, z));
979 				const Vec4	refColor	(m_sampleMask == 0x0u
980 										? Vec4(clearValue,
981 												componentCount > 1 ? clearValue : 0.0f,
982 												componentCount > 2 ? clearValue : 0.0f,
983 												componentCount > 3 ? clearValue : 1.0f)
984 										: m_sampleMask == ((0x1u << m_sampleCount) - 1u)
985 										? Vec4(renderValue,
986 												componentCount > 1 ? renderValue : 0.0f,
987 												componentCount > 2 ? renderValue : 0.0f,
988 												componentCount > 3 ? renderValue : 1.0f)
989 										: firstColor);
990 
991 				errorMask.getAccess().setPixel(okColor, x, y, z);
992 
993 				for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
994 				{
995 					const Vec4 color (accesses[attachmentNdx].getPixel(x, y, z));
996 
997 					if (refColor != color)
998 					{
999 						isOk = false;
1000 						errorMask.getAccess().setPixel(errorColor, x, y, z);
1001 						break;
1002 					}
1003 				}
1004 
1005 				{
1006 					const Vec4 old = m_sum.getAccess().getPixel(x, y, z);
1007 					m_sum.getAccess().setPixel(old + (tcu::isSRGB(format) ? tcu::sRGBToLinear(firstColor) : firstColor), x, y, z);
1008 
1009 					const Vec4 oldSrgb = m_sumSrgb.getAccess().getPixel(x, y, z);
1010 					m_sumSrgb.getAccess().setPixel(oldSrgb + firstColor, x, y, z);
1011 				}
1012 			}
1013 
1014 			if (!isOk)
1015 			{
1016 				const std::string			sectionName	("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1017 				const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
1018 
1019 				for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1020 					logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1021 
1022 				logImage("ErrorMask", errorMask.getAccess());
1023 
1024 				if (m_sampleMask == 0x0u)
1025 				{
1026 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
1027 					m_resultCollector.fail("Empty sample mask didn't produce correct pixel values");
1028 				}
1029 				else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1030 				{
1031 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
1032 					m_resultCollector.fail("Full sample mask didn't produce correct pixel values");
1033 				}
1034 				else
1035 				{
1036 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve is inconsistent between attachments" << tcu::TestLog::EndMessage;
1037 					m_resultCollector.fail("Resolve is inconsistent between attachments");
1038 				}
1039 			}
1040 			break;
1041 		}
1042 
1043 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1044 		{
1045 			const int		componentCount			(tcu::getNumUsedChannels(format.order));
1046 			const UVec4		bitDepth				(tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1047 			const UVec4		renderValue				(tcu::select((UVec4(1u) << tcu::min(UVec4(8u), bitDepth)) - UVec4(1u),
1048 																  UVec4(0u, 0u, 0u, 1u),
1049 																  tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1050 			const UVec4		clearValue				(tcu::select(UVec4(0u),
1051 																 UVec4(0u, 0u, 0u, 1u),
1052 																 tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1053 			bool			unexpectedValues		= false;
1054 			bool			inconsistentComponents	= false;
1055 			bool			inconsistentAttachments	= false;
1056 
1057 			for (deUint32 z = 0; z < m_layerCount; z++)
1058 			for (deUint32 y = 0; y < m_height; y++)
1059 			for (deUint32 x = 0; x < m_width; x++)
1060 			{
1061 				// Color has to be all zeros if no samples were covered, all 255 if all samples were covered or consistent across all attachments
1062 				const UVec4 refColor	(m_sampleMask == 0x0u
1063 										? clearValue
1064 										: m_sampleMask == ((0x1u << m_sampleCount) - 1u)
1065 										? renderValue
1066 										: accesses[0].getPixelUint(x, y, z));
1067 				bool		isOk		= true;
1068 
1069 				// If reference value was taken from first attachment, check that it is valid value i.e. clear or render value
1070 				if (m_sampleMask != 0x0u && m_sampleMask != ((0x1u << m_sampleCount) - 1u))
1071 				{
1072 					// Each component must be resolved same way
1073 					const BVec4		isRenderValue			(refColor == renderValue);
1074 					const BVec4		isClearValue			(refColor == clearValue);
1075 					const bool		unexpectedValue			(tcu::anyNotEqual(tcu::logicalOr(isRenderValue, isClearValue), BVec4(true)));
1076 					const bool		inconsistentComponent	(!(tcu::allEqual(isRenderValue, BVec4(true)) || tcu::allEqual(isClearValue, BVec4(true))));
1077 
1078 					unexpectedValues		|= unexpectedValue;
1079 					inconsistentComponents	|= inconsistentComponent;
1080 
1081 					if (unexpectedValue || inconsistentComponent)
1082 						isOk = false;
1083 				}
1084 
1085 				for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1086 				{
1087 					const UVec4 color (accesses[attachmentNdx].getPixelUint(x, y, z));
1088 
1089 					if (refColor != color)
1090 					{
1091 						isOk = false;
1092 						inconsistentAttachments = true;
1093 						break;
1094 					}
1095 				}
1096 
1097 				errorMask.getAccess().setPixel((isOk ? okColor : errorColor), x, y, z);
1098 			}
1099 
1100 			if (unexpectedValues || inconsistentComponents || inconsistentAttachments)
1101 			{
1102 				const std::string			sectionName	("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1103 				const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
1104 
1105 				for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1106 					logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1107 
1108 				logImage("ErrorMask", errorMask.getAccess());
1109 
1110 				if (m_sampleMask == 0x0u)
1111 				{
1112 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
1113 					m_resultCollector.fail("Empty sample mask didn't produce correct pixels");
1114 				}
1115 				else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1116 				{
1117 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
1118 					m_resultCollector.fail("Full sample mask didn't produce correct pixels");
1119 				}
1120 				else
1121 				{
1122 					if (unexpectedValues)
1123 					{
1124 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve produced unexpected values i.e. not " << clearValue << " or " << renderValue << tcu::TestLog::EndMessage;
1125 						m_resultCollector.fail("Resolve produced unexpected values");
1126 					}
1127 
1128 					if (inconsistentComponents)
1129 					{
1130 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different components of attachment were resolved to different values." << tcu::TestLog::EndMessage;
1131 						m_resultCollector.fail("Different components of attachment were resolved to different values.");
1132 					}
1133 
1134 					if (inconsistentAttachments)
1135 					{
1136 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different attachments were resolved to different values." << tcu::TestLog::EndMessage;
1137 						m_resultCollector.fail("Different attachments were resolved to different values.");
1138 					}
1139 				}
1140 			}
1141 			break;
1142 		}
1143 
1144 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1145 		{
1146 			const int		componentCount			(tcu::getNumUsedChannels(format.order));
1147 			const IVec4		bitDepth				(tcu::getTextureFormatBitDepth(format));
1148 			const IVec4		renderValue				(tcu::select((IVec4(1) << (tcu::min(IVec4(8), bitDepth) - IVec4(1))) - IVec4(1),
1149 																  IVec4(0, 0, 0, 1),
1150 																  tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1151 			const IVec4		clearValue				(tcu::select(-(IVec4(1) << (tcu::min(IVec4(8), bitDepth) - IVec4(1))),
1152 																 IVec4(0, 0, 0, 1),
1153 																 tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1154 			bool			unexpectedValues		= false;
1155 			bool			inconsistentComponents	= false;
1156 			bool			inconsistentAttachments	= false;
1157 
1158 			for (deUint32 z = 0; z < m_layerCount; z++)
1159 			for (deUint32 y = 0; y < m_height; y++)
1160 			for (deUint32 x = 0; x < m_width; x++)
1161 			{
1162 				// Color has to be all zeros if no samples were covered, all 255 if all samples were covered or consistent across all attachments
1163 				const IVec4 refColor	(m_sampleMask == 0x0u
1164 										? clearValue
1165 										: m_sampleMask == ((0x1u << m_sampleCount) - 1u)
1166 										? renderValue
1167 										: accesses[0].getPixelInt(x, y, z));
1168 				bool		isOk		= true;
1169 
1170 				// If reference value was taken from first attachment, check that it is valid value i.e. clear or render value
1171 				if (m_sampleMask != 0x0u && m_sampleMask != ((0x1u << m_sampleCount) - 1u))
1172 				{
1173 					// Each component must be resolved same way
1174 					const BVec4		isRenderValue			(refColor == renderValue);
1175 					const BVec4		isClearValue			(refColor == clearValue);
1176 					const bool		unexpectedValue			(tcu::anyNotEqual(tcu::logicalOr(isRenderValue, isClearValue), BVec4(true)));
1177 					const bool		inconsistentComponent	(!(tcu::allEqual(isRenderValue, BVec4(true)) || tcu::allEqual(isClearValue, BVec4(true))));
1178 
1179 					unexpectedValues		|= unexpectedValue;
1180 					inconsistentComponents	|= inconsistentComponent;
1181 
1182 					if (unexpectedValue || inconsistentComponent)
1183 						isOk = false;
1184 				}
1185 
1186 				for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1187 				{
1188 					const IVec4 color (accesses[attachmentNdx].getPixelInt(x, y, z));
1189 
1190 					if (refColor != color)
1191 					{
1192 						isOk = false;
1193 						inconsistentAttachments = true;
1194 						break;
1195 					}
1196 				}
1197 
1198 				errorMask.getAccess().setPixel((isOk ? okColor : errorColor), x, y, z);
1199 			}
1200 
1201 			if (unexpectedValues || inconsistentComponents || inconsistentAttachments)
1202 			{
1203 				const std::string			sectionName	("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1204 				const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
1205 
1206 				for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1207 					logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1208 
1209 				logImage("ErrorMask", errorMask.getAccess());
1210 
1211 				if (m_sampleMask == 0x0u)
1212 				{
1213 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
1214 					m_resultCollector.fail("Empty sample mask didn't produce correct pixels");
1215 				}
1216 				else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1217 				{
1218 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
1219 					m_resultCollector.fail("Full sample mask didn't produce correct pixels");
1220 				}
1221 				else
1222 				{
1223 					if (unexpectedValues)
1224 					{
1225 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve produced unexpected values i.e. not " << clearValue << " or " << renderValue << tcu::TestLog::EndMessage;
1226 						m_resultCollector.fail("Resolve produced unexpected values");
1227 					}
1228 
1229 					if (inconsistentComponents)
1230 					{
1231 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different components of attachment were resolved to different values." << tcu::TestLog::EndMessage;
1232 						m_resultCollector.fail("Different components of attachment were resolved to different values.");
1233 					}
1234 
1235 					if (inconsistentAttachments)
1236 					{
1237 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different attachments were resolved to different values." << tcu::TestLog::EndMessage;
1238 						m_resultCollector.fail("Different attachments were resolved to different values.");
1239 					}
1240 				}
1241 			}
1242 			break;
1243 		}
1244 
1245 		default:
1246 			DE_FATAL("Unknown channel class");
1247 	}
1248 }
1249 
iterate(void)1250 tcu::TestStatus MultisampleRenderPassTestInstance::iterate (void)
1251 {
1252 	if (m_sampleMask == 0u)
1253 	{
1254 		const tcu::TextureFormat		format			(mapVkFormat(m_format));
1255 		const tcu::TextureChannelClass	channelClass	(tcu::getTextureChannelClass(format.type));
1256 		tcu::TestLog&					log				(m_context.getTestContext().getLog());
1257 
1258 		switch (channelClass)
1259 		{
1260 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1261 				log << TestLog::Message << "Clearing target to zero and rendering 255 pixels with every possible sample mask" << TestLog::EndMessage;
1262 				break;
1263 
1264 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1265 				log << TestLog::Message << "Clearing target to -128 and rendering 127 pixels with every possible sample mask" << TestLog::EndMessage;
1266 				break;
1267 
1268 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1269 			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1270 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1271 				log << TestLog::Message << "Clearing target to black and rendering white pixels with every possible sample mask" << TestLog::EndMessage;
1272 				break;
1273 
1274 			default:
1275 				DE_FATAL("Unknown channel class");
1276 		}
1277 	}
1278 
1279 	submitSwitch(m_renderingType);
1280 	verify();
1281 
1282 	if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1283 	{
1284 		const tcu::TextureFormat		format			(mapVkFormat(m_format));
1285 		const tcu::TextureChannelClass	channelClass	(tcu::getTextureChannelClass(format.type));
1286 		const Vec4						threshold		(getFormatThreshold());
1287 		tcu::TestLog&					log				(m_context.getTestContext().getLog());
1288 
1289 		if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT
1290 				|| channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT
1291 				|| channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
1292 		{
1293 			const int			componentCount	(tcu::getNumUsedChannels(format.order));
1294 			const Vec4			errorColor		(1.0f, 0.0f, 0.0f, 1.0f);
1295 			const Vec4			okColor			(0.0f, 1.0f, 0.0f, 1.0f);
1296 			tcu::TextureLevel	errorMask		(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width, m_height, m_layerCount);
1297 			bool				isOk			= true;
1298 			Vec4				maxDiff			(0.0f);
1299 			Vec4				expectedAverage;
1300 
1301 			switch (channelClass)
1302 			{
1303 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1304 				{
1305 					expectedAverage = Vec4(0.5f, componentCount > 1 ? 0.5f : 0.0f, componentCount > 2 ? 0.5f : 0.0f, componentCount > 3 ? 0.5f : 1.0f);
1306 					break;
1307 				}
1308 
1309 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1310 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1311 				{
1312 					expectedAverage = Vec4(0.0f, 0.0f, 0.0f, componentCount > 3 ? 0.0f : 1.0f);
1313 					break;
1314 				}
1315 
1316 				default:
1317 					DE_FATAL("Unknown channel class");
1318 			}
1319 
1320 			for (deUint32 z = 0; z < m_layerCount; z++)
1321 			for (deUint32 y = 0; y < m_height; y++)
1322 			for (deUint32 x = 0; x < m_width; x++)
1323 			{
1324 				const Vec4	sum		(m_sum.getAccess().getPixel(x, y, z));
1325 				const Vec4	average	(sum / Vec4((float)(0x1u << m_sampleCount)));
1326 				const Vec4	diff	(tcu::abs(average - expectedAverage));
1327 
1328 				m_sum.getAccess().setPixel(average, x, y, z);
1329 				errorMask.getAccess().setPixel(okColor, x, y, z);
1330 
1331 				bool failThreshold;
1332 
1333 				if (!tcu::isSRGB(format))
1334 				{
1335 					failThreshold = (diff[0] > threshold.x()
1336 										|| diff[1] > threshold.y()
1337 										|| diff[2] > threshold.z()
1338 										|| diff[3] > threshold.w());
1339 				}
1340 				else
1341 				{
1342 					const Vec4	sumSrgb(m_sumSrgb.getAccess().getPixel(x, y, z));
1343 					const Vec4	averageSrgb(sumSrgb / Vec4((float)(0x1u << m_sampleCount)));
1344 					const Vec4	diffSrgb(tcu::abs(averageSrgb - expectedAverage));
1345 
1346 					m_sumSrgb.getAccess().setPixel(averageSrgb, x, y, z);
1347 
1348 					// Spec doesn't restrict implementation to downsample in linear color space. So, comparing both non linear and
1349 					// linear diff's in case of srgb formats.
1350 					failThreshold = ((diff[0] > threshold.x()
1351 										|| diff[1] > threshold.y()
1352 										|| diff[2] > threshold.z()
1353 										|| diff[3] > threshold.w()) &&
1354 									(diffSrgb[0] > threshold.x()
1355 										|| diffSrgb[1] > threshold.y()
1356 										|| diffSrgb[2] > threshold.z()
1357 										|| diffSrgb[3] > threshold.w()));
1358 
1359 				}
1360 
1361 				if (failThreshold)
1362 				{
1363 					isOk	= false;
1364 					maxDiff	= tcu::max(maxDiff, diff);
1365 					errorMask.getAccess().setPixel(errorColor, x, y, z);
1366 				}
1367 			}
1368 
1369 			log << TestLog::Image("Average resolved values in attachment 0", "Average resolved values in attachment 0", m_sum);
1370 
1371 			if (!isOk)
1372 			{
1373 				std::stringstream	message;
1374 
1375 				m_context.getTestContext().getLog() << tcu::LogImage("ErrorMask", "ErrorMask", errorMask.getAccess());
1376 
1377 				message << "Average resolved values differ from expected average values by more than ";
1378 
1379 				switch (componentCount)
1380 				{
1381 					case 1:
1382 						message << threshold.x();
1383 						break;
1384 					case 2:
1385 						message << "vec2" << Vec2(threshold.x(), threshold.y());
1386 						break;
1387 					case 3:
1388 						message << "vec3" << Vec3(threshold.x(), threshold.y(), threshold.z());
1389 						break;
1390 					default:
1391 						message << "vec4" << threshold;
1392 				}
1393 
1394 				message << ". Max diff " << maxDiff;
1395 				log << TestLog::Message << message.str() << TestLog::EndMessage;
1396 
1397 				m_resultCollector.fail("Average resolved values differ from expected average values");
1398 			}
1399 		}
1400 
1401 		return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1402 	}
1403 	else
1404 	{
1405 		m_sampleMask++;
1406 		return tcu::TestStatus::incomplete();
1407 	}
1408 }
1409 
1410 template<typename RenderPassTrait>
createRenderPass(bool usedResolveAttachment)1411 Move<VkRenderPass> MultisampleRenderPassTestInstance::createRenderPass (bool usedResolveAttachment)
1412 {
1413 	// make name for RenderPass1Trait or RenderPass2Trait shorter
1414 	typedef RenderPassTrait RPT;
1415 	typedef typename RPT::AttDesc				AttDesc;
1416 	typedef typename RPT::AttRef				AttRef;
1417 	typedef typename RPT::SubpassDesc			SubpassDesc;
1418 	typedef typename RPT::RenderPassCreateInfo	RenderPassCreateInfo;
1419 
1420 	const DeviceInterface&	vkd						= m_context.getDeviceInterface();
1421 	VkDevice				device					= m_context.getDevice();
1422 	std::vector<AttDesc>	attachments;
1423 	std::vector<AttRef>		colorAttachmentRefs;
1424 	std::vector<AttRef>		resolveAttachmentRefs;
1425 
1426 	for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1427 	{
1428 		{
1429 			const AttDesc multisampleAttachment
1430 			(
1431 															// sType
1432 				DE_NULL,									// pNext
1433 				0u,											// flags
1434 				m_format,									// format
1435 				m_sampleCount,								// samples
1436 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// loadOp
1437 				VK_ATTACHMENT_STORE_OP_DONT_CARE,			// storeOp
1438 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// stencilLoadOp
1439 				VK_ATTACHMENT_STORE_OP_DONT_CARE,			// stencilStoreOp
1440 				VK_IMAGE_LAYOUT_UNDEFINED,					// initialLayout
1441 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// finalLayout
1442 			);
1443 			const AttRef attachmentRef
1444 			(
1445 															// sType
1446 				DE_NULL,									// pNext
1447 				(deUint32)attachments.size(),				// attachment
1448 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// layout
1449 				0u											// aspectMask
1450 			);
1451 			colorAttachmentRefs.push_back(attachmentRef);
1452 			attachments.push_back(multisampleAttachment);
1453 		}
1454 		{
1455 			const AttDesc singlesampleAttachment
1456 			(
1457 															// sType
1458 				DE_NULL,									// pNext
1459 				0u,											// flags
1460 				m_format,									// format
1461 				VK_SAMPLE_COUNT_1_BIT,						// samples
1462 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// loadOp
1463 				VK_ATTACHMENT_STORE_OP_STORE,				// storeOp
1464 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// stencilLoadOp
1465 				VK_ATTACHMENT_STORE_OP_DONT_CARE,			// stencilStoreOp
1466 				VK_IMAGE_LAYOUT_UNDEFINED,					// initialLayout
1467 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL		// finalLayout
1468 			);
1469 			const auto attachmentId = (usedResolveAttachment ? static_cast<deUint32>(attachments.size()) : VK_ATTACHMENT_UNUSED);
1470 			const AttRef attachmentRef
1471 			(
1472 															// sType
1473 				DE_NULL,									// pNext
1474 				attachmentId,								// attachment
1475 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// layout
1476 				0u											// aspectMask
1477 			);
1478 			resolveAttachmentRefs.push_back(attachmentRef);
1479 			attachments.push_back(singlesampleAttachment);
1480 		}
1481 	}
1482 
1483 	DE_ASSERT(colorAttachmentRefs.size() == resolveAttachmentRefs.size());
1484 	DE_ASSERT(attachments.size() == colorAttachmentRefs.size() + resolveAttachmentRefs.size());
1485 
1486 	const SubpassDesc subpass
1487 	(
1488 														// sType
1489 		DE_NULL,										// pNext
1490 		(VkSubpassDescriptionFlags)0,					// flags
1491 		VK_PIPELINE_BIND_POINT_GRAPHICS,				// pipelineBindPoint
1492 		0u,												// viewMask
1493 		0u,												// inputAttachmentCount
1494 		DE_NULL,										// pInputAttachments
1495 		(deUint32)colorAttachmentRefs.size(),			// colorAttachmentCount
1496 		&colorAttachmentRefs[0],						// pColorAttachments
1497 		&resolveAttachmentRefs[0],						// pResolveAttachments
1498 		DE_NULL,										// pDepthStencilAttachment
1499 		0u,												// preserveAttachmentCount
1500 		DE_NULL											// pPreserveAttachments
1501 	);
1502 	const RenderPassCreateInfo renderPassCreator
1503 	(
1504 														// sType
1505 		DE_NULL,										// pNext
1506 		(VkRenderPassCreateFlags)0u,					// flags
1507 		(deUint32)attachments.size(),					// attachmentCount
1508 		&attachments[0],								// pAttachments
1509 		1u,												// subpassCount
1510 		&subpass,										// pSubpasses
1511 		0u,												// dependencyCount
1512 		DE_NULL,										// pDependencies
1513 		0u,												// correlatedViewMaskCount
1514 		DE_NULL											// pCorrelatedViewMasks
1515 	);
1516 
1517 	return renderPassCreator.createRenderPass(vkd, device);
1518 }
1519 
createRenderPassSwitch(bool usedResolveAttachment)1520 Move<VkRenderPass> MultisampleRenderPassTestInstance::createRenderPassSwitch (bool usedResolveAttachment)
1521 {
1522 	switch (m_renderingType)
1523 	{
1524 		case RENDERING_TYPE_RENDERPASS_LEGACY:
1525 			return createRenderPass<RenderPass1Trait>(usedResolveAttachment);
1526 		case RENDERING_TYPE_RENDERPASS2:
1527 			return createRenderPass<RenderPass2Trait>(usedResolveAttachment);
1528 		case RENDERING_TYPE_DYNAMIC_RENDERING:
1529 			return Move<VkRenderPass>();
1530 		default:
1531 			TCU_THROW(InternalError, "Impossible");
1532 	}
1533 }
1534 
createRenderPassCompatible(void)1535 Move<VkRenderPass> MultisampleRenderPassTestInstance::createRenderPassCompatible (void)
1536 {
1537 	if (m_testCompatibility)
1538 	{
1539 		// The compatible render pass is always created with a used resolve attachment.
1540 		return createRenderPassSwitch(true);
1541 	}
1542 	else
1543 	{
1544 		return {};
1545 	}
1546 }
1547 
createRenderPipelineLayout(void)1548 Move<VkPipelineLayout> MultisampleRenderPassTestInstance::createRenderPipelineLayout (void)
1549 {
1550 	const DeviceInterface&	vkd		= m_context.getDeviceInterface();
1551 	VkDevice				device	= m_context.getDevice();
1552 
1553 	const VkPushConstantRange pushConstant =
1554 	{
1555 		VK_SHADER_STAGE_FRAGMENT_BIT,
1556 		0u,
1557 		4u
1558 	};
1559 	const VkPipelineLayoutCreateInfo createInfo =
1560 	{
1561 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1562 		DE_NULL,
1563 		(vk::VkPipelineLayoutCreateFlags)0,
1564 
1565 		0u,
1566 		DE_NULL,
1567 
1568 		1u,
1569 		&pushConstant
1570 	};
1571 
1572 	return createPipelineLayout(vkd, device, &createInfo);
1573 }
1574 
createRenderPipeline(void)1575 Move<VkPipeline> MultisampleRenderPassTestInstance::createRenderPipeline (void)
1576 {
1577 	const DeviceInterface&			vkd						= m_context.getDeviceInterface();
1578 	VkDevice						device					= m_context.getDevice();
1579 	const vk::BinaryCollection&		binaryCollection		= m_context.getBinaryCollection();
1580 	const Unique<VkShaderModule>	vertexShaderModule		(createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
1581 	const Unique<VkShaderModule>	fragmentShaderModule	(createShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u));
1582 	const Move<VkShaderModule>		geometryShaderModule	(m_layerCount == 1 ? Move<VkShaderModule>() : createShaderModule(vkd, device, binaryCollection.get("geom"), 0u));
1583 	// Disable blending
1584 	const VkPipelineColorBlendAttachmentState attachmentBlendState =
1585 	{
1586 		VK_FALSE,
1587 		VK_BLEND_FACTOR_SRC_ALPHA,
1588 		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
1589 		VK_BLEND_OP_ADD,
1590 		VK_BLEND_FACTOR_ONE,
1591 		VK_BLEND_FACTOR_ONE,
1592 		VK_BLEND_OP_ADD,
1593 		VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
1594 	};
1595 	std::vector<VkPipelineColorBlendAttachmentState>	attachmentBlendStates(m_attachmentsCount, attachmentBlendState);
1596 	const VkPipelineVertexInputStateCreateInfo			vertexInputState =
1597 	{
1598 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
1599 		DE_NULL,
1600 		(VkPipelineVertexInputStateCreateFlags)0u,
1601 
1602 		0u,
1603 		DE_NULL,
1604 
1605 		0u,
1606 		DE_NULL
1607 	};
1608 	const tcu::UVec2				renderArea	(m_width, m_height);
1609 	const std::vector<VkViewport>	viewports	(1, makeViewport(renderArea));
1610 	const std::vector<VkRect2D>		scissors	(1, makeRect2D(renderArea));
1611 
1612 	const VkPipelineMultisampleStateCreateInfo multisampleState =
1613 	{
1614 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
1615 		DE_NULL,
1616 		(VkPipelineMultisampleStateCreateFlags)0u,
1617 
1618 		sampleCountBitFromSampleCount(m_sampleCount),
1619 		VK_FALSE,
1620 		0.0f,
1621 		DE_NULL,
1622 		VK_FALSE,
1623 		VK_FALSE,
1624 	};
1625 	const VkPipelineDepthStencilStateCreateInfo depthStencilState =
1626 	{
1627 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
1628 		DE_NULL,
1629 		(VkPipelineDepthStencilStateCreateFlags)0u,
1630 
1631 		VK_FALSE,
1632 		VK_TRUE,
1633 		VK_COMPARE_OP_ALWAYS,
1634 		VK_FALSE,
1635 		VK_TRUE,
1636 		{
1637 			VK_STENCIL_OP_KEEP,
1638 			VK_STENCIL_OP_INCREMENT_AND_WRAP,
1639 			VK_STENCIL_OP_KEEP,
1640 			VK_COMPARE_OP_ALWAYS,
1641 			~0u,
1642 			~0u,
1643 			0xFFu / (m_sampleCount + 1)
1644 		},
1645 		{
1646 			VK_STENCIL_OP_KEEP,
1647 			VK_STENCIL_OP_INCREMENT_AND_WRAP,
1648 			VK_STENCIL_OP_KEEP,
1649 			VK_COMPARE_OP_ALWAYS,
1650 			~0u,
1651 			~0u,
1652 			0xFFu / (m_sampleCount + 1)
1653 		},
1654 
1655 		0.0f,
1656 		1.0f
1657 	};
1658 	const VkPipelineColorBlendStateCreateInfo blendState =
1659 	{
1660 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
1661 		DE_NULL,
1662 		(VkPipelineColorBlendStateCreateFlags)0u,
1663 
1664 		VK_FALSE,
1665 		VK_LOGIC_OP_COPY,
1666 		deUint32(attachmentBlendStates.size()),
1667 		&attachmentBlendStates[0],
1668 		{ 0.0f, 0.0f, 0.0f, 0.0f }
1669 	};
1670 
1671 	VkPipelineRenderingCreateInfoKHR* pNext = DE_NULL;
1672 	std::vector<VkFormat> attachmentFormats(m_attachmentsCount, m_format);
1673 	VkPipelineRenderingCreateInfoKHR renderingCreateInfo
1674 	{
1675 		VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
1676 		DE_NULL,
1677 		0u,
1678 		m_attachmentsCount,
1679 		attachmentFormats.data(),
1680 		VK_FORMAT_UNDEFINED,
1681 		VK_FORMAT_UNDEFINED
1682 	};
1683 	if (m_renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
1684 		pNext = &renderingCreateInfo;
1685 
1686 	return makeGraphicsPipeline(vkd,												// const DeviceInterface&                        vk
1687 								device,												// const VkDevice                                device
1688 								*m_renderPipelineLayout,							// const VkPipelineLayout                        pipelineLayout
1689 								*vertexShaderModule,								// const VkShaderModule                          vertexShaderModule
1690 								DE_NULL,											// const VkShaderModule                          tessellationControlShaderModule
1691 								DE_NULL,											// const VkShaderModule                          tessellationEvalShaderModule
1692 								m_layerCount != 1 ? *geometryShaderModule : DE_NULL,// const VkShaderModule                          geometryShaderModule
1693 								*fragmentShaderModule,								// const VkShaderModule                          fragmentShaderModule
1694 								*m_renderPass,										// const VkRenderPass                            renderPass
1695 								viewports,											// const std::vector<VkViewport>&                viewports
1696 								scissors,											// const std::vector<VkRect2D>&                  scissors
1697 								VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,				// const VkPrimitiveTopology                     topology
1698 								0u,													// const deUint32                                subpass
1699 								0u,													// const deUint32                                patchControlPoints
1700 								&vertexInputState,									// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
1701 								DE_NULL,											// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1702 								&multisampleState,									// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
1703 								&depthStencilState,									// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
1704 								&blendState,										// const VkPipelineColorBlendStateCreateInfo*    colorBlendStateCreateInfo
1705 								DE_NULL,											// const VkPipelineDynamicStateCreateInfo*       dynamicStateCreateInfo
1706 								pNext);												// const void*                                   pNext
1707 }
1708 
1709 class MaxAttachmenstsRenderPassTestInstance : public MultisampleRenderPassTestBase
1710 {
1711 public:
1712 	MaxAttachmenstsRenderPassTestInstance	(Context& context, TestConfig config);
1713 	~MaxAttachmenstsRenderPassTestInstance	(void);
1714 
1715 	tcu::TestStatus			iterate			(void);
1716 
1717 private:
1718 
1719 	template<typename RenderpassSubpass>
1720 	void					submit						(void);
1721 	void					submitSwitch				(RenderingType renderingType);
1722 	void					verify						(void);
1723 
1724 	Move<VkDescriptorSetLayout>	createDescriptorSetLayout	(void);
1725 	Move<VkDescriptorPool>		createDescriptorPool		(void);
1726 	Move<VkDescriptorSet>		createDescriptorSet			(void);
1727 
1728 	template<typename RenderPassTrait>
1729 	Move<VkRenderPass>		createRenderPass			(void);
1730 	Move<VkRenderPass>		createRenderPassSwitch		(const RenderingType renderingType);
1731 	Move<VkPipelineLayout>	createRenderPipelineLayout	(bool secondSubpass);
1732 	Move<VkPipeline>		createRenderPipeline		(bool secondSubpass);
1733 
1734 private:
1735 
1736 	const std::vector<VkImageSp>			m_multisampleImages;
1737 	const std::vector<AllocationSp>			m_multisampleImageMemory;
1738 	const std::vector<VkImageViewSp>		m_multisampleImageViews;
1739 
1740 	const std::vector<VkImageSp>			m_singlesampleImages;
1741 	const std::vector<AllocationSp>			m_singlesampleImageMemory;
1742 	const std::vector<VkImageViewSp>		m_singlesampleImageViews;
1743 
1744 	const Unique<VkDescriptorSetLayout>		m_descriptorSetLayout;
1745 	const Unique<VkDescriptorPool>			m_descriptorPool;
1746 	const Unique<VkDescriptorSet>			m_descriptorSet;
1747 
1748 	const Unique<VkRenderPass>				m_renderPass;
1749 	const Unique<VkFramebuffer>				m_framebuffer;
1750 
1751 	const Unique<VkPipelineLayout>			m_pipelineLayoutPass0;
1752 	const Unique<VkPipeline>				m_pipelinePass0;
1753 	const Unique<VkPipelineLayout>			m_pipelineLayoutPass1;
1754 	const Unique<VkPipeline>				m_pipelinePass1;
1755 
1756 	const std::vector<VkBufferSp>			m_buffers;
1757 	const std::vector<AllocationSp>			m_bufferMemory;
1758 
1759 	const Unique<VkCommandPool>				m_commandPool;
1760 	tcu::ResultCollector					m_resultCollector;
1761 };
1762 
MaxAttachmenstsRenderPassTestInstance(Context & context,TestConfig config)1763 MaxAttachmenstsRenderPassTestInstance::MaxAttachmenstsRenderPassTestInstance (Context& context, TestConfig config)
1764 	: MultisampleRenderPassTestBase(context, config)
1765 
1766 	, m_multisampleImages		(createImages(m_sampleCount, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
1767 	, m_multisampleImageMemory	(createImageMemory(m_multisampleImages))
1768 	, m_multisampleImageViews	(createImageViews(m_multisampleImages))
1769 
1770 	, 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))
1771 	, m_singlesampleImageMemory	(createImageMemory(m_singlesampleImages))
1772 	, m_singlesampleImageViews	(createImageViews(m_singlesampleImages))
1773 
1774 	, m_descriptorSetLayout		(createDescriptorSetLayout())
1775 	, m_descriptorPool			(createDescriptorPool())
1776 	, m_descriptorSet			(createDescriptorSet())
1777 
1778 	, m_renderPass				(createRenderPassSwitch(config.renderingType))
1779 	, m_framebuffer				(createFramebuffer(m_multisampleImageViews, m_singlesampleImageViews, *m_renderPass))
1780 
1781 	, m_pipelineLayoutPass0		(createRenderPipelineLayout(0))
1782 	, m_pipelinePass0			(createRenderPipeline(0))
1783 	, m_pipelineLayoutPass1		(createRenderPipelineLayout(1))
1784 	, m_pipelinePass1			(createRenderPipeline(1))
1785 
1786 	, m_buffers					(createBuffers())
1787 	, m_bufferMemory			(createBufferMemory(m_buffers))
1788 
1789 	, m_commandPool				(createCommandPool(context.getDeviceInterface(), context.getDevice(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
1790 {
1791 }
1792 
~MaxAttachmenstsRenderPassTestInstance(void)1793 MaxAttachmenstsRenderPassTestInstance::~MaxAttachmenstsRenderPassTestInstance (void)
1794 {
1795 }
1796 
1797 template<typename RenderpassSubpass>
submit(void)1798 void MaxAttachmenstsRenderPassTestInstance::submit (void)
1799 {
1800 	const DeviceInterface&								vkd					(m_context.getDeviceInterface());
1801 	const VkDevice										device				(m_context.getDevice());
1802 	const Unique<VkCommandBuffer>						commandBuffer		(allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1803 	const typename RenderpassSubpass::SubpassBeginInfo	subpassBeginInfo	(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
1804 	const typename RenderpassSubpass::SubpassEndInfo	subpassEndInfo		(DE_NULL);
1805 
1806 	beginCommandBuffer(vkd, *commandBuffer);
1807 
1808 	// Memory barriers between previous copies and rendering
1809 	{
1810 		std::vector<VkImageMemoryBarrier> barriers;
1811 
1812 		for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
1813 		{
1814 			const VkImageMemoryBarrier barrier =
1815 			{
1816 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
1817 				DE_NULL,
1818 
1819 				VK_ACCESS_TRANSFER_READ_BIT,
1820 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1821 
1822 				VK_IMAGE_LAYOUT_UNDEFINED,
1823 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1824 
1825 				VK_QUEUE_FAMILY_IGNORED,
1826 				VK_QUEUE_FAMILY_IGNORED,
1827 
1828 				**m_singlesampleImages[dstNdx],
1829 				{
1830 					VK_IMAGE_ASPECT_COLOR_BIT,
1831 					0u,
1832 					1u,
1833 					0u,
1834 					m_layerCount
1835 				}
1836 			};
1837 
1838 			barriers.push_back(barrier);
1839 		}
1840 
1841 		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]);
1842 	}
1843 
1844 	{
1845 		const VkRenderPassBeginInfo beginInfo =
1846 		{
1847 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
1848 			DE_NULL,
1849 
1850 			*m_renderPass,
1851 			*m_framebuffer,
1852 
1853 			{
1854 				{ 0u, 0u },
1855 				{ m_width, m_height }
1856 			},
1857 
1858 			0u,
1859 			DE_NULL
1860 		};
1861 		RenderpassSubpass::cmdBeginRenderPass(vkd, *commandBuffer, &beginInfo, &subpassBeginInfo);
1862 	}
1863 
1864 	// Clear everything to black
1865 	clearAttachments(*commandBuffer);
1866 
1867 	// First subpass - render black samples
1868 	{
1869 		vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelinePass0);
1870 		vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
1871 	}
1872 
1873 	// Second subpasss - merge attachments
1874 	{
1875 		RenderpassSubpass::cmdNextSubpass(vkd, *commandBuffer, &subpassBeginInfo, &subpassEndInfo);
1876 		vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelinePass1);
1877 		vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayoutPass1, 0, 1u, &*m_descriptorSet, 0, NULL);
1878 		vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
1879 	}
1880 
1881 	RenderpassSubpass::cmdEndRenderPass(vkd, *commandBuffer, &subpassEndInfo);
1882 
1883 	// Memory barriers between rendering and copies
1884 	{
1885 		std::vector<VkImageMemoryBarrier> barriers;
1886 
1887 		for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
1888 		{
1889 			const VkImageMemoryBarrier barrier =
1890 			{
1891 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
1892 				DE_NULL,
1893 
1894 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1895 				VK_ACCESS_TRANSFER_READ_BIT,
1896 
1897 				VK_IMAGE_LAYOUT_GENERAL,
1898 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1899 
1900 				VK_QUEUE_FAMILY_IGNORED,
1901 				VK_QUEUE_FAMILY_IGNORED,
1902 
1903 				**m_singlesampleImages[dstNdx],
1904 				{
1905 					VK_IMAGE_ASPECT_COLOR_BIT,
1906 					0u,
1907 					1u,
1908 					0u,
1909 					m_layerCount
1910 				}
1911 			};
1912 
1913 			barriers.push_back(barrier);
1914 		}
1915 
1916 		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]);
1917 	}
1918 
1919 	// Copy image memory to buffers
1920 	for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
1921 	{
1922 		const VkBufferImageCopy region =
1923 		{
1924 			0u,
1925 			0u,
1926 			0u,
1927 			{
1928 				VK_IMAGE_ASPECT_COLOR_BIT,
1929 				0u,
1930 				0u,
1931 				m_layerCount,
1932 			},
1933 			{ 0u, 0u, 0u },
1934 			{ m_width, m_height, 1u }
1935 		};
1936 
1937 		vkd.cmdCopyImageToBuffer(*commandBuffer, **m_singlesampleImages[dstNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_buffers[dstNdx], 1u, &region);
1938 	}
1939 
1940 	// Memory barriers between copies and host access
1941 	{
1942 		std::vector<VkBufferMemoryBarrier> barriers;
1943 
1944 		for (size_t dstNdx = 0; dstNdx < m_buffers.size(); dstNdx++)
1945 		{
1946 			const VkBufferMemoryBarrier barrier =
1947 			{
1948 				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
1949 				DE_NULL,
1950 
1951 				VK_ACCESS_TRANSFER_WRITE_BIT,
1952 				VK_ACCESS_HOST_READ_BIT,
1953 
1954 				VK_QUEUE_FAMILY_IGNORED,
1955 				VK_QUEUE_FAMILY_IGNORED,
1956 
1957 				**m_buffers[dstNdx],
1958 				0u,
1959 				VK_WHOLE_SIZE
1960 			};
1961 
1962 			barriers.push_back(barrier);
1963 		}
1964 
1965 		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);
1966 	}
1967 
1968 	endCommandBuffer(vkd, *commandBuffer);
1969 
1970 	submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *commandBuffer);
1971 
1972 	for (size_t memoryBufferNdx = 0; memoryBufferNdx < m_bufferMemory.size(); memoryBufferNdx++)
1973 		invalidateMappedMemoryRange(vkd, device, m_bufferMemory[memoryBufferNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
1974 }
1975 
submitSwitch(RenderingType renderingType)1976 void MaxAttachmenstsRenderPassTestInstance::submitSwitch (RenderingType renderingType)
1977 {
1978 	switch (renderingType)
1979 	{
1980 		case RENDERING_TYPE_RENDERPASS_LEGACY:
1981 			submit<RenderpassSubpass1>();
1982 			break;
1983 		case RENDERING_TYPE_RENDERPASS2:
1984 			submit<RenderpassSubpass2>();
1985 			break;
1986 		default:
1987 			TCU_THROW(InternalError, "Impossible");
1988 	}
1989 }
1990 
1991 template <typename VecType>
isValueAboveThreshold1(const VecType & vale,const VecType & threshold)1992 bool isValueAboveThreshold1 (const VecType& vale, const VecType& threshold)
1993 {
1994 	return (vale[0] > threshold[0]);
1995 }
1996 
1997 template <typename VecType>
isValueAboveThreshold2(const VecType & vale,const VecType & threshold)1998 bool isValueAboveThreshold2 (const VecType& vale, const VecType& threshold)
1999 {
2000 	return (vale[0] > threshold[0]) || (vale[1] > threshold[1]);
2001 }
2002 
2003 template <typename VecType>
isValueAboveThreshold3(const VecType & vale,const VecType & threshold)2004 bool isValueAboveThreshold3 (const VecType& vale, const VecType& threshold)
2005 {
2006 	return (vale[0] > threshold[0]) || (vale[1] > threshold[1]) || (vale[2] > threshold[2]);
2007 }
2008 
2009 template <typename VecType>
isValueAboveThreshold4(const VecType & vale,const VecType & threshold)2010 bool isValueAboveThreshold4 (const VecType& vale, const VecType& threshold)
2011 {
2012 	return (vale[0] > threshold[0]) || (vale[1] > threshold[1]) || (vale[2] > threshold[2]) || (vale[3] > threshold[3]);
2013 }
2014 
verify(void)2015 void MaxAttachmenstsRenderPassTestInstance::verify (void)
2016 {
2017 	const Vec4							errorColor		(1.0f, 0.0f, 0.0f, 1.0f);
2018 	const Vec4							okColor			(0.0f, 1.0f, 0.0f, 1.0f);
2019 	const tcu::TextureFormat			format			(mapVkFormat(m_format));
2020 	const tcu::TextureChannelClass		channelClass	(tcu::getTextureChannelClass(format.type));
2021 	const int							componentCount	(tcu::getNumUsedChannels(format.order));
2022 	const int							outputsCount	= m_attachmentsCount / 2;
2023 
2024 	DE_ASSERT((componentCount >= 0) && (componentCount < 5));
2025 
2026 	std::vector<tcu::ConstPixelBufferAccess> accesses;
2027 	for (int outputNdx = 0; outputNdx < outputsCount; ++outputNdx)
2028 	{
2029 		void* const ptr = m_bufferMemory[outputNdx]->getHostPtr();
2030 		accesses.push_back(tcu::ConstPixelBufferAccess(format, m_width, m_height, 1, ptr));
2031 	}
2032 
2033 	tcu::TextureLevel	errorMask	(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width, m_height, outputsCount);
2034 	tcu::TestLog&		log			(m_context.getTestContext().getLog());
2035 	bool				isOk		= true;
2036 
2037 	switch (channelClass)
2038 	{
2039 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2040 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2041 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2042 		{
2043 			const Vec4 refColor(0.0f, 0.3f, 0.6f, 0.75f);
2044 			const Vec4 threshold(getFormatThreshold());
2045 
2046 			typedef bool(*ValueAboveThresholdFn)(const Vec4&, const Vec4&);
2047 			ValueAboveThresholdFn componentToFnMap[4] =
2048 			{
2049 				isValueAboveThreshold1<Vec4>,
2050 				isValueAboveThreshold2<Vec4>,
2051 				isValueAboveThreshold3<Vec4>,
2052 				isValueAboveThreshold4<Vec4>
2053 			};
2054 			ValueAboveThresholdFn	isValueAboveThreshold	= componentToFnMap[componentCount - 1];
2055 			bool					isSRGBFormat			= tcu::isSRGB(format);
2056 
2057 			for (int outputNdx = 0; outputNdx < outputsCount; outputNdx++)
2058 			for (int y = 0; y < (int)m_height; y++)
2059 			for (int x = 0; x < (int)m_width; x++)
2060 			{
2061 				Vec4 color = accesses[outputNdx].getPixel(x, y);
2062 				if (isSRGBFormat)
2063 					color = tcu::sRGBToLinear(color);
2064 
2065 				const Vec4 diff(tcu::abs(color - refColor));
2066 
2067 				if (isValueAboveThreshold(diff, threshold))
2068 				{
2069 					isOk = false;
2070 					errorMask.getAccess().setPixel(errorColor, x, y, outputNdx);
2071 					break;
2072 				}
2073 				else
2074 					errorMask.getAccess().setPixel(okColor, x, y, outputNdx);
2075 			}
2076 			break;
2077 		}
2078 
2079 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2080 		{
2081 			const UVec4	refColor(0, 48, 144, 189);
2082 			UVec4		threshold(1, 1, 1, 1);
2083 
2084 			if (m_format == VK_FORMAT_A2B10G10R10_UINT_PACK32)
2085 				threshold[3] = 200;
2086 
2087 			typedef bool(*ValueAboveThresholdFn)(const UVec4&, const UVec4&);
2088 			ValueAboveThresholdFn componentToFnMap[4] =
2089 			{
2090 				isValueAboveThreshold1<UVec4>,
2091 				isValueAboveThreshold2<UVec4>,
2092 				isValueAboveThreshold3<UVec4>,
2093 				isValueAboveThreshold4<UVec4>
2094 			};
2095 			ValueAboveThresholdFn isValueAboveThreshold = componentToFnMap[componentCount - 1];
2096 
2097 			for (int outputNdx = 0; outputNdx < outputsCount; outputNdx++)
2098 			for (int y = 0; y < (int)m_height; y++)
2099 			for (int x = 0; x < (int)m_width; x++)
2100 			{
2101 				const UVec4 color	(accesses[outputNdx].getPixelUint(x, y));
2102 				const UVec4 diff	(std::abs(int(color.x()) - int(refColor.x())),
2103 									 std::abs(int(color.y()) - int(refColor.y())),
2104 									 std::abs(int(color.z()) - int(refColor.z())),
2105 									 std::abs(int(color.w()) - int(refColor.w())));
2106 
2107 				if (isValueAboveThreshold(diff, threshold))
2108 				{
2109 					isOk = false;
2110 					errorMask.getAccess().setPixel(errorColor, x, y, outputNdx);
2111 					break;
2112 				}
2113 				else
2114 					errorMask.getAccess().setPixel(okColor, x, y, outputNdx);
2115 			}
2116 			break;
2117 		}
2118 
2119 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2120 		{
2121 			const IVec4 refColor	(0, 24, 75, 93);
2122 			const IVec4 threshold	(1, 1, 1, 1);
2123 
2124 			typedef bool(*ValueAboveThresholdFn)(const IVec4&, const IVec4&);
2125 			ValueAboveThresholdFn componentToFnMap[4] =
2126 			{
2127 				isValueAboveThreshold1<IVec4>,
2128 				isValueAboveThreshold2<IVec4>,
2129 				isValueAboveThreshold3<IVec4>,
2130 				isValueAboveThreshold4<IVec4>
2131 			};
2132 			ValueAboveThresholdFn isValueAboveThreshold = componentToFnMap[componentCount - 1];
2133 
2134 			for (int outputNdx = 0; outputNdx < outputsCount; outputNdx++)
2135 			for (int y = 0; y < (int)m_height; y++)
2136 			for (int x = 0; x < (int)m_width; x++)
2137 			{
2138 				const IVec4 color	(accesses[outputNdx].getPixelInt(x, y));
2139 				const IVec4 diff	(std::abs(color.x() - refColor.x()),
2140 									 std::abs(color.y() - refColor.y()),
2141 									 std::abs(color.z() - refColor.z()),
2142 									 std::abs(color.w() - refColor.w()));
2143 
2144 				if (isValueAboveThreshold(diff, threshold))
2145 				{
2146 					isOk = false;
2147 					errorMask.getAccess().setPixel(errorColor, x, y, outputNdx);
2148 					break;
2149 				}
2150 				else
2151 					errorMask.getAccess().setPixel(okColor, x, y, outputNdx);
2152 			}
2153 			break;
2154 		}
2155 
2156 		default:
2157 			DE_FATAL("Unknown channel class");
2158 	}
2159 
2160 	if (!isOk)
2161 	{
2162 		const std::string			sectionName	("MaxAttachmentsVerify");
2163 		const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
2164 
2165 		logImage("ErrorMask", errorMask.getAccess());
2166 		m_resultCollector.fail("Fail");
2167 	}
2168 }
2169 
iterate(void)2170 tcu::TestStatus MaxAttachmenstsRenderPassTestInstance::iterate(void)
2171 {
2172 	submitSwitch(m_renderingType);
2173 	verify();
2174 
2175 	return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
2176 }
2177 
createDescriptorSetLayout()2178 Move<VkDescriptorSetLayout> MaxAttachmenstsRenderPassTestInstance::createDescriptorSetLayout()
2179 {
2180 	const VkDescriptorSetLayoutBinding bindingTemplate =
2181 	{
2182 		0,														// binding
2183 		VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,					// descriptorType
2184 		1u,														// descriptorCount
2185 		VK_SHADER_STAGE_FRAGMENT_BIT,							// stageFlags
2186 		DE_NULL													// pImmutableSamplers
2187 	};
2188 
2189 	std::vector<VkDescriptorSetLayoutBinding> bindings(m_attachmentsCount, bindingTemplate);
2190 	for (deUint32 idx = 0; idx < m_attachmentsCount; ++idx)
2191 		bindings[idx].binding = idx;
2192 
2193 	const VkDescriptorSetLayoutCreateInfo createInfo =
2194 	{
2195 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// sType
2196 		DE_NULL,												// pNext
2197 		0u,														// flags
2198 		m_attachmentsCount,										// bindingCount
2199 		&bindings[0]											// pBindings
2200 	};
2201 
2202 	return ::createDescriptorSetLayout(m_context.getDeviceInterface(), m_context.getDevice(), &createInfo);
2203 }
2204 
createDescriptorPool()2205 Move<VkDescriptorPool> MaxAttachmenstsRenderPassTestInstance::createDescriptorPool()
2206 {
2207 	const VkDescriptorPoolSize size =
2208 	{
2209 		VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,					// type
2210 		m_attachmentsCount										// descriptorCount
2211 	};
2212 
2213 	const VkDescriptorPoolCreateInfo createInfo =
2214 	{
2215 		VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,			// sType
2216 		DE_NULL,												// pNext
2217 		VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,		// flags
2218 		1u,														// maxSets
2219 		1u,														// poolSizeCount
2220 		&size													// pPoolSizes
2221 	};
2222 
2223 	return ::createDescriptorPool(m_context.getDeviceInterface(), m_context.getDevice(), &createInfo);
2224 }
2225 
createDescriptorSet()2226 Move<VkDescriptorSet> MaxAttachmenstsRenderPassTestInstance::createDescriptorSet()
2227 {
2228 	const VkDescriptorSetAllocateInfo allocateInfo =
2229 	{
2230 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,			// sType
2231 		DE_NULL,												// pNext
2232 		*m_descriptorPool,										// descriptorPool
2233 		1u,														// descriptorSetCount
2234 		&*m_descriptorSetLayout									// pSetLayouts
2235 	};
2236 
2237 	const vk::DeviceInterface&		vkd					= m_context.getDeviceInterface();
2238 	vk::VkDevice					device				= m_context.getDevice();
2239 	Move<VkDescriptorSet>			descriptorSet		= allocateDescriptorSet(vkd, device, &allocateInfo);
2240 	vector<VkDescriptorImageInfo>	descriptorImageInfo	(m_attachmentsCount);
2241 	vector<VkWriteDescriptorSet>	descriptorWrites	(m_attachmentsCount);
2242 
2243 	for (deUint32 idx = 0; idx < m_attachmentsCount; ++idx)
2244 	{
2245 		const VkDescriptorImageInfo imageInfo =
2246 		{
2247 			DE_NULL,									// VkSampler		sampler
2248 			**m_singlesampleImageViews[idx],			// VkImageView		imageView
2249 			VK_IMAGE_LAYOUT_GENERAL						// VkImageLayout	imageLayout
2250 		};
2251 		descriptorImageInfo[idx] = imageInfo;
2252 
2253 		const VkWriteDescriptorSet	write =
2254 		{
2255 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,		// VkStructureType					sType
2256 			DE_NULL,									// const void*						pNext
2257 			*descriptorSet,								// VkDescriptorSet					dstSet
2258 			(deUint32)idx,								// uint32_t							dstBinding
2259 			0u,											// uint32_t							dstArrayElement
2260 			1u,											// uint32_t							descriptorCount
2261 			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,		// VkDescriptorType					descriptorType
2262 			&descriptorImageInfo[idx],					// const VkDescriptorImageInfo*		pImageInfo
2263 			DE_NULL,									// const VkDescriptorBufferInfo*	pBufferInfo
2264 			DE_NULL										// const VkBufferView*				pTexelBufferView
2265 		};
2266 
2267 		descriptorWrites[idx] = write;
2268 	}
2269 
2270 	vkd.updateDescriptorSets(device, (deUint32)descriptorWrites.size(), &descriptorWrites[0], 0u, DE_NULL);
2271 	return descriptorSet;
2272 }
2273 
2274 template<typename RenderPassTrait>
createRenderPass(void)2275 Move<VkRenderPass> MaxAttachmenstsRenderPassTestInstance::createRenderPass(void)
2276 {
2277 	// make name for RenderPass1Trait or RenderPass2Trait shorter
2278 	typedef RenderPassTrait RPT;
2279 
2280 	typedef RenderPassTrait RPT;
2281 	typedef typename RPT::AttDesc				AttDesc;
2282 	typedef typename RPT::AttRef				AttRef;
2283 	typedef typename RPT::SubpassDep			SubpassDep;
2284 	typedef typename RPT::SubpassDesc			SubpassDesc;
2285 	typedef typename RPT::RenderPassCreateInfo	RenderPassCreateInfo;
2286 
2287 	const DeviceInterface&	vkd		= m_context.getDeviceInterface();
2288 	VkDevice				device	= m_context.getDevice();
2289 	std::vector<AttDesc>	attachments;
2290 	std::vector<AttRef>		sp0colorAttachmentRefs;
2291 	std::vector<AttRef>		sp0resolveAttachmentRefs;
2292 	std::vector<AttRef>		sp1inAttachmentRefs;
2293 	std::vector<AttRef>		sp1colorAttachmentRefs;
2294 
2295 	for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
2296 	{
2297 		// define first subpass outputs
2298 		{
2299 			const AttDesc multisampleAttachment
2300 			(
2301 				DE_NULL,									// pNext
2302 				0u,											// flags
2303 				m_format,									// format
2304 				m_sampleCount,								// samples
2305 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// loadOp
2306 				VK_ATTACHMENT_STORE_OP_STORE,				// storeOp
2307 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// stencilLoadOp
2308 				VK_ATTACHMENT_STORE_OP_DONT_CARE,			// stencilStoreOp
2309 				VK_IMAGE_LAYOUT_UNDEFINED,					// initialLayout
2310 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// finalLayout
2311 			);
2312 			const AttRef attachmentRef
2313 			(
2314 				DE_NULL,
2315 				(deUint32)attachments.size(),				// attachment
2316 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// layout
2317 				0u											// aspectMask
2318 			);
2319 			sp0colorAttachmentRefs.push_back(attachmentRef);
2320 			attachments.push_back(multisampleAttachment);
2321 		}
2322 		// define first subpass resolve attachments
2323 		{
2324 			const AttDesc singlesampleAttachment
2325 			(
2326 				DE_NULL,									// pNext
2327 				0u,											// flags
2328 				m_format,									// format
2329 				VK_SAMPLE_COUNT_1_BIT,						// samples
2330 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// loadOp
2331 				VK_ATTACHMENT_STORE_OP_STORE,				// storeOp
2332 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// stencilLoadOp
2333 				VK_ATTACHMENT_STORE_OP_DONT_CARE,			// stencilStoreOp
2334 				VK_IMAGE_LAYOUT_UNDEFINED,					// initialLayout
2335 				VK_IMAGE_LAYOUT_GENERAL						// finalLayout
2336 			);
2337 			const AttRef attachmentRef
2338 			(
2339 				DE_NULL,									// pNext
2340 				(deUint32)attachments.size(),				// attachment
2341 				VK_IMAGE_LAYOUT_GENERAL,					// layout
2342 				0u											// aspectMask
2343 			);
2344 			sp0resolveAttachmentRefs.push_back(attachmentRef);
2345 			attachments.push_back(singlesampleAttachment);
2346 		}
2347 		// define second subpass inputs
2348 		{
2349 			const AttRef attachmentRef
2350 			(
2351 				DE_NULL,									// pNext
2352 				(deUint32)attachments.size() - 1,			// attachment
2353 				VK_IMAGE_LAYOUT_GENERAL,					// layout
2354 				VK_IMAGE_ASPECT_COLOR_BIT					// aspectMask
2355 			);
2356 			sp1inAttachmentRefs.push_back(attachmentRef);
2357 		}
2358 		// define second subpass outputs - it merges pairs of
2359 		// results that were produced by the first subpass
2360 		if (attachmentNdx < (m_attachmentsCount / 2))
2361 		{
2362 			const AttRef colorAttachmentRef
2363 			(
2364 				DE_NULL,									// pNext
2365 				(deUint32)attachments.size() - 1,			// attachment
2366 				VK_IMAGE_LAYOUT_GENERAL,					// layout
2367 				0u											// aspectMask
2368 			);
2369 			sp1colorAttachmentRefs.push_back(colorAttachmentRef);
2370 		}
2371 	}
2372 
2373 	DE_ASSERT(sp0colorAttachmentRefs.size() == sp0resolveAttachmentRefs.size());
2374 	DE_ASSERT(attachments.size() == sp0colorAttachmentRefs.size() + sp0resolveAttachmentRefs.size());
2375 
2376 	{
2377 		const SubpassDesc subpass0
2378 		(
2379 															// sType
2380 			DE_NULL,										// pNext
2381 			(VkSubpassDescriptionFlags)0,					// flags
2382 			VK_PIPELINE_BIND_POINT_GRAPHICS,				// pipelineBindPoint
2383 			0u,												// viewMask
2384 			0u,												// inputAttachmentCount
2385 			DE_NULL,										// pInputAttachments
2386 			(deUint32)sp0colorAttachmentRefs.size(),		// colorAttachmentCount
2387 			&sp0colorAttachmentRefs[0],						// pColorAttachments
2388 			&sp0resolveAttachmentRefs[0],					// pResolveAttachments
2389 			DE_NULL,										// pDepthStencilAttachment
2390 			0u,												// preserveAttachmentCount
2391 			DE_NULL											// pPreserveAttachments
2392 		);
2393 		const SubpassDesc subpass1
2394 		(
2395 															// sType
2396 			DE_NULL,										// pNext
2397 			(VkSubpassDescriptionFlags)0,					// flags
2398 			VK_PIPELINE_BIND_POINT_GRAPHICS,				// pipelineBindPoint
2399 			0u,												// viewMask
2400 			(deUint32)sp1inAttachmentRefs.size(),			// inputAttachmentCount
2401 			&sp1inAttachmentRefs[0],						// pInputAttachments
2402 			(deUint32)sp1colorAttachmentRefs.size(),		// colorAttachmentCount
2403 			&sp1colorAttachmentRefs[0],						// pColorAttachments
2404 			DE_NULL,										// pResolveAttachments
2405 			DE_NULL,										// pDepthStencilAttachment
2406 			0u,												// preserveAttachmentCount
2407 			DE_NULL											// pPreserveAttachments
2408 		);
2409 		SubpassDesc subpasses[] =
2410 		{
2411 			subpass0,
2412 			subpass1
2413 		};
2414 		const SubpassDep subpassDependency
2415 		(
2416 			DE_NULL,										// pNext
2417 			0u,												// srcSubpass
2418 			1u,												// dstSubpass
2419 			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,	// srcStageMask
2420 			VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,			// dstStageMask
2421 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// srcAccessMask
2422 			VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,			// dstAccessMask
2423 			0u,												// dependencyFlags
2424 			0u												// viewOffset
2425 		);
2426 		const RenderPassCreateInfo renderPassCreator
2427 		(
2428 															// sType
2429 			DE_NULL,										// pNext
2430 			(VkRenderPassCreateFlags)0u,					// flags
2431 			(deUint32)attachments.size(),					// attachmentCount
2432 			&attachments[0],								// pAttachments
2433 			2u,												// subpassCount
2434 			subpasses,										// pSubpasses
2435 			1u,												// dependencyCount
2436 			&subpassDependency,								// pDependencies
2437 			0u,												// correlatedViewMaskCount
2438 			DE_NULL											// pCorrelatedViewMasks
2439 		);
2440 
2441 		return renderPassCreator.createRenderPass(vkd, device);
2442 	}
2443 }
2444 
createRenderPassSwitch(const RenderingType renderingType)2445 Move<VkRenderPass> MaxAttachmenstsRenderPassTestInstance::createRenderPassSwitch(const RenderingType renderingType)
2446 {
2447 	switch (renderingType)
2448 	{
2449 		case RENDERING_TYPE_RENDERPASS_LEGACY:
2450 			return createRenderPass<RenderPass1Trait>();
2451 		case RENDERING_TYPE_RENDERPASS2:
2452 			return createRenderPass<RenderPass2Trait>();
2453 		default:
2454 			TCU_THROW(InternalError, "Impossible");
2455 	}
2456 }
2457 
createRenderPipelineLayout(bool secondSubpass)2458 Move<VkPipelineLayout> MaxAttachmenstsRenderPassTestInstance::createRenderPipelineLayout(bool secondSubpass)
2459 {
2460 	const DeviceInterface&	vkd		= m_context.getDeviceInterface();
2461 	VkDevice				device	= m_context.getDevice();
2462 
2463 	const VkPipelineLayoutCreateInfo createInfo =
2464 	{
2465 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
2466 		DE_NULL,
2467 		(vk::VkPipelineLayoutCreateFlags)0,
2468 
2469 		secondSubpass ? 1u : 0u,
2470 		secondSubpass ? &*m_descriptorSetLayout : DE_NULL,
2471 
2472 		0u,
2473 		DE_NULL
2474 	};
2475 
2476 	return createPipelineLayout(vkd, device, &createInfo);
2477 }
2478 
createRenderPipeline(bool secondSubpass)2479 Move<VkPipeline> MaxAttachmenstsRenderPassTestInstance::createRenderPipeline(bool secondSubpass)
2480 {
2481 	const DeviceInterface&			vkd						= m_context.getDeviceInterface();
2482 	VkDevice						device					= m_context.getDevice();
2483 	const vk::BinaryCollection&		binaryCollection		= m_context.getBinaryCollection();
2484 	VkSampleCountFlagBits			sampleCount				= sampleCountBitFromSampleCount(m_sampleCount);
2485 	deUint32						blendStatesCount		= m_attachmentsCount;
2486 	std::string						fragShaderNameBase		= "quad-frag-sp0-";
2487 
2488 	if (secondSubpass)
2489 	{
2490 		sampleCount			= VK_SAMPLE_COUNT_1_BIT;
2491 		blendStatesCount	/= 2;
2492 		fragShaderNameBase	= "quad-frag-sp1-";
2493 	}
2494 
2495 	std::string						fragShaderName			= fragShaderNameBase + de::toString(m_attachmentsCount);
2496 	const Unique<VkShaderModule>	vertexShaderModule		(createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
2497 	const Unique<VkShaderModule>	fragmentShaderModule	(createShaderModule(vkd, device, binaryCollection.get(fragShaderName), 0u));
2498 	const Move<VkShaderModule>		geometryShaderModule	(m_layerCount == 1 ? Move<VkShaderModule>() : createShaderModule(vkd, device, binaryCollection.get("geom"), 0u));
2499 
2500 	// Disable blending
2501 	const VkPipelineColorBlendAttachmentState attachmentBlendState =
2502 	{
2503 		VK_FALSE,
2504 		VK_BLEND_FACTOR_SRC_ALPHA,
2505 		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
2506 		VK_BLEND_OP_ADD,
2507 		VK_BLEND_FACTOR_ONE,
2508 		VK_BLEND_FACTOR_ONE,
2509 		VK_BLEND_OP_ADD,
2510 		VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
2511 	};
2512 	std::vector<VkPipelineColorBlendAttachmentState>	attachmentBlendStates(blendStatesCount, attachmentBlendState);
2513 	const VkPipelineVertexInputStateCreateInfo			vertexInputState =
2514 	{
2515 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
2516 		DE_NULL,
2517 		(VkPipelineVertexInputStateCreateFlags)0u,
2518 
2519 		0u,
2520 		DE_NULL,
2521 
2522 		0u,
2523 		DE_NULL
2524 	};
2525 	const tcu::UVec2				renderArea	(m_width, m_height);
2526 	const std::vector<VkViewport>	viewports	(1, makeViewport(renderArea));
2527 	const std::vector<VkRect2D>		scissors	(1, makeRect2D(renderArea));
2528 
2529 	const VkPipelineMultisampleStateCreateInfo multisampleState =
2530 	{
2531 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
2532 		DE_NULL,
2533 		(VkPipelineMultisampleStateCreateFlags)0u,
2534 
2535 		sampleCount,
2536 		VK_FALSE,
2537 		0.0f,
2538 		DE_NULL,
2539 		VK_FALSE,
2540 		VK_FALSE,
2541 	};
2542 	const VkPipelineDepthStencilStateCreateInfo depthStencilState =
2543 	{
2544 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
2545 		DE_NULL,
2546 		(VkPipelineDepthStencilStateCreateFlags)0u,
2547 
2548 		VK_FALSE,
2549 		VK_TRUE,
2550 		VK_COMPARE_OP_ALWAYS,
2551 		VK_FALSE,
2552 		VK_TRUE,
2553 		{
2554 			VK_STENCIL_OP_KEEP,
2555 			VK_STENCIL_OP_INCREMENT_AND_WRAP,
2556 			VK_STENCIL_OP_KEEP,
2557 			VK_COMPARE_OP_ALWAYS,
2558 			~0u,
2559 			~0u,
2560 			0xFFu / (m_sampleCount + 1)
2561 		},
2562 		{
2563 			VK_STENCIL_OP_KEEP,
2564 			VK_STENCIL_OP_INCREMENT_AND_WRAP,
2565 			VK_STENCIL_OP_KEEP,
2566 			VK_COMPARE_OP_ALWAYS,
2567 			~0u,
2568 			~0u,
2569 			0xFFu / (m_sampleCount + 1)
2570 		},
2571 
2572 		0.0f,
2573 		1.0f
2574 	};
2575 	const VkPipelineColorBlendStateCreateInfo blendState =
2576 	{
2577 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
2578 		DE_NULL,
2579 		(VkPipelineColorBlendStateCreateFlags)0u,
2580 
2581 		VK_FALSE,
2582 		VK_LOGIC_OP_COPY,
2583 		deUint32(attachmentBlendStates.size()),
2584 		&attachmentBlendStates[0],
2585 		{ 0.0f, 0.0f, 0.0f, 0.0f }
2586 	};
2587 
2588 	return makeGraphicsPipeline(vkd,																// vk
2589 								device,																// device
2590 								secondSubpass ? *m_pipelineLayoutPass1 : *m_pipelineLayoutPass0,	// pipelineLayout
2591 								*vertexShaderModule,												// vertexShaderModule
2592 								DE_NULL,															// tessellationControlShaderModule
2593 								DE_NULL,															// tessellationEvalShaderModule
2594 								m_layerCount != 1 ? *geometryShaderModule : DE_NULL,				// geometryShaderModule
2595 								*fragmentShaderModule,												// fragmentShaderModule
2596 								*m_renderPass,														// renderPass
2597 								viewports,															// viewports
2598 								scissors,															// scissors
2599 								VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,								// topology
2600 								secondSubpass,														// subpass
2601 								0u,																	// patchControlPoints
2602 								&vertexInputState,													// vertexInputStateCreateInfo
2603 								DE_NULL,															// rasterizationStateCreateInfo
2604 								&multisampleState,													// multisampleStateCreateInfo
2605 								&depthStencilState,													// depthStencilStateCreateInfo
2606 								&blendState);														// colorBlendStateCreateInfo
2607 }
2608 
2609 class MultisampleRenderPassResolveLevelTestInstance : public MultisampleRenderPassTestInstance
2610 {
2611 public:
2612 	MultisampleRenderPassResolveLevelTestInstance	(Context& context, TestConfig2 config);
2613 	~MultisampleRenderPassResolveLevelTestInstance	(void) = default;
2614 };
2615 
MultisampleRenderPassResolveLevelTestInstance(Context & context,TestConfig2 config)2616 MultisampleRenderPassResolveLevelTestInstance::MultisampleRenderPassResolveLevelTestInstance (Context& context, TestConfig2 config)
2617 	: MultisampleRenderPassTestInstance(context, config, config.resolveLevel)
2618 {
2619 }
2620 
2621 struct Programs
2622 {
initvkt::__anon687a28300111::Programs2623 	void init(vk::SourceCollections& dst, TestConfig config) const
2624 	{
2625 		const tcu::TextureFormat		format			(mapVkFormat(config.format));
2626 		const tcu::TextureChannelClass	channelClass	(tcu::getTextureChannelClass(format.type));
2627 
2628 		dst.glslSources.add("quad-vert") << glu::VertexSource(
2629 			"#version 450\n"
2630 			"out gl_PerVertex {\n"
2631 			"\tvec4 gl_Position;\n"
2632 			"};\n"
2633 			"highp float;\n"
2634 			"void main (void) {\n"
2635 			"\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
2636 			"\t                   ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
2637 			"}\n");
2638 
2639 		if (config.layerCount > 1)
2640 		{
2641 			std::ostringstream src;
2642 
2643 			src << "#version 450\n"
2644 				<< "highp float;\n"
2645 				<< "\n"
2646 				<< "layout(triangles) in;\n"
2647 				<< "layout(triangle_strip, max_vertices = " << 3 * 2 * config.layerCount << ") out;\n"
2648 				<< "\n"
2649 				<< "in gl_PerVertex {\n"
2650 				<< "    vec4 gl_Position;\n"
2651 				<< "} gl_in[];\n"
2652 				<< "\n"
2653 				<< "out gl_PerVertex {\n"
2654 				<< "    vec4 gl_Position;\n"
2655 				<< "};\n"
2656 				<< "\n"
2657 				<< "void main (void) {\n"
2658 				<< "    for (int layerNdx = 0; layerNdx < " << config.layerCount << "; ++layerNdx) {\n"
2659 				<< "        for(int vertexNdx = 0; vertexNdx < gl_in.length(); vertexNdx++) {\n"
2660 				<< "            gl_Position = gl_in[vertexNdx].gl_Position;\n"
2661 				<< "            gl_Layer    = layerNdx;\n"
2662 				<< "            EmitVertex();\n"
2663 				<< "        };\n"
2664 				<< "        EndPrimitive();\n"
2665 				<< "    };\n"
2666 				<< "}\n";
2667 
2668 			dst.glslSources.add("geom") << glu::GeometrySource(src.str());
2669 		}
2670 
2671 		const tcu::StringTemplate genericLayoutTemplate("layout(location = ${INDEX}) out ${TYPE_PREFIX}vec4 o_color${INDEX};\n");
2672 		const tcu::StringTemplate genericBodyTemplate("\to_color${INDEX} = ${TYPE_PREFIX}vec4(${COLOR_VAL});\n");
2673 
2674 		if (config.testType == RESOLVE || config.testType == COMPATIBILITY)
2675 		{
2676 			const tcu::StringTemplate fragTemplate("#version 450\n"
2677 												   "layout(push_constant) uniform PushConstant {\n"
2678 												   "\thighp uint sampleMask;\n"
2679 												   "} pushConstants;\n"
2680 												   "${LAYOUT}"
2681 												   "void main (void)\n"
2682 												   "{\n"
2683 												   "${BODY}"
2684 												   "}\n");
2685 
2686 			std::map<std::string, std::string> parameters;
2687 			switch (channelClass)
2688 			{
2689 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2690 					parameters["TYPE_PREFIX"] = "u";
2691 					parameters["COLOR_VAL"] = "255";
2692 					break;
2693 
2694 				case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2695 					parameters["TYPE_PREFIX"] = "i";
2696 					parameters["COLOR_VAL"] = "127";
2697 					break;
2698 
2699 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2700 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2701 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2702 					parameters["TYPE_PREFIX"] = "";
2703 					parameters["COLOR_VAL"] = "1.0";
2704 					break;
2705 
2706 				default:
2707 					DE_FATAL("Unknown channel class");
2708 			}
2709 
2710 			std::string layoutDefinitions = "";
2711 			std::string shaderBody = "\tgl_SampleMask[0] = int(pushConstants.sampleMask);\n";
2712 
2713 			for (deUint32 attIdx = 0; attIdx < config.attachmentCount; ++attIdx)
2714 			{
2715 				parameters["INDEX"]	= de::toString(attIdx);
2716 				layoutDefinitions	+= genericLayoutTemplate.specialize(parameters);
2717 				shaderBody			+= genericBodyTemplate.specialize(parameters);
2718 			}
2719 
2720 			parameters["LAYOUT"]	= layoutDefinitions;
2721 			parameters["BODY"]		= shaderBody;
2722 			dst.glslSources.add("quad-frag") << glu::FragmentSource(fragTemplate.specialize(parameters));
2723 		}
2724 		else	// MAX_ATTACMENTS
2725 		{
2726 			const tcu::StringTemplate fragTemplate("#version 450\n"
2727 												   "${LAYOUT}"
2728 												   "void main (void)\n"
2729 												   "{\n"
2730 												   "${BODY}"
2731 												   "}\n");
2732 
2733 			std::map<std::string, std::string> parameters;
2734 			switch (channelClass)
2735 			{
2736 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2737 					parameters["TYPE_PREFIX"] = "u";
2738 					parameters["COLOR_VAL"] = "0, 64, 192, 252";
2739 					break;
2740 
2741 				case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2742 					parameters["TYPE_PREFIX"] = "i";
2743 					parameters["COLOR_VAL"] = "0, 32, 100, 124";
2744 					break;
2745 
2746 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2747 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2748 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2749 					parameters["TYPE_PREFIX"] = "";
2750 					parameters["COLOR_VAL"] = "0.0, 0.4, 0.8, 1.0";
2751 					break;
2752 
2753 				default:
2754 					DE_FATAL("Unknown channel class");
2755 			}
2756 
2757 			// parts of fragment shader for second subpass - Vulkan introduced a new uniform type and syntax to glsl for input attachments
2758 			const tcu::StringTemplate subpassLayoutTemplate("layout (input_attachment_index = ${INDEX}, set = 0, binding = ${INDEX}) uniform ${TYPE_PREFIX}subpassInput i_color${INDEX};\n");
2759 			const tcu::StringTemplate subpassFBodyTemplate("\to_color${INDEX} = subpassLoad(i_color${INDEX})*0.5 + subpassLoad(i_color${MIX_INDEX})*0.25;\n");
2760 			const tcu::StringTemplate subpassIBodyTemplate("\to_color${INDEX} = subpassLoad(i_color${INDEX}) / 2 + subpassLoad(i_color${MIX_INDEX}) / 4;\n");
2761 
2762 			bool selectIBody = isIntFormat(config.format) || isUintFormat(config.format);
2763 			const tcu::StringTemplate& subpassBodyTemplate = selectIBody ? subpassIBodyTemplate : subpassFBodyTemplate;
2764 
2765 			std::string sp0layoutDefinitions	= "";
2766 			std::string sp0shaderBody			= "";
2767 			std::string sp1inLayoutDefinitions	= "";
2768 			std::string sp1outLayoutDefinitions	= "";
2769 			std::string sp1shaderBody			= "";
2770 
2771 			deUint32 halfAttachments = config.attachmentCount / 2;
2772 			for (deUint32 attIdx = 0; attIdx < config.attachmentCount; ++attIdx)
2773 			{
2774 				parameters["INDEX"] = de::toString(attIdx);
2775 
2776 				sp0layoutDefinitions	+= genericLayoutTemplate.specialize(parameters);
2777 				sp0shaderBody			+= genericBodyTemplate.specialize(parameters);
2778 
2779 				sp1inLayoutDefinitions += subpassLayoutTemplate.specialize(parameters);
2780 				if (attIdx < halfAttachments)
2781 				{
2782 					// we are combining pairs of input attachments to produce half the number of outputs
2783 					parameters["MIX_INDEX"]	= de::toString(halfAttachments + attIdx);
2784 					sp1outLayoutDefinitions	+= genericLayoutTemplate.specialize(parameters);
2785 					sp1shaderBody			+= subpassBodyTemplate.specialize(parameters);
2786 				}
2787 			}
2788 
2789 			// construct fragment shaders for subpass1 and subpass2; note that there
2790 			// is different shader definition depending on number of attachments
2791 			std::string nameBase	= "quad-frag-sp";
2792 			std::string namePostfix	= de::toString(config.attachmentCount);
2793 			parameters["LAYOUT"]	= sp0layoutDefinitions;
2794 			parameters["BODY"]		= sp0shaderBody;
2795 			dst.glslSources.add(nameBase + "0-" + namePostfix) << glu::FragmentSource(fragTemplate.specialize(parameters));
2796 			parameters["LAYOUT"]	= sp1inLayoutDefinitions + sp1outLayoutDefinitions;
2797 			parameters["BODY"]		= sp1shaderBody;
2798 			dst.glslSources.add(nameBase + "1-" + namePostfix) << glu::FragmentSource(fragTemplate.specialize(parameters));
2799 		}
2800 	}
2801 };
2802 
2803 template<class TestConfigType>
checkSupport(Context & context,TestConfigType config)2804 void checkSupport(Context& context, TestConfigType config)
2805 {
2806 	if (config.layerCount > 1)
2807 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
2808 
2809 	if (config.renderingType == RENDERING_TYPE_RENDERPASS2)
2810 		context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
2811 
2812 	if (config.renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
2813 		context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
2814 
2815 	if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
2816 		!context.getPortabilitySubsetFeatures().multisampleArrayImage &&
2817 		(config.sampleCount != VK_SAMPLE_COUNT_1_BIT) && (config.layerCount != 1))
2818 	{
2819 		TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Implementation does not support image array with multiple samples per texel");
2820 	}
2821 
2822 	const InstanceInterface&				vki				= context.getInstanceInterface();
2823 	vk::VkPhysicalDevice					physicalDevice	= context.getPhysicalDevice();
2824 	const vk::VkPhysicalDeviceProperties	properties		= vk::getPhysicalDeviceProperties(vki, physicalDevice);
2825 
2826 	if (config.attachmentCount > properties.limits.maxColorAttachments)
2827 		TCU_THROW(NotSupportedError, "Required number of color attachments not supported.");
2828 }
2829 
formatToName(VkFormat format)2830 std::string formatToName (VkFormat format)
2831 {
2832 	const std::string	formatStr	= de::toString(format);
2833 	const std::string	prefix		= "VK_FORMAT_";
2834 
2835 	DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
2836 
2837 	return de::toLower(formatStr.substr(prefix.length()));
2838 }
2839 
initTests(tcu::TestCaseGroup * group,RenderingType renderingType)2840 void initTests (tcu::TestCaseGroup* group, RenderingType renderingType)
2841 {
2842 	static const VkFormat	formats[] =
2843 	{
2844 		VK_FORMAT_R5G6B5_UNORM_PACK16,
2845 		VK_FORMAT_R8_UNORM,
2846 		VK_FORMAT_R8_SNORM,
2847 		VK_FORMAT_R8_UINT,
2848 		VK_FORMAT_R8_SINT,
2849 		VK_FORMAT_R8G8_UNORM,
2850 		VK_FORMAT_R8G8_SNORM,
2851 		VK_FORMAT_R8G8_UINT,
2852 		VK_FORMAT_R8G8_SINT,
2853 		VK_FORMAT_R8G8B8A8_UNORM,
2854 		VK_FORMAT_R8G8B8A8_SNORM,
2855 		VK_FORMAT_R8G8B8A8_UINT,
2856 		VK_FORMAT_R8G8B8A8_SINT,
2857 		VK_FORMAT_R8G8B8A8_SRGB,
2858 		VK_FORMAT_A8B8G8R8_UNORM_PACK32,
2859 		VK_FORMAT_A8B8G8R8_SNORM_PACK32,
2860 		VK_FORMAT_A8B8G8R8_UINT_PACK32,
2861 		VK_FORMAT_A8B8G8R8_SINT_PACK32,
2862 		VK_FORMAT_A8B8G8R8_SRGB_PACK32,
2863 		VK_FORMAT_B8G8R8A8_UNORM,
2864 		VK_FORMAT_B8G8R8A8_SRGB,
2865 		VK_FORMAT_A2R10G10B10_UNORM_PACK32,
2866 		VK_FORMAT_A2B10G10R10_UNORM_PACK32,
2867 		VK_FORMAT_A2B10G10R10_UINT_PACK32,
2868 		VK_FORMAT_R16_UNORM,
2869 		VK_FORMAT_R16_SNORM,
2870 		VK_FORMAT_R16_UINT,
2871 		VK_FORMAT_R16_SINT,
2872 		VK_FORMAT_R16_SFLOAT,
2873 		VK_FORMAT_R16G16_UNORM,
2874 		VK_FORMAT_R16G16_SNORM,
2875 		VK_FORMAT_R16G16_UINT,
2876 		VK_FORMAT_R16G16_SINT,
2877 		VK_FORMAT_R16G16_SFLOAT,
2878 		VK_FORMAT_R16G16B16A16_UNORM,
2879 		VK_FORMAT_R16G16B16A16_SNORM,
2880 		VK_FORMAT_R16G16B16A16_UINT,
2881 		VK_FORMAT_R16G16B16A16_SINT,
2882 		VK_FORMAT_R16G16B16A16_SFLOAT,
2883 		VK_FORMAT_R32_UINT,
2884 		VK_FORMAT_R32_SINT,
2885 		VK_FORMAT_R32_SFLOAT,
2886 		VK_FORMAT_R32G32_UINT,
2887 		VK_FORMAT_R32G32_SINT,
2888 		VK_FORMAT_R32G32_SFLOAT,
2889 		VK_FORMAT_R32G32B32A32_UINT,
2890 		VK_FORMAT_R32G32B32A32_SINT,
2891 		VK_FORMAT_R32G32B32A32_SFLOAT,
2892 		VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
2893 	};
2894 	const deUint32			sampleCounts[] =
2895 	{
2896 		2u, 4u, 8u
2897 	};
2898 	const deUint32			layerCounts[] =
2899 	{
2900 		1u, 3u, 6u
2901 	};
2902 	const deUint32			resolveLevels[] =
2903 	{
2904 		2u, 3u, 4u
2905 	};
2906 	tcu::TestContext&		testCtx	(group->getTestContext());
2907 
2908 	for (size_t layerCountNdx = 0; layerCountNdx < DE_LENGTH_OF_ARRAY(layerCounts); layerCountNdx++)
2909 	{
2910 		const deUint32					layerCount		(layerCounts[layerCountNdx]);
2911 		const std::string				layerGroupName	("layers_" + de::toString(layerCount));
2912 		de::MovePtr<tcu::TestCaseGroup>	layerGroup		(new tcu::TestCaseGroup(testCtx, layerGroupName.c_str(), layerGroupName.c_str()));
2913 
2914 		for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
2915 		{
2916 			const VkFormat					format		(formats[formatNdx]);
2917 			const std::string				formatName	(formatToName(format));
2918 			de::MovePtr<tcu::TestCaseGroup>	formatGroup	(new tcu::TestCaseGroup(testCtx, formatName.c_str(), formatName.c_str()));
2919 
2920 			for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++)
2921 			{
2922 				const deUint32	sampleCount(sampleCounts[sampleCountNdx]);
2923 
2924 				// Skip this test as it is rather slow
2925 				if (layerCount == 6 && sampleCount == 8)
2926 					continue;
2927 
2928 				std::string			testName	("samples_" + de::toString(sampleCount));
2929 				const TestConfig	testConfig =
2930 				{
2931 					RESOLVE,
2932 					format,
2933 					sampleCount,
2934 					layerCount,
2935 					4u,
2936 					32u,
2937 					32u,
2938 					renderingType
2939 				};
2940 
2941 				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)));
2942 
2943 				for (deUint32 resolveLevel : resolveLevels)
2944 				{
2945 					const TestConfig2 testConfig2(testConfig, resolveLevel);
2946 					std::string resolveLevelTestNameStr(testName + "_resolve_level_" + de::toString(resolveLevel));
2947 					const char* resolveLevelTestName = resolveLevelTestNameStr.c_str();
2948 
2949 					formatGroup->addChild(new InstanceFactory1WithSupport<MultisampleRenderPassResolveLevelTestInstance, TestConfig2, FunctionSupport1<TestConfig2>, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, resolveLevelTestName, resolveLevelTestName, testConfig2, typename FunctionSupport1<TestConfig2>::Args(checkSupport, testConfig2)));
2950 				}
2951 
2952 				// MaxAttachmenstsRenderPassTest is ment to test extreme cases where applications might consume all available on-chip
2953 				// memory. This is achieved by using maxColorAttachments attachments and two subpasses, but during test creation we
2954 				// dont know what is the maximal number of attachments (spirv tools are not available on all platforms) so we cant
2955 				// construct shaders during test execution. To be able to test this we need to execute tests for all available
2956 				// numbers of attachments despite the fact that we are only interested in the maximal number; test construction code
2957 				// assumes that the number of attachments is power of two
2958 				if ((renderingType != RENDERING_TYPE_DYNAMIC_RENDERING) && (layerCount == 1))
2959 				{
2960 					for (deUint32 power = 2; power < 5; ++power)
2961 					{
2962 						deUint32	attachmentCount					= 1 << power;
2963 						std::string	maxAttName						= "max_attachments_" + de::toString(attachmentCount) + "_" + testName;
2964 
2965 						TestConfig	maxAttachmentsTestConfig		= testConfig;
2966 						maxAttachmentsTestConfig.testType			= MAX_ATTACHMENTS;
2967 						maxAttachmentsTestConfig.attachmentCount	= attachmentCount;
2968 
2969 						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)));
2970 					}
2971 
2972 					{
2973 						std::string	compatibilityTestName			= "compatibility_" + testName;
2974 
2975 						TestConfig	compatibilityTestConfig			= testConfig;
2976 						compatibilityTestConfig.testType			= COMPATIBILITY;
2977 						compatibilityTestConfig.attachmentCount		= 1;
2978 
2979 						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)));
2980 					}
2981 				}
2982 			}
2983 
2984 			if (layerCount == 1)
2985 				group->addChild(formatGroup.release());
2986 			else
2987 				layerGroup->addChild(formatGroup.release());
2988 		}
2989 
2990 		if (layerCount != 1)
2991 			group->addChild(layerGroup.release());
2992 	}
2993 }
2994 
2995 } // anonymous
2996 
createRenderPassMultisampleResolveTests(tcu::TestContext & testCtx)2997 tcu::TestCaseGroup* createRenderPassMultisampleResolveTests (tcu::TestContext& testCtx)
2998 {
2999 	return createTestGroup(testCtx, "multisample_resolve", "Multisample render pass resolve tests", initTests, RENDERING_TYPE_RENDERPASS_LEGACY);
3000 }
3001 
createRenderPass2MultisampleResolveTests(tcu::TestContext & testCtx)3002 tcu::TestCaseGroup* createRenderPass2MultisampleResolveTests (tcu::TestContext& testCtx)
3003 {
3004 	return createTestGroup(testCtx, "multisample_resolve", "Multisample render pass resolve tests", initTests, RENDERING_TYPE_RENDERPASS2);
3005 }
3006 
createDynamicRenderingMultisampleResolveTests(tcu::TestContext & testCtx)3007 tcu::TestCaseGroup* createDynamicRenderingMultisampleResolveTests (tcu::TestContext& testCtx)
3008 {
3009 	return createTestGroup(testCtx, "multisample_resolve", "Multisample dynamic rendering resolve tests", initTests, RENDERING_TYPE_DYNAMIC_RENDERING);
3010 }
3011 
3012 } // vkt
3013