• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 Google Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Tests for render passses with multisample attachments
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRenderPassMultisampleTests.hpp"
25 
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28 
29 #include "vkDefs.hpp"
30 #include "vkDeviceUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkPlatform.hpp"
34 #include "vkPrograms.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkRef.hpp"
37 #include "vkRefUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 
40 #include "tcuFloat.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "tcuFormatUtil.hpp"
43 #include "tcuMaybe.hpp"
44 #include "tcuResultCollector.hpp"
45 #include "tcuTestLog.hpp"
46 #include "tcuTextureUtil.hpp"
47 #include "tcuVectorUtil.hpp"
48 
49 #include "deUniquePtr.hpp"
50 #include "deSharedPtr.hpp"
51 
52 using namespace vk;
53 
54 using tcu::BVec4;
55 using tcu::IVec2;
56 using tcu::IVec4;
57 using tcu::UVec2;
58 using tcu::UVec4;
59 using tcu::Vec2;
60 using tcu::Vec4;
61 
62 using tcu::Maybe;
63 using tcu::just;
64 using tcu::nothing;
65 
66 using tcu::ConstPixelBufferAccess;
67 using tcu::PixelBufferAccess;
68 
69 using tcu::TestLog;
70 
71 using std::pair;
72 using std::string;
73 using std::vector;
74 
75 typedef de::SharedPtr<vk::Unique<VkImage> > VkImageSp;
76 typedef de::SharedPtr<vk::Unique<VkImageView> > VkImageViewSp;
77 typedef de::SharedPtr<vk::Unique<VkBuffer> > VkBufferSp;
78 typedef de::SharedPtr<vk::Unique<VkPipeline> > VkPipelineSp;
79 
80 namespace vkt
81 {
82 namespace
83 {
84 enum
85 {
86 	MAX_COLOR_ATTACHMENT_COUNT = 4u
87 };
88 
89 template<typename T>
safeSharedPtr(T * ptr)90 de::SharedPtr<T> safeSharedPtr (T* ptr)
91 {
92 	try
93 	{
94 		return de::SharedPtr<T>(ptr);
95 	}
96 	catch (...)
97 	{
98 		delete ptr;
99 		throw;
100 	}
101 }
102 
getImageAspectFlags(VkFormat vkFormat)103 VkImageAspectFlags getImageAspectFlags (VkFormat vkFormat)
104 {
105 	const tcu::TextureFormat	format		(mapVkFormat(vkFormat));
106 	const bool					hasDepth	(tcu::hasDepthComponent(format.order));
107 	const bool					hasStencil	(tcu::hasStencilComponent(format.order));
108 
109 	if (hasDepth || hasStencil)
110 	{
111 		return (hasDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : (VkImageAspectFlagBits)0u)
112 				| (hasStencil ? VK_IMAGE_ASPECT_STENCIL_BIT : (VkImageAspectFlagBits)0u);
113 	}
114 	else
115 		return VK_IMAGE_ASPECT_COLOR_BIT;
116 }
117 
bindBufferMemory(const DeviceInterface & vk,VkDevice device,VkBuffer buffer,VkDeviceMemory mem,VkDeviceSize memOffset)118 void bindBufferMemory (const DeviceInterface& vk, VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset)
119 {
120 	VK_CHECK(vk.bindBufferMemory(device, buffer, mem, memOffset));
121 }
122 
bindImageMemory(const DeviceInterface & vk,VkDevice device,VkImage image,VkDeviceMemory mem,VkDeviceSize memOffset)123 void bindImageMemory (const DeviceInterface& vk, VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset)
124 {
125 	VK_CHECK(vk.bindImageMemory(device, image, mem, memOffset));
126 }
127 
createBufferMemory(const DeviceInterface & vk,VkDevice device,Allocator & allocator,VkBuffer buffer)128 de::MovePtr<Allocation> createBufferMemory (const DeviceInterface&	vk,
129 											VkDevice				device,
130 											Allocator&				allocator,
131 											VkBuffer				buffer)
132 {
133 	de::MovePtr<Allocation> allocation (allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), MemoryRequirement::HostVisible));
134 	bindBufferMemory(vk, device, buffer, allocation->getMemory(), allocation->getOffset());
135 	return allocation;
136 }
137 
createImageMemory(const DeviceInterface & vk,VkDevice device,Allocator & allocator,VkImage image)138 de::MovePtr<Allocation> createImageMemory (const DeviceInterface&	vk,
139 										   VkDevice					device,
140 										   Allocator&				allocator,
141 										   VkImage					image)
142 {
143 	de::MovePtr<Allocation> allocation (allocator.allocate(getImageMemoryRequirements(vk, device, image), MemoryRequirement::Any));
144 	bindImageMemory(vk, device, image, allocation->getMemory(), allocation->getOffset());
145 	return allocation;
146 }
147 
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)148 Move<VkImage> createImage (const DeviceInterface&	vk,
149 						   VkDevice					device,
150 						   VkImageCreateFlags		flags,
151 						   VkImageType				imageType,
152 						   VkFormat					format,
153 						   VkExtent3D				extent,
154 						   deUint32					mipLevels,
155 						   deUint32					arrayLayers,
156 						   VkSampleCountFlagBits	samples,
157 						   VkImageTiling			tiling,
158 						   VkImageUsageFlags		usage,
159 						   VkSharingMode			sharingMode,
160 						   deUint32					queueFamilyCount,
161 						   const deUint32*			pQueueFamilyIndices,
162 						   VkImageLayout			initialLayout)
163 {
164 	const VkImageCreateInfo pCreateInfo =
165 	{
166 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
167 		DE_NULL,
168 		flags,
169 		imageType,
170 		format,
171 		extent,
172 		mipLevels,
173 		arrayLayers,
174 		samples,
175 		tiling,
176 		usage,
177 		sharingMode,
178 		queueFamilyCount,
179 		pQueueFamilyIndices,
180 		initialLayout
181 	};
182 	return createImage(vk, device, &pCreateInfo);
183 }
184 
createImageView(const DeviceInterface & vk,VkDevice device,VkImageViewCreateFlags flags,VkImage image,VkImageViewType viewType,VkFormat format,VkComponentMapping components,VkImageSubresourceRange subresourceRange)185 Move<VkImageView> createImageView (const DeviceInterface&	vk,
186 								   VkDevice					device,
187 								   VkImageViewCreateFlags	flags,
188 								   VkImage					image,
189 								   VkImageViewType			viewType,
190 								   VkFormat					format,
191 								   VkComponentMapping		components,
192 								   VkImageSubresourceRange	subresourceRange)
193 {
194 	const VkImageViewCreateInfo pCreateInfo =
195 	{
196 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
197 		DE_NULL,
198 		flags,
199 		image,
200 		viewType,
201 		format,
202 		components,
203 		subresourceRange,
204 	};
205 	return createImageView(vk, device, &pCreateInfo);
206 }
207 
createImage(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const DeviceInterface & vkd,VkDevice device,VkFormat vkFormat,VkSampleCountFlagBits sampleCountBit,VkImageUsageFlags usage,deUint32 width,deUint32 height)208 Move<VkImage> createImage (const InstanceInterface&	vki,
209 						   VkPhysicalDevice			physicalDevice,
210 						   const DeviceInterface&	vkd,
211 						   VkDevice					device,
212 						   VkFormat					vkFormat,
213 						   VkSampleCountFlagBits	sampleCountBit,
214 						   VkImageUsageFlags		usage,
215 						   deUint32					width,
216 						   deUint32					height)
217 {
218 	try
219 	{
220 		const tcu::TextureFormat		format					(mapVkFormat(vkFormat));
221 		const VkImageType				imageType				(VK_IMAGE_TYPE_2D);
222 		const VkImageTiling				imageTiling				(VK_IMAGE_TILING_OPTIMAL);
223 		const VkFormatProperties		formatProperties		(getPhysicalDeviceFormatProperties(vki, physicalDevice, vkFormat));
224 		const VkImageFormatProperties	imageFormatProperties	(getPhysicalDeviceImageFormatProperties(vki, physicalDevice, vkFormat, imageType, imageTiling, usage, 0u));
225 		const VkExtent3D				imageExtent				=
226 		{
227 			width,
228 			height,
229 			1u
230 		};
231 
232 		if ((tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
233 			&& (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)
234 			TCU_THROW(NotSupportedError, "Format can't be used as depth stencil attachment");
235 
236 		if (!(tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
237 			&& (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)
238 			TCU_THROW(NotSupportedError, "Format can't be used as color attachment");
239 
240 		if (imageFormatProperties.maxExtent.width < imageExtent.width
241 			|| imageFormatProperties.maxExtent.height < imageExtent.height
242 			|| ((imageFormatProperties.sampleCounts & sampleCountBit) == 0))
243 		{
244 			TCU_THROW(NotSupportedError, "Image type not supported");
245 		}
246 
247 		return createImage(vkd, device, 0u, imageType, vkFormat, imageExtent, 1u, 1u, sampleCountBit, imageTiling, usage, VK_SHARING_MODE_EXCLUSIVE, 0u, DE_NULL, VK_IMAGE_LAYOUT_UNDEFINED);
248 	}
249 	catch (const vk::Error& error)
250 	{
251 		if (error.getError() == VK_ERROR_FORMAT_NOT_SUPPORTED)
252 			TCU_THROW(NotSupportedError, "Image format not supported");
253 
254 		throw;
255 	}
256 }
257 
createImageAttachmentView(const DeviceInterface & vkd,VkDevice device,VkImage image,VkFormat format,VkImageAspectFlags aspect)258 Move<VkImageView> createImageAttachmentView (const DeviceInterface&	vkd,
259 											 VkDevice				device,
260 											 VkImage				image,
261 											 VkFormat				format,
262 											 VkImageAspectFlags		aspect)
263 {
264 	const VkImageSubresourceRange	range =
265 	{
266 		aspect,
267 		0u,
268 		1u,
269 		0u,
270 		1u
271 	};
272 
273 	return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
274 }
275 
createSrcPrimaryInputImageView(const DeviceInterface & vkd,VkDevice device,VkImage image,VkFormat format,VkImageAspectFlags aspect)276 Move<VkImageView> createSrcPrimaryInputImageView (const DeviceInterface&	vkd,
277 												  VkDevice					device,
278 												  VkImage					image,
279 												  VkFormat					format,
280 												  VkImageAspectFlags		aspect)
281 {
282 	const VkImageSubresourceRange	range =
283 	{
284 		aspect == (VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT)
285 			? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT
286 			: aspect,
287 		0u,
288 		1u,
289 		0u,
290 		1u
291 	};
292 
293 	return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
294 }
295 
createSrcSecondaryInputImageView(const DeviceInterface & vkd,VkDevice device,VkImage image,VkFormat format,VkImageAspectFlags aspect)296 Move<VkImageView> createSrcSecondaryInputImageView (const DeviceInterface&	vkd,
297 													VkDevice				device,
298 													VkImage					image,
299 													VkFormat				format,
300 													VkImageAspectFlags		aspect)
301 {
302 	if (aspect == (VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT))
303 	{
304 		const VkImageSubresourceRange	range =
305 		{
306 			VK_IMAGE_ASPECT_STENCIL_BIT,
307 			0u,
308 			1u,
309 			0u,
310 			1u
311 		};
312 
313 		return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
314 	}
315 	else
316 		return Move<VkImageView>();
317 }
318 
getPixelSize(VkFormat vkFormat)319 VkDeviceSize getPixelSize (VkFormat vkFormat)
320 {
321 	const tcu::TextureFormat	format	(mapVkFormat(vkFormat));
322 
323 	return format.getPixelSize();
324 }
325 
createBuffer(const DeviceInterface & vkd,VkDevice device,VkFormat format,deUint32 width,deUint32 height)326 Move<VkBuffer> createBuffer (const DeviceInterface&		vkd,
327 							 VkDevice					device,
328 							 VkFormat					format,
329 							 deUint32					width,
330 							 deUint32					height)
331 {
332 	const VkBufferUsageFlags	bufferUsage			(VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
333 	const VkDeviceSize			pixelSize			(getPixelSize(format));
334 	const VkBufferCreateInfo	createInfo			=
335 	{
336 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
337 		DE_NULL,
338 		0u,
339 
340 		width * height * pixelSize,
341 		bufferUsage,
342 
343 		VK_SHARING_MODE_EXCLUSIVE,
344 		0u,
345 		DE_NULL
346 	};
347 	return createBuffer(vkd, device, &createInfo);
348 }
349 
sampleCountBitFromomSampleCount(deUint32 count)350 VkSampleCountFlagBits sampleCountBitFromomSampleCount (deUint32 count)
351 {
352 	switch (count)
353 	{
354 		case 1:  return VK_SAMPLE_COUNT_1_BIT;
355 		case 2:  return VK_SAMPLE_COUNT_2_BIT;
356 		case 4:  return VK_SAMPLE_COUNT_4_BIT;
357 		case 8:  return VK_SAMPLE_COUNT_8_BIT;
358 		case 16: return VK_SAMPLE_COUNT_16_BIT;
359 		case 32: return VK_SAMPLE_COUNT_32_BIT;
360 		case 64: return VK_SAMPLE_COUNT_64_BIT;
361 
362 		default:
363 			DE_FATAL("Invalid sample count");
364 			return (VkSampleCountFlagBits)(0x1u << count);
365 	}
366 }
367 
createMultisampleImages(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const DeviceInterface & vkd,VkDevice device,VkFormat format,deUint32 sampleCount,deUint32 width,deUint32 height)368 std::vector<VkImageSp> createMultisampleImages (const InstanceInterface&	vki,
369 												VkPhysicalDevice			physicalDevice,
370 												const DeviceInterface&		vkd,
371 												VkDevice					device,
372 												VkFormat					format,
373 												deUint32					sampleCount,
374 												deUint32					width,
375 												deUint32					height)
376 {
377 	std::vector<VkImageSp> images (sampleCount);
378 
379 	for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
380 		images[imageNdx] = safeSharedPtr(new vk::Unique<VkImage>(createImage(vki, physicalDevice, vkd, device, format, sampleCountBitFromomSampleCount(sampleCount), VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, width, height)));
381 
382 	return images;
383 }
384 
createSingleSampleImages(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const DeviceInterface & vkd,VkDevice device,VkFormat format,deUint32 sampleCount,deUint32 width,deUint32 height)385 std::vector<VkImageSp> createSingleSampleImages (const InstanceInterface&	vki,
386 												 VkPhysicalDevice			physicalDevice,
387 												 const DeviceInterface&		vkd,
388 												 VkDevice					device,
389 												 VkFormat					format,
390 												 deUint32					sampleCount,
391 												 deUint32					width,
392 												 deUint32					height)
393 {
394 	std::vector<VkImageSp> images (sampleCount);
395 
396 	for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
397 		images[imageNdx] = safeSharedPtr(new vk::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)));
398 
399 	return images;
400 }
401 
createImageMemory(const DeviceInterface & vkd,VkDevice device,Allocator & allocator,const std::vector<VkImageSp> images)402 std::vector<de::SharedPtr<Allocation> > createImageMemory (const DeviceInterface&		vkd,
403 														   VkDevice						device,
404 														   Allocator&					allocator,
405 														   const std::vector<VkImageSp>	images)
406 {
407 	std::vector<de::SharedPtr<Allocation> > memory (images.size());
408 
409 	for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
410 		memory[memoryNdx] = safeSharedPtr(createImageMemory(vkd, device, allocator, **images[memoryNdx]).release());
411 
412 	return memory;
413 }
414 
createImageAttachmentViews(const DeviceInterface & vkd,VkDevice device,const std::vector<VkImageSp> & images,VkFormat format,VkImageAspectFlagBits aspect)415 std::vector<VkImageViewSp> createImageAttachmentViews (const DeviceInterface&			vkd,
416 													   VkDevice							device,
417 													   const std::vector<VkImageSp>&	images,
418 													   VkFormat							format,
419 													   VkImageAspectFlagBits			aspect)
420 {
421 	std::vector<VkImageViewSp> views (images.size());
422 
423 	for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
424 		views[imageNdx] = safeSharedPtr(new vk::Unique<VkImageView>(createImageAttachmentView(vkd, device, **images[imageNdx], format, aspect)));
425 
426 	return views;
427 }
428 
createBuffers(const DeviceInterface & vkd,VkDevice device,VkFormat format,deUint32 sampleCount,deUint32 width,deUint32 height)429 std::vector<VkBufferSp> createBuffers (const DeviceInterface&	vkd,
430 									   VkDevice					device,
431 									   VkFormat					format,
432 									   deUint32					sampleCount,
433 									   deUint32					width,
434 									   deUint32					height)
435 {
436 	std::vector<VkBufferSp> buffers (sampleCount);
437 
438 	for (size_t bufferNdx = 0; bufferNdx < buffers.size(); bufferNdx++)
439 		buffers[bufferNdx] = safeSharedPtr(new vk::Unique<VkBuffer>(createBuffer(vkd, device, format, width, height)));
440 
441 	return buffers;
442 }
443 
createBufferMemory(const DeviceInterface & vkd,VkDevice device,Allocator & allocator,const std::vector<VkBufferSp> buffers)444 std::vector<de::SharedPtr<Allocation> > createBufferMemory (const DeviceInterface&			vkd,
445 															VkDevice						device,
446 															Allocator&						allocator,
447 															const std::vector<VkBufferSp>	buffers)
448 {
449 	std::vector<de::SharedPtr<Allocation> > memory (buffers.size());
450 
451 	for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
452 		memory[memoryNdx] = safeSharedPtr(createBufferMemory(vkd, device, allocator, **buffers[memoryNdx]).release());
453 
454 	return memory;
455 }
456 
createRenderPass(const DeviceInterface & vkd,VkDevice device,VkFormat srcFormat,VkFormat dstFormat,deUint32 sampleCount)457 Move<VkRenderPass> createRenderPass (const DeviceInterface&	vkd,
458 									 VkDevice				device,
459 									 VkFormat				srcFormat,
460 									 VkFormat				dstFormat,
461 									 deUint32				sampleCount)
462 {
463 	const VkSampleCountFlagBits				samples						(sampleCountBitFromomSampleCount(sampleCount));
464 	const deUint32							splitSubpassCount			(deDivRoundUp32(sampleCount, MAX_COLOR_ATTACHMENT_COUNT));
465 	const tcu::TextureFormat				format						(mapVkFormat(srcFormat));
466 	const bool								isDepthStencilFormat		(tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order));
467 	vector<VkSubpassDescription>			subpasses;
468 	vector<vector<VkAttachmentReference> >	dstAttachmentRefs			(splitSubpassCount);
469 	vector<vector<VkAttachmentReference> >	dstResolveAttachmentRefs	(splitSubpassCount);
470 	vector<VkAttachmentDescription>			attachments;
471 	vector<VkSubpassDependency>				dependencies;
472 	const VkAttachmentReference				srcAttachmentRef =
473 	{
474 		0u,
475 		isDepthStencilFormat
476 			? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
477 			: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
478 	};
479 	const VkAttachmentReference				srcAttachmentInputRef =
480 	{
481 		0u,
482 		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
483 	};
484 
485 	{
486 		const VkAttachmentDescription srcAttachment =
487 		{
488 			0u,
489 
490 			srcFormat,
491 			samples,
492 
493 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,
494 			VK_ATTACHMENT_STORE_OP_DONT_CARE,
495 
496 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,
497 			VK_ATTACHMENT_STORE_OP_DONT_CARE,
498 
499 			VK_IMAGE_LAYOUT_UNDEFINED,
500 			VK_IMAGE_LAYOUT_GENERAL
501 		};
502 
503 		attachments.push_back(srcAttachment);
504 	}
505 
506 	for (deUint32 splitSubpassIndex = 0; splitSubpassIndex < splitSubpassCount; splitSubpassIndex++)
507 	{
508 		for (deUint32 sampleNdx = 0; sampleNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, sampleCount  - splitSubpassIndex * MAX_COLOR_ATTACHMENT_COUNT); sampleNdx++)
509 		{
510 			// Multisample color attachment
511 			{
512 				const VkAttachmentDescription dstAttachment =
513 				{
514 					0u,
515 
516 					dstFormat,
517 					samples,
518 
519 					VK_ATTACHMENT_LOAD_OP_DONT_CARE,
520 					VK_ATTACHMENT_STORE_OP_DONT_CARE,
521 
522 					VK_ATTACHMENT_LOAD_OP_DONT_CARE,
523 					VK_ATTACHMENT_STORE_OP_DONT_CARE,
524 
525 					VK_IMAGE_LAYOUT_UNDEFINED,
526 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
527 				};
528 				const VkAttachmentReference dstAttachmentRef =
529 				{
530 					(deUint32)attachments.size(),
531 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
532 				};
533 
534 				attachments.push_back(dstAttachment);
535 				dstAttachmentRefs[splitSubpassIndex].push_back(dstAttachmentRef);
536 			}
537 			// Resolve attachment
538 			{
539 				const VkAttachmentDescription dstAttachment =
540 				{
541 					0u,
542 
543 					dstFormat,
544 					VK_SAMPLE_COUNT_1_BIT,
545 
546 					VK_ATTACHMENT_LOAD_OP_DONT_CARE,
547 					VK_ATTACHMENT_STORE_OP_STORE,
548 
549 					VK_ATTACHMENT_LOAD_OP_DONT_CARE,
550 					VK_ATTACHMENT_STORE_OP_STORE,
551 
552 					VK_IMAGE_LAYOUT_UNDEFINED,
553 					VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
554 				};
555 				const VkAttachmentReference dstAttachmentRef =
556 				{
557 					(deUint32)attachments.size(),
558 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
559 				};
560 
561 				attachments.push_back(dstAttachment);
562 				dstResolveAttachmentRefs[splitSubpassIndex].push_back(dstAttachmentRef);
563 			}
564 		}
565 	}
566 
567 	{
568 		{
569 			const VkSubpassDescription	subpass =
570 			{
571 				(VkSubpassDescriptionFlags)0,
572 				VK_PIPELINE_BIND_POINT_GRAPHICS,
573 
574 				0u,
575 				DE_NULL,
576 
577 				isDepthStencilFormat ? 0u : 1u,
578 				isDepthStencilFormat ? DE_NULL : &srcAttachmentRef,
579 				DE_NULL,
580 
581 				isDepthStencilFormat ? &srcAttachmentRef : DE_NULL,
582 				0u,
583 				DE_NULL
584 			};
585 
586 			subpasses.push_back(subpass);
587 		}
588 
589 		for (deUint32 splitSubpassIndex = 0; splitSubpassIndex < splitSubpassCount; splitSubpassIndex++)
590 		{
591 			{
592 				const VkSubpassDescription	subpass =
593 				{
594 					(VkSubpassDescriptionFlags)0,
595 					VK_PIPELINE_BIND_POINT_GRAPHICS,
596 
597 					1u,
598 					&srcAttachmentInputRef,
599 
600 					(deUint32)dstAttachmentRefs[splitSubpassIndex].size(),
601 					&dstAttachmentRefs[splitSubpassIndex][0],
602 					&dstResolveAttachmentRefs[splitSubpassIndex][0],
603 
604 					DE_NULL,
605 					0u,
606 					DE_NULL
607 				};
608 				subpasses.push_back(subpass);
609 			}
610 			{
611 				const VkSubpassDependency		dependency	=
612 				{
613 					0u, splitSubpassIndex + 1,
614 					VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
615 					VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
616 
617 					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
618 					VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
619 
620 					VK_DEPENDENCY_BY_REGION_BIT
621 				};
622 
623 				dependencies.push_back(dependency);
624 			}
625 		};
626 		const VkRenderPassCreateInfo	createInfo	=
627 		{
628 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
629 			DE_NULL,
630 			(VkRenderPassCreateFlags)0u,
631 
632 			(deUint32)attachments.size(),
633 			&attachments[0],
634 
635 			(deUint32)subpasses.size(),
636 			&subpasses[0],
637 
638 			(deUint32)dependencies.size(),
639 			&dependencies[0]
640 		};
641 
642 		return createRenderPass(vkd, device, &createInfo);
643 	}
644 }
645 
createFramebuffer(const DeviceInterface & vkd,VkDevice device,VkRenderPass renderPass,VkImageView srcImageView,const std::vector<VkImageViewSp> & dstMultisampleImageViews,const std::vector<VkImageViewSp> & dstSinglesampleImageViews,deUint32 width,deUint32 height)646 Move<VkFramebuffer> createFramebuffer (const DeviceInterface&				vkd,
647 									   VkDevice								device,
648 									   VkRenderPass							renderPass,
649 									   VkImageView							srcImageView,
650 									   const std::vector<VkImageViewSp>&	dstMultisampleImageViews,
651 									   const std::vector<VkImageViewSp>&	dstSinglesampleImageViews,
652 									   deUint32								width,
653 									   deUint32								height)
654 {
655 	std::vector<VkImageView> attachments;
656 
657 	attachments.reserve(dstMultisampleImageViews.size() + dstSinglesampleImageViews.size() + 1u);
658 
659 	attachments.push_back(srcImageView);
660 
661 	DE_ASSERT(dstMultisampleImageViews.size() == dstSinglesampleImageViews.size());
662 
663 	for (size_t ndx = 0; ndx < dstMultisampleImageViews.size(); ndx++)
664 	{
665 		attachments.push_back(**dstMultisampleImageViews[ndx]);
666 		attachments.push_back(**dstSinglesampleImageViews[ndx]);
667 	}
668 
669 	const VkFramebufferCreateInfo createInfo =
670 	{
671 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
672 		DE_NULL,
673 		0u,
674 
675 		renderPass,
676 		(deUint32)attachments.size(),
677 		&attachments[0],
678 
679 		width,
680 		height,
681 		1u
682 	};
683 
684 	return createFramebuffer(vkd, device, &createInfo);
685 }
686 
createRenderPipelineLayout(const DeviceInterface & vkd,VkDevice device)687 Move<VkPipelineLayout> createRenderPipelineLayout (const DeviceInterface&	vkd,
688 												   VkDevice					device)
689 {
690 	const VkPushConstantRange			pushConstant			=
691 	{
692 		VK_SHADER_STAGE_FRAGMENT_BIT,
693 		0u,
694 		4u
695 	};
696 	const VkPipelineLayoutCreateInfo	createInfo	=
697 	{
698 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
699 		DE_NULL,
700 		(vk::VkPipelineLayoutCreateFlags)0,
701 
702 		0u,
703 		DE_NULL,
704 
705 		1u,
706 		&pushConstant
707 	};
708 
709 	return createPipelineLayout(vkd, device, &createInfo);
710 }
711 
createRenderPipeline(const DeviceInterface & vkd,VkDevice device,VkRenderPass renderPass,VkPipelineLayout pipelineLayout,const vk::ProgramCollection<vk::ProgramBinary> & binaryCollection,deUint32 width,deUint32 height,deUint32 sampleCount)712 Move<VkPipeline> createRenderPipeline (const DeviceInterface&							vkd,
713 									   VkDevice											device,
714 									   VkRenderPass										renderPass,
715 									   VkPipelineLayout									pipelineLayout,
716 									   const vk::ProgramCollection<vk::ProgramBinary>&	binaryCollection,
717 									   deUint32											width,
718 									   deUint32											height,
719 									   deUint32											sampleCount)
720 {
721 	const Unique<VkShaderModule>	vertexShaderModule			(createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
722 	const Unique<VkShaderModule>	fragmentShaderModule		(createShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u));
723 	const VkSpecializationInfo		emptyShaderSpecializations	=
724 	{
725 		0u,
726 		DE_NULL,
727 
728 		0u,
729 		DE_NULL
730 	};
731 	// Disable blending
732 	const VkPipelineColorBlendAttachmentState attachmentBlendState =
733 	{
734 		VK_FALSE,
735 		VK_BLEND_FACTOR_SRC_ALPHA,
736 		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
737 		VK_BLEND_OP_ADD,
738 		VK_BLEND_FACTOR_ONE,
739 		VK_BLEND_FACTOR_ONE,
740 		VK_BLEND_OP_ADD,
741 		VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT
742 	};
743 	const VkPipelineShaderStageCreateInfo shaderStages[2] =
744 	{
745 		{
746 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
747 			DE_NULL,
748 			(VkPipelineShaderStageCreateFlags)0u,
749 			VK_SHADER_STAGE_VERTEX_BIT,
750 			*vertexShaderModule,
751 			"main",
752 			&emptyShaderSpecializations
753 		},
754 		{
755 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
756 			DE_NULL,
757 			(VkPipelineShaderStageCreateFlags)0u,
758 			VK_SHADER_STAGE_FRAGMENT_BIT,
759 			*fragmentShaderModule,
760 			"main",
761 			&emptyShaderSpecializations
762 		}
763 	};
764 	const VkPipelineVertexInputStateCreateInfo vertexInputState =
765 	{
766 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
767 		DE_NULL,
768 		(VkPipelineVertexInputStateCreateFlags)0u,
769 
770 		0u,
771 		DE_NULL,
772 
773 		0u,
774 		DE_NULL
775 	};
776 	const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
777 	{
778 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
779 		DE_NULL,
780 
781 		(VkPipelineInputAssemblyStateCreateFlags)0u,
782 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
783 		VK_FALSE
784 	};
785 	const VkViewport viewport =
786 	{
787 		0.0f,  0.0f,
788 		(float)width, (float)height,
789 
790 		0.0f, 1.0f
791 	};
792 	const VkRect2D scissor =
793 	{
794 		{ 0u, 0u },
795 		{ width, height }
796 	};
797 	const VkPipelineViewportStateCreateInfo viewportState =
798 	{
799 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
800 		DE_NULL,
801 		(VkPipelineViewportStateCreateFlags)0u,
802 
803 		1u,
804 		&viewport,
805 
806 		1u,
807 		&scissor
808 	};
809 	const VkPipelineRasterizationStateCreateInfo rasterState =
810 	{
811 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
812 		DE_NULL,
813 		(VkPipelineRasterizationStateCreateFlags)0u,
814 		VK_TRUE,
815 		VK_FALSE,
816 		VK_POLYGON_MODE_FILL,
817 		VK_CULL_MODE_NONE,
818 		VK_FRONT_FACE_COUNTER_CLOCKWISE,
819 		VK_FALSE,
820 		0.0f,
821 		0.0f,
822 		0.0f,
823 		1.0f
824 	};
825 	const VkPipelineMultisampleStateCreateInfo multisampleState =
826 	{
827 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
828 		DE_NULL,
829 		(VkPipelineMultisampleStateCreateFlags)0u,
830 
831 		sampleCountBitFromomSampleCount(sampleCount),
832 		VK_FALSE,
833 		0.0f,
834 		DE_NULL,
835 		VK_FALSE,
836 		VK_FALSE,
837 	};
838 	const VkPipelineDepthStencilStateCreateInfo depthStencilState =
839 	{
840 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
841 		DE_NULL,
842 		(VkPipelineDepthStencilStateCreateFlags)0u,
843 
844 		VK_TRUE,
845 		VK_TRUE,
846 		VK_COMPARE_OP_ALWAYS,
847 		VK_FALSE,
848 		VK_TRUE,
849 		{
850 			VK_STENCIL_OP_KEEP,
851 			VK_STENCIL_OP_INCREMENT_AND_WRAP,
852 			VK_STENCIL_OP_KEEP,
853 			VK_COMPARE_OP_ALWAYS,
854 			~0u,
855 			~0u,
856 			0xFFu / (sampleCount + 1)
857 		},
858 		{
859 			VK_STENCIL_OP_KEEP,
860 			VK_STENCIL_OP_INCREMENT_AND_WRAP,
861 			VK_STENCIL_OP_KEEP,
862 			VK_COMPARE_OP_ALWAYS,
863 			~0u,
864 			~0u,
865 			0xFFu / (sampleCount + 1)
866 		},
867 
868 		0.0f,
869 		1.0f
870 	};
871 	const VkPipelineColorBlendStateCreateInfo blendState =
872 	{
873 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
874 		DE_NULL,
875 		(VkPipelineColorBlendStateCreateFlags)0u,
876 
877 		VK_FALSE,
878 		VK_LOGIC_OP_COPY,
879 		1u,
880 		&attachmentBlendState,
881 		{ 0.0f, 0.0f, 0.0f, 0.0f }
882 	};
883 	const VkGraphicsPipelineCreateInfo createInfo =
884 	{
885 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
886 		DE_NULL,
887 		(VkPipelineCreateFlags)0u,
888 
889 		2,
890 		shaderStages,
891 
892 		&vertexInputState,
893 		&inputAssemblyState,
894 		DE_NULL,
895 		&viewportState,
896 		&rasterState,
897 		&multisampleState,
898 		&depthStencilState,
899 		&blendState,
900 		(const VkPipelineDynamicStateCreateInfo*)DE_NULL,
901 		pipelineLayout,
902 
903 		renderPass,
904 		0u,
905 		DE_NULL,
906 		0u
907 	};
908 
909 	return createGraphicsPipeline(vkd, device, DE_NULL, &createInfo);
910 }
911 
createSplitDescriptorSetLayout(const DeviceInterface & vkd,VkDevice device,VkFormat vkFormat)912 Move<VkDescriptorSetLayout> createSplitDescriptorSetLayout (const DeviceInterface&	vkd,
913 															VkDevice				device,
914 															VkFormat				vkFormat)
915 {
916 	const tcu::TextureFormat				format		(mapVkFormat(vkFormat));
917 	const bool								hasDepth	(tcu::hasDepthComponent(format.order));
918 	const bool								hasStencil	(tcu::hasStencilComponent(format.order));
919 	const VkDescriptorSetLayoutBinding		bindings[]	=
920 	{
921 		{
922 			0u,
923 			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
924 			1u,
925 			VK_SHADER_STAGE_FRAGMENT_BIT,
926 			DE_NULL
927 		},
928 		{
929 			1u,
930 			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
931 			1u,
932 			VK_SHADER_STAGE_FRAGMENT_BIT,
933 			DE_NULL
934 		}
935 	};
936 	const VkDescriptorSetLayoutCreateInfo	createInfo	=
937 	{
938 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
939 		DE_NULL,
940 		0u,
941 
942 		hasDepth && hasStencil ? 2u : 1u,
943 		bindings
944 	};
945 
946 	return createDescriptorSetLayout(vkd, device, &createInfo);
947 }
948 
createSplitPipelineLayout(const DeviceInterface & vkd,VkDevice device,VkDescriptorSetLayout descriptorSetLayout)949 Move<VkPipelineLayout> createSplitPipelineLayout (const DeviceInterface&	vkd,
950 												  VkDevice					device,
951 												  VkDescriptorSetLayout		descriptorSetLayout)
952 {
953 	const VkPushConstantRange			pushConstant			=
954 	{
955 		VK_SHADER_STAGE_FRAGMENT_BIT,
956 		0u,
957 		4u
958 	};
959 	const VkPipelineLayoutCreateInfo	createInfo	=
960 	{
961 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
962 		DE_NULL,
963 		(vk::VkPipelineLayoutCreateFlags)0,
964 
965 		1u,
966 		&descriptorSetLayout,
967 
968 		1u,
969 		&pushConstant
970 	};
971 
972 	return createPipelineLayout(vkd, device, &createInfo);
973 }
974 
createSplitPipeline(const DeviceInterface & vkd,VkDevice device,VkRenderPass renderPass,deUint32 subpassIndex,VkPipelineLayout pipelineLayout,const vk::ProgramCollection<vk::ProgramBinary> & binaryCollection,deUint32 width,deUint32 height,deUint32 sampleCount)975 Move<VkPipeline> createSplitPipeline (const DeviceInterface&							vkd,
976 									  VkDevice											device,
977 									  VkRenderPass										renderPass,
978 									  deUint32											subpassIndex,
979 									  VkPipelineLayout									pipelineLayout,
980 									  const vk::ProgramCollection<vk::ProgramBinary>&	binaryCollection,
981 									  deUint32											width,
982 									  deUint32											height,
983 									  deUint32											sampleCount)
984 {
985 	const Unique<VkShaderModule>	vertexShaderModule			(createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
986 	const Unique<VkShaderModule>	fragmentShaderModule		(createShaderModule(vkd, device, binaryCollection.get("quad-split-frag"), 0u));
987 	const VkSpecializationInfo		emptyShaderSpecializations	=
988 	{
989 		0u,
990 		DE_NULL,
991 
992 		0u,
993 		DE_NULL
994 	};
995 	// Disable blending
996 	const VkPipelineColorBlendAttachmentState attachmentBlendState =
997 	{
998 		VK_FALSE,
999 		VK_BLEND_FACTOR_SRC_ALPHA,
1000 		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
1001 		VK_BLEND_OP_ADD,
1002 		VK_BLEND_FACTOR_ONE,
1003 		VK_BLEND_FACTOR_ONE,
1004 		VK_BLEND_OP_ADD,
1005 		VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT
1006 	};
1007 	const std::vector<VkPipelineColorBlendAttachmentState> attachmentBlendStates (de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, sampleCount), attachmentBlendState);
1008 	const VkPipelineShaderStageCreateInfo shaderStages[2] =
1009 	{
1010 		{
1011 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1012 			DE_NULL,
1013 			(VkPipelineShaderStageCreateFlags)0u,
1014 			VK_SHADER_STAGE_VERTEX_BIT,
1015 			*vertexShaderModule,
1016 			"main",
1017 			&emptyShaderSpecializations
1018 		},
1019 		{
1020 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1021 			DE_NULL,
1022 			(VkPipelineShaderStageCreateFlags)0u,
1023 			VK_SHADER_STAGE_FRAGMENT_BIT,
1024 			*fragmentShaderModule,
1025 			"main",
1026 			&emptyShaderSpecializations
1027 		}
1028 	};
1029 	const VkPipelineVertexInputStateCreateInfo vertexInputState =
1030 	{
1031 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
1032 		DE_NULL,
1033 		(VkPipelineVertexInputStateCreateFlags)0u,
1034 
1035 		0u,
1036 		DE_NULL,
1037 
1038 		0u,
1039 		DE_NULL
1040 	};
1041 	const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
1042 	{
1043 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
1044 		DE_NULL,
1045 
1046 		(VkPipelineInputAssemblyStateCreateFlags)0u,
1047 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
1048 		VK_FALSE
1049 	};
1050 	const VkViewport viewport =
1051 	{
1052 		0.0f,  0.0f,
1053 		(float)width, (float)height,
1054 
1055 		0.0f, 1.0f
1056 	};
1057 	const VkRect2D scissor =
1058 	{
1059 		{ 0u, 0u },
1060 		{ width, height }
1061 	};
1062 	const VkPipelineViewportStateCreateInfo viewportState =
1063 	{
1064 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
1065 		DE_NULL,
1066 		(VkPipelineViewportStateCreateFlags)0u,
1067 
1068 		1u,
1069 		&viewport,
1070 
1071 		1u,
1072 		&scissor
1073 	};
1074 	const VkPipelineRasterizationStateCreateInfo rasterState =
1075 	{
1076 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
1077 		DE_NULL,
1078 		(VkPipelineRasterizationStateCreateFlags)0u,
1079 		VK_TRUE,
1080 		VK_FALSE,
1081 		VK_POLYGON_MODE_FILL,
1082 		VK_CULL_MODE_NONE,
1083 		VK_FRONT_FACE_COUNTER_CLOCKWISE,
1084 		VK_FALSE,
1085 		0.0f,
1086 		0.0f,
1087 		0.0f,
1088 		1.0f
1089 	};
1090 	const VkPipelineMultisampleStateCreateInfo multisampleState =
1091 	{
1092 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
1093 		DE_NULL,
1094 		(VkPipelineMultisampleStateCreateFlags)0u,
1095 
1096 		sampleCountBitFromomSampleCount(sampleCount),
1097 		VK_FALSE,
1098 		0.0f,
1099 		DE_NULL,
1100 		VK_FALSE,
1101 		VK_FALSE,
1102 	};
1103 	const VkPipelineDepthStencilStateCreateInfo depthStencilState =
1104 	{
1105 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
1106 		DE_NULL,
1107 		(VkPipelineDepthStencilStateCreateFlags)0u,
1108 
1109 		VK_FALSE,
1110 		VK_FALSE,
1111 		VK_COMPARE_OP_ALWAYS,
1112 		VK_FALSE,
1113 		VK_FALSE,
1114 		{
1115 			VK_STENCIL_OP_REPLACE,
1116 			VK_STENCIL_OP_REPLACE,
1117 			VK_STENCIL_OP_REPLACE,
1118 			VK_COMPARE_OP_ALWAYS,
1119 			~0u,
1120 			~0u,
1121 			0x0u
1122 		},
1123 		{
1124 			VK_STENCIL_OP_REPLACE,
1125 			VK_STENCIL_OP_REPLACE,
1126 			VK_STENCIL_OP_REPLACE,
1127 			VK_COMPARE_OP_ALWAYS,
1128 			~0u,
1129 			~0u,
1130 			0x0u
1131 		},
1132 
1133 		0.0f,
1134 		1.0f
1135 	};
1136 	const VkPipelineColorBlendStateCreateInfo blendState =
1137 	{
1138 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
1139 		DE_NULL,
1140 		(VkPipelineColorBlendStateCreateFlags)0u,
1141 
1142 		VK_FALSE,
1143 		VK_LOGIC_OP_COPY,
1144 
1145 		(deUint32)attachmentBlendStates.size(),
1146 		&attachmentBlendStates[0],
1147 
1148 		{ 0.0f, 0.0f, 0.0f, 0.0f }
1149 	};
1150 	const VkGraphicsPipelineCreateInfo createInfo =
1151 	{
1152 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
1153 		DE_NULL,
1154 		(VkPipelineCreateFlags)0u,
1155 
1156 		2,
1157 		shaderStages,
1158 
1159 		&vertexInputState,
1160 		&inputAssemblyState,
1161 		DE_NULL,
1162 		&viewportState,
1163 		&rasterState,
1164 		&multisampleState,
1165 		&depthStencilState,
1166 		&blendState,
1167 		(const VkPipelineDynamicStateCreateInfo*)DE_NULL,
1168 		pipelineLayout,
1169 
1170 		renderPass,
1171 		subpassIndex,
1172 		DE_NULL,
1173 		0u
1174 	};
1175 
1176 	return createGraphicsPipeline(vkd, device, DE_NULL, &createInfo);
1177 }
1178 
createSplitPipelines(const DeviceInterface & vkd,VkDevice device,VkRenderPass renderPass,VkPipelineLayout pipelineLayout,const vk::ProgramCollection<vk::ProgramBinary> & binaryCollection,deUint32 width,deUint32 height,deUint32 sampleCount)1179 vector<VkPipeline> createSplitPipelines (const DeviceInterface&								vkd,
1180 										 VkDevice											device,
1181 										 VkRenderPass										renderPass,
1182 										 VkPipelineLayout									pipelineLayout,
1183 										 const vk::ProgramCollection<vk::ProgramBinary>&	binaryCollection,
1184 										 deUint32											width,
1185 										 deUint32											height,
1186 										 deUint32											sampleCount)
1187 {
1188 	vector<VkPipeline> pipelines (deDivRoundUp32(sampleCount, MAX_COLOR_ATTACHMENT_COUNT), (VkPipeline)0u);
1189 
1190 	try
1191 	{
1192 		for (size_t ndx = 0; ndx < pipelines.size(); ndx++)
1193 			pipelines[ndx] = createSplitPipeline(vkd, device, renderPass, (deUint32)(ndx + 1), pipelineLayout, binaryCollection, width, height, sampleCount).disown();
1194 	}
1195 	catch (...)
1196 	{
1197 		for (size_t ndx = 0; ndx < pipelines.size(); ndx++)
1198 			vkd.destroyPipeline(device, pipelines[ndx], DE_NULL);
1199 
1200 		throw;
1201 	}
1202 
1203 	return pipelines;
1204 }
1205 
createSplitDescriptorPool(const DeviceInterface & vkd,VkDevice device)1206 Move<VkDescriptorPool> createSplitDescriptorPool (const DeviceInterface&	vkd,
1207 												  VkDevice					device)
1208 {
1209 	const VkDescriptorPoolSize			size		=
1210 	{
1211 		VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 2u
1212 	};
1213 	const VkDescriptorPoolCreateInfo	createInfo	=
1214 	{
1215 		VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
1216 		DE_NULL,
1217 		VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
1218 
1219 
1220 		2u,
1221 		1u,
1222 		&size
1223 	};
1224 
1225 	return createDescriptorPool(vkd, device, &createInfo);
1226 }
1227 
createSplitDescriptorSet(const DeviceInterface & vkd,VkDevice device,VkDescriptorPool pool,VkDescriptorSetLayout layout,VkImageView primaryImageView,VkImageView secondaryImageView)1228 Move<VkDescriptorSet> createSplitDescriptorSet (const DeviceInterface&	vkd,
1229 												VkDevice				device,
1230 												VkDescriptorPool		pool,
1231 												VkDescriptorSetLayout	layout,
1232 												VkImageView				primaryImageView,
1233 												VkImageView				secondaryImageView)
1234 {
1235 	const VkDescriptorSetAllocateInfo	allocateInfo	=
1236 	{
1237 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1238 		DE_NULL,
1239 
1240 		pool,
1241 		1u,
1242 		&layout
1243 	};
1244 	Move<VkDescriptorSet> set (allocateDescriptorSet(vkd, device, &allocateInfo));
1245 
1246 	{
1247 		const VkDescriptorImageInfo	imageInfos[]	=
1248 		{
1249 			{
1250 				(VkSampler)0u,
1251 				primaryImageView,
1252 				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
1253 			},
1254 			{
1255 				(VkSampler)0u,
1256 				secondaryImageView,
1257 				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
1258 			}
1259 		};
1260 		const VkWriteDescriptorSet	writes[]	=
1261 		{
1262 			{
1263 				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1264 				DE_NULL,
1265 
1266 				*set,
1267 				0u,
1268 				0u,
1269 				1u,
1270 				VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
1271 				&imageInfos[0],
1272 				DE_NULL,
1273 				DE_NULL
1274 			},
1275 			{
1276 				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1277 				DE_NULL,
1278 
1279 				*set,
1280 				1u,
1281 				0u,
1282 				1u,
1283 				VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
1284 				&imageInfos[1],
1285 				DE_NULL,
1286 				DE_NULL
1287 			}
1288 		};
1289 		const deUint32	count	= secondaryImageView != (VkImageView)0
1290 								? 2u
1291 								: 1u;
1292 
1293 		vkd.updateDescriptorSets(device, count, writes, 0u, DE_NULL);
1294 	}
1295 	return set;
1296 }
1297 
1298 struct TestConfig
1299 {
TestConfigvkt::__anon7e6592500111::TestConfig1300 				TestConfig		(VkFormat	format_,
1301 								 deUint32	sampleCount_)
1302 		: format		(format_)
1303 		, sampleCount	(sampleCount_)
1304 	{
1305 	}
1306 
1307 	VkFormat	format;
1308 	deUint32	sampleCount;
1309 };
1310 
getSrcImageUsage(VkFormat vkFormat)1311 VkImageUsageFlags getSrcImageUsage (VkFormat vkFormat)
1312 {
1313 	const tcu::TextureFormat	format		(mapVkFormat(vkFormat));
1314 	const bool					hasDepth	(tcu::hasDepthComponent(format.order));
1315 	const bool					hasStencil	(tcu::hasStencilComponent(format.order));
1316 
1317 	if (hasDepth || hasStencil)
1318 		return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
1319 	else
1320 		return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
1321 }
1322 
getDstFormat(VkFormat vkFormat)1323 VkFormat getDstFormat (VkFormat vkFormat)
1324 {
1325 	const tcu::TextureFormat	format		(mapVkFormat(vkFormat));
1326 	const bool					hasDepth	(tcu::hasDepthComponent(format.order));
1327 	const bool					hasStencil	(tcu::hasStencilComponent(format.order));
1328 
1329 	if (hasDepth && hasStencil)
1330 		return VK_FORMAT_R32G32_SFLOAT;
1331 	else if (hasDepth || hasStencil)
1332 		return VK_FORMAT_R32_SFLOAT;
1333 	else
1334 		return vkFormat;
1335 }
1336 
1337 
1338 class MultisampleRenderPassTestInstance : public TestInstance
1339 {
1340 public:
1341 					MultisampleRenderPassTestInstance	(Context& context, TestConfig config);
1342 					~MultisampleRenderPassTestInstance	(void);
1343 
1344 	tcu::TestStatus	iterate								(void);
1345 
1346 private:
1347 	const VkFormat									m_srcFormat;
1348 	const VkFormat									m_dstFormat;
1349 	const deUint32									m_sampleCount;
1350 	const deUint32									m_width;
1351 	const deUint32									m_height;
1352 
1353 	const VkImageAspectFlags						m_srcImageAspect;
1354 	const VkImageUsageFlags							m_srcImageUsage;
1355 	const Unique<VkImage>							m_srcImage;
1356 	const de::UniquePtr<Allocation>					m_srcImageMemory;
1357 	const Unique<VkImageView>						m_srcImageView;
1358 	const Unique<VkImageView>						m_srcPrimaryInputImageView;
1359 	const Unique<VkImageView>						m_srcSecondaryInputImageView;
1360 
1361 	const std::vector<VkImageSp>					m_dstMultisampleImages;
1362 	const std::vector<de::SharedPtr<Allocation> >	m_dstMultisampleImageMemory;
1363 	const std::vector<VkImageViewSp>				m_dstMultisampleImageViews;
1364 
1365 	const std::vector<VkImageSp>					m_dstSinglesampleImages;
1366 	const std::vector<de::SharedPtr<Allocation> >	m_dstSinglesampleImageMemory;
1367 	const std::vector<VkImageViewSp>				m_dstSinglesampleImageViews;
1368 
1369 	const std::vector<VkBufferSp>					m_dstBuffers;
1370 	const std::vector<de::SharedPtr<Allocation> >	m_dstBufferMemory;
1371 
1372 	const Unique<VkRenderPass>						m_renderPass;
1373 	const Unique<VkFramebuffer>						m_framebuffer;
1374 
1375 	const Unique<VkPipelineLayout>					m_renderPipelineLayout;
1376 	const Unique<VkPipeline>						m_renderPipeline;
1377 
1378 	const Unique<VkDescriptorSetLayout>				m_splitDescriptorSetLayout;
1379 	const Unique<VkPipelineLayout>					m_splitPipelineLayout;
1380 	const vector<VkPipeline>						m_splitPipelines;
1381 	const Unique<VkDescriptorPool>					m_splitDescriptorPool;
1382 	const Unique<VkDescriptorSet>					m_splitDescriptorSet;
1383 
1384 	const Unique<VkCommandPool>						m_commandPool;
1385 	tcu::ResultCollector							m_resultCollector;
1386 };
1387 
MultisampleRenderPassTestInstance(Context & context,TestConfig config)1388 MultisampleRenderPassTestInstance::MultisampleRenderPassTestInstance (Context& context, TestConfig config)
1389 	: TestInstance					(context)
1390 	, m_srcFormat					(config.format)
1391 	, m_dstFormat					(getDstFormat(config.format))
1392 	, m_sampleCount					(config.sampleCount)
1393 	, m_width						(32u)
1394 	, m_height						(32u)
1395 
1396 	, m_srcImageAspect				(getImageAspectFlags(m_srcFormat))
1397 	, m_srcImageUsage				(getSrcImageUsage(m_srcFormat))
1398 	, m_srcImage					(createImage(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_srcFormat, sampleCountBitFromomSampleCount(m_sampleCount), m_srcImageUsage, m_width, m_height))
1399 	, m_srcImageMemory				(createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), *m_srcImage))
1400 	, m_srcImageView				(createImageAttachmentView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect))
1401 	, m_srcPrimaryInputImageView	(createSrcPrimaryInputImageView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect))
1402 	, m_srcSecondaryInputImageView	(createSrcSecondaryInputImageView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect))
1403 
1404 	, m_dstMultisampleImages		(createMultisampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height))
1405 	, m_dstMultisampleImageMemory	(createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstMultisampleImages))
1406 	, m_dstMultisampleImageViews	(createImageAttachmentViews(context.getDeviceInterface(), context.getDevice(), m_dstMultisampleImages, m_dstFormat, VK_IMAGE_ASPECT_COLOR_BIT))
1407 
1408 	, m_dstSinglesampleImages		(createSingleSampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height))
1409 	, m_dstSinglesampleImageMemory	(createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstSinglesampleImages))
1410 	, m_dstSinglesampleImageViews	(createImageAttachmentViews(context.getDeviceInterface(), context.getDevice(), m_dstSinglesampleImages, m_dstFormat, VK_IMAGE_ASPECT_COLOR_BIT))
1411 
1412 	, m_dstBuffers					(createBuffers(context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height))
1413 	, m_dstBufferMemory				(createBufferMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstBuffers))
1414 
1415 	, m_renderPass					(createRenderPass(context.getDeviceInterface(), context.getDevice(), m_srcFormat, m_dstFormat, m_sampleCount))
1416 	, m_framebuffer					(createFramebuffer(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_srcImageView, m_dstMultisampleImageViews, m_dstSinglesampleImageViews, m_width, m_height))
1417 
1418 	, m_renderPipelineLayout		(createRenderPipelineLayout(context.getDeviceInterface(), context.getDevice()))
1419 	, m_renderPipeline				(createRenderPipeline(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_renderPipelineLayout, context.getBinaryCollection(), m_width, m_height, m_sampleCount))
1420 
1421 	, m_splitDescriptorSetLayout	(createSplitDescriptorSetLayout(context.getDeviceInterface(), context.getDevice(), m_srcFormat))
1422 	, m_splitPipelineLayout			(createSplitPipelineLayout(context.getDeviceInterface(), context.getDevice(), *m_splitDescriptorSetLayout))
1423 	, m_splitPipelines				(createSplitPipelines(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_splitPipelineLayout, context.getBinaryCollection(), m_width, m_height, m_sampleCount))
1424 	, m_splitDescriptorPool			(createSplitDescriptorPool(context.getDeviceInterface(), context.getDevice()))
1425 	, m_splitDescriptorSet			(createSplitDescriptorSet(context.getDeviceInterface(), context.getDevice(), *m_splitDescriptorPool, *m_splitDescriptorSetLayout, *m_srcPrimaryInputImageView, *m_srcSecondaryInputImageView))
1426 	, m_commandPool					(createCommandPool(context.getDeviceInterface(), context.getDevice(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
1427 {
1428 }
1429 
~MultisampleRenderPassTestInstance(void)1430 MultisampleRenderPassTestInstance::~MultisampleRenderPassTestInstance (void)
1431 {
1432 }
1433 
iterate(void)1434 tcu::TestStatus MultisampleRenderPassTestInstance::iterate (void)
1435 {
1436 	const DeviceInterface&			vkd				(m_context.getDeviceInterface());
1437 	const VkDevice					device			(m_context.getDevice());
1438 	const Unique<VkCommandBuffer>	commandBuffer	(allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1439 
1440 	{
1441 		const VkCommandBufferBeginInfo beginInfo =
1442 		{
1443 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
1444 			DE_NULL,
1445 
1446 			VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
1447 			DE_NULL
1448 		};
1449 
1450 		VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &beginInfo));
1451 	}
1452 
1453 	{
1454 		const VkRenderPassBeginInfo beginInfo =
1455 		{
1456 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
1457 			DE_NULL,
1458 
1459 			*m_renderPass,
1460 			*m_framebuffer,
1461 
1462 			{
1463 				{ 0u, 0u },
1464 				{ m_width, m_height }
1465 			},
1466 
1467 			0u,
1468 			DE_NULL
1469 		};
1470 		vkd.cmdBeginRenderPass(*commandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE);
1471 	}
1472 
1473 	vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
1474 
1475 	for (deUint32 sampleNdx = 0; sampleNdx < m_sampleCount; sampleNdx++)
1476 	{
1477 		vkd.cmdPushConstants(*commandBuffer, *m_renderPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(sampleNdx), &sampleNdx);
1478 		vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
1479 	}
1480 
1481 	for (deUint32 splitPipelineNdx = 0; splitPipelineNdx < m_splitPipelines.size(); splitPipelineNdx++)
1482 	{
1483 		vkd.cmdNextSubpass(*commandBuffer, VK_SUBPASS_CONTENTS_INLINE);
1484 
1485 		vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_splitPipelines[splitPipelineNdx]);
1486 		vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_splitPipelineLayout, 0u, 1u,  &*m_splitDescriptorSet, 0u, DE_NULL);
1487 		vkd.cmdPushConstants(*commandBuffer, *m_splitPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(splitPipelineNdx), &splitPipelineNdx);
1488 		vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
1489 	}
1490 
1491 	vkd.cmdEndRenderPass(*commandBuffer);
1492 
1493 	// Memory barriers between rendering and copies
1494 	{
1495 		std::vector<VkImageMemoryBarrier> barriers;
1496 
1497 		for (size_t dstNdx = 0; dstNdx < m_dstSinglesampleImages.size(); dstNdx++)
1498 		{
1499 			const VkImageMemoryBarrier barrier =
1500 			{
1501 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
1502 				DE_NULL,
1503 
1504 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1505 				VK_ACCESS_TRANSFER_READ_BIT,
1506 
1507 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1508 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1509 
1510 				VK_QUEUE_FAMILY_IGNORED,
1511 				VK_QUEUE_FAMILY_IGNORED,
1512 
1513 				**m_dstSinglesampleImages[dstNdx],
1514 				{
1515 					VK_IMAGE_ASPECT_COLOR_BIT,
1516 					0u,
1517 					1u,
1518 					0u,
1519 					1u
1520 				}
1521 			};
1522 
1523 			barriers.push_back(barrier);
1524 		}
1525 
1526 		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]);
1527 	}
1528 
1529 	// Copy image memory to buffers
1530 	for (size_t dstNdx = 0; dstNdx < m_dstSinglesampleImages.size(); dstNdx++)
1531 	{
1532 		const VkBufferImageCopy region =
1533 		{
1534 			0u,
1535 			0u,
1536 			0u,
1537 			{
1538 				VK_IMAGE_ASPECT_COLOR_BIT,
1539 				0u,
1540 				0u,
1541 				1u,
1542 			},
1543 			{ 0u, 0u, 0u },
1544 			{ m_width, m_height, 1u }
1545 		};
1546 
1547 		vkd.cmdCopyImageToBuffer(*commandBuffer, **m_dstSinglesampleImages[dstNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_dstBuffers[dstNdx], 1u, &region);
1548 	}
1549 
1550 	// Memory barriers between copies and host access
1551 	{
1552 		std::vector<VkBufferMemoryBarrier> barriers;
1553 
1554 		for (size_t dstNdx = 0; dstNdx < m_dstBuffers.size(); dstNdx++)
1555 		{
1556 			const VkBufferMemoryBarrier barrier =
1557 			{
1558 				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
1559 				DE_NULL,
1560 
1561 				VK_ACCESS_TRANSFER_WRITE_BIT,
1562 				VK_ACCESS_HOST_READ_BIT,
1563 
1564 				VK_QUEUE_FAMILY_IGNORED,
1565 				VK_QUEUE_FAMILY_IGNORED,
1566 
1567 				**m_dstBuffers[dstNdx],
1568 				0u,
1569 				VK_WHOLE_SIZE
1570 			};
1571 
1572 			barriers.push_back(barrier);
1573 		}
1574 
1575 		vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0], 0u, DE_NULL);
1576 	}
1577 
1578 	VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
1579 
1580 	{
1581 		const VkSubmitInfo submitInfo =
1582 		{
1583 			VK_STRUCTURE_TYPE_SUBMIT_INFO,
1584 			DE_NULL,
1585 
1586 			0u,
1587 			DE_NULL,
1588 			DE_NULL,
1589 
1590 			1u,
1591 			&*commandBuffer,
1592 
1593 			0u,
1594 			DE_NULL
1595 		};
1596 
1597 		VK_CHECK(vkd.queueSubmit(m_context.getUniversalQueue(), 1u, &submitInfo, (VkFence)0u));
1598 
1599 		VK_CHECK(vkd.queueWaitIdle(m_context.getUniversalQueue()));
1600 	}
1601 
1602 	{
1603 		const tcu::TextureFormat		format			(mapVkFormat(m_dstFormat));
1604 		const tcu::TextureFormat		srcFormat		(mapVkFormat(m_srcFormat));
1605 		const bool						hasDepth		(tcu::hasDepthComponent(srcFormat.order));
1606 		const bool						hasStencil		(tcu::hasStencilComponent(srcFormat.order));
1607 
1608 		for (deUint32 sampleNdx = 0; sampleNdx < m_sampleCount; sampleNdx++)
1609 		{
1610 			const std::string					name		("Sample" + de::toString(sampleNdx));
1611 			const void* const					ptr			(m_dstBufferMemory[sampleNdx]->getHostPtr());
1612 			const tcu::ConstPixelBufferAccess	access		(format, m_width, m_height, 1, ptr);
1613 			tcu::TextureLevel					reference	(format, m_width, m_height);
1614 
1615 			if (hasDepth || hasStencil)
1616 			{
1617 				if (hasDepth)
1618 				{
1619 					for (deUint32 y = 0; y < m_height; y++)
1620 					for (deUint32 x = 0; x < m_width; x++)
1621 					{
1622 						const deUint32	x1				= x ^ sampleNdx;
1623 						const deUint32	y1				= y ^ sampleNdx;
1624 						const float		range			= 1.0f;
1625 						float			depth			= 0.0f;
1626 						deUint32		divider			= 2;
1627 
1628 						// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1629 						for (size_t bitNdx = 0; bitNdx < 10; bitNdx++)
1630 						{
1631 							depth += (range / (float)divider)
1632 									* (((bitNdx % 2 == 0 ? x1 : y1) & (0x1u << (bitNdx / 2u))) == 0u ? 0u : 1u);
1633 							divider *= 2;
1634 						}
1635 
1636 						reference.getAccess().setPixel(Vec4(depth, 0.0f, 0.0f, 0.0f), x, y);
1637 					}
1638 				}
1639 				if (hasStencil)
1640 				{
1641 					for (deUint32 y = 0; y < m_height; y++)
1642 					for (deUint32 x = 0; x < m_width; x++)
1643 					{
1644 						const deUint32	stencil	= sampleNdx + 1u;
1645 
1646 						if (hasDepth)
1647 						{
1648 							const Vec4 src (reference.getAccess().getPixel(x, y));
1649 
1650 							reference.getAccess().setPixel(Vec4(src.x(), (float)stencil, 0.0f, 0.0f), x, y);
1651 						}
1652 						else
1653 							reference.getAccess().setPixel(Vec4((float)stencil, 0.0f, 0.0f, 0.0f), x, y);
1654 					}
1655 				}
1656 				{
1657 					const Vec4 threshold (hasDepth ? (1.0f / 1024.0f) : 0.0f, 0.0f, 0.0f, 0.0f);
1658 
1659 					if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
1660 						m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1661 				}
1662 			}
1663 			else
1664 			{
1665 				const tcu::TextureChannelClass	channelClass	(tcu::getTextureChannelClass(format.type));
1666 
1667 				switch (channelClass)
1668 				{
1669 					case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1670 					{
1671 						const UVec4		bits			(tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1672 						const UVec4		minValue		(0);
1673 						const UVec4		range			(UVec4(1u) << tcu::min(bits, UVec4(31)));
1674 						const int		componentCount	(tcu::getNumUsedChannels(format.order));
1675 						const deUint32	bitSize			(bits[0] + bits[1] + bits[2] + bits[3]);
1676 
1677 						for (deUint32 y = 0; y < m_height; y++)
1678 						for (deUint32 x = 0; x < m_width; x++)
1679 						{
1680 							const deUint32	x1				= x ^ sampleNdx;
1681 							const deUint32	y1				= y ^ sampleNdx;
1682 							UVec4			color			(minValue);
1683 							deUint32		dstBitsUsed[4]	= { 0u, 0u, 0u, 0u };
1684 							deUint32		nextSrcBit		= 0;
1685 							deUint32		divider			= 2;
1686 
1687 							// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1688 							while (nextSrcBit < de::min(bitSize, 10u))
1689 							{
1690 								for (int compNdx = 0; compNdx < componentCount; compNdx++)
1691 								{
1692 									if (dstBitsUsed[compNdx] > bits[compNdx])
1693 										continue;
1694 
1695 									color[compNdx] += (range[compNdx] / divider)
1696 													* (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
1697 
1698 									nextSrcBit++;
1699 									dstBitsUsed[compNdx]++;
1700 								}
1701 
1702 								divider *= 2;
1703 							}
1704 
1705 							reference.getAccess().setPixel(color, x, y);
1706 						}
1707 
1708 						if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, UVec4(0u), tcu::COMPARE_LOG_ON_ERROR))
1709 							m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1710 
1711 						break;
1712 					}
1713 
1714 					case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1715 					{
1716 						const UVec4		bits			(tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1717 						const IVec4		minValue		(0);
1718 						const IVec4		range			((UVec4(1u) << tcu::min(bits, UVec4(30))).cast<deInt32>());
1719 						const int		componentCount	(tcu::getNumUsedChannels(format.order));
1720 						const deUint32	bitSize			(bits[0] + bits[1] + bits[2] + bits[3]);
1721 
1722 						for (deUint32 y = 0; y < m_height; y++)
1723 						for (deUint32 x = 0; x < m_width; x++)
1724 						{
1725 							const deUint32	x1				= x ^ sampleNdx;
1726 							const deUint32	y1				= y ^ sampleNdx;
1727 							IVec4			color			(minValue);
1728 							deUint32		dstBitsUsed[4]	= { 0u, 0u, 0u, 0u };
1729 							deUint32		nextSrcBit		= 0;
1730 							deUint32		divider			= 2;
1731 
1732 							// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1733 							while (nextSrcBit < de::min(bitSize, 10u))
1734 							{
1735 								for (int compNdx = 0; compNdx < componentCount; compNdx++)
1736 								{
1737 									if (dstBitsUsed[compNdx] > bits[compNdx])
1738 										continue;
1739 
1740 									color[compNdx] += (range[compNdx] / divider)
1741 													* (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
1742 
1743 									nextSrcBit++;
1744 									dstBitsUsed[compNdx]++;
1745 								}
1746 
1747 								divider *= 2;
1748 							}
1749 
1750 							reference.getAccess().setPixel(color, x, y);
1751 						}
1752 
1753 						if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, UVec4(0u), tcu::COMPARE_LOG_ON_ERROR))
1754 							m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1755 
1756 						break;
1757 					}
1758 
1759 					case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1760 					case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1761 					case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1762 					{
1763 						const tcu::TextureFormatInfo	info			(tcu::getTextureFormatInfo(format));
1764 						const UVec4						bits			(tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1765 						const Vec4						minLimit		(-65536.0);
1766 						const Vec4						maxLimit		(65536.0);
1767 						const Vec4						minValue		(tcu::max(info.valueMin, minLimit));
1768 						const Vec4						range			(tcu::min(info.valueMax, maxLimit) - minValue);
1769 						const int						componentCount	(tcu::getNumUsedChannels(format.order));
1770 						const deUint32					bitSize			(bits[0] + bits[1] + bits[2] + bits[3]);
1771 
1772 						for (deUint32 y = 0; y < m_height; y++)
1773 						for (deUint32 x = 0; x < m_width; x++)
1774 						{
1775 							const deUint32	x1				= x ^ sampleNdx;
1776 							const deUint32	y1				= y ^ sampleNdx;
1777 							Vec4			color			(minValue);
1778 							deUint32		dstBitsUsed[4]	= { 0u, 0u, 0u, 0u };
1779 							deUint32		nextSrcBit		= 0;
1780 							deUint32		divider			= 2;
1781 
1782 							// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1783 							while (nextSrcBit < de::min(bitSize, 10u))
1784 							{
1785 								for (int compNdx = 0; compNdx < componentCount; compNdx++)
1786 								{
1787 									if (dstBitsUsed[compNdx] > bits[compNdx])
1788 										continue;
1789 
1790 									color[compNdx] += (range[compNdx] / (float)divider)
1791 													* (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
1792 
1793 									nextSrcBit++;
1794 									dstBitsUsed[compNdx]++;
1795 								}
1796 
1797 								divider *= 2;
1798 							}
1799 
1800 							if (tcu::isSRGB(format))
1801 								reference.getAccess().setPixel(tcu::linearToSRGB(color), x, y);
1802 							else
1803 								reference.getAccess().setPixel(color, x, y);
1804 						}
1805 
1806 						if (channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
1807 						{
1808 							// Convert target format ulps to float ulps and allow 64ulp differences
1809 							const UVec4 threshold (64u * (UVec4(1u) << (UVec4(23) - tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>())));
1810 
1811 							if (!tcu::floatUlpThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
1812 								m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1813 						}
1814 						else
1815 						{
1816 							// Allow error of 4 times the minimum presentable difference
1817 							const Vec4 threshold (4.0f * 1.0f / ((UVec4(1u) << tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>()) - 1u).cast<float>());
1818 
1819 							if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
1820 								m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1821 						}
1822 
1823 						break;
1824 					}
1825 
1826 					default:
1827 						DE_FATAL("Unknown channel class");
1828 				}
1829 			}
1830 		}
1831 	}
1832 
1833 	return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1834 }
1835 
1836 struct Programs
1837 {
initvkt::__anon7e6592500111::Programs1838 	void init (vk::SourceCollections& dst, TestConfig config) const
1839 	{
1840 		const tcu::TextureFormat		format			(mapVkFormat(config.format));
1841 		const tcu::TextureChannelClass	channelClass	(tcu::getTextureChannelClass(format.type));
1842 
1843 		dst.glslSources.add("quad-vert") << glu::VertexSource(
1844 			"#version 450\n"
1845 			"out gl_PerVertex {\n"
1846 			"\tvec4 gl_Position;\n"
1847 			"};\n"
1848 			"highp float;\n"
1849 			"void main (void) {\n"
1850 			"\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
1851 			"\t                   ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
1852 			"}\n");
1853 
1854 		if (tcu::hasDepthComponent(format.order))
1855 		{
1856 			const Vec4			minValue		(0.0f);
1857 			const Vec4			range			(1.0f);
1858 			std::ostringstream	fragmentShader;
1859 
1860 			fragmentShader <<
1861 				"#version 450\n"
1862 				"layout(push_constant) uniform PushConstant {\n"
1863 				"\thighp uint sampleIndex;\n"
1864 				"} pushConstants;\n"
1865 				"void main (void)\n"
1866 				"{\n"
1867 				"\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
1868 				"\tgl_SampleMask[0] = int((~0x0u) << sampleIndex);\n"
1869 				"\thighp float depth;\n"
1870 				"\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
1871 				"\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
1872 
1873 			fragmentShader << "\tdepth = "  << minValue[0] << ";\n";
1874 
1875 			{
1876 				deUint32 divider = 2;
1877 
1878 				// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1879 				for (size_t bitNdx = 0; bitNdx < 10; bitNdx++)
1880 				{
1881 					fragmentShader <<
1882 							"\tdepth += " << (range[0] / (float)divider)
1883 							<< " * float(bitfieldExtract(" << (bitNdx % 2 == 0 ? "x" : "y") << ", " << (bitNdx / 2) << ", 1));\n";
1884 
1885 					divider *= 2;
1886 				}
1887 			}
1888 
1889 			fragmentShader <<
1890 				"\tgl_FragDepth = depth;\n"
1891 				"}\n";
1892 
1893 			dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
1894 		}
1895 		else if (tcu::hasStencilComponent(format.order))
1896 		{
1897 			dst.glslSources.add("quad-frag") << glu::FragmentSource(
1898 				"#version 450\n"
1899 				"layout(push_constant) uniform PushConstant {\n"
1900 				"\thighp uint sampleIndex;\n"
1901 				"} pushConstants;\n"
1902 				"void main (void)\n"
1903 				"{\n"
1904 				"\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
1905 				"\tgl_SampleMask[0] = int((~0x0u) << sampleIndex);\n"
1906 				"}\n");
1907 		}
1908 		else
1909 		{
1910 			switch (channelClass)
1911 			{
1912 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1913 				{
1914 					const UVec4	bits		(tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1915 					const UVec4 minValue	(0);
1916 					const UVec4 range		(UVec4(1u) << tcu::min(bits, UVec4(31)));
1917 					std::ostringstream		fragmentShader;
1918 
1919 					fragmentShader <<
1920 						"#version 450\n"
1921 						"layout(location = 0) out highp uvec4 o_color;\n"
1922 						"layout(push_constant) uniform PushConstant {\n"
1923 						"\thighp uint sampleIndex;\n"
1924 						"} pushConstants;\n"
1925 						"void main (void)\n"
1926 						"{\n"
1927 						"\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
1928 						"\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
1929 						"\thighp uint color[4];\n"
1930 						"\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
1931 						"\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
1932 
1933 					for (int ndx = 0; ndx < 4; ndx++)
1934 						fragmentShader << "\tcolor[" << ndx << "] = "  << minValue[ndx] << ";\n";
1935 
1936 					{
1937 						const int		componentCount	= tcu::getNumUsedChannels(format.order);
1938 						const deUint32	bitSize			(bits[0] + bits[1] + bits[2] + bits[3]);
1939 						deUint32		dstBitsUsed[4]	= { 0u, 0u, 0u, 0u };
1940 						deUint32		nextSrcBit		= 0;
1941 						deUint32		divider			= 2;
1942 
1943 						// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1944 						while (nextSrcBit < de::min(bitSize, 10u))
1945 						{
1946 							for (int compNdx = 0; compNdx < componentCount; compNdx++)
1947 							{
1948 								if (dstBitsUsed[compNdx] > bits[compNdx])
1949 									continue;
1950 
1951 								fragmentShader <<
1952 										"\tcolor[" << compNdx << "] += " << (range[compNdx] / divider)
1953 										<< " * bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1);\n";
1954 
1955 								nextSrcBit++;
1956 								dstBitsUsed[compNdx]++;
1957 							}
1958 
1959 							divider *= 2;
1960 						}
1961 					}
1962 
1963 					fragmentShader <<
1964 						"\to_color = uvec4(color[0], color[1], color[2], color[3]);\n"
1965 						"}\n";
1966 
1967 					dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
1968 					break;
1969 				}
1970 
1971 				case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1972 				{
1973 					const UVec4	bits		(tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1974 					const IVec4 minValue	(0);
1975 					const IVec4 range		((UVec4(1u) << tcu::min(bits, UVec4(30))).cast<deInt32>());
1976 					std::ostringstream		fragmentShader;
1977 
1978 					fragmentShader <<
1979 						"#version 450\n"
1980 						"layout(location = 0) out highp ivec4 o_color;\n"
1981 						"layout(push_constant) uniform PushConstant {\n"
1982 						"\thighp uint sampleIndex;\n"
1983 						"} pushConstants;\n"
1984 						"void main (void)\n"
1985 						"{\n"
1986 						"\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
1987 						"\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
1988 						"\thighp int color[4];\n"
1989 						"\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
1990 						"\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
1991 
1992 					for (int ndx = 0; ndx < 4; ndx++)
1993 						fragmentShader << "\tcolor[" << ndx << "] = "  << minValue[ndx] << ";\n";
1994 
1995 					{
1996 						const int		componentCount	= tcu::getNumUsedChannels(format.order);
1997 						const deUint32	bitSize			(bits[0] + bits[1] + bits[2] + bits[3]);
1998 						deUint32		dstBitsUsed[4]	= { 0u, 0u, 0u, 0u };
1999 						deUint32		nextSrcBit		= 0;
2000 						deUint32		divider			= 2;
2001 
2002 						// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
2003 						while (nextSrcBit < de::min(bitSize, 10u))
2004 						{
2005 							for (int compNdx = 0; compNdx < componentCount; compNdx++)
2006 							{
2007 								if (dstBitsUsed[compNdx] > bits[compNdx])
2008 									continue;
2009 
2010 								fragmentShader <<
2011 										"\tcolor[" << compNdx << "] += " << (range[compNdx] / divider)
2012 										<< " * int(bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1));\n";
2013 
2014 								nextSrcBit++;
2015 								dstBitsUsed[compNdx]++;
2016 							}
2017 
2018 							divider *= 2;
2019 						}
2020 					}
2021 
2022 					fragmentShader <<
2023 						"\to_color = ivec4(color[0], color[1], color[2], color[3]);\n"
2024 						"}\n";
2025 
2026 					dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
2027 					break;
2028 				}
2029 
2030 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2031 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2032 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2033 				{
2034 					const tcu::TextureFormatInfo	info			(tcu::getTextureFormatInfo(format));
2035 					const UVec4						bits			(tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>());
2036 					const Vec4						minLimit		(-65536.0);
2037 					const Vec4						maxLimit		(65536.0);
2038 					const Vec4						minValue		(tcu::max(info.valueMin, minLimit));
2039 					const Vec4						range			(tcu::min(info.valueMax, maxLimit) - minValue);
2040 					std::ostringstream				fragmentShader;
2041 
2042 					fragmentShader <<
2043 						"#version 450\n"
2044 						"layout(location = 0) out highp vec4 o_color;\n"
2045 						"layout(push_constant) uniform PushConstant {\n"
2046 						"\thighp uint sampleIndex;\n"
2047 						"} pushConstants;\n"
2048 						"void main (void)\n"
2049 						"{\n"
2050 						"\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
2051 						"\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
2052 						"\thighp float color[4];\n"
2053 						"\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
2054 						"\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
2055 
2056 					for (int ndx = 0; ndx < 4; ndx++)
2057 						fragmentShader << "\tcolor[" << ndx << "] = "  << minValue[ndx] << ";\n";
2058 
2059 					{
2060 						const int		componentCount	= tcu::getNumUsedChannels(format.order);
2061 						const deUint32	bitSize			(bits[0] + bits[1] + bits[2] + bits[3]);
2062 						deUint32		dstBitsUsed[4]	= { 0u, 0u, 0u, 0u };
2063 						deUint32		nextSrcBit		= 0;
2064 						deUint32		divider			= 2;
2065 
2066 						// \note Limited to ten bits since the target is 32x32, so there are 10 input bits
2067 						while (nextSrcBit < de::min(bitSize, 10u))
2068 						{
2069 							for (int compNdx = 0; compNdx < componentCount; compNdx++)
2070 							{
2071 								if (dstBitsUsed[compNdx] > bits[compNdx])
2072 									continue;
2073 
2074 								fragmentShader <<
2075 										"\tcolor[" << compNdx << "] += " << (range[compNdx] / (float)divider)
2076 										<< " * float(bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1));\n";
2077 
2078 								nextSrcBit++;
2079 								dstBitsUsed[compNdx]++;
2080 							}
2081 
2082 							divider *= 2;
2083 						}
2084 					}
2085 
2086 					fragmentShader <<
2087 						"\to_color = vec4(color[0], color[1], color[2], color[3]);\n"
2088 						"}\n";
2089 
2090 					dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
2091 					break;
2092 				}
2093 
2094 				default:
2095 					DE_FATAL("Unknown channel class");
2096 			}
2097 		}
2098 
2099 		if (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
2100 		{
2101 			std::ostringstream splitShader;
2102 
2103 			splitShader <<
2104 				"#version 450\n";
2105 
2106 			if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
2107 			{
2108 				splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInputMS i_depth;\n"
2109 							<< "layout(input_attachment_index = 0, set = 0, binding = 1) uniform highp usubpassInputMS i_stencil;\n";
2110 			}
2111 			else if (tcu::hasDepthComponent(format.order))
2112 				splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInputMS i_depth;\n";
2113 			else if (tcu::hasStencilComponent(format.order))
2114 				splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp usubpassInputMS i_stencil;\n";
2115 
2116 			splitShader <<
2117 				"layout(push_constant) uniform PushConstant {\n"
2118 				"\thighp uint splitSubpassIndex;\n"
2119 				"} pushConstants;\n";
2120 
2121 			for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
2122 			{
2123 				if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
2124 					splitShader << "layout(location = " << attachmentNdx << ") out highp vec2 o_color" << attachmentNdx << ";\n";
2125 				else
2126 					splitShader << "layout(location = " << attachmentNdx << ") out highp float o_color" << attachmentNdx << ";\n";
2127 			}
2128 
2129 			splitShader <<
2130 				"void main (void)\n"
2131 				"{\n";
2132 
2133 			for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
2134 			{
2135 				if (tcu::hasDepthComponent(format.order))
2136 					splitShader << "\thighp float depth" << attachmentNdx << " = subpassLoad(i_depth, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u)).x;\n";
2137 
2138 				if (tcu::hasStencilComponent(format.order))
2139 					splitShader << "\thighp uint stencil" << attachmentNdx << " = subpassLoad(i_stencil, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u)).x;\n";
2140 
2141 				if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
2142 					splitShader << "\to_color" << attachmentNdx << " = vec2(depth" << attachmentNdx << ", float(stencil" << attachmentNdx << "));\n";
2143 				else if (tcu::hasDepthComponent(format.order))
2144 					splitShader << "\to_color" << attachmentNdx << " = float(depth" << attachmentNdx << ");\n";
2145 				else if (tcu::hasStencilComponent(format.order))
2146 					splitShader << "\to_color" << attachmentNdx << " = float(stencil" << attachmentNdx << ");\n";
2147 			}
2148 
2149 			splitShader <<
2150 				"}\n";
2151 
2152 			dst.glslSources.add("quad-split-frag") << glu::FragmentSource(splitShader.str());
2153 		}
2154 		else
2155 		{
2156 			std::string subpassType;
2157 			std::string outputType;
2158 
2159 			switch (channelClass)
2160 			{
2161 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2162 					subpassType	= "usubpassInputMS";
2163 					outputType	= "uvec4";
2164 					break;
2165 
2166 				case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2167 					subpassType	= "isubpassInputMS";
2168 					outputType	= "ivec4";
2169 					break;
2170 
2171 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2172 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2173 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2174 					subpassType	= "subpassInputMS";
2175 					outputType	= "vec4";
2176 					break;
2177 
2178 				default:
2179 					DE_FATAL("Unknown channel class");
2180 			}
2181 
2182 			std::ostringstream splitShader;
2183 			splitShader <<
2184 				"#version 450\n"
2185 				"layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp " << subpassType << " i_color;\n"
2186 				"layout(push_constant) uniform PushConstant {\n"
2187 				"\thighp uint splitSubpassIndex;\n"
2188 				"} pushConstants;\n";
2189 
2190 			for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
2191 				splitShader << "layout(location = " << attachmentNdx << ") out highp " << outputType << " o_color" << attachmentNdx << ";\n";
2192 
2193 			splitShader <<
2194 				"void main (void)\n"
2195 				"{\n";
2196 
2197 			for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
2198 				splitShader << "\to_color" << attachmentNdx << " = subpassLoad(i_color, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u));\n";
2199 
2200 			splitShader <<
2201 				"}\n";
2202 
2203 			dst.glslSources.add("quad-split-frag") << glu::FragmentSource(splitShader.str());
2204 		}
2205 	}
2206 };
2207 
formatToName(VkFormat format)2208 std::string formatToName (VkFormat format)
2209 {
2210 	const std::string	formatStr	= de::toString(format);
2211 	const std::string	prefix		= "VK_FORMAT_";
2212 
2213 	DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
2214 
2215 	return de::toLower(formatStr.substr(prefix.length()));
2216 }
2217 
initTests(tcu::TestCaseGroup * group)2218 void initTests (tcu::TestCaseGroup* group)
2219 {
2220 	static const VkFormat	formats[]	=
2221 	{
2222 		VK_FORMAT_R5G6B5_UNORM_PACK16,
2223 		VK_FORMAT_R8_UNORM,
2224 		VK_FORMAT_R8_SNORM,
2225 		VK_FORMAT_R8_UINT,
2226 		VK_FORMAT_R8_SINT,
2227 		VK_FORMAT_R8G8_UNORM,
2228 		VK_FORMAT_R8G8_SNORM,
2229 		VK_FORMAT_R8G8_UINT,
2230 		VK_FORMAT_R8G8_SINT,
2231 		VK_FORMAT_R8G8B8A8_UNORM,
2232 		VK_FORMAT_R8G8B8A8_SNORM,
2233 		VK_FORMAT_R8G8B8A8_UINT,
2234 		VK_FORMAT_R8G8B8A8_SINT,
2235 		VK_FORMAT_R8G8B8A8_SRGB,
2236 		VK_FORMAT_A8B8G8R8_UNORM_PACK32,
2237 		VK_FORMAT_A8B8G8R8_SNORM_PACK32,
2238 		VK_FORMAT_A8B8G8R8_UINT_PACK32,
2239 		VK_FORMAT_A8B8G8R8_SINT_PACK32,
2240 		VK_FORMAT_A8B8G8R8_SRGB_PACK32,
2241 		VK_FORMAT_B8G8R8A8_UNORM,
2242 		VK_FORMAT_B8G8R8A8_SRGB,
2243 		VK_FORMAT_A2R10G10B10_UNORM_PACK32,
2244 		VK_FORMAT_A2B10G10R10_UNORM_PACK32,
2245 		VK_FORMAT_A2B10G10R10_UINT_PACK32,
2246 		VK_FORMAT_R16_UNORM,
2247 		VK_FORMAT_R16_SNORM,
2248 		VK_FORMAT_R16_UINT,
2249 		VK_FORMAT_R16_SINT,
2250 		VK_FORMAT_R16_SFLOAT,
2251 		VK_FORMAT_R16G16_UNORM,
2252 		VK_FORMAT_R16G16_SNORM,
2253 		VK_FORMAT_R16G16_UINT,
2254 		VK_FORMAT_R16G16_SINT,
2255 		VK_FORMAT_R16G16_SFLOAT,
2256 		VK_FORMAT_R16G16B16A16_UNORM,
2257 		VK_FORMAT_R16G16B16A16_SNORM,
2258 		VK_FORMAT_R16G16B16A16_UINT,
2259 		VK_FORMAT_R16G16B16A16_SINT,
2260 		VK_FORMAT_R16G16B16A16_SFLOAT,
2261 		VK_FORMAT_R32_UINT,
2262 		VK_FORMAT_R32_SINT,
2263 		VK_FORMAT_R32_SFLOAT,
2264 		VK_FORMAT_R32G32_UINT,
2265 		VK_FORMAT_R32G32_SINT,
2266 		VK_FORMAT_R32G32_SFLOAT,
2267 		VK_FORMAT_R32G32B32A32_UINT,
2268 		VK_FORMAT_R32G32B32A32_SINT,
2269 		VK_FORMAT_R32G32B32A32_SFLOAT,
2270 
2271 		VK_FORMAT_D16_UNORM,
2272 		VK_FORMAT_X8_D24_UNORM_PACK32,
2273 		VK_FORMAT_D32_SFLOAT,
2274 		VK_FORMAT_S8_UINT,
2275 		VK_FORMAT_D16_UNORM_S8_UINT,
2276 		VK_FORMAT_D24_UNORM_S8_UINT,
2277 		VK_FORMAT_D32_SFLOAT_S8_UINT
2278 	};
2279 	const deUint32			sampleCounts[] =
2280 	{
2281 		2u, 4u, 8u, 16u, 32u
2282 	};
2283 	tcu::TestContext&		testCtx		(group->getTestContext());
2284 
2285 	for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
2286 	{
2287 		const VkFormat					format		(formats[formatNdx]);
2288 		const std::string				formatName	(formatToName(format));
2289 		de::MovePtr<tcu::TestCaseGroup>	formatGroup	(new tcu::TestCaseGroup(testCtx, formatName.c_str(), formatName.c_str()));
2290 
2291 		for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++)
2292 		{
2293 			const deUint32		sampleCount	(sampleCounts[sampleCountNdx]);
2294 			const std::string	testName	("samples_" + de::toString(sampleCount));
2295 
2296 			formatGroup->addChild(new InstanceFactory1<MultisampleRenderPassTestInstance, TestConfig, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, testName.c_str(), testName.c_str(), TestConfig(format, sampleCount)));
2297 		}
2298 
2299 		group->addChild(formatGroup.release());
2300 	}
2301 }
2302 
2303 } // anonymous
2304 
createRenderPassMultisampleTests(tcu::TestContext & testCtx)2305 tcu::TestCaseGroup* createRenderPassMultisampleTests (tcu::TestContext& testCtx)
2306 {
2307 	return createTestGroup(testCtx, "multisample", "Multisample render pass tests", initTests);
2308 }
2309 
2310 } // vkt
2311