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