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 
52 #include "deUniquePtr.hpp"
53 #include "deSharedPtr.hpp"
54 
55 using namespace vk;
56 
57 using tcu::BVec4;
58 using tcu::IVec2;
59 using tcu::IVec4;
60 using tcu::UVec2;
61 using tcu::UVec4;
62 using tcu::Vec2;
63 using tcu::Vec3;
64 using tcu::Vec4;
65 
66 using tcu::Maybe;
67 using tcu::just;
68 using tcu::nothing;
69 
70 using tcu::ConstPixelBufferAccess;
71 using tcu::PixelBufferAccess;
72 
73 using tcu::TestLog;
74 
75 using std::pair;
76 using std::string;
77 using std::vector;
78 
79 typedef de::SharedPtr<vk::Unique<VkImage> >		VkImageSp;
80 typedef de::SharedPtr<vk::Unique<VkImageView> >	VkImageViewSp;
81 typedef de::SharedPtr<vk::Unique<VkBuffer> >	VkBufferSp;
82 typedef de::SharedPtr<vk::Unique<VkPipeline> >	VkPipelineSp;
83 
84 namespace vkt
85 {
86 namespace
87 {
88 
89 using namespace renderpass;
90 
91 enum
92 {
93 	MAX_COLOR_ATTACHMENT_COUNT = 4u
94 };
95 
96 template<typename T>
safeSharedPtr(T * ptr)97 de::SharedPtr<T> safeSharedPtr (T* ptr)
98 {
99 	try
100 	{
101 		return de::SharedPtr<T>(ptr);
102 	}
103 	catch (...)
104 	{
105 		delete ptr;
106 		throw;
107 	}
108 }
109 
getFormatThreshold(VkFormat format)110 tcu::Vec4 getFormatThreshold (VkFormat format)
111 {
112 	const tcu::TextureFormat	tcuFormat		(mapVkFormat(format));
113 	const deUint32				componentCount	(tcu::getNumUsedChannels(tcuFormat.order));
114 
115 	if (isSnormFormat(format))
116 	{
117 		return Vec4((componentCount >= 1) ? 1.5f * getRepresentableDiffSnorm(format, 0) : 0.0f,
118 					(componentCount >= 2) ? 1.5f * getRepresentableDiffSnorm(format, 1) : 0.0f,
119 					(componentCount >= 3) ? 1.5f * getRepresentableDiffSnorm(format, 2) : 0.0f,
120 					(componentCount == 4) ? 1.5f * getRepresentableDiffSnorm(format, 3) : 0.0f);
121 	}
122 	else if (isUnormFormat(format))
123 	{
124 		return Vec4((componentCount >= 1) ? 1.5f * getRepresentableDiffUnorm(format, 0) : 0.0f,
125 					(componentCount >= 2) ? 1.5f * getRepresentableDiffUnorm(format, 1) : 0.0f,
126 					(componentCount >= 3) ? 1.5f * getRepresentableDiffUnorm(format, 2) : 0.0f,
127 					(componentCount == 4) ? 1.5f * getRepresentableDiffUnorm(format, 3) : 0.0f);
128 	}
129 	else if (isFloatFormat(format))
130 		return Vec4(0.00001f);
131 	else
132 		return Vec4(0.001f);
133 }
134 
bindBufferMemory(const DeviceInterface & vk,VkDevice device,VkBuffer buffer,VkDeviceMemory mem,VkDeviceSize memOffset)135 void bindBufferMemory (const DeviceInterface& vk, VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset)
136 {
137 	VK_CHECK(vk.bindBufferMemory(device, buffer, mem, memOffset));
138 }
139 
bindImageMemory(const DeviceInterface & vk,VkDevice device,VkImage image,VkDeviceMemory mem,VkDeviceSize memOffset)140 void bindImageMemory (const DeviceInterface& vk, VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset)
141 {
142 	VK_CHECK(vk.bindImageMemory(device, image, mem, memOffset));
143 }
144 
createBufferMemory(const DeviceInterface & vk,VkDevice device,Allocator & allocator,VkBuffer buffer)145 de::MovePtr<Allocation> createBufferMemory (const DeviceInterface&	vk,
146 											VkDevice				device,
147 											Allocator&				allocator,
148 											VkBuffer				buffer)
149 {
150 	de::MovePtr<Allocation> allocation (allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), MemoryRequirement::HostVisible));
151 	bindBufferMemory(vk, device, buffer, allocation->getMemory(), allocation->getOffset());
152 	return allocation;
153 }
154 
createImageMemory(const DeviceInterface & vk,VkDevice device,Allocator & allocator,VkImage image)155 de::MovePtr<Allocation> createImageMemory (const DeviceInterface&	vk,
156 										   VkDevice					device,
157 										   Allocator&				allocator,
158 										   VkImage					image)
159 {
160 	de::MovePtr<Allocation> allocation (allocator.allocate(getImageMemoryRequirements(vk, device, image), MemoryRequirement::Any));
161 	bindImageMemory(vk, device, image, allocation->getMemory(), allocation->getOffset());
162 	return allocation;
163 }
164 
createImage(const DeviceInterface & vk,VkDevice device,VkImageCreateFlags flags,VkImageType imageType,VkFormat format,VkExtent3D extent,deUint32 mipLevels,deUint32 arrayLayers,VkSampleCountFlagBits samples,VkImageTiling tiling,VkImageUsageFlags usage,VkSharingMode sharingMode,deUint32 queueFamilyCount,const deUint32 * pQueueFamilyIndices,VkImageLayout initialLayout)165 Move<VkImage> createImage (const DeviceInterface&	vk,
166 						   VkDevice					device,
167 						   VkImageCreateFlags		flags,
168 						   VkImageType				imageType,
169 						   VkFormat					format,
170 						   VkExtent3D				extent,
171 						   deUint32					mipLevels,
172 						   deUint32					arrayLayers,
173 						   VkSampleCountFlagBits	samples,
174 						   VkImageTiling			tiling,
175 						   VkImageUsageFlags		usage,
176 						   VkSharingMode			sharingMode,
177 						   deUint32					queueFamilyCount,
178 						   const deUint32*			pQueueFamilyIndices,
179 						   VkImageLayout			initialLayout)
180 {
181 	const VkImageCreateInfo pCreateInfo =
182 	{
183 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
184 		DE_NULL,
185 		flags,
186 		imageType,
187 		format,
188 		extent,
189 		mipLevels,
190 		arrayLayers,
191 		samples,
192 		tiling,
193 		usage,
194 		sharingMode,
195 		queueFamilyCount,
196 		pQueueFamilyIndices,
197 		initialLayout
198 	};
199 	return createImage(vk, device, &pCreateInfo);
200 }
201 
createImageView(const DeviceInterface & vk,VkDevice device,VkImageViewCreateFlags flags,VkImage image,VkImageViewType viewType,VkFormat format,VkComponentMapping components,VkImageSubresourceRange subresourceRange)202 Move<VkImageView> createImageView (const DeviceInterface&	vk,
203 								   VkDevice					device,
204 								   VkImageViewCreateFlags	flags,
205 								   VkImage					image,
206 								   VkImageViewType			viewType,
207 								   VkFormat					format,
208 								   VkComponentMapping		components,
209 								   VkImageSubresourceRange	subresourceRange)
210 {
211 	const VkImageViewCreateInfo pCreateInfo =
212 	{
213 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
214 		DE_NULL,
215 		flags,
216 		image,
217 		viewType,
218 		format,
219 		components,
220 		subresourceRange,
221 	};
222 	return createImageView(vk, device, &pCreateInfo);
223 }
224 
createImage(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const DeviceInterface & vkd,VkDevice device,VkFormat vkFormat,VkSampleCountFlagBits sampleCountBit,VkImageUsageFlags usage,deUint32 width,deUint32 height,deUint32 layerCount)225 Move<VkImage> createImage (const InstanceInterface&	vki,
226 						   VkPhysicalDevice			physicalDevice,
227 						   const DeviceInterface&	vkd,
228 						   VkDevice					device,
229 						   VkFormat					vkFormat,
230 						   VkSampleCountFlagBits	sampleCountBit,
231 						   VkImageUsageFlags		usage,
232 						   deUint32					width,
233 						   deUint32					height,
234 						   deUint32					layerCount)
235 {
236 	try
237 	{
238 		const tcu::TextureFormat		format					(mapVkFormat(vkFormat));
239 		const VkImageType				imageType				(VK_IMAGE_TYPE_2D);
240 		const VkImageTiling				imageTiling				(VK_IMAGE_TILING_OPTIMAL);
241 		const VkFormatProperties		formatProperties		(getPhysicalDeviceFormatProperties(vki, physicalDevice, vkFormat));
242 		const VkImageFormatProperties	imageFormatProperties	(getPhysicalDeviceImageFormatProperties(vki, physicalDevice, vkFormat, imageType, imageTiling, usage, 0u));
243 		const VkExtent3D				imageExtent				=
244 		{
245 			width,
246 			height,
247 			1u
248 		};
249 
250 		if ((tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
251 			&& (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)
252 			TCU_THROW(NotSupportedError, "Format can't be used as depth stencil attachment");
253 
254 		if (!(tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
255 			&& (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)
256 			TCU_THROW(NotSupportedError, "Format can't be used as color attachment");
257 
258 		if (imageFormatProperties.maxExtent.width < imageExtent.width
259 			|| imageFormatProperties.maxExtent.height < imageExtent.height
260 			|| ((imageFormatProperties.sampleCounts & sampleCountBit) == 0)
261 			|| imageFormatProperties.maxArrayLayers < layerCount)
262 		{
263 			TCU_THROW(NotSupportedError, "Image type not supported");
264 		}
265 
266 		return createImage(vkd, device, 0u, imageType, vkFormat, imageExtent, 1u, layerCount, sampleCountBit, imageTiling, usage, VK_SHARING_MODE_EXCLUSIVE, 0u, DE_NULL, VK_IMAGE_LAYOUT_UNDEFINED);
267 	}
268 	catch (const vk::Error& error)
269 	{
270 		if (error.getError() == VK_ERROR_FORMAT_NOT_SUPPORTED)
271 			TCU_THROW(NotSupportedError, "Image format not supported");
272 
273 		throw;
274 	}
275 }
276 
createImageView(const DeviceInterface & vkd,VkDevice device,VkImage image,VkFormat format,VkImageAspectFlags aspect,deUint32 layerCount)277 Move<VkImageView> createImageView (const DeviceInterface&	vkd,
278 								   VkDevice					device,
279 								   VkImage					image,
280 								   VkFormat					format,
281 								   VkImageAspectFlags		aspect,
282 								   deUint32					layerCount)
283 {
284 	const VkImageSubresourceRange	range =
285 	{
286 		aspect,
287 		0u,
288 		1u,
289 		0u,
290 		layerCount
291 	};
292 
293 	return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D_ARRAY, format, makeComponentMappingRGBA(), range);
294 }
295 
getPixelSize(VkFormat vkFormat)296 VkDeviceSize getPixelSize (VkFormat vkFormat)
297 {
298 	const tcu::TextureFormat	format	(mapVkFormat(vkFormat));
299 
300 	return format.getPixelSize();
301 }
302 
createBuffer(const DeviceInterface & vkd,VkDevice device,VkFormat format,deUint32 width,deUint32 height,deUint32 layerCount)303 Move<VkBuffer> createBuffer (const DeviceInterface&		vkd,
304 							 VkDevice					device,
305 							 VkFormat					format,
306 							 deUint32					width,
307 							 deUint32					height,
308 							 deUint32					layerCount)
309 {
310 	const VkBufferUsageFlags	bufferUsage			(VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
311 	const VkDeviceSize			pixelSize			(getPixelSize(format));
312 	const VkBufferCreateInfo	createInfo			=
313 	{
314 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
315 		DE_NULL,
316 		0u,
317 
318 		width * height * layerCount * pixelSize,
319 		bufferUsage,
320 
321 		VK_SHARING_MODE_EXCLUSIVE,
322 		0u,
323 		DE_NULL
324 	};
325 	return createBuffer(vkd, device, &createInfo);
326 }
327 
sampleCountBitFromSampleCount(deUint32 count)328 VkSampleCountFlagBits sampleCountBitFromSampleCount (deUint32 count)
329 {
330 	switch (count)
331 	{
332 		case 1:  return VK_SAMPLE_COUNT_1_BIT;
333 		case 2:  return VK_SAMPLE_COUNT_2_BIT;
334 		case 4:  return VK_SAMPLE_COUNT_4_BIT;
335 		case 8:  return VK_SAMPLE_COUNT_8_BIT;
336 		case 16: return VK_SAMPLE_COUNT_16_BIT;
337 		case 32: return VK_SAMPLE_COUNT_32_BIT;
338 		case 64: return VK_SAMPLE_COUNT_64_BIT;
339 
340 		default:
341 			DE_FATAL("Invalid sample count");
342 			return (VkSampleCountFlagBits)0x0;
343 	}
344 }
345 
createMultisampleImages(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const DeviceInterface & vkd,VkDevice device,VkFormat format,deUint32 sampleCount,deUint32 width,deUint32 height,deUint32 layerCount)346 std::vector<VkImageSp> createMultisampleImages (const InstanceInterface&	vki,
347 												VkPhysicalDevice			physicalDevice,
348 												const DeviceInterface&		vkd,
349 												VkDevice					device,
350 												VkFormat					format,
351 												deUint32					sampleCount,
352 												deUint32					width,
353 												deUint32					height,
354 												deUint32					layerCount)
355 {
356 	std::vector<VkImageSp> images (MAX_COLOR_ATTACHMENT_COUNT);
357 
358 	for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
359 		images[imageNdx] = safeSharedPtr(new Unique<VkImage>(createImage(vki, physicalDevice, vkd, device, format, sampleCountBitFromSampleCount(sampleCount), VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, width, height, layerCount)));
360 
361 	return images;
362 }
363 
createSingleSampleImages(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const DeviceInterface & vkd,VkDevice device,VkFormat format,deUint32 width,deUint32 height,deUint32 layerCount)364 std::vector<VkImageSp> createSingleSampleImages (const InstanceInterface&	vki,
365 												 VkPhysicalDevice			physicalDevice,
366 												 const DeviceInterface&		vkd,
367 												 VkDevice					device,
368 												 VkFormat					format,
369 												 deUint32					width,
370 												 deUint32					height,
371 												 deUint32					layerCount)
372 {
373 	std::vector<VkImageSp> images (MAX_COLOR_ATTACHMENT_COUNT);
374 
375 	for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
376 		images[imageNdx] = safeSharedPtr(new Unique<VkImage>(createImage(vki, physicalDevice, vkd, device, format, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, width, height, layerCount)));
377 
378 	return images;
379 }
380 
createImageMemory(const DeviceInterface & vkd,VkDevice device,Allocator & allocator,const std::vector<VkImageSp> images)381 std::vector<de::SharedPtr<Allocation> > createImageMemory (const DeviceInterface&		vkd,
382 														   VkDevice						device,
383 														   Allocator&					allocator,
384 														   const std::vector<VkImageSp>	images)
385 {
386 	std::vector<de::SharedPtr<Allocation> > memory (images.size());
387 
388 	for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
389 		memory[memoryNdx] = safeSharedPtr(createImageMemory(vkd, device, allocator, **images[memoryNdx]).release());
390 
391 	return memory;
392 }
393 
createImageViews(const DeviceInterface & vkd,VkDevice device,const std::vector<VkImageSp> & images,VkFormat format,VkImageAspectFlagBits aspect,deUint32 layerCount)394 std::vector<VkImageViewSp> createImageViews (const DeviceInterface&			vkd,
395 											 VkDevice						device,
396 											 const std::vector<VkImageSp>&	images,
397 											 VkFormat						format,
398 											 VkImageAspectFlagBits			aspect,
399 											 deUint32						layerCount)
400 {
401 	std::vector<VkImageViewSp> views (images.size());
402 
403 	for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
404 		views[imageNdx] = safeSharedPtr(new Unique<VkImageView>(createImageView(vkd, device, **images[imageNdx], format, aspect, layerCount)));
405 
406 	return views;
407 }
408 
createBuffers(const DeviceInterface & vkd,VkDevice device,VkFormat format,deUint32 width,deUint32 height,deUint32 layerCount)409 std::vector<VkBufferSp> createBuffers (const DeviceInterface&	vkd,
410 									   VkDevice					device,
411 									   VkFormat					format,
412 									   deUint32					width,
413 									   deUint32					height,
414 									   deUint32					layerCount)
415 {
416 	std::vector<VkBufferSp> buffers (MAX_COLOR_ATTACHMENT_COUNT);
417 
418 	for (size_t bufferNdx = 0; bufferNdx < buffers.size(); bufferNdx++)
419 		buffers[bufferNdx] = safeSharedPtr(new Unique<VkBuffer>(createBuffer(vkd, device, format, width, height, layerCount)));
420 
421 	return buffers;
422 }
423 
createBufferMemory(const DeviceInterface & vkd,VkDevice device,Allocator & allocator,const std::vector<VkBufferSp> buffers)424 std::vector<de::SharedPtr<Allocation> > createBufferMemory (const DeviceInterface&			vkd,
425 															VkDevice						device,
426 															Allocator&						allocator,
427 															const std::vector<VkBufferSp>	buffers)
428 {
429 	std::vector<de::SharedPtr<Allocation> > memory (buffers.size());
430 
431 	for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
432 		memory[memoryNdx] = safeSharedPtr(createBufferMemory(vkd, device, allocator, **buffers[memoryNdx]).release());
433 
434 	return memory;
435 }
436 
437 template<typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep, typename RenderPassCreateInfo>
createRenderPass(const DeviceInterface & vkd,VkDevice device,VkFormat format,deUint32 sampleCount)438 Move<VkRenderPass> createRenderPass (const DeviceInterface&	vkd,
439 									 VkDevice				device,
440 									 VkFormat				format,
441 									 deUint32				sampleCount)
442 {
443 	const VkSampleCountFlagBits		samples						(sampleCountBitFromSampleCount(sampleCount));
444 	std::vector<AttachmentDesc>		attachments;
445 	std::vector<AttachmentRef>		colorAttachmentRefs;
446 	std::vector<AttachmentRef>		resolveAttachmentRefs;
447 
448 	for (size_t attachmentNdx = 0; attachmentNdx < 4; attachmentNdx++)
449 	{
450 		{
451 			const AttachmentDesc multisampleAttachment		// VkAttachmentDescription										||  VkAttachmentDescription2KHR
452 			(
453 															//																||  VkStructureType						sType;
454 				DE_NULL,									//																||  const void*							pNext;
455 				0u,											//  VkAttachmentDescriptionFlags	flags;						||  VkAttachmentDescriptionFlags		flags;
456 				format,										//  VkFormat						format;						||  VkFormat							format;
457 				samples,									//  VkSampleCountFlagBits			samples;					||  VkSampleCountFlagBits				samples;
458 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//  VkAttachmentLoadOp				loadOp;						||  VkAttachmentLoadOp					loadOp;
459 				VK_ATTACHMENT_STORE_OP_DONT_CARE,			//  VkAttachmentStoreOp				storeOp;					||  VkAttachmentStoreOp					storeOp;
460 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//  VkAttachmentLoadOp				stencilLoadOp;				||  VkAttachmentLoadOp					stencilLoadOp;
461 				VK_ATTACHMENT_STORE_OP_DONT_CARE,			//  VkAttachmentStoreOp				stencilStoreOp;				||  VkAttachmentStoreOp					stencilStoreOp;
462 				VK_IMAGE_LAYOUT_UNDEFINED,					//  VkImageLayout					initialLayout;				||  VkImageLayout						initialLayout;
463 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL		//  VkImageLayout					finalLayout;				||  VkImageLayout						finalLayout;
464 			);
465 			const AttachmentRef attachmentRef				//  VkAttachmentReference										||  VkAttachmentReference2KHR
466 			(
467 															//																||  VkStructureType						sType;
468 				DE_NULL,									//																||  const void*							pNext;
469 				(deUint32)attachments.size(),				//  deUint32						attachment;					||  deUint32							attachment;
470 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//  VkImageLayout					layout;						||  VkImageLayout						layout;
471 				0u											//																||  VkImageAspectFlags					aspectMask;
472 			);
473 			colorAttachmentRefs.push_back(attachmentRef);
474 			attachments.push_back(multisampleAttachment);
475 		}
476 		{
477 			const AttachmentDesc singlesampleAttachment		// VkAttachmentDescription										||  VkAttachmentDescription2KHR
478 			(
479 															//																||  VkStructureType						sType;
480 				DE_NULL,									//																||  const void*							pNext;
481 				0u,											//  VkAttachmentDescriptionFlags	flags;						||  VkAttachmentDescriptionFlags		flags;
482 				format,										//  VkFormat						format;						||  VkFormat							format;
483 				VK_SAMPLE_COUNT_1_BIT,						//  VkSampleCountFlagBits			samples;					||  VkSampleCountFlagBits				samples;
484 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//  VkAttachmentLoadOp				loadOp;						||  VkAttachmentLoadOp					loadOp;
485 				VK_ATTACHMENT_STORE_OP_STORE,				//  VkAttachmentStoreOp				storeOp;					||  VkAttachmentStoreOp					storeOp;
486 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//  VkAttachmentLoadOp				stencilLoadOp;				||  VkAttachmentLoadOp					stencilLoadOp;
487 				VK_ATTACHMENT_STORE_OP_DONT_CARE,			//  VkAttachmentStoreOp				stencilStoreOp;				||  VkAttachmentStoreOp					stencilStoreOp;
488 				VK_IMAGE_LAYOUT_UNDEFINED,					//  VkImageLayout					initialLayout;				||  VkImageLayout						initialLayout;
489 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL		//  VkImageLayout					finalLayout;				||  VkImageLayout						finalLayout;
490 			);
491 			const AttachmentRef attachmentRef				//  VkAttachmentReference										||  VkAttachmentReference2KHR
492 			(
493 															//																||  VkStructureType						sType;
494 				DE_NULL,									//																||  const void*							pNext;
495 				(deUint32)attachments.size(),				//  deUint32						attachment;					||  deUint32							attachment;
496 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//  VkImageLayout					layout;						||  VkImageLayout						layout;
497 				0u											//																||  VkImageAspectFlags					aspectMask;
498 			);
499 			resolveAttachmentRefs.push_back(attachmentRef);
500 			attachments.push_back(singlesampleAttachment);
501 		}
502 	}
503 
504 	DE_ASSERT(colorAttachmentRefs.size() == resolveAttachmentRefs.size());
505 	DE_ASSERT(attachments.size() == colorAttachmentRefs.size() + resolveAttachmentRefs.size());
506 
507 	{
508 		const SubpassDesc	subpass							//  VkSubpassDescription										||  VkSubpassDescription2KHR
509 		(
510 															//																||  VkStructureType						sType;
511 			DE_NULL,										//																||  const void*							pNext;
512 			(VkSubpassDescriptionFlags)0,					//  VkSubpassDescriptionFlags		flags;						||  VkSubpassDescriptionFlags			flags;
513 			VK_PIPELINE_BIND_POINT_GRAPHICS,				//  VkPipelineBindPoint				pipelineBindPoint;			||  VkPipelineBindPoint					pipelineBindPoint;
514 			0u,												//																||  deUint32							viewMask;
515 			0u,												//  deUint32						inputAttachmentCount;		||  deUint32							inputAttachmentCount;
516 			DE_NULL,										//  const VkAttachmentReference*	pInputAttachments;			||  const VkAttachmentReference2KHR*	pInputAttachments;
517 			(deUint32)colorAttachmentRefs.size(),			//  deUint32						colorAttachmentCount;		||  deUint32							colorAttachmentCount;
518 			&colorAttachmentRefs[0],						//  const VkAttachmentReference*	pColorAttachments;			||  const VkAttachmentReference2KHR*	pColorAttachments;
519 			&resolveAttachmentRefs[0],						//  const VkAttachmentReference*	pResolveAttachments;		||  const VkAttachmentReference2KHR*	pResolveAttachments;
520 			DE_NULL,										//  const VkAttachmentReference*	pDepthStencilAttachment;	||  const VkAttachmentReference2KHR*	pDepthStencilAttachment;
521 			0u,												//  deUint32						preserveAttachmentCount;	||  deUint32							preserveAttachmentCount;
522 			DE_NULL											//  const deUint32*					pPreserveAttachments;		||  const deUint32*						pPreserveAttachments;
523 		);
524 		const RenderPassCreateInfo	renderPassCreator		//  VkRenderPassCreateInfo										||  VkRenderPassCreateInfo2KHR
525 		(
526 															//  VkStructureType					sType;						||  VkStructureType						sType;
527 			DE_NULL,										//  const void*						pNext;						||  const void*							pNext;
528 			(VkRenderPassCreateFlags)0u,					//  VkRenderPassCreateFlags			flags;						||  VkRenderPassCreateFlags				flags;
529 			(deUint32)attachments.size(),					//  deUint32						attachmentCount;			||  deUint32							attachmentCount;
530 			&attachments[0],								//  const VkAttachmentDescription*	pAttachments;				||  const VkAttachmentDescription2KHR*	pAttachments;
531 			1u,												//  deUint32						subpassCount;				||  deUint32							subpassCount;
532 			&subpass,										//  const VkSubpassDescription*		pSubpasses;					||  const VkSubpassDescription2KHR*		pSubpasses;
533 			0u,												//  deUint32						dependencyCount;			||  deUint32							dependencyCount;
534 			DE_NULL,										//  const VkSubpassDependency*		pDependencies;				||  const VkSubpassDependency2KHR*		pDependencies;
535 			0u,												//																||  deUint32							correlatedViewMaskCount;
536 			DE_NULL											//																||  const deUint32*						pCorrelatedViewMasks;
537 		);
538 
539 		return renderPassCreator.createRenderPass(vkd, device);
540 	}
541 }
542 
createRenderPass(const DeviceInterface & vkd,VkDevice device,VkFormat format,deUint32 sampleCount,const RenderPassType renderPassType)543 Move<VkRenderPass> createRenderPass (const DeviceInterface&	vkd,
544 									 VkDevice				device,
545 									 VkFormat				format,
546 									 deUint32				sampleCount,
547 									 const RenderPassType	renderPassType)
548 {
549 	switch (renderPassType)
550 	{
551 		case RENDERPASS_TYPE_LEGACY:
552 			return createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(vkd, device, format, sampleCount);
553 		case RENDERPASS_TYPE_RENDERPASS2:
554 			return createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2, RenderPassCreateInfo2>(vkd, device, format, sampleCount);
555 		default:
556 			TCU_THROW(InternalError, "Impossible");
557 	}
558 }
559 
createFramebuffer(const DeviceInterface & vkd,VkDevice device,VkRenderPass renderPass,const std::vector<VkImageViewSp> & multisampleImageViews,const std::vector<VkImageViewSp> & singlesampleImageViews,deUint32 width,deUint32 height,deUint32 layerCount)560 Move<VkFramebuffer> createFramebuffer (const DeviceInterface&			vkd,
561 									   VkDevice							device,
562 									   VkRenderPass						renderPass,
563 									   const std::vector<VkImageViewSp>&	multisampleImageViews,
564 									   const std::vector<VkImageViewSp>&	singlesampleImageViews,
565 									   deUint32							width,
566 									   deUint32							height,
567 									   deUint32							layerCount)
568 {
569 	std::vector<VkImageView> attachments;
570 
571 	attachments.reserve(multisampleImageViews.size() + singlesampleImageViews.size());
572 
573 	DE_ASSERT(multisampleImageViews.size() == singlesampleImageViews.size());
574 
575 	for (size_t ndx = 0; ndx < multisampleImageViews.size(); ndx++)
576 	{
577 		attachments.push_back(**multisampleImageViews[ndx]);
578 		attachments.push_back(**singlesampleImageViews[ndx]);
579 	}
580 
581 	const VkFramebufferCreateInfo createInfo =
582 	{
583 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
584 		DE_NULL,
585 		0u,
586 
587 		renderPass,
588 		(deUint32)attachments.size(),
589 		&attachments[0],
590 
591 		width,
592 		height,
593 		layerCount
594 	};
595 
596 	return createFramebuffer(vkd, device, &createInfo);
597 }
598 
createRenderPipelineLayout(const DeviceInterface & vkd,VkDevice device)599 Move<VkPipelineLayout> createRenderPipelineLayout (const DeviceInterface&	vkd,
600 												   VkDevice					device)
601 {
602 	const VkPushConstantRange			pushConstant			=
603 	{
604 		VK_SHADER_STAGE_FRAGMENT_BIT,
605 		0u,
606 		4u
607 	};
608 	const VkPipelineLayoutCreateInfo	createInfo	=
609 	{
610 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
611 		DE_NULL,
612 		(vk::VkPipelineLayoutCreateFlags)0,
613 
614 		0u,
615 		DE_NULL,
616 
617 		1u,
618 		&pushConstant
619 	};
620 
621 	return createPipelineLayout(vkd, device, &createInfo);
622 }
623 
createRenderPipeline(const DeviceInterface & vkd,VkDevice device,VkRenderPass renderPass,VkPipelineLayout pipelineLayout,const vk::BinaryCollection & binaryCollection,deUint32 width,deUint32 height,deUint32 sampleCount,deUint32 layerCount)624 Move<VkPipeline> createRenderPipeline (const DeviceInterface&		vkd,
625 									   VkDevice						device,
626 									   VkRenderPass					renderPass,
627 									   VkPipelineLayout				pipelineLayout,
628 									   const vk::BinaryCollection&	binaryCollection,
629 									   deUint32						width,
630 									   deUint32						height,
631 									   deUint32						sampleCount,
632 									   deUint32						layerCount)
633 {
634 	const Unique<VkShaderModule>	vertexShaderModule			(createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
635 	const Unique<VkShaderModule>	fragmentShaderModule		(createShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u));
636 	const Move<VkShaderModule>		geometryShaderModule		(layerCount == 1 ? Move<VkShaderModule>() : createShaderModule(vkd, device, binaryCollection.get("geom"), 0u));
637 	// Disable blending
638 	const VkPipelineColorBlendAttachmentState attachmentBlendState =
639 	{
640 		VK_FALSE,
641 		VK_BLEND_FACTOR_SRC_ALPHA,
642 		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
643 		VK_BLEND_OP_ADD,
644 		VK_BLEND_FACTOR_ONE,
645 		VK_BLEND_FACTOR_ONE,
646 		VK_BLEND_OP_ADD,
647 		VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT
648 	};
649 	const VkPipelineColorBlendAttachmentState attachmentBlendStates[] =
650 	{
651 		attachmentBlendState,
652 		attachmentBlendState,
653 		attachmentBlendState,
654 		attachmentBlendState,
655 	};
656 	const VkPipelineVertexInputStateCreateInfo vertexInputState =
657 	{
658 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
659 		DE_NULL,
660 		(VkPipelineVertexInputStateCreateFlags)0u,
661 
662 		0u,
663 		DE_NULL,
664 
665 		0u,
666 		DE_NULL
667 	};
668 	const tcu::UVec2				renderArea	(width, height);
669 	const std::vector<VkViewport>	viewports	(1, makeViewport(renderArea));
670 	const std::vector<VkRect2D>		scissors	(1, makeRect2D(renderArea));
671 
672 	const VkPipelineMultisampleStateCreateInfo multisampleState =
673 	{
674 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
675 		DE_NULL,
676 		(VkPipelineMultisampleStateCreateFlags)0u,
677 
678 		sampleCountBitFromSampleCount(sampleCount),
679 		VK_FALSE,
680 		0.0f,
681 		DE_NULL,
682 		VK_FALSE,
683 		VK_FALSE,
684 	};
685 	const VkPipelineDepthStencilStateCreateInfo depthStencilState =
686 	{
687 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
688 		DE_NULL,
689 		(VkPipelineDepthStencilStateCreateFlags)0u,
690 
691 		VK_FALSE,
692 		VK_TRUE,
693 		VK_COMPARE_OP_ALWAYS,
694 		VK_FALSE,
695 		VK_TRUE,
696 		{
697 			VK_STENCIL_OP_KEEP,
698 			VK_STENCIL_OP_INCREMENT_AND_WRAP,
699 			VK_STENCIL_OP_KEEP,
700 			VK_COMPARE_OP_ALWAYS,
701 			~0u,
702 			~0u,
703 			0xFFu / (sampleCount + 1)
704 		},
705 		{
706 			VK_STENCIL_OP_KEEP,
707 			VK_STENCIL_OP_INCREMENT_AND_WRAP,
708 			VK_STENCIL_OP_KEEP,
709 			VK_COMPARE_OP_ALWAYS,
710 			~0u,
711 			~0u,
712 			0xFFu / (sampleCount + 1)
713 		},
714 
715 		0.0f,
716 		1.0f
717 	};
718 	const VkPipelineColorBlendStateCreateInfo blendState =
719 	{
720 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
721 		DE_NULL,
722 		(VkPipelineColorBlendStateCreateFlags)0u,
723 
724 		VK_FALSE,
725 		VK_LOGIC_OP_COPY,
726 		DE_LENGTH_OF_ARRAY(attachmentBlendStates),
727 		attachmentBlendStates,
728 		{ 0.0f, 0.0f, 0.0f, 0.0f }
729 	};
730 
731 	return makeGraphicsPipeline(vkd,												// const DeviceInterface&                        vk
732 								device,												// const VkDevice                                device
733 								pipelineLayout,										// const VkPipelineLayout                        pipelineLayout
734 								*vertexShaderModule,								// const VkShaderModule                          vertexShaderModule
735 								DE_NULL,											// const VkShaderModule                          tessellationControlShaderModule
736 								DE_NULL,											// const VkShaderModule                          tessellationEvalShaderModule
737 								layerCount != 1 ? *geometryShaderModule : DE_NULL,	// const VkShaderModule                          geometryShaderModule
738 								*fragmentShaderModule,								// const VkShaderModule                          fragmentShaderModule
739 								renderPass,											// const VkRenderPass                            renderPass
740 								viewports,											// const std::vector<VkViewport>&                viewports
741 								scissors,											// const std::vector<VkRect2D>&                  scissors
742 								VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,				// const VkPrimitiveTopology                     topology
743 								0u,													// const deUint32                                subpass
744 								0u,													// const deUint32                                patchControlPoints
745 								&vertexInputState,									// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
746 								DE_NULL,											// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
747 								&multisampleState,									// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
748 								&depthStencilState,									// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
749 								&blendState);										// const VkPipelineColorBlendStateCreateInfo*    colorBlendStateCreateInfo
750 }
751 
752 struct TestConfig
753 {
TestConfigvkt::__anon156ab5910111::TestConfig754 				TestConfig		(VkFormat		format_,
755 								 deUint32		sampleCount_,
756 								 deUint32		layerCount_,
757 								 RenderPassType	renderPassType_)
758 		: format			(format_)
759 		, sampleCount		(sampleCount_)
760 		, layerCount		(layerCount_)
761 		, renderPassType	(renderPassType_)
762 	{
763 	}
764 
765 	VkFormat		format;
766 	deUint32		sampleCount;
767 	deUint32		layerCount;
768 	RenderPassType	renderPassType;
769 };
770 
771 class MultisampleRenderPassTestInstance : public TestInstance
772 {
773 public:
774 													MultisampleRenderPassTestInstance	(Context& context, TestConfig config);
775 													~MultisampleRenderPassTestInstance	(void);
776 
777 	tcu::TestStatus									iterate								(void);
778 
779 private:
780 	template<typename RenderpassSubpass>
781 	void											submit								(void);
782 	void											submitSwitch						(RenderPassType						renderPassType);
783 	void											verify								(void);
784 	void											logImage							(const std::string&					name,
785 																						 const tcu::ConstPixelBufferAccess&	image);
786 
787 	const bool										m_featuresSupported;
788 	const bool										m_extensionSupported;
789 	const RenderPassType							m_renderPassType;
790 
791 	const VkFormat									m_format;
792 	const deUint32									m_sampleCount;
793 	const deUint32									m_layerCount;
794 	const deUint32									m_width;
795 	const deUint32									m_height;
796 
797 	const std::vector<VkImageSp>					m_multisampleImages;
798 	const std::vector<de::SharedPtr<Allocation> >	m_multisampleImageMemory;
799 	const std::vector<VkImageViewSp>				m_multisampleImageViews;
800 
801 	const std::vector<VkImageSp>					m_singlesampleImages;
802 	const std::vector<de::SharedPtr<Allocation> >	m_singlesampleImageMemory;
803 	const std::vector<VkImageViewSp>				m_singlesampleImageViews;
804 
805 	const Unique<VkRenderPass>						m_renderPass;
806 	const Unique<VkFramebuffer>						m_framebuffer;
807 
808 	const Unique<VkPipelineLayout>					m_renderPipelineLayout;
809 	const Unique<VkPipeline>						m_renderPipeline;
810 
811 	const std::vector<VkBufferSp>					m_buffers;
812 	const std::vector<de::SharedPtr<Allocation> >	m_bufferMemory;
813 
814 	const Unique<VkCommandPool>						m_commandPool;
815 	tcu::TextureLevel								m_sum;
816 	deUint32										m_sampleMask;
817 	tcu::ResultCollector							m_resultCollector;
818 };
819 
MultisampleRenderPassTestInstance(Context & context,TestConfig config)820 MultisampleRenderPassTestInstance::MultisampleRenderPassTestInstance (Context& context, TestConfig config)
821 	: TestInstance				(context)
822 	, m_featuresSupported		((config.layerCount > 1) && context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER))
823 	, m_extensionSupported		((config.renderPassType == RENDERPASS_TYPE_RENDERPASS2) && context.requireDeviceExtension("VK_KHR_create_renderpass2"))
824 	, m_renderPassType			(config.renderPassType)
825 	, m_format					(config.format)
826 	, m_sampleCount				(config.sampleCount)
827 	, m_layerCount				(config.layerCount)
828 	, m_width					(32u)
829 	, m_height					(32u)
830 
831 	, m_multisampleImages		(createMultisampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_format, m_sampleCount, m_width, m_height, m_layerCount))
832 	, m_multisampleImageMemory	(createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_multisampleImages))
833 	, m_multisampleImageViews	(createImageViews(context.getDeviceInterface(), context.getDevice(), m_multisampleImages, m_format, VK_IMAGE_ASPECT_COLOR_BIT, m_layerCount))
834 
835 	, m_singlesampleImages		(createSingleSampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_format, m_width, m_height, m_layerCount))
836 	, m_singlesampleImageMemory	(createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_singlesampleImages))
837 	, m_singlesampleImageViews	(createImageViews(context.getDeviceInterface(), context.getDevice(), m_singlesampleImages, m_format, VK_IMAGE_ASPECT_COLOR_BIT, m_layerCount))
838 
839 	, m_renderPass				(createRenderPass(context.getDeviceInterface(), context.getDevice(), m_format, m_sampleCount, config.renderPassType))
840 	, m_framebuffer				(createFramebuffer(context.getDeviceInterface(), context.getDevice(), *m_renderPass, m_multisampleImageViews, m_singlesampleImageViews, m_width, m_height, m_layerCount))
841 
842 	, m_renderPipelineLayout	(createRenderPipelineLayout(context.getDeviceInterface(), context.getDevice()))
843 	, m_renderPipeline			(createRenderPipeline(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_renderPipelineLayout, context.getBinaryCollection(), m_width, m_height, m_sampleCount, m_layerCount))
844 
845 	, m_buffers					(createBuffers(context.getDeviceInterface(), context.getDevice(), m_format, m_width, m_height, m_layerCount))
846 	, m_bufferMemory			(createBufferMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_buffers))
847 
848 	, m_commandPool				(createCommandPool(context.getDeviceInterface(), context.getDevice(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
849 	, m_sum						(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), m_width, m_height, m_layerCount)
850 	, m_sampleMask				(0x0u)
851 {
852 	tcu::clear(m_sum.getAccess(), Vec4(0.0f, 0.0f, 0.0f, 0.0f));
853 }
854 
~MultisampleRenderPassTestInstance(void)855 MultisampleRenderPassTestInstance::~MultisampleRenderPassTestInstance (void)
856 {
857 }
858 
logImage(const std::string & name,const tcu::ConstPixelBufferAccess & image)859 void MultisampleRenderPassTestInstance::logImage (const std::string& name, const tcu::ConstPixelBufferAccess& image)
860 {
861 	m_context.getTestContext().getLog() << tcu::LogImage(name.c_str(), name.c_str(), image);
862 
863 	for (deUint32 layerNdx = 0; layerNdx < m_layerCount; ++layerNdx)
864 	{
865 		const std::string			layerName	(name + " Layer:" + de::toString(layerNdx));
866 		tcu::ConstPixelBufferAccess	layerImage	(image.getFormat(), m_width, m_height, 1, image.getPixelPtr(0, 0, layerNdx));
867 
868 		m_context.getTestContext().getLog() << tcu::LogImage(layerName.c_str(), layerName.c_str(), layerImage);
869 	}
870 }
871 
872 template<typename RenderpassSubpass>
submit(void)873 void MultisampleRenderPassTestInstance::submit (void)
874 {
875 	const DeviceInterface&								vkd					(m_context.getDeviceInterface());
876 	const VkDevice										device				(m_context.getDevice());
877 	const Unique<VkCommandBuffer>						commandBuffer		(allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
878 	const typename RenderpassSubpass::SubpassBeginInfo	subpassBeginInfo	(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
879 	const typename RenderpassSubpass::SubpassEndInfo	subpassEndInfo		(DE_NULL);
880 
881 	beginCommandBuffer(vkd, *commandBuffer);
882 
883 	// Memory barriers between previous copies and rendering
884 	{
885 		std::vector<VkImageMemoryBarrier> barriers;
886 
887 		for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
888 		{
889 			const VkImageMemoryBarrier barrier =
890 			{
891 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
892 				DE_NULL,
893 
894 				VK_ACCESS_TRANSFER_READ_BIT,
895 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
896 
897 				VK_IMAGE_LAYOUT_UNDEFINED,
898 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
899 
900 				VK_QUEUE_FAMILY_IGNORED,
901 				VK_QUEUE_FAMILY_IGNORED,
902 
903 				**m_singlesampleImages[dstNdx],
904 				{
905 					VK_IMAGE_ASPECT_COLOR_BIT,
906 					0u,
907 					1u,
908 					0u,
909 					m_layerCount
910 				}
911 			};
912 
913 			barriers.push_back(barrier);
914 		}
915 
916 		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]);
917 	}
918 
919 	{
920 		const VkRenderPassBeginInfo beginInfo =
921 		{
922 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
923 			DE_NULL,
924 
925 			*m_renderPass,
926 			*m_framebuffer,
927 
928 			{
929 				{ 0u, 0u },
930 				{ m_width, m_height }
931 			},
932 
933 			0u,
934 			DE_NULL
935 		};
936 		RenderpassSubpass::cmdBeginRenderPass(vkd, *commandBuffer, &beginInfo, &subpassBeginInfo);
937 	}
938 
939 	// Clear everything to black
940 	{
941 		const tcu::TextureFormat			format			(mapVkFormat(m_format));
942 		const tcu::TextureChannelClass		channelClass	(tcu::getTextureChannelClass(format.type));
943 		VkClearValue						value;
944 
945 		switch (channelClass)
946 		{
947 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
948 				value = makeClearValueColorF32(-1.0f, -1.0f, -1.0f, -1.0f);
949 				break;
950 
951 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
952 				value = makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f);
953 				break;
954 
955 			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
956 				value = makeClearValueColorF32(-1.0f, -1.0f, -1.0f, -1.0f);
957 				break;
958 
959 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
960 				value = makeClearValueColorI32(-128, -128, -128, -128);
961 				break;
962 
963 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
964 				value = makeClearValueColorU32(0u, 0u, 0u, 0u);
965 				break;
966 
967 			default:
968 				DE_FATAL("Unknown channel class");
969 		}
970 		const VkClearAttachment				colors[]		=
971 		{
972 			{
973 				VK_IMAGE_ASPECT_COLOR_BIT,
974 				0u,
975 				value
976 			},
977 			{
978 				VK_IMAGE_ASPECT_COLOR_BIT,
979 				1u,
980 				value
981 			},
982 			{
983 				VK_IMAGE_ASPECT_COLOR_BIT,
984 				2u,
985 				value
986 			},
987 			{
988 				VK_IMAGE_ASPECT_COLOR_BIT,
989 				3u,
990 				value
991 			}
992 		};
993 		const VkClearRect rect =
994 		{
995 			{
996 				{ 0u, 0u },
997 				{ m_width, m_height }
998 			},
999 			0u,
1000 			m_layerCount,
1001 		};
1002 		vkd.cmdClearAttachments(*commandBuffer, DE_LENGTH_OF_ARRAY(colors), colors, 1u, &rect);
1003 	}
1004 
1005 	// Render black samples
1006 	{
1007 		vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
1008 		vkd.cmdPushConstants(*commandBuffer, *m_renderPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(m_sampleMask), &m_sampleMask);
1009 		vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
1010 	}
1011 
1012 	RenderpassSubpass::cmdEndRenderPass(vkd, *commandBuffer, &subpassEndInfo);
1013 
1014 	for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
1015 		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);
1016 
1017 	endCommandBuffer(vkd, *commandBuffer);
1018 
1019 	submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *commandBuffer);
1020 
1021 	for (size_t memoryBufferNdx = 0; memoryBufferNdx < m_bufferMemory.size(); memoryBufferNdx++)
1022 		invalidateMappedMemoryRange(vkd, device, m_bufferMemory[memoryBufferNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
1023 }
1024 
submitSwitch(RenderPassType renderPassType)1025 void MultisampleRenderPassTestInstance::submitSwitch (RenderPassType renderPassType)
1026 {
1027 	switch (renderPassType)
1028 	{
1029 		case RENDERPASS_TYPE_LEGACY:
1030 			submit<RenderpassSubpass1>();
1031 			break;
1032 		case RENDERPASS_TYPE_RENDERPASS2:
1033 			submit<RenderpassSubpass2>();
1034 			break;
1035 		default:
1036 			TCU_THROW(InternalError, "Impossible");
1037 	}
1038 }
1039 
verify(void)1040 void MultisampleRenderPassTestInstance::verify (void)
1041 {
1042 	const Vec4							errorColor		(1.0f, 0.0f, 0.0f, 1.0f);
1043 	const Vec4							okColor			(0.0f, 1.0f, 0.0f, 1.0f);
1044 	const tcu::TextureFormat			format			(mapVkFormat(m_format));
1045 	const tcu::TextureChannelClass		channelClass	(tcu::getTextureChannelClass(format.type));
1046 	const void* const					ptrs[]			=
1047 	{
1048 		m_bufferMemory[0]->getHostPtr(),
1049 		m_bufferMemory[1]->getHostPtr(),
1050 		m_bufferMemory[2]->getHostPtr(),
1051 		m_bufferMemory[3]->getHostPtr()
1052 	};
1053 	const tcu::ConstPixelBufferAccess	accesses[]		=
1054 	{
1055 		tcu::ConstPixelBufferAccess(format, m_width, m_height, m_layerCount, ptrs[0]),
1056 		tcu::ConstPixelBufferAccess(format, m_width, m_height, m_layerCount, ptrs[1]),
1057 		tcu::ConstPixelBufferAccess(format, m_width, m_height, m_layerCount, ptrs[2]),
1058 		tcu::ConstPixelBufferAccess(format, m_width, m_height, m_layerCount, ptrs[3])
1059 	};
1060 	tcu::TextureLevel					errorMask		(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width, m_height, m_layerCount);
1061 	tcu::TestLog&						log				(m_context.getTestContext().getLog());
1062 
1063 	switch (channelClass)
1064 	{
1065 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1066 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1067 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1068 		{
1069 			const int	componentCount	(tcu::getNumUsedChannels(format.order));
1070 			bool		isOk			= true;
1071 			float		clearValue;
1072 			float		renderValue;
1073 
1074 			switch (channelClass)
1075 			{
1076 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1077 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1078 					clearValue  = -1.0f;
1079 					renderValue = 1.0f;
1080 					break;
1081 
1082 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1083 					clearValue  = 0.0f;
1084 					renderValue = 1.0f;
1085 					break;
1086 
1087 				default:
1088 					clearValue  = 0.0f;
1089 					renderValue = 0.0f;
1090 					DE_FATAL("Unknown channel class");
1091 			}
1092 
1093 			for (deUint32 z = 0; z < m_layerCount; z++)
1094 			for (deUint32 y = 0; y < m_height; y++)
1095 			for (deUint32 x = 0; x < m_width; x++)
1096 			{
1097 				// Color has to be black if no samples were covered, white if all samples were covered or same in every attachment
1098 				const Vec4	firstColor	(accesses[0].getPixel(x, y, z));
1099 				const Vec4	refColor	(m_sampleMask == 0x0u
1100 										? Vec4(clearValue,
1101 												componentCount > 1 ? clearValue : 0.0f,
1102 												componentCount > 2 ? clearValue : 0.0f,
1103 												componentCount > 3 ? clearValue : 1.0f)
1104 										: m_sampleMask == ((0x1u << m_sampleCount) - 1u)
1105 										? Vec4(renderValue,
1106 												componentCount > 1 ? renderValue : 0.0f,
1107 												componentCount > 2 ? renderValue : 0.0f,
1108 												componentCount > 3 ? renderValue : 1.0f)
1109 										: firstColor);
1110 
1111 				errorMask.getAccess().setPixel(okColor, x, y, z);
1112 
1113 				for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
1114 				{
1115 					const Vec4 color (accesses[attachmentNdx].getPixel(x, y, z));
1116 
1117 					if (refColor != color)
1118 					{
1119 						isOk = false;
1120 						errorMask.getAccess().setPixel(errorColor, x, y, z);
1121 						break;
1122 					}
1123 				}
1124 
1125 				{
1126 					const Vec4 old = m_sum.getAccess().getPixel(x, y, z);
1127 					m_sum.getAccess().setPixel(old + (tcu::isSRGB(format) ? tcu::sRGBToLinear(firstColor) : firstColor), x, y, z);
1128 				}
1129 			}
1130 
1131 			if (!isOk)
1132 			{
1133 				const std::string			sectionName	("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1134 				const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
1135 
1136 				for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
1137 					logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1138 
1139 				logImage("ErrorMask", errorMask.getAccess());
1140 
1141 				if (m_sampleMask == 0x0u)
1142 				{
1143 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
1144 					m_resultCollector.fail("Empty sample mask didn't produce correct pixel values");
1145 				}
1146 				else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1147 				{
1148 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
1149 					m_resultCollector.fail("Full sample mask didn't produce correct pixel values");
1150 				}
1151 				else
1152 				{
1153 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve is inconsistent between attachments" << tcu::TestLog::EndMessage;
1154 					m_resultCollector.fail("Resolve is inconsistent between attachments");
1155 				}
1156 			}
1157 			break;
1158 		}
1159 
1160 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1161 		{
1162 			const int		componentCount			(tcu::getNumUsedChannels(format.order));
1163 			const UVec4		bitDepth				(tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1164 			const UVec4		renderValue				(tcu::select((UVec4(1u) << tcu::min(UVec4(8u), bitDepth)) - UVec4(1u),
1165 																  UVec4(0u, 0u, 0u, 1u),
1166 																  tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1167 			const UVec4		clearValue				(tcu::select(UVec4(0u),
1168 																 UVec4(0u, 0u, 0u, 1u),
1169 																 tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1170 			bool			unexpectedValues		= false;
1171 			bool			inconsistentComponents	= false;
1172 			bool			inconsistentAttachments	= false;
1173 
1174 			for (deUint32 z = 0; z < m_layerCount; z++)
1175 			for (deUint32 y = 0; y < m_height; y++)
1176 			for (deUint32 x = 0; x < m_width; x++)
1177 			{
1178 				// Color has to be all zeros if no samples were covered, all 255 if all samples were covered or consistent across all attachments
1179 				const UVec4 refColor	(m_sampleMask == 0x0u
1180 										? clearValue
1181 										: m_sampleMask == ((0x1u << m_sampleCount) - 1u)
1182 										? renderValue
1183 										: accesses[0].getPixelUint(x, y, z));
1184 				bool		isOk		= true;
1185 
1186 				// If reference value was taken from first attachment, check that it is valid value i.e. clear or render value
1187 				if (m_sampleMask != 0x0u && m_sampleMask != ((0x1u << m_sampleCount) - 1u))
1188 				{
1189 					// Each component must be resolved same way
1190 					const BVec4		isRenderValue			(refColor == renderValue);
1191 					const BVec4		isClearValue			(refColor == clearValue);
1192 					const bool		unexpectedValue			(tcu::anyNotEqual(tcu::logicalOr(isRenderValue, isClearValue), BVec4(true)));
1193 					const bool		inconsistentComponent	(!(tcu::allEqual(isRenderValue, BVec4(true)) || tcu::allEqual(isClearValue, BVec4(true))));
1194 
1195 					unexpectedValues		|= unexpectedValue;
1196 					inconsistentComponents	|= inconsistentComponent;
1197 
1198 					if (unexpectedValue || inconsistentComponent)
1199 						isOk = false;
1200 				}
1201 
1202 				for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
1203 				{
1204 					const UVec4 color (accesses[attachmentNdx].getPixelUint(x, y, z));
1205 
1206 					if (refColor != color)
1207 					{
1208 						isOk = false;
1209 						inconsistentAttachments = true;
1210 						break;
1211 					}
1212 				}
1213 
1214 				errorMask.getAccess().setPixel((isOk ? okColor : errorColor), x, y, z);
1215 			}
1216 
1217 			if (unexpectedValues || inconsistentComponents || inconsistentAttachments)
1218 			{
1219 				const std::string			sectionName	("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1220 				const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
1221 
1222 				for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
1223 					logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1224 
1225 				logImage("ErrorMask", errorMask.getAccess());
1226 
1227 				if (m_sampleMask == 0x0u)
1228 				{
1229 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
1230 					m_resultCollector.fail("Empty sample mask didn't produce correct pixels");
1231 				}
1232 				else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1233 				{
1234 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
1235 					m_resultCollector.fail("Full sample mask didn't produce correct pixels");
1236 				}
1237 				else
1238 				{
1239 					if (unexpectedValues)
1240 					{
1241 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve produced unexpected values i.e. not " << clearValue << " or " << renderValue << tcu::TestLog::EndMessage;
1242 						m_resultCollector.fail("Resolve produced unexpected values");
1243 					}
1244 
1245 					if (inconsistentComponents)
1246 					{
1247 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different components of attachment were resolved to different values." << tcu::TestLog::EndMessage;
1248 						m_resultCollector.fail("Different components of attachment were resolved to different values.");
1249 					}
1250 
1251 					if (inconsistentAttachments)
1252 					{
1253 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different attachments were resolved to different values." << tcu::TestLog::EndMessage;
1254 						m_resultCollector.fail("Different attachments were resolved to different values.");
1255 					}
1256 				}
1257 			}
1258 			break;
1259 		}
1260 
1261 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1262 		{
1263 			const int		componentCount			(tcu::getNumUsedChannels(format.order));
1264 			const IVec4		bitDepth				(tcu::getTextureFormatBitDepth(format));
1265 			const IVec4		renderValue				(tcu::select((IVec4(1) << (tcu::min(IVec4(8), bitDepth) - IVec4(1))) - IVec4(1),
1266 																  IVec4(0, 0, 0, 1),
1267 																  tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1268 			const IVec4		clearValue				(tcu::select(-(IVec4(1) << (tcu::min(IVec4(8), bitDepth) - IVec4(1))),
1269 																 IVec4(0, 0, 0, 1),
1270 																 tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1271 			bool			unexpectedValues		= false;
1272 			bool			inconsistentComponents	= false;
1273 			bool			inconsistentAttachments	= false;
1274 
1275 			for (deUint32 z = 0; z < m_layerCount; z++)
1276 			for (deUint32 y = 0; y < m_height; y++)
1277 			for (deUint32 x = 0; x < m_width; x++)
1278 			{
1279 				// Color has to be all zeros if no samples were covered, all 255 if all samples were covered or consistent across all attachments
1280 				const IVec4 refColor	(m_sampleMask == 0x0u
1281 										? clearValue
1282 										: m_sampleMask == ((0x1u << m_sampleCount) - 1u)
1283 										? renderValue
1284 										: accesses[0].getPixelInt(x, y, z));
1285 				bool		isOk		= true;
1286 
1287 				// If reference value was taken from first attachment, check that it is valid value i.e. clear or render value
1288 				if (m_sampleMask != 0x0u && m_sampleMask != ((0x1u << m_sampleCount) - 1u))
1289 				{
1290 					// Each component must be resolved same way
1291 					const BVec4		isRenderValue			(refColor == renderValue);
1292 					const BVec4		isClearValue			(refColor == clearValue);
1293 					const bool		unexpectedValue			(tcu::anyNotEqual(tcu::logicalOr(isRenderValue, isClearValue), BVec4(true)));
1294 					const bool		inconsistentComponent	(!(tcu::allEqual(isRenderValue, BVec4(true)) || tcu::allEqual(isClearValue, BVec4(true))));
1295 
1296 					unexpectedValues		|= unexpectedValue;
1297 					inconsistentComponents	|= inconsistentComponent;
1298 
1299 					if (unexpectedValue || inconsistentComponent)
1300 						isOk = false;
1301 				}
1302 
1303 				for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
1304 				{
1305 					const IVec4 color (accesses[attachmentNdx].getPixelInt(x, y, z));
1306 
1307 					if (refColor != color)
1308 					{
1309 						isOk = false;
1310 						inconsistentAttachments = true;
1311 						break;
1312 					}
1313 				}
1314 
1315 				errorMask.getAccess().setPixel((isOk ? okColor : errorColor), x, y, z);
1316 			}
1317 
1318 			if (unexpectedValues || inconsistentComponents || inconsistentAttachments)
1319 			{
1320 				const std::string			sectionName	("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1321 				const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
1322 
1323 				for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
1324 					logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1325 
1326 				logImage("ErrorMask", errorMask.getAccess());
1327 
1328 				if (m_sampleMask == 0x0u)
1329 				{
1330 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
1331 					m_resultCollector.fail("Empty sample mask didn't produce correct pixels");
1332 				}
1333 				else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1334 				{
1335 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
1336 					m_resultCollector.fail("Full sample mask didn't produce correct pixels");
1337 				}
1338 				else
1339 				{
1340 					if (unexpectedValues)
1341 					{
1342 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve produced unexpected values i.e. not " << clearValue << " or " << renderValue << tcu::TestLog::EndMessage;
1343 						m_resultCollector.fail("Resolve produced unexpected values");
1344 					}
1345 
1346 					if (inconsistentComponents)
1347 					{
1348 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different components of attachment were resolved to different values." << tcu::TestLog::EndMessage;
1349 						m_resultCollector.fail("Different components of attachment were resolved to different values.");
1350 					}
1351 
1352 					if (inconsistentAttachments)
1353 					{
1354 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different attachments were resolved to different values." << tcu::TestLog::EndMessage;
1355 						m_resultCollector.fail("Different attachments were resolved to different values.");
1356 					}
1357 				}
1358 			}
1359 			break;
1360 		}
1361 
1362 		default:
1363 			DE_FATAL("Unknown channel class");
1364 	}
1365 }
1366 
iterate(void)1367 tcu::TestStatus MultisampleRenderPassTestInstance::iterate (void)
1368 {
1369 	if (m_sampleMask == 0u)
1370 	{
1371 		const tcu::TextureFormat		format			(mapVkFormat(m_format));
1372 		const tcu::TextureChannelClass	channelClass	(tcu::getTextureChannelClass(format.type));
1373 		tcu::TestLog&					log				(m_context.getTestContext().getLog());
1374 
1375 		switch (channelClass)
1376 		{
1377 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1378 				log << TestLog::Message << "Clearing target to zero and rendering 255 pixels with every possible sample mask" << TestLog::EndMessage;
1379 				break;
1380 
1381 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1382 				log << TestLog::Message << "Clearing target to -128 and rendering 127 pixels with every possible sample mask" << TestLog::EndMessage;
1383 				break;
1384 
1385 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1386 			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1387 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1388 				log << TestLog::Message << "Clearing target to black and rendering white pixels with every possible sample mask" << TestLog::EndMessage;
1389 				break;
1390 
1391 			default:
1392 				DE_FATAL("Unknown channel class");
1393 		}
1394 	}
1395 
1396 	submitSwitch(m_renderPassType);
1397 	verify();
1398 
1399 	if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1400 	{
1401 		const tcu::TextureFormat		format			(mapVkFormat(m_format));
1402 		const tcu::TextureChannelClass	channelClass	(tcu::getTextureChannelClass(format.type));
1403 		const Vec4						threshold		(getFormatThreshold(m_format));
1404 		tcu::TestLog&					log				(m_context.getTestContext().getLog());
1405 
1406 		if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT
1407 				|| channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT
1408 				|| channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
1409 		{
1410 			const int			componentCount	(tcu::getNumUsedChannels(format.order));
1411 			const Vec4			errorColor		(1.0f, 0.0f, 0.0f, 1.0f);
1412 			const Vec4			okColor			(0.0f, 1.0f, 0.0f, 1.0f);
1413 			tcu::TextureLevel	errorMask		(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width, m_height, m_layerCount);
1414 			bool				isOk			= true;
1415 			Vec4				maxDiff			(0.0f);
1416 			Vec4				expectedAverage;
1417 
1418 			switch (channelClass)
1419 			{
1420 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1421 				{
1422 					expectedAverage = Vec4(0.5f, componentCount > 1 ? 0.5f : 0.0f, componentCount > 2 ? 0.5f : 0.0f, componentCount > 3 ? 0.5f : 1.0f);
1423 					break;
1424 				}
1425 
1426 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1427 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1428 				{
1429 					expectedAverage = Vec4(0.0f, 0.0f, 0.0f, componentCount > 3 ? 0.0f : 1.0f);
1430 					break;
1431 				}
1432 
1433 				default:
1434 					DE_FATAL("Unknown channel class");
1435 			}
1436 
1437 			for (deUint32 z = 0; z < m_layerCount; z++)
1438 			for (deUint32 y = 0; y < m_height; y++)
1439 			for (deUint32 x = 0; x < m_width; x++)
1440 			{
1441 				const Vec4	sum		(m_sum.getAccess().getPixel(x, y, z));
1442 				const Vec4	average	(sum / Vec4((float)(0x1u << m_sampleCount)));
1443 				const Vec4	diff	(tcu::abs(average - expectedAverage));
1444 
1445 				m_sum.getAccess().setPixel(average, x, y, z);
1446 				errorMask.getAccess().setPixel(okColor, x, y, z);
1447 
1448 				if (diff[0] > threshold.x()
1449 						|| diff[1] > threshold.y()
1450 						|| diff[2] > threshold.z()
1451 						|| diff[3] > threshold.w())
1452 				{
1453 					isOk	= false;
1454 					maxDiff	= tcu::max(maxDiff, diff);
1455 					errorMask.getAccess().setPixel(errorColor, x, y, z);
1456 				}
1457 			}
1458 
1459 			log << TestLog::Image("Average resolved values in attachment 0", "Average resolved values in attachment 0", m_sum);
1460 
1461 			if (!isOk)
1462 			{
1463 				std::stringstream	message;
1464 
1465 				m_context.getTestContext().getLog() << tcu::LogImage("ErrorMask", "ErrorMask", errorMask.getAccess());
1466 
1467 				message << "Average resolved values differ from expected average values by more than ";
1468 
1469 				switch (componentCount)
1470 				{
1471 					case 1:
1472 						message << threshold.x();
1473 						break;
1474 					case 2:
1475 						message << "vec2" << Vec2(threshold.x(), threshold.y());
1476 						break;
1477 					case 3:
1478 						message << "vec3" << Vec3(threshold.x(), threshold.y(), threshold.z());
1479 						break;
1480 					default:
1481 						message << "vec4" << threshold;
1482 				}
1483 
1484 				message << ". Max diff " << maxDiff;
1485 				log << TestLog::Message << message.str() <<  TestLog::EndMessage;
1486 
1487 				m_resultCollector.fail("Average resolved values differ from expected average values");
1488 			}
1489 		}
1490 
1491 		return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1492 	}
1493 	else
1494 	{
1495 		m_sampleMask++;
1496 		return tcu::TestStatus::incomplete();
1497 	}
1498 }
1499 
1500 struct Programs
1501 {
initvkt::__anon156ab5910111::Programs1502 	void init (vk::SourceCollections& dst, TestConfig config) const
1503 	{
1504 		const tcu::TextureFormat		format			(mapVkFormat(config.format));
1505 		const tcu::TextureChannelClass	channelClass	(tcu::getTextureChannelClass(format.type));
1506 
1507 		dst.glslSources.add("quad-vert") << glu::VertexSource(
1508 			"#version 450\n"
1509 			"out gl_PerVertex {\n"
1510 			"\tvec4 gl_Position;\n"
1511 			"};\n"
1512 			"highp float;\n"
1513 			"void main (void) {\n"
1514 			"\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
1515 			"\t                   ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
1516 			"}\n");
1517 
1518 		if (config.layerCount > 1)
1519 		{
1520 			std::ostringstream src;
1521 
1522 			src << "#version 450\n"
1523 				<< "highp float;\n"
1524 				<< "\n"
1525 				<< "layout(triangles) in;\n"
1526 				<< "layout(triangle_strip, max_vertices = " << 3 * 2 * config.layerCount << ") out;\n"
1527 				<< "\n"
1528 				<< "in gl_PerVertex {\n"
1529 				<< "    vec4 gl_Position;\n"
1530 				<< "} gl_in[];\n"
1531 				<< "\n"
1532 				<< "out gl_PerVertex {\n"
1533 				<< "    vec4 gl_Position;\n"
1534 				<< "};\n"
1535 				<< "\n"
1536 				<< "void main (void) {\n"
1537 				<< "    for (int layerNdx = 0; layerNdx < " << config.layerCount << "; ++layerNdx) {\n"
1538 				<< "        for(int vertexNdx = 0; vertexNdx < gl_in.length(); vertexNdx++) {\n"
1539 				<< "            gl_Position = gl_in[vertexNdx].gl_Position;\n"
1540 				<< "            gl_Layer    = layerNdx;\n"
1541 				<< "            EmitVertex();\n"
1542 				<< "        };\n"
1543 				<< "        EndPrimitive();\n"
1544 				<< "    };\n"
1545 				<< "}\n";
1546 
1547 			dst.glslSources.add("geom") << glu::GeometrySource(src.str());
1548 		}
1549 
1550 		switch (channelClass)
1551 		{
1552 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1553 				dst.glslSources.add("quad-frag") << glu::FragmentSource(
1554 					"#version 450\n"
1555 					"layout(push_constant) uniform PushConstant {\n"
1556 					"\thighp uint sampleMask;\n"
1557 					"} pushConstants;\n"
1558 					"layout(location = 0) out highp uvec4 o_color0;\n"
1559 					"layout(location = 1) out highp uvec4 o_color1;\n"
1560 					"layout(location = 2) out highp uvec4 o_color2;\n"
1561 					"layout(location = 3) out highp uvec4 o_color3;\n"
1562 					"void main (void)\n"
1563 					"{\n"
1564 					"\tgl_SampleMask[0] = int(pushConstants.sampleMask);\n"
1565 					"\to_color0 = uvec4(255);\n"
1566 					"\to_color1 = uvec4(255);\n"
1567 					"\to_color2 = uvec4(255);\n"
1568 					"\to_color3 = uvec4(255);\n"
1569 					"}\n");
1570 				break;
1571 
1572 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1573 				dst.glslSources.add("quad-frag") << glu::FragmentSource(
1574 					"#version 450\n"
1575 					"layout(push_constant) uniform PushConstant {\n"
1576 					"\thighp uint sampleMask;\n"
1577 					"} pushConstants;\n"
1578 					"layout(location = 0) out highp ivec4 o_color0;\n"
1579 					"layout(location = 1) out highp ivec4 o_color1;\n"
1580 					"layout(location = 2) out highp ivec4 o_color2;\n"
1581 					"layout(location = 3) out highp ivec4 o_color3;\n"
1582 					"void main (void)\n"
1583 					"{\n"
1584 					"\tgl_SampleMask[0] = int(pushConstants.sampleMask);\n"
1585 					"\to_color0 = ivec4(127);\n"
1586 					"\to_color1 = ivec4(127);\n"
1587 					"\to_color2 = ivec4(127);\n"
1588 					"\to_color3 = ivec4(127);\n"
1589 					"}\n");
1590 				break;
1591 
1592 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1593 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1594 			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1595 				dst.glslSources.add("quad-frag") << glu::FragmentSource(
1596 					"#version 450\n"
1597 					"layout(push_constant) uniform PushConstant {\n"
1598 					"\thighp uint sampleMask;\n"
1599 					"} pushConstants;\n"
1600 					"layout(location = 0) out highp vec4 o_color0;\n"
1601 					"layout(location = 1) out highp vec4 o_color1;\n"
1602 					"layout(location = 2) out highp vec4 o_color2;\n"
1603 					"layout(location = 3) out highp vec4 o_color3;\n"
1604 					"void main (void)\n"
1605 					"{\n"
1606 					"\tgl_SampleMask[0] = int(pushConstants.sampleMask);\n"
1607 					"\to_color0 = vec4(1.0);\n"
1608 					"\to_color1 = vec4(1.0);\n"
1609 					"\to_color2 = vec4(1.0);\n"
1610 					"\to_color3 = vec4(1.0);\n"
1611 					"}\n");
1612 				break;
1613 
1614 			default:
1615 				DE_FATAL("Unknown channel class");
1616 		}
1617 	}
1618 };
1619 
formatToName(VkFormat format)1620 std::string formatToName (VkFormat format)
1621 {
1622 	const std::string	formatStr	= de::toString(format);
1623 	const std::string	prefix		= "VK_FORMAT_";
1624 
1625 	DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
1626 
1627 	return de::toLower(formatStr.substr(prefix.length()));
1628 }
1629 
initTests(tcu::TestCaseGroup * group,RenderPassType renderPassType)1630 void initTests (tcu::TestCaseGroup* group, RenderPassType renderPassType)
1631 {
1632 	static const VkFormat	formats[]	=
1633 	{
1634 		VK_FORMAT_R5G6B5_UNORM_PACK16,
1635 		VK_FORMAT_R8_UNORM,
1636 		VK_FORMAT_R8_SNORM,
1637 		VK_FORMAT_R8_UINT,
1638 		VK_FORMAT_R8_SINT,
1639 		VK_FORMAT_R8G8_UNORM,
1640 		VK_FORMAT_R8G8_SNORM,
1641 		VK_FORMAT_R8G8_UINT,
1642 		VK_FORMAT_R8G8_SINT,
1643 		VK_FORMAT_R8G8B8A8_UNORM,
1644 		VK_FORMAT_R8G8B8A8_SNORM,
1645 		VK_FORMAT_R8G8B8A8_UINT,
1646 		VK_FORMAT_R8G8B8A8_SINT,
1647 		VK_FORMAT_R8G8B8A8_SRGB,
1648 		VK_FORMAT_A8B8G8R8_UNORM_PACK32,
1649 		VK_FORMAT_A8B8G8R8_SNORM_PACK32,
1650 		VK_FORMAT_A8B8G8R8_UINT_PACK32,
1651 		VK_FORMAT_A8B8G8R8_SINT_PACK32,
1652 		VK_FORMAT_A8B8G8R8_SRGB_PACK32,
1653 		VK_FORMAT_B8G8R8A8_UNORM,
1654 		VK_FORMAT_B8G8R8A8_SRGB,
1655 		VK_FORMAT_A2R10G10B10_UNORM_PACK32,
1656 		VK_FORMAT_A2B10G10R10_UNORM_PACK32,
1657 		VK_FORMAT_A2B10G10R10_UINT_PACK32,
1658 		VK_FORMAT_R16_UNORM,
1659 		VK_FORMAT_R16_SNORM,
1660 		VK_FORMAT_R16_UINT,
1661 		VK_FORMAT_R16_SINT,
1662 		VK_FORMAT_R16_SFLOAT,
1663 		VK_FORMAT_R16G16_UNORM,
1664 		VK_FORMAT_R16G16_SNORM,
1665 		VK_FORMAT_R16G16_UINT,
1666 		VK_FORMAT_R16G16_SINT,
1667 		VK_FORMAT_R16G16_SFLOAT,
1668 		VK_FORMAT_R16G16B16A16_UNORM,
1669 		VK_FORMAT_R16G16B16A16_SNORM,
1670 		VK_FORMAT_R16G16B16A16_UINT,
1671 		VK_FORMAT_R16G16B16A16_SINT,
1672 		VK_FORMAT_R16G16B16A16_SFLOAT,
1673 		VK_FORMAT_R32_UINT,
1674 		VK_FORMAT_R32_SINT,
1675 		VK_FORMAT_R32_SFLOAT,
1676 		VK_FORMAT_R32G32_UINT,
1677 		VK_FORMAT_R32G32_SINT,
1678 		VK_FORMAT_R32G32_SFLOAT,
1679 		VK_FORMAT_R32G32B32A32_UINT,
1680 		VK_FORMAT_R32G32B32A32_SINT,
1681 		VK_FORMAT_R32G32B32A32_SFLOAT,
1682 	};
1683 	const deUint32			sampleCounts[] =
1684 	{
1685 		2u, 4u, 8u
1686 	};
1687 	const deUint32			layerCounts[] =
1688 	{
1689 		1u, 3u, 6u
1690 	};
1691 	tcu::TestContext&		testCtx		(group->getTestContext());
1692 
1693 	for (size_t layerCountNdx = 0; layerCountNdx < DE_LENGTH_OF_ARRAY(layerCounts); layerCountNdx++)
1694 	{
1695 		const deUint32					layerCount		(layerCounts[layerCountNdx]);
1696 		const std::string				layerGroupName	("layers_" + de::toString(layerCount));
1697 		de::MovePtr<tcu::TestCaseGroup>	layerGroup		(new tcu::TestCaseGroup(testCtx, layerGroupName.c_str(), layerGroupName.c_str()));
1698 
1699 		for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1700 		{
1701 			const VkFormat					format		(formats[formatNdx]);
1702 			const std::string				formatName	(formatToName(format));
1703 			de::MovePtr<tcu::TestCaseGroup>	formatGroup	(new tcu::TestCaseGroup(testCtx, formatName.c_str(), formatName.c_str()));
1704 
1705 			for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++)
1706 			{
1707 				const deUint32		sampleCount	(sampleCounts[sampleCountNdx]);
1708 				const std::string	testName	("samples_" + de::toString(sampleCount));
1709 				const TestConfig	testConfig	(format, sampleCount, layerCount, renderPassType);
1710 
1711 				// Skip this test as it is rather slow
1712 				if (layerCount == 6 && sampleCount == 8)
1713 					continue;
1714 
1715 				formatGroup->addChild(new InstanceFactory1<MultisampleRenderPassTestInstance, TestConfig, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, testName.c_str(), testName.c_str(), testConfig));
1716 			}
1717 
1718 			if (layerCount == 1)
1719 				group->addChild(formatGroup.release());
1720 			else
1721 				layerGroup->addChild(formatGroup.release());
1722 		}
1723 
1724 		if (layerCount != 1)
1725 			group->addChild(layerGroup.release());
1726 	}
1727 }
1728 
1729 } // anonymous
1730 
createRenderPassMultisampleResolveTests(tcu::TestContext & testCtx)1731 tcu::TestCaseGroup* createRenderPassMultisampleResolveTests (tcu::TestContext& testCtx)
1732 {
1733 	return createTestGroup(testCtx, "multisample_resolve", "Multisample render pass resolve tests", initTests, RENDERPASS_TYPE_LEGACY);
1734 }
1735 
createRenderPass2MultisampleResolveTests(tcu::TestContext & testCtx)1736 tcu::TestCaseGroup* createRenderPass2MultisampleResolveTests (tcu::TestContext& testCtx)
1737 {
1738 	return createTestGroup(testCtx, "multisample_resolve", "Multisample render pass resolve tests", initTests, RENDERPASS_TYPE_RENDERPASS2);
1739 }
1740 
1741 } // vkt
1742