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