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