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