1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Imagination Technologies Ltd.
7  * Copyright (c) 2023 LunarG, Inc.
8  * Copyright (c) 2023 Nintendo
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief Image sampling case
25  *//*--------------------------------------------------------------------*/
26 
27 #include "vktPipelineImageSamplingInstance.hpp"
28 #include "vktPipelineClearUtil.hpp"
29 #include "vktPipelineReferenceRenderer.hpp"
30 #include "vkBuilderUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkPrograms.hpp"
33 #include "vkQueryUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkObjUtil.hpp"
39 #include "tcuTexLookupVerifier.hpp"
40 #include "tcuTextureUtil.hpp"
41 #include "tcuTestLog.hpp"
42 #include "deSTLUtil.hpp"
43 
44 namespace vkt
45 {
46 namespace pipeline
47 {
48 
49 using namespace vk;
50 using de::MovePtr;
51 using de::UniquePtr;
52 
53 namespace
54 {
allocateBuffer(const InstanceInterface& vki, const DeviceInterface& vkd, const VkPhysicalDevice& physDevice, const VkDevice device, const VkBuffer& buffer, const MemoryRequirement requirement, Allocator& allocator, AllocationKind allocationKind)55 de::MovePtr<Allocation> allocateBuffer (const InstanceInterface&	vki,
56 										const DeviceInterface&		vkd,
57 										const VkPhysicalDevice&		physDevice,
58 										const VkDevice				device,
59 										const VkBuffer&				buffer,
60 										const MemoryRequirement		requirement,
61 										Allocator&					allocator,
62 										AllocationKind				allocationKind)
63 {
64 	switch (allocationKind)
65 	{
66 		case ALLOCATION_KIND_SUBALLOCATED:
67 		{
68 			const VkMemoryRequirements	memoryRequirements	= getBufferMemoryRequirements(vkd, device, buffer);
69 
70 			return allocator.allocate(memoryRequirements, requirement);
71 		}
72 
73 		case ALLOCATION_KIND_DEDICATED:
74 		{
75 			return allocateDedicated(vki, vkd, physDevice, device, buffer, requirement);
76 		}
77 
78 		default:
79 		{
80 			TCU_THROW(InternalError, "Invalid allocation kind");
81 		}
82 	}
83 }
84 
allocateImage(const InstanceInterface& vki, const DeviceInterface& vkd, const VkPhysicalDevice& physDevice, const VkDevice device, const VkImage& image, const MemoryRequirement requirement, Allocator& allocator, AllocationKind allocationKind)85 de::MovePtr<Allocation> allocateImage (const InstanceInterface&		vki,
86 									   const DeviceInterface&		vkd,
87 									   const VkPhysicalDevice&		physDevice,
88 									   const VkDevice				device,
89 									   const VkImage&				image,
90 									   const MemoryRequirement		requirement,
91 									   Allocator&					allocator,
92 									   AllocationKind				allocationKind)
93 {
94 	switch (allocationKind)
95 	{
96 		case ALLOCATION_KIND_SUBALLOCATED:
97 		{
98 			const VkMemoryRequirements	memoryRequirements	= getImageMemoryRequirements(vkd, device, image);
99 
100 			return allocator.allocate(memoryRequirements, requirement);
101 		}
102 
103 		case ALLOCATION_KIND_DEDICATED:
104 		{
105 			return allocateDedicated(vki, vkd, physDevice, device, image, requirement);
106 		}
107 
108 		default:
109 		{
110 			TCU_THROW(InternalError, "Invalid allocation kind");
111 		}
112 	}
113 }
114 
getCompatibleImageType(VkImageViewType viewType)115 static VkImageType getCompatibleImageType (VkImageViewType viewType)
116 {
117 	switch (viewType)
118 	{
119 		case VK_IMAGE_VIEW_TYPE_1D:				return VK_IMAGE_TYPE_1D;
120 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:		return VK_IMAGE_TYPE_1D;
121 		case VK_IMAGE_VIEW_TYPE_2D:				return VK_IMAGE_TYPE_2D;
122 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:		return VK_IMAGE_TYPE_2D;
123 		case VK_IMAGE_VIEW_TYPE_3D:				return VK_IMAGE_TYPE_3D;
124 		case VK_IMAGE_VIEW_TYPE_CUBE:			return VK_IMAGE_TYPE_2D;
125 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:		return VK_IMAGE_TYPE_2D;
126 		default:
127 			break;
128 	}
129 
130 	DE_ASSERT(false);
131 	return VK_IMAGE_TYPE_1D;
132 }
133 
134 template<typename TcuFormatType>
createTestTexture(const TcuFormatType format, VkImageViewType viewType, const tcu::IVec3& size, int layerCount)135 static MovePtr<TestTexture> createTestTexture (const TcuFormatType format, VkImageViewType viewType, const tcu::IVec3& size, int layerCount)
136 {
137 	MovePtr<TestTexture>	texture;
138 	const VkImageType		imageType = getCompatibleImageType(viewType);
139 
140 	switch (imageType)
141 	{
142 		case VK_IMAGE_TYPE_1D:
143 			if (layerCount == 1)
144 				texture = MovePtr<TestTexture>(new TestTexture1D(format, size.x()));
145 			else
146 				texture = MovePtr<TestTexture>(new TestTexture1DArray(format, size.x(), layerCount));
147 
148 			break;
149 
150 		case VK_IMAGE_TYPE_2D:
151 			if (layerCount == 1)
152 			{
153 				texture = MovePtr<TestTexture>(new TestTexture2D(format, size.x(), size.y()));
154 			}
155 			else
156 			{
157 				if (viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
158 				{
159 					if (layerCount == tcu::CUBEFACE_LAST && viewType == VK_IMAGE_VIEW_TYPE_CUBE)
160 					{
161 						texture = MovePtr<TestTexture>(new TestTextureCube(format, size.x()));
162 					}
163 					else
164 					{
165 						DE_ASSERT(layerCount % tcu::CUBEFACE_LAST == 0);
166 
167 						texture = MovePtr<TestTexture>(new TestTextureCubeArray(format, size.x(), layerCount));
168 					}
169 				}
170 				else
171 				{
172 					texture = MovePtr<TestTexture>(new TestTexture2DArray(format, size.x(), size.y(), layerCount));
173 				}
174 			}
175 
176 			break;
177 
178 		case VK_IMAGE_TYPE_3D:
179 			texture = MovePtr<TestTexture>(new TestTexture3D(format, size.x(), size.y(), size.z()));
180 			break;
181 
182 		default:
183 			DE_ASSERT(false);
184 	}
185 
186 	return texture;
187 }
188 
189 } // anonymous
190 
checkSupportImageSamplingInstance(Context& context, ImageSamplingInstanceParams params)191 void checkSupportImageSamplingInstance (Context& context, ImageSamplingInstanceParams params)
192 {
193 
194 	if (de::abs(params.samplerParams.mipLodBias) > context.getDeviceProperties().limits.maxSamplerLodBias)
195 		TCU_THROW(NotSupportedError, "Unsupported sampler Lod bias value");
196 
197 	if (!isSupportedSamplableFormat(context.getInstanceInterface(), context.getPhysicalDevice(), params.imageFormat))
198 		throw tcu::NotSupportedError(std::string("Unsupported format for sampling: ") + getFormatName(params.imageFormat));
199 
200 	if ((deUint32)params.imageCount > context.getDeviceProperties().limits.maxColorAttachments)
201 		throw tcu::NotSupportedError(std::string("Unsupported render target count: ") + de::toString(params.imageCount));
202 
203 	if ((params.samplerParams.minFilter == VK_FILTER_LINEAR ||
204 		 params.samplerParams.magFilter == VK_FILTER_LINEAR ||
205 		 params.samplerParams.mipmapMode == VK_SAMPLER_MIPMAP_MODE_LINEAR) &&
206 		!isLinearFilteringSupported(context.getInstanceInterface(), context.getPhysicalDevice(), params.imageFormat, VK_IMAGE_TILING_OPTIMAL))
207 		throw tcu::NotSupportedError(std::string("Unsupported format for linear filtering: ") + getFormatName(params.imageFormat));
208 
209 	if (params.separateStencilUsage)
210 	{
211 		context.requireDeviceFunctionality("VK_EXT_separate_stencil_usage");
212 		context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
213 
214 		const VkImageStencilUsageCreateInfo  stencilUsage	=
215 		{
216 			VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO,
217 			DE_NULL,
218 			VK_IMAGE_USAGE_TRANSFER_DST_BIT
219 		};
220 
221 		const VkPhysicalDeviceImageFormatInfo2	formatInfo2		=
222 		{
223 			VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,		//	VkStructureType			sType
224 			params.separateStencilUsage ? &stencilUsage
225 										: DE_NULL,						//	const void*				pNext
226 			params.imageFormat,											//	VkFormat				format
227 			getCompatibleImageType(params.imageViewType),				//	VkImageType				type
228 			VK_IMAGE_TILING_OPTIMAL,									//	VkImageTiling			tiling
229 			VK_IMAGE_USAGE_SAMPLED_BIT
230 			| VK_IMAGE_USAGE_TRANSFER_DST_BIT,							//	VkImageUsageFlags		usage
231 			(VkImageCreateFlags)0u										//	VkImageCreateFlags		flags
232 		};
233 
234 		VkImageFormatProperties2				extProperties	=
235 		{
236 			VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
237 			DE_NULL,
238 			{
239 				{
240 					0,	// width
241 					0,	// height
242 					0,	// depth
243 				},
244 				0u,		// maxMipLevels
245 				0u,		// maxArrayLayers
246 				0,		// sampleCounts
247 				0u,		// maxResourceSize
248 			},
249 		};
250 
251 		if ((context.getInstanceInterface().getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &formatInfo2, &extProperties) == VK_ERROR_FORMAT_NOT_SUPPORTED)
252 			|| extProperties.imageFormatProperties.maxExtent.width < (deUint32)params.imageSize.x()
253 			|| extProperties.imageFormatProperties.maxExtent.height < (deUint32)params.imageSize.y())
254 		{
255 			TCU_THROW(NotSupportedError, "Image format not supported");
256 		}
257 	}
258 
259 	void const* pNext = params.samplerParams.pNext;
260 	while (pNext != DE_NULL)
261 	{
262 		const VkStructureType nextType = *reinterpret_cast<const VkStructureType*>(pNext);
263 		switch (nextType)
264 		{
265 			case VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO:
266 			{
267 				context.requireDeviceFunctionality("VK_EXT_sampler_filter_minmax");
268 
269 				if (!isMinMaxFilteringSupported(context.getInstanceInterface(), context.getPhysicalDevice(), params.imageFormat, VK_IMAGE_TILING_OPTIMAL))
270 					throw tcu::NotSupportedError(std::string("Unsupported format for min/max filtering: ") + getFormatName(params.imageFormat));
271 
272 				pNext = reinterpret_cast<const VkSamplerReductionModeCreateInfo*>(pNext)->pNext;
273 				break;
274 			}
275 			case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO:
276 				context.requireDeviceFunctionality("VK_KHR_sampler_ycbcr_conversion");
277 
278 				pNext = reinterpret_cast<const VkSamplerYcbcrConversionInfo*>(pNext)->pNext;
279 				break;
280 			case VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT:
281 				pNext = reinterpret_cast<const VkSamplerCustomBorderColorCreateInfoEXT*>(pNext)->pNext;
282 
283 				if (!context.getCustomBorderColorFeaturesEXT().customBorderColors)
284 				{
285 					throw tcu::NotSupportedError("customBorderColors feature is not supported");
286 				}
287 
288 				break;
289 			default:
290 				TCU_FAIL("Unrecognized sType in chained sampler create info");
291 		}
292 	}
293 
294 	if (params.samplerParams.addressModeU == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE ||
295 		params.samplerParams.addressModeV == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE ||
296 		params.samplerParams.addressModeW == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE)
297 	{
298 		context.requireDeviceFunctionality("VK_KHR_sampler_mirror_clamp_to_edge");
299 	}
300 
301 	if ((isCompressedFormat(params.imageFormat) || isDepthStencilFormat(params.imageFormat)) && params.imageViewType == VK_IMAGE_VIEW_TYPE_3D)
302 	{
303 		// \todo [2016-01-22 pyry] Mandate VK_ERROR_FORMAT_NOT_SUPPORTED
304 		try
305 		{
306 			const VkImageFormatProperties	formatProperties	= getPhysicalDeviceImageFormatProperties(context.getInstanceInterface(),
307 																										 context.getPhysicalDevice(),
308 																										 params.imageFormat,
309 																										 VK_IMAGE_TYPE_3D,
310 																										 VK_IMAGE_TILING_OPTIMAL,
311 																										 VK_IMAGE_USAGE_SAMPLED_BIT,
312 																										 (VkImageCreateFlags)0);
313 
314 			if (formatProperties.maxExtent.width == 0 &&
315 				formatProperties.maxExtent.height == 0 &&
316 				formatProperties.maxExtent.depth == 0)
317 				TCU_THROW(NotSupportedError, "3D compressed or depth format not supported");
318 		}
319 		catch (const Error&)
320 		{
321 			TCU_THROW(NotSupportedError, "3D compressed or depth format not supported");
322 		}
323 	}
324 
325 	if (params.imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
326 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
327 
328 	if (params.allocationKind == ALLOCATION_KIND_DEDICATED)
329 		context.requireDeviceFunctionality("VK_KHR_dedicated_allocation");
330 
331 #ifndef CTS_USES_VULKANSC
332 	if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset"))
333 	{
334 		const auto portabilitySubsetFeatures	= context.getPortabilitySubsetFeatures();
335 		const auto componentMapping				= params.componentMapping;
336 		if (!portabilitySubsetFeatures.imageViewFormatSwizzle &&
337 			((componentMapping.r != VK_COMPONENT_SWIZZLE_IDENTITY) ||
338 			 (componentMapping.g != VK_COMPONENT_SWIZZLE_IDENTITY) ||
339 			 (componentMapping.b != VK_COMPONENT_SWIZZLE_IDENTITY) ||
340 			 (componentMapping.a != VK_COMPONENT_SWIZZLE_IDENTITY)))
341 		{
342 			TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Implementation does not support remapping format components");
343 		}
344 	}
345 
346 	bool formatRgba10x6WithoutYCbCrSampler = context.getRGBA10X6FormatsFeaturesEXT().formatRgba10x6WithoutYCbCrSampler;
347 #else
348 	bool formatRgba10x6WithoutYCbCrSampler = VK_FALSE;
349 #endif // CTS_USES_VULKANSC
350 
351 	if ((params.imageFormat == VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16) && (params.subresourceRange.levelCount > 1) && (formatRgba10x6WithoutYCbCrSampler == VK_FALSE))
352 	{
353 		TCU_THROW(NotSupportedError, "formatRgba10x6WithoutYCbCrSampler not supported");
354 	}
355 }
356 
ImageSamplingInstance(Context& context, ImageSamplingInstanceParams params)357 ImageSamplingInstance::ImageSamplingInstance (Context&						context,
358 											  ImageSamplingInstanceParams	params)
359 	: vkt::TestInstance				(context)
360 	, m_allocationKind				(params.allocationKind)
361 	, m_samplingType				(params.samplingType)
362 	, m_imageViewType				(params.imageViewType)
363 	, m_imageFormat					(params.imageFormat)
364 	, m_imageSize					(params.imageSize)
365 	, m_layerCount					(params.layerCount)
366 	, m_imageCount					(params.imageCount)
367 	, m_componentMapping			(params.componentMapping)
368 	, m_componentMask				(true)
369 	, m_subresourceRange			(params.subresourceRange)
370 	, m_samplerParams				(params.samplerParams)
371 	, m_samplerLod					(params.samplerLod)
372 	, m_renderSize					(params.renderSize)
373 	, m_colorFormat					(VK_FORMAT_R8G8B8A8_UNORM)
374 	, m_vertices					(params.vertices)
375 	, m_graphicsPipeline			(context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), m_context.getDeviceExtensions(), params.pipelineConstructionType, params.pipelineCreateFlags)
376 	, m_pipelineConstructionType	(params.pipelineConstructionType)
377 	, m_imageLayout					(params.imageLayout)
378 {
379 }
380 
setup()381 void ImageSamplingInstance::setup ()
382 {
383 	const InstanceInterface&				vki						= m_context.getInstanceInterface();
384 	const DeviceInterface&					vk						= m_context.getDeviceInterface();
385 	const VkPhysicalDevice					physDevice				= m_context.getPhysicalDevice();
386 	const VkDevice							vkDevice				= m_context.getDevice();
387 	const VkQueue							queue					= m_context.getUniversalQueue();
388 	const deUint32							queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
389 	SimpleAllocator							memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
390 	const VkComponentMapping				componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
391 
392 	void const* pNext = m_samplerParams.pNext;
393 	while (pNext != DE_NULL)
394 	{
395 		const VkStructureType nextType = *reinterpret_cast<const VkStructureType*>(pNext);
396 		switch (nextType)
397 		{
398 			case VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO:
399 			{
400 				VkPhysicalDeviceSamplerFilterMinmaxProperties	physicalDeviceSamplerMinMaxProperties =
401 				{
402 					VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES,
403 					DE_NULL,
404 					DE_FALSE,
405 					DE_FALSE
406 				};
407 				VkPhysicalDeviceProperties2						physicalDeviceProperties;
408 				physicalDeviceProperties.sType	= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
409 				physicalDeviceProperties.pNext	= &physicalDeviceSamplerMinMaxProperties;
410 
411 				vki.getPhysicalDeviceProperties2(m_context.getPhysicalDevice(), &physicalDeviceProperties);
412 
413 				if (physicalDeviceSamplerMinMaxProperties.filterMinmaxImageComponentMapping != VK_TRUE)
414 				{
415 					// If filterMinmaxImageComponentMapping is VK_FALSE the component mapping of the image
416 					// view used with min/max filtering must have been created with the r component set to
417 					// VK_COMPONENT_SWIZZLE_IDENTITY. Only the r component of the sampled image value is
418 					// defined and the other component values are undefined
419 
420 					m_componentMask = tcu::BVec4(true, false, false, false);
421 
422 					if (m_componentMapping.r != VK_COMPONENT_SWIZZLE_IDENTITY && m_componentMapping.r != VK_COMPONENT_SWIZZLE_R)
423 					{
424 						TCU_THROW(NotSupportedError, "filterMinmaxImageComponentMapping is not supported (R mapping is not IDENTITY)");
425 					}
426 				}
427 				pNext = reinterpret_cast<const VkSamplerReductionModeCreateInfo*>(pNext)->pNext;
428 			}
429 			break;
430 			case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO:
431 				pNext = reinterpret_cast<const VkSamplerYcbcrConversionInfo*>(pNext)->pNext;
432 				break;
433 			case VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT:
434 			{
435 				const VkSamplerCustomBorderColorCreateInfoEXT customBorderColorCreateInfo = *reinterpret_cast<const VkSamplerCustomBorderColorCreateInfoEXT*>(pNext);
436 
437 				VkPhysicalDeviceCustomBorderColorFeaturesEXT	physicalDeviceCustomBorderColorFeatures =
438 				{
439 					VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT,
440 					DE_NULL,
441 					DE_FALSE,
442 					DE_FALSE
443 				};
444 				VkPhysicalDeviceFeatures2						physicalDeviceFeatures;
445 				physicalDeviceFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
446 				physicalDeviceFeatures.pNext = &physicalDeviceCustomBorderColorFeatures;
447 
448 				vki.getPhysicalDeviceFeatures2(m_context.getPhysicalDevice(), &physicalDeviceFeatures);
449 
450 				if (physicalDeviceCustomBorderColorFeatures.customBorderColors != VK_TRUE)
451 				{
452 					TCU_THROW(NotSupportedError, "customBorderColors are not supported");
453 				}
454 
455 				if (physicalDeviceCustomBorderColorFeatures.customBorderColorWithoutFormat != VK_TRUE &&
456 					customBorderColorCreateInfo.format == VK_FORMAT_UNDEFINED)
457 				{
458 					TCU_THROW(NotSupportedError, "customBorderColorWithoutFormat is not supported");
459 				}
460 
461 				pNext = reinterpret_cast<const VkSamplerCustomBorderColorCreateInfoEXT*>(pNext)->pNext;
462 			}
463 			break;
464 			default:
465 				TCU_FAIL("Unrecognized sType in chained sampler create info");
466 		}
467 	}
468 
469 	// Create texture images, views and samplers
470 	{
471 		VkImageCreateFlags			imageFlags			= 0u;
472 
473 		if (m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE || m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
474 			imageFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
475 
476 		// Initialize texture data
477 		if (isCompressedFormat(m_imageFormat))
478 			m_texture = createTestTexture(mapVkCompressedFormat(m_imageFormat), m_imageViewType, m_imageSize, m_layerCount);
479 		else
480 			m_texture = createTestTexture(mapVkFormat(m_imageFormat), m_imageViewType, m_imageSize, m_layerCount);
481 
482 		const VkImageCreateInfo	imageParams =
483 		{
484 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,							// VkStructureType			sType;
485 			DE_NULL,														// const void*				pNext;
486 			imageFlags,														// VkImageCreateFlags		flags;
487 			getCompatibleImageType(m_imageViewType),						// VkImageType				imageType;
488 			m_imageFormat,													// VkFormat					format;
489 			{																// VkExtent3D				extent;
490 				(deUint32)m_imageSize.x(),
491 				(deUint32)m_imageSize.y(),
492 				(deUint32)m_imageSize.z()
493 			},
494 			(deUint32)m_texture->getNumLevels(),							// deUint32					mipLevels;
495 			(deUint32)m_layerCount,											// deUint32					arrayLayers;
496 			VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits	samples;
497 			VK_IMAGE_TILING_OPTIMAL,										// VkImageTiling			tiling;
498 			VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,	// VkImageUsageFlags		usage;
499 			VK_SHARING_MODE_EXCLUSIVE,										// VkSharingMode			sharingMode;
500 			1u,																// deUint32					queueFamilyIndexCount;
501 			&queueFamilyIndex,												// const deUint32*			pQueueFamilyIndices;
502 			VK_IMAGE_LAYOUT_UNDEFINED										// VkImageLayout			initialLayout;
503 		};
504 
505 		m_images.resize(m_imageCount);
506 		m_imageAllocs.resize(m_imageCount);
507 		m_imageViews.resize(m_imageCount);
508 
509 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
510 		{
511 			m_images[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &imageParams)));
512 			m_imageAllocs[imgNdx] = SharedAllocPtr(new UniqueAlloc(allocateImage(vki, vk, physDevice, vkDevice, **m_images[imgNdx], MemoryRequirement::Any, memAlloc, m_allocationKind)));
513 			VK_CHECK(vk.bindImageMemory(vkDevice, **m_images[imgNdx], (*m_imageAllocs[imgNdx])->getMemory(), (*m_imageAllocs[imgNdx])->getOffset()));
514 
515 			// Upload texture data
516 			uploadTestTexture(vk, vkDevice, queue, queueFamilyIndex, memAlloc, *m_texture, **m_images[imgNdx]);
517 
518 			// Create image view and sampler
519 			const VkImageViewCreateInfo imageViewParams =
520 			{
521 				VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
522 				DE_NULL,									// const void*				pNext;
523 				0u,											// VkImageViewCreateFlags	flags;
524 				**m_images[imgNdx],							// VkImage					image;
525 				m_imageViewType,							// VkImageViewType			viewType;
526 				m_imageFormat,								// VkFormat					format;
527 				m_componentMapping,							// VkComponentMapping		components;
528 				m_subresourceRange,							// VkImageSubresourceRange	subresourceRange;
529 			};
530 
531 			m_imageViews[imgNdx] = SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &imageViewParams)));
532 		}
533 
534 		m_sampler	= createSampler(vk, vkDevice, &m_samplerParams);
535 	}
536 
537 	// Create descriptor set for image and sampler
538 	{
539 		DescriptorPoolBuilder descriptorPoolBuilder;
540 		if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
541 			descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLER, 1u);
542 		descriptorPoolBuilder.addType(m_samplingType, m_imageCount);
543 		m_descriptorPool = descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
544 			m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? m_imageCount + 1u : m_imageCount);
545 
546 		DescriptorSetLayoutBuilder setLayoutBuilder;
547 		if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
548 			setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
549 		setLayoutBuilder.addArrayBinding(m_samplingType, m_imageCount, VK_SHADER_STAGE_FRAGMENT_BIT);
550 		m_descriptorSetLayout = setLayoutBuilder.build(vk, vkDevice);
551 
552 		const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
553 		{
554 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType				sType;
555 			DE_NULL,											// const void*					pNext;
556 			*m_descriptorPool,									// VkDescriptorPool				descriptorPool;
557 			1u,													// deUint32						setLayoutCount;
558 			&m_descriptorSetLayout.get()						// const VkDescriptorSetLayout*	pSetLayouts;
559 		};
560 
561 		m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
562 
563 		const VkSampler sampler = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? DE_NULL : *m_sampler;
564 		std::vector<VkDescriptorImageInfo> descriptorImageInfo(m_imageCount);
565 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
566 		{
567 			descriptorImageInfo[imgNdx].sampler		= sampler;									// VkSampler		sampler;
568 			descriptorImageInfo[imgNdx].imageView	= **m_imageViews[imgNdx];					// VkImageView		imageView;
569 			descriptorImageInfo[imgNdx].imageLayout	= VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;	// VkImageLayout	imageLayout;
570 		}
571 
572 		DescriptorSetUpdateBuilder setUpdateBuilder;
573 		if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
574 		{
575 			const VkDescriptorImageInfo descriptorSamplerInfo =
576 			{
577 				*m_sampler,									// VkSampler		sampler;
578 				DE_NULL,									// VkImageView		imageView;
579 				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL	// VkImageLayout	imageLayout;
580 			};
581 			setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_SAMPLER, &descriptorSamplerInfo);
582 		}
583 
584 		const deUint32 binding = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? 1u : 0u;
585 		setUpdateBuilder.writeArray(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(binding), m_samplingType, m_imageCount, descriptorImageInfo.data());
586 		setUpdateBuilder.update(vk, vkDevice);
587 	}
588 
589 	// Create color images and views
590 	{
591 		const VkImageCreateInfo colorImageParams =
592 		{
593 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
594 			DE_NULL,																	// const void*				pNext;
595 			0u,																			// VkImageCreateFlags		flags;
596 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
597 			m_colorFormat,																// VkFormat					format;
598 			{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u },				// VkExtent3D				extent;
599 			1u,																			// deUint32					mipLevels;
600 			1u,																			// deUint32					arrayLayers;
601 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
602 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
603 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
604 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
605 			1u,																			// deUint32					queueFamilyIndexCount;
606 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
607 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
608 		};
609 
610 		m_colorImages.resize(m_imageCount);
611 		m_colorImageAllocs.resize(m_imageCount);
612 		m_colorAttachmentViews.resize(m_imageCount);
613 
614 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
615 		{
616 			m_colorImages[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &colorImageParams)));
617 			m_colorImageAllocs[imgNdx] = SharedAllocPtr(new UniqueAlloc(allocateImage(vki, vk, physDevice, vkDevice, **m_colorImages[imgNdx], MemoryRequirement::Any, memAlloc, m_allocationKind)));
618 			VK_CHECK(vk.bindImageMemory(vkDevice, **m_colorImages[imgNdx], (*m_colorImageAllocs[imgNdx])->getMemory(), (*m_colorImageAllocs[imgNdx])->getOffset()));
619 
620 			const VkImageViewCreateInfo colorAttachmentViewParams =
621 			{
622 				VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
623 				DE_NULL,											// const void*				pNext;
624 				0u,													// VkImageViewCreateFlags	flags;
625 				**m_colorImages[imgNdx],							// VkImage					image;
626 				VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
627 				m_colorFormat,										// VkFormat					format;
628 				componentMappingRGBA,								// VkComponentMapping		components;
629 				{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
630 			};
631 
632 			m_colorAttachmentViews[imgNdx] = SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &colorAttachmentViewParams)));
633 		}
634 	}
635 
636 	// Create render pass
637 	{
638 		std::vector<VkAttachmentDescription>	colorAttachmentDescriptions(m_imageCount);
639 		std::vector<VkAttachmentReference>		colorAttachmentReferences(m_imageCount);
640 
641 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
642 		{
643 			colorAttachmentDescriptions[imgNdx].flags			= 0u;										// VkAttachmentDescriptionFlags		flags;
644 			colorAttachmentDescriptions[imgNdx].format			= m_colorFormat;							// VkFormat							format;
645 			colorAttachmentDescriptions[imgNdx].samples			= VK_SAMPLE_COUNT_1_BIT;					// VkSampleCountFlagBits			samples;
646 			colorAttachmentDescriptions[imgNdx].loadOp			= VK_ATTACHMENT_LOAD_OP_CLEAR;				// VkAttachmentLoadOp				loadOp;
647 			colorAttachmentDescriptions[imgNdx].storeOp			= VK_ATTACHMENT_STORE_OP_STORE;				// VkAttachmentStoreOp				storeOp;
648 			colorAttachmentDescriptions[imgNdx].stencilLoadOp	= VK_ATTACHMENT_LOAD_OP_DONT_CARE;			// VkAttachmentLoadOp				stencilLoadOp;
649 			colorAttachmentDescriptions[imgNdx].stencilStoreOp	= VK_ATTACHMENT_STORE_OP_DONT_CARE;			// VkAttachmentStoreOp				stencilStoreOp;
650 			colorAttachmentDescriptions[imgNdx].initialLayout	= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;	// VkImageLayout					initialLayout;
651 			colorAttachmentDescriptions[imgNdx].finalLayout		= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;	// VkImageLayout					finalLayout;
652 
653 			colorAttachmentReferences[imgNdx].attachment		= (deUint32)imgNdx;							// deUint32							attachment;
654 			colorAttachmentReferences[imgNdx].layout			= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;	// VkImageLayout					layout;
655 		}
656 
657 		const VkSubpassDescription subpassDescription =
658 		{
659 			0u,													// VkSubpassDescriptionFlags	flags;
660 			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint			pipelineBindPoint;
661 			0u,													// deUint32						inputAttachmentCount;
662 			DE_NULL,											// const VkAttachmentReference*	pInputAttachments;
663 			(deUint32)m_imageCount,								// deUint32						colorAttachmentCount;
664 			&colorAttachmentReferences[0],						// const VkAttachmentReference*	pColorAttachments;
665 			DE_NULL,											// const VkAttachmentReference*	pResolveAttachments;
666 			DE_NULL,											// const VkAttachmentReference*	pDepthStencilAttachment;
667 			0u,													// deUint32						preserveAttachmentCount;
668 			DE_NULL												// const VkAttachmentReference*	pPreserveAttachments;
669 		};
670 
671 		const VkRenderPassCreateInfo renderPassParams =
672 		{
673 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
674 			DE_NULL,											// const void*						pNext;
675 			0u,													// VkRenderPassCreateFlags			flags;
676 			(deUint32)m_imageCount,								// deUint32							attachmentCount;
677 			&colorAttachmentDescriptions[0],					// const VkAttachmentDescription*	pAttachments;
678 			1u,													// deUint32							subpassCount;
679 			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
680 			0u,													// deUint32							dependencyCount;
681 			DE_NULL												// const VkSubpassDependency*		pDependencies;
682 		};
683 
684 		m_renderPass = RenderPassWrapper(m_pipelineConstructionType, vk, vkDevice, &renderPassParams);
685 	}
686 
687 	// Create framebuffer
688 	{
689 		std::vector<VkImage>		images			(m_imageCount);
690 		std::vector<VkImageView>	pAttachments	(m_imageCount);
691 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
692 		{
693 			images[imgNdx] = m_colorImages[imgNdx]->get();
694 			pAttachments[imgNdx] = m_colorAttachmentViews[imgNdx]->get();
695 		}
696 
697 		const VkFramebufferCreateInfo framebufferParams =
698 		{
699 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType			sType;
700 			DE_NULL,											// const void*				pNext;
701 			0u,													// VkFramebufferCreateFlags	flags;
702 			*m_renderPass,										// VkRenderPass				renderPass;
703 			(deUint32)m_imageCount,								// deUint32					attachmentCount;
704 			&pAttachments[0],									// const VkImageView*		pAttachments;
705 			(deUint32)m_renderSize.x(),							// deUint32					width;
706 			(deUint32)m_renderSize.y(),							// deUint32					height;
707 			1u													// deUint32					layers;
708 		};
709 
710 		m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, images);
711 	}
712 
713 	// Create pipeline layout
714 	{
715 #ifndef CTS_USES_VULKANSC
716 		VkPipelineLayoutCreateFlags pipelineLayoutFlags = (!isConstructionTypeLibrary(m_pipelineConstructionType)) ? 0u : deUint32(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
717 #else
718 		VkPipelineLayoutCreateFlags pipelineLayoutFlags = 0u;
719 #endif // CTS_USES_VULKANSC
720 		VkPipelineLayoutCreateInfo	pipelineLayoutParams
721 		{
722 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
723 			DE_NULL,											// const void*					pNext;
724 			pipelineLayoutFlags,								// VkPipelineLayoutCreateFlags	flags;
725 			0u,													// deUint32						setLayoutCount;
726 			DE_NULL,											// const VkDescriptorSetLayout*	pSetLayouts;
727 			0u,													// deUint32						pushConstantRangeCount;
728 			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
729 		};
730 
731 		m_preRasterizationStatePipelineLayout	= PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
732 		pipelineLayoutParams.setLayoutCount		= 1u;
733 		pipelineLayoutParams.pSetLayouts		= &m_descriptorSetLayout.get();
734 		m_fragmentStatePipelineLayout			= PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
735 	}
736 
737 	m_vertexShaderModule	= ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("tex_vert"), 0);
738 	m_fragmentShaderModule	= ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("tex_frag"), 0);
739 
740 	// Create pipeline
741 	{
742 		const VkVertexInputBindingDescription vertexInputBindingDescription =
743 		{
744 			0u,									// deUint32					binding;
745 			sizeof(Vertex4Tex4),				// deUint32					strideInBytes;
746 			VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputStepRate	inputRate;
747 		};
748 
749 		const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
750 		{
751 			{
752 				0u,										// deUint32	location;
753 				0u,										// deUint32	binding;
754 				VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat	format;
755 				0u										// deUint32	offset;
756 			},
757 			{
758 				1u,										// deUint32	location;
759 				0u,										// deUint32	binding;
760 				VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat	format;
761 				DE_OFFSET_OF(Vertex4Tex4, texCoord),	// deUint32	offset;
762 			}
763 		};
764 
765 		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
766 		{
767 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
768 			DE_NULL,														// const void*								pNext;
769 			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
770 			1u,																// deUint32									vertexBindingDescriptionCount;
771 			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
772 			2u,																// deUint32									vertexAttributeDescriptionCount;
773 			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
774 		};
775 
776 		const std::vector<VkViewport>	viewports	{ makeViewport(m_renderSize) };
777 		const std::vector<VkRect2D>		scissors	{ makeRect2D(m_renderSize) };
778 
779 		std::vector<VkPipelineColorBlendAttachmentState>	colorBlendAttachmentStates(m_imageCount);
780 
781 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
782 		{
783 			colorBlendAttachmentStates[imgNdx].blendEnable			= false;												// VkBool32					blendEnable;
784 			colorBlendAttachmentStates[imgNdx].srcColorBlendFactor	= VK_BLEND_FACTOR_ONE;									// VkBlendFactor			srcColorBlendFactor;
785 			colorBlendAttachmentStates[imgNdx].dstColorBlendFactor	= VK_BLEND_FACTOR_ZERO;									// VkBlendFactor			dstColorBlendFactor;
786 			colorBlendAttachmentStates[imgNdx].colorBlendOp			= VK_BLEND_OP_ADD;										// VkBlendOp				colorBlendOp;
787 			colorBlendAttachmentStates[imgNdx].srcAlphaBlendFactor	= VK_BLEND_FACTOR_ONE;									// VkBlendFactor			srcAlphaBlendFactor;
788 			colorBlendAttachmentStates[imgNdx].dstAlphaBlendFactor	= VK_BLEND_FACTOR_ZERO;									// VkBlendFactor			dstAlphaBlendFactor;
789 			colorBlendAttachmentStates[imgNdx].alphaBlendOp			= VK_BLEND_OP_ADD;										// VkBlendOp				alphaBlendOp;
790 			colorBlendAttachmentStates[imgNdx].colorWriteMask		= VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |	// VkColorComponentFlags	colorWriteMask;
791 																		VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
792 		}
793 
794 		const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
795 		{
796 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
797 			DE_NULL,													// const void*									pNext;
798 			0u,															// VkPipelineColorBlendStateCreateFlags			flags;
799 			false,														// VkBool32										logicOpEnable;
800 			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
801 			(deUint32)m_imageCount,										// deUint32										attachmentCount;
802 			&colorBlendAttachmentStates[0],								// const VkPipelineColorBlendAttachmentState*	pAttachments;
803 			{ 0.0f, 0.0f, 0.0f, 0.0f }									// float										blendConstants[4];
804 		};
805 
806 		m_graphicsPipeline.setMonolithicPipelineLayout(m_fragmentStatePipelineLayout)
807 						  .setDefaultDepthStencilState()
808 						  .setDefaultRasterizationState()
809 						  .setDefaultMultisampleState()
810 						  .setupVertexInputState(&vertexInputStateParams)
811 						  .setupPreRasterizationShaderState(viewports,
812 														scissors,
813 														m_preRasterizationStatePipelineLayout,
814 														*m_renderPass,
815 														0u,
816 														m_vertexShaderModule)
817 						  .setupFragmentShaderState(m_fragmentStatePipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule)
818 						  .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateParams)
819 						  .buildPipeline();
820 	}
821 
822 	// Create vertex buffer
823 	{
824 		const VkDeviceSize			vertexBufferSize	= (VkDeviceSize)(m_vertices.size() * sizeof(Vertex4Tex4));
825 		const VkBufferCreateInfo	vertexBufferParams	=
826 		{
827 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
828 			DE_NULL,									// const void*			pNext;
829 			0u,											// VkBufferCreateFlags	flags;
830 			vertexBufferSize,							// VkDeviceSize			size;
831 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
832 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
833 			1u,											// deUint32				queueFamilyIndexCount;
834 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
835 		};
836 
837 		DE_ASSERT(vertexBufferSize > 0);
838 
839 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
840 		m_vertexBufferAlloc = allocateBuffer(vki, vk, physDevice, vkDevice, *m_vertexBuffer, MemoryRequirement::HostVisible, memAlloc, m_allocationKind);
841 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
842 
843 		// Load vertices into vertex buffer
844 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), &m_vertices[0], (size_t)vertexBufferSize);
845 		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
846 	}
847 
848 	// Create command pool
849 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
850 
851 	// Create command buffer
852 	{
853 		const std::vector<VkClearValue> attachmentClearValues (m_imageCount, defaultClearValue(m_colorFormat));
854 
855 		std::vector<VkImageMemoryBarrier> preAttachmentBarriers(m_imageCount);
856 
857 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
858 		{
859 			preAttachmentBarriers[imgNdx].sType								= VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;	// VkStructureType			sType;
860 			preAttachmentBarriers[imgNdx].pNext								= DE_NULL;									// const void*				pNext;
861 			preAttachmentBarriers[imgNdx].srcAccessMask						= 0u;										// VkAccessFlags			srcAccessMask;
862 			preAttachmentBarriers[imgNdx].dstAccessMask						= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;		// VkAccessFlags			dstAccessMask;
863 			preAttachmentBarriers[imgNdx].oldLayout							= VK_IMAGE_LAYOUT_UNDEFINED;				// VkImageLayout			oldLayout;
864 			preAttachmentBarriers[imgNdx].newLayout							= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;	// VkImageLayout			newLayout;
865 			preAttachmentBarriers[imgNdx].srcQueueFamilyIndex				= VK_QUEUE_FAMILY_IGNORED;					// deUint32					srcQueueFamilyIndex;
866 			preAttachmentBarriers[imgNdx].dstQueueFamilyIndex				= VK_QUEUE_FAMILY_IGNORED;					// deUint32					dstQueueFamilyIndex;
867 			preAttachmentBarriers[imgNdx].image								= **m_colorImages[imgNdx];					// VkImage					image;
868 			preAttachmentBarriers[imgNdx].subresourceRange.aspectMask		= VK_IMAGE_ASPECT_COLOR_BIT;				// VkImageSubresourceRange	subresourceRange;
869 			preAttachmentBarriers[imgNdx].subresourceRange.baseMipLevel		= 0u;
870 			preAttachmentBarriers[imgNdx].subresourceRange.levelCount		= 1u;
871 			preAttachmentBarriers[imgNdx].subresourceRange.baseArrayLayer	= 0u;
872 			preAttachmentBarriers[imgNdx].subresourceRange.layerCount		= 1u;
873 		}
874 
875 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
876 
877 		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
878 
879 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0,
880 			0u, DE_NULL, 0u, DE_NULL, (deUint32)m_imageCount, &preAttachmentBarriers[0]);
881 
882 		m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), (deUint32)attachmentClearValues.size(), &attachmentClearValues[0]);
883 
884 		m_graphicsPipeline.bind(*m_cmdBuffer);
885 
886 		m_fragmentStatePipelineLayout.bindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
887 
888 		const VkDeviceSize vertexBufferOffset = 0;
889 		vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
890 		vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
891 
892 		m_renderPass.end(vk, *m_cmdBuffer);
893 		endCommandBuffer(vk, *m_cmdBuffer);
894 	}
895 }
896 
~ImageSamplingInstance(void)897 ImageSamplingInstance::~ImageSamplingInstance (void)
898 {
899 }
900 
iterate(void)901 tcu::TestStatus ImageSamplingInstance::iterate (void)
902 {
903 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
904 	const VkDevice				vkDevice	= m_context.getDevice();
905 	const VkQueue				queue		= m_context.getUniversalQueue();
906 
907 	setup();
908 
909 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
910 
911 	return verifyImage();
912 }
913 
914 namespace
915 {
916 
isLookupResultValid(const tcu::Texture1DView& texture, const tcu::Sampler& sampler, const tcu::LookupPrecision& precision, const tcu::Vec4& coords, const tcu::Vec2& lodBounds, const tcu::Vec4& result)917 bool isLookupResultValid (const tcu::Texture1DView&		texture,
918 						  const tcu::Sampler&			sampler,
919 						  const tcu::LookupPrecision&	precision,
920 						  const tcu::Vec4&				coords,
921 						  const tcu::Vec2&				lodBounds,
922 						  const tcu::Vec4&				result)
923 {
924 	return tcu::isLookupResultValid(texture, sampler, precision, coords.x(), lodBounds, result);
925 }
926 
isLookupResultValid(const tcu::Texture1DArrayView& texture, const tcu::Sampler& sampler, const tcu::LookupPrecision& precision, const tcu::Vec4& coords, const tcu::Vec2& lodBounds, const tcu::Vec4& result)927 bool isLookupResultValid (const tcu::Texture1DArrayView&	texture,
928 						  const tcu::Sampler&				sampler,
929 						  const tcu::LookupPrecision&		precision,
930 						  const tcu::Vec4&					coords,
931 						  const tcu::Vec2&					lodBounds,
932 						  const tcu::Vec4&					result)
933 {
934 	return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1), lodBounds, result);
935 }
936 
isLookupResultValid(const tcu::Texture2DView& texture, const tcu::Sampler& sampler, const tcu::LookupPrecision& precision, const tcu::Vec4& coords, const tcu::Vec2& lodBounds, const tcu::Vec4& result)937 bool isLookupResultValid (const tcu::Texture2DView&		texture,
938 						  const tcu::Sampler&			sampler,
939 						  const tcu::LookupPrecision&	precision,
940 						  const tcu::Vec4&				coords,
941 						  const tcu::Vec2&				lodBounds,
942 						  const tcu::Vec4&				result)
943 {
944 	return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1), lodBounds, result);
945 }
946 
isLookupResultValid(const tcu::Texture2DArrayView& texture, const tcu::Sampler& sampler, const tcu::LookupPrecision& precision, const tcu::Vec4& coords, const tcu::Vec2& lodBounds, const tcu::Vec4& result)947 bool isLookupResultValid (const tcu::Texture2DArrayView&	texture,
948 						  const tcu::Sampler&				sampler,
949 						  const tcu::LookupPrecision&		precision,
950 						  const tcu::Vec4&					coords,
951 						  const tcu::Vec2&					lodBounds,
952 						  const tcu::Vec4&					result)
953 {
954 	return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1,2), lodBounds, result);
955 }
956 
isLookupResultValid(const tcu::TextureCubeView& texture, const tcu::Sampler& sampler, const tcu::LookupPrecision& precision, const tcu::Vec4& coords, const tcu::Vec2& lodBounds, const tcu::Vec4& result)957 bool isLookupResultValid (const tcu::TextureCubeView&	texture,
958 						  const tcu::Sampler&			sampler,
959 						  const tcu::LookupPrecision&	precision,
960 						  const tcu::Vec4&				coords,
961 						  const tcu::Vec2&				lodBounds,
962 						  const tcu::Vec4&				result)
963 {
964 	return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1,2), lodBounds, result);
965 }
966 
isLookupResultValid(const tcu::TextureCubeArrayView& texture, const tcu::Sampler& sampler, const tcu::LookupPrecision& precision, const tcu::Vec4& coords, const tcu::Vec2& lodBounds, const tcu::Vec4& result)967 bool isLookupResultValid (const tcu::TextureCubeArrayView&	texture,
968 						  const tcu::Sampler&				sampler,
969 						  const tcu::LookupPrecision&		precision,
970 						  const tcu::Vec4&					coords,
971 						  const tcu::Vec2&					lodBounds,
972 						  const tcu::Vec4&					result)
973 {
974 	return tcu::isLookupResultValid(texture, sampler, precision, tcu::IVec4(precision.coordBits.x()), coords, lodBounds, result);
975 }
976 
isLookupResultValid(const tcu::Texture3DView& texture, const tcu::Sampler& sampler, const tcu::LookupPrecision& precision, const tcu::Vec4& coords, const tcu::Vec2& lodBounds, const tcu::Vec4& result)977 bool isLookupResultValid(const tcu::Texture3DView&		texture,
978 						 const tcu::Sampler&			sampler,
979 						 const tcu::LookupPrecision&	precision,
980 						 const tcu::Vec4&				coords,
981 						 const tcu::Vec2&				lodBounds,
982 						 const tcu::Vec4&				result)
983 {
984 	return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1,2), lodBounds, result);
985 }
986 
987 template<typename TextureViewType>
validateResultImage(const TextureViewType& texture, const tcu::Sampler& sampler, const tcu::ConstPixelBufferAccess& texCoords, const tcu::Vec2& lodBounds, const tcu::LookupPrecision& lookupPrecision, const tcu::Vec4& lookupScale, const tcu::Vec4& lookupBias, const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask)988 bool validateResultImage (const TextureViewType&				texture,
989 						  const tcu::Sampler&					sampler,
990 						  const tcu::ConstPixelBufferAccess&	texCoords,
991 						  const tcu::Vec2&						lodBounds,
992 						  const tcu::LookupPrecision&			lookupPrecision,
993 						  const tcu::Vec4&						lookupScale,
994 						  const tcu::Vec4&						lookupBias,
995 						  const tcu::ConstPixelBufferAccess&	result,
996 						  const tcu::PixelBufferAccess&			errorMask)
997 {
998 	const int	w		= result.getWidth();
999 	const int	h		= result.getHeight();
1000 	bool		allOk	= true;
1001 
1002 	for (int y = 0; y < h; ++y)
1003 	{
1004 		for (int x = 0; x < w; ++x)
1005 		{
1006 			const tcu::Vec4		resultPixel	= result.getPixel(x, y);
1007 			const tcu::Vec4		resultColor	= (resultPixel - lookupBias) / lookupScale;
1008 			const tcu::Vec4		texCoord	= texCoords.getPixel(x, y);
1009 			const bool			pixelOk		= isLookupResultValid(texture, sampler, lookupPrecision, texCoord, lodBounds, resultColor);
1010 
1011 			errorMask.setPixel(tcu::Vec4(pixelOk?0.0f:1.0f, pixelOk?1.0f:0.0f, 0.0f, 1.0f), x, y);
1012 
1013 			if (!pixelOk)
1014 				allOk = false;
1015 		}
1016 	}
1017 
1018 	return allOk;
1019 }
1020 
1021 template<typename ScalarType>
getSwizzledComp(const tcu::Vector<ScalarType, 4>& vec, vk::VkComponentSwizzle comp, int identityNdx)1022 ScalarType getSwizzledComp (const tcu::Vector<ScalarType, 4>& vec, vk::VkComponentSwizzle comp, int identityNdx)
1023 {
1024 	if (comp == vk::VK_COMPONENT_SWIZZLE_IDENTITY)
1025 		return vec[identityNdx];
1026 	else if (comp == vk::VK_COMPONENT_SWIZZLE_ZERO)
1027 		return ScalarType(0);
1028 	else if (comp == vk::VK_COMPONENT_SWIZZLE_ONE)
1029 		return ScalarType(1);
1030 	else
1031 		return vec[comp - vk::VK_COMPONENT_SWIZZLE_R];
1032 }
1033 
1034 template<typename ScalarType>
swizzle(const tcu::Vector<ScalarType, 4>& vec, const vk::VkComponentMapping& swz)1035 tcu::Vector<ScalarType, 4> swizzle (const tcu::Vector<ScalarType, 4>& vec, const vk::VkComponentMapping& swz)
1036 {
1037 	return tcu::Vector<ScalarType, 4>(getSwizzledComp(vec, swz.r, 0),
1038 									  getSwizzledComp(vec, swz.g, 1),
1039 									  getSwizzledComp(vec, swz.b, 2),
1040 									  getSwizzledComp(vec, swz.a, 3));
1041 }
1042 
1043 /*--------------------------------------------------------------------*//*!
1044 * \brief Swizzle scale or bias vector by given mapping
1045 *
1046 * \param vec scale or bias vector
1047 * \param swz swizzle component mapping, may include ZERO, ONE, or IDENTITY
1048 * \param zeroOrOneValue vector value for component swizzled as ZERO or ONE
1049 * \return swizzled vector
1050 *//*--------------------------------------------------------------------*/
swizzleScaleBias(const tcu::Vec4& vec, const vk::VkComponentMapping& swz, float zeroOrOneValue)1051 tcu::Vec4 swizzleScaleBias (const tcu::Vec4& vec, const vk::VkComponentMapping& swz, float zeroOrOneValue)
1052 {
1053 
1054 	// Remove VK_COMPONENT_SWIZZLE_IDENTITY to avoid addressing channelValues[0]
1055 	const vk::VkComponentMapping nonIdentitySwz =
1056 	{
1057 		swz.r == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_R : swz.r,
1058 		swz.g == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_G : swz.g,
1059 		swz.b == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_B : swz.b,
1060 		swz.a == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_A : swz.a
1061 	};
1062 
1063 	const float channelValues[] =
1064 	{
1065 		-1.0f,				// impossible
1066 		zeroOrOneValue,		// SWIZZLE_ZERO
1067 		zeroOrOneValue,		// SWIZZLE_ONE
1068 		vec.x(),
1069 		vec.y(),
1070 		vec.z(),
1071 		vec.w(),
1072 	};
1073 
1074 	return tcu::Vec4(channelValues[nonIdentitySwz.r], channelValues[nonIdentitySwz.g], channelValues[nonIdentitySwz.b], channelValues[nonIdentitySwz.a]);
1075 }
1076 
1077 template<typename ScalarType>
swizzleT(const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& dst, const vk::VkComponentMapping& swz)1078 void swizzleT (const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& dst, const vk::VkComponentMapping& swz)
1079 {
1080 	for (int z = 0; z < dst.getDepth(); ++z)
1081 	for (int y = 0; y < dst.getHeight(); ++y)
1082 	for (int x = 0; x < dst.getWidth(); ++x)
1083 		dst.setPixel(swizzle(src.getPixelT<ScalarType>(x, y, z), swz), x, y, z);
1084 }
1085 
swizzleFromSRGB(const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& dst, const vk::VkComponentMapping& swz)1086 void swizzleFromSRGB (const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& dst, const vk::VkComponentMapping& swz)
1087 {
1088 	for (int z = 0; z < dst.getDepth(); ++z)
1089 	for (int y = 0; y < dst.getHeight(); ++y)
1090 	for (int x = 0; x < dst.getWidth(); ++x)
1091 		dst.setPixel(swizzle(tcu::sRGBToLinear(src.getPixelT<float>(x, y, z)), swz), x, y, z);
1092 }
1093 
swizzle(const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& dst, const vk::VkComponentMapping& swz)1094 void swizzle (const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& dst, const vk::VkComponentMapping& swz)
1095 {
1096 	const tcu::TextureChannelClass	chnClass	= tcu::getTextureChannelClass(dst.getFormat().type);
1097 
1098 	DE_ASSERT(src.getWidth() == dst.getWidth() &&
1099 			  src.getHeight() == dst.getHeight() &&
1100 			  src.getDepth() == dst.getDepth());
1101 
1102 	if (chnClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
1103 		swizzleT<deInt32>(src, dst, swz);
1104 	else if (chnClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
1105 		swizzleT<deUint32>(src, dst, swz);
1106 	else if (tcu::isSRGB(src.getFormat()) && !tcu::isSRGB(dst.getFormat()))
1107 		swizzleFromSRGB(src, dst, swz);
1108 	else
1109 		swizzleT<float>(src, dst, swz);
1110 }
1111 
isIdentitySwizzle(const vk::VkComponentMapping& swz)1112 bool isIdentitySwizzle (const vk::VkComponentMapping& swz)
1113 {
1114 	return (swz.r == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.r == vk::VK_COMPONENT_SWIZZLE_R) &&
1115 		   (swz.g == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.g == vk::VK_COMPONENT_SWIZZLE_G) &&
1116 		   (swz.b == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.b == vk::VK_COMPONENT_SWIZZLE_B) &&
1117 		   (swz.a == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.a == vk::VK_COMPONENT_SWIZZLE_A);
1118 }
1119 
1120 template<typename TextureViewType> struct TexViewTraits;
1121 
1122 template<> struct TexViewTraits<tcu::Texture1DView>			{ typedef tcu::Texture1D		TextureType; };
1123 template<> struct TexViewTraits<tcu::Texture1DArrayView>	{ typedef tcu::Texture1DArray	TextureType; };
1124 template<> struct TexViewTraits<tcu::Texture2DView>			{ typedef tcu::Texture2D		TextureType; };
1125 template<> struct TexViewTraits<tcu::Texture2DArrayView>	{ typedef tcu::Texture2DArray	TextureType; };
1126 template<> struct TexViewTraits<tcu::TextureCubeView>		{ typedef tcu::TextureCube		TextureType; };
1127 template<> struct TexViewTraits<tcu::TextureCubeArrayView>	{ typedef tcu::TextureCubeArray	TextureType; };
1128 template<> struct TexViewTraits<tcu::Texture3DView>			{ typedef tcu::Texture3D		TextureType; };
1129 
1130 template<typename TextureViewType>
1131 typename TexViewTraits<TextureViewType>::TextureType* createSkeletonClone (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0);
1132 
getSwizzleTargetFormat(tcu::TextureFormat format)1133 tcu::TextureFormat getSwizzleTargetFormat (tcu::TextureFormat format)
1134 {
1135 	// Swizzled texture needs to hold all four channels
1136 	// \todo [2016-09-21 pyry] We could save some memory by using smaller formats
1137 	//						   when possible (for example U8).
1138 
1139 	const tcu::TextureChannelClass	chnClass	= tcu::getTextureChannelClass(format.type);
1140 
1141 	if (chnClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
1142 		return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32);
1143 	else if (chnClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
1144 		return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32);
1145 	else
1146 		return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
1147 }
1148 
1149 template<>
createSkeletonClone(tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)1150 tcu::Texture1D* createSkeletonClone<tcu::Texture1DView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1151 {
1152 	return new tcu::Texture1D(format, level0.getWidth());
1153 }
1154 
1155 template<>
createSkeletonClone(tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)1156 tcu::Texture1DArray* createSkeletonClone<tcu::Texture1DArrayView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1157 {
1158 	return new tcu::Texture1DArray(format, level0.getWidth(), level0.getHeight());
1159 }
1160 
1161 template<>
createSkeletonClone(tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)1162 tcu::Texture2D* createSkeletonClone<tcu::Texture2DView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1163 {
1164 	return new tcu::Texture2D(format, level0.getWidth(), level0.getHeight());
1165 }
1166 
1167 template<>
createSkeletonClone(tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)1168 tcu::Texture2DArray* createSkeletonClone<tcu::Texture2DArrayView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1169 {
1170 	return new tcu::Texture2DArray(format, level0.getWidth(), level0.getHeight(), level0.getDepth());
1171 }
1172 
1173 template<>
createSkeletonClone(tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)1174 tcu::Texture3D* createSkeletonClone<tcu::Texture3DView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1175 {
1176 	return new tcu::Texture3D(format, level0.getWidth(), level0.getHeight(), level0.getDepth());
1177 }
1178 
1179 template<>
createSkeletonClone(tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)1180 tcu::TextureCubeArray* createSkeletonClone<tcu::TextureCubeArrayView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0)
1181 {
1182 	return new tcu::TextureCubeArray(format, level0.getWidth(), level0.getDepth());
1183 }
1184 
1185 template<typename TextureViewType>
createSwizzledCopy(const TextureViewType& texture, const vk::VkComponentMapping& swz)1186 MovePtr<typename TexViewTraits<TextureViewType>::TextureType> createSwizzledCopy (const TextureViewType& texture, const vk::VkComponentMapping& swz)
1187 {
1188 	MovePtr<typename TexViewTraits<TextureViewType>::TextureType>	copy	(createSkeletonClone<TextureViewType>(getSwizzleTargetFormat(texture.getLevel(0).getFormat()), texture.getLevel(0)));
1189 
1190 	for (int levelNdx = 0; levelNdx < texture.getNumLevels(); ++levelNdx)
1191 	{
1192 		copy->allocLevel(levelNdx);
1193 		swizzle(texture.getLevel(levelNdx), copy->getLevel(levelNdx), swz);
1194 	}
1195 
1196 	return copy;
1197 }
1198 
1199 template<>
createSwizzledCopy(const tcu::TextureCubeView& texture, const vk::VkComponentMapping& swz)1200 MovePtr<tcu::TextureCube> createSwizzledCopy (const tcu::TextureCubeView& texture, const vk::VkComponentMapping& swz)
1201 {
1202 	MovePtr<tcu::TextureCube>	copy	(new tcu::TextureCube(getSwizzleTargetFormat(texture.getLevelFace(0, tcu::CUBEFACE_NEGATIVE_X).getFormat()), texture.getSize()));
1203 
1204 	for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
1205 	{
1206 		for (int levelNdx = 0; levelNdx < texture.getNumLevels(); ++levelNdx)
1207 		{
1208 			copy->allocLevel((tcu::CubeFace)faceNdx, levelNdx);
1209 			swizzle(texture.getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), copy->getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), swz);
1210 		}
1211 	}
1212 
1213 	return copy;
1214 }
1215 
1216 template<typename TextureViewType>
validateResultImage(const TextureViewType& texture, const tcu::Sampler& sampler, const vk::VkComponentMapping& swz, const tcu::ConstPixelBufferAccess& texCoords, const tcu::Vec2& lodBounds, const tcu::LookupPrecision& lookupPrecision, const tcu::Vec4& lookupScale, const tcu::Vec4& lookupBias, const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask)1217 bool validateResultImage (const TextureViewType&				texture,
1218 						  const tcu::Sampler&					sampler,
1219 						  const vk::VkComponentMapping&			swz,
1220 						  const tcu::ConstPixelBufferAccess&	texCoords,
1221 						  const tcu::Vec2&						lodBounds,
1222 						  const tcu::LookupPrecision&			lookupPrecision,
1223 						  const tcu::Vec4&						lookupScale,
1224 						  const tcu::Vec4&						lookupBias,
1225 						  const tcu::ConstPixelBufferAccess&	result,
1226 						  const tcu::PixelBufferAccess&			errorMask)
1227 {
1228 	if (isIdentitySwizzle(swz))
1229 		return validateResultImage(texture, sampler, texCoords, lodBounds, lookupPrecision, lookupScale, lookupBias, result, errorMask);
1230 	else
1231 	{
1232 		// There is (currently) no way to handle swizzling inside validation loop
1233 		// and thus we need to pre-swizzle the texture.
1234 		UniquePtr<typename TexViewTraits<TextureViewType>::TextureType>	swizzledTex	(createSwizzledCopy(texture, swz));
1235 
1236 		return validateResultImage(*swizzledTex, sampler, texCoords, lodBounds, lookupPrecision, swizzleScaleBias(lookupScale, swz, 1.0f), swizzleScaleBias(lookupBias, swz, 0.0f), result, errorMask);
1237 	}
1238 }
1239 
resolveSubresourceRange(const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource)1240 vk::VkImageSubresourceRange resolveSubresourceRange (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource)
1241 {
1242 	vk::VkImageSubresourceRange	resolved					= subresource;
1243 
1244 	if (subresource.levelCount == VK_REMAINING_MIP_LEVELS)
1245 		resolved.levelCount = testTexture.getNumLevels()-subresource.baseMipLevel;
1246 
1247 	if (subresource.layerCount == VK_REMAINING_ARRAY_LAYERS)
1248 		resolved.layerCount = testTexture.getArraySize()-subresource.baseArrayLayer;
1249 
1250 	return resolved;
1251 }
1252 
getTexture1DView(const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)1253 MovePtr<tcu::Texture1DView> getTexture1DView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1254 {
1255 	DE_ASSERT(subresource.layerCount == 1);
1256 
1257 	levels.resize(subresource.levelCount);
1258 
1259 	for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1260 	{
1261 		const tcu::ConstPixelBufferAccess& srcLevel = testTexture.getLevel((int)subresource.baseMipLevel+levelNdx, subresource.baseArrayLayer);
1262 
1263 		levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, 0, srcLevel.getWidth(), 1, 1);
1264 	}
1265 
1266 	return MovePtr<tcu::Texture1DView>(new tcu::Texture1DView((int)levels.size(), &levels[0]));
1267 }
1268 
getTexture1DArrayView(const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)1269 MovePtr<tcu::Texture1DArrayView> getTexture1DArrayView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1270 {
1271 	const TestTexture1D*		tex1D		= dynamic_cast<const TestTexture1D*>(&testTexture);
1272 	const TestTexture1DArray*	tex1DArray	= dynamic_cast<const TestTexture1DArray*>(&testTexture);
1273 
1274 	DE_ASSERT(!!tex1D != !!tex1DArray);
1275 	DE_ASSERT(tex1DArray || subresource.baseArrayLayer == 0);
1276 
1277 	levels.resize(subresource.levelCount);
1278 
1279 	for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1280 	{
1281 		const tcu::ConstPixelBufferAccess& srcLevel = tex1D ? tex1D->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx)
1282 															: tex1DArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx);
1283 
1284 		levels[levelNdx] = tcu::getSubregion(srcLevel, 0, (int)subresource.baseArrayLayer, 0, srcLevel.getWidth(), (int)subresource.layerCount, 1);
1285 	}
1286 
1287 	return MovePtr<tcu::Texture1DArrayView>(new tcu::Texture1DArrayView((int)levels.size(), &levels[0]));
1288 }
1289 
getTexture2DView(const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)1290 MovePtr<tcu::Texture2DView> getTexture2DView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1291 {
1292 	const TestTexture2D*		tex2D		= dynamic_cast<const TestTexture2D*>(&testTexture);
1293 	const TestTexture2DArray*	tex2DArray	= dynamic_cast<const TestTexture2DArray*>(&testTexture);
1294 
1295 	DE_ASSERT(subresource.layerCount == 1);
1296 	DE_ASSERT(!!tex2D != !!tex2DArray);
1297 	DE_ASSERT(tex2DArray || subresource.baseArrayLayer == 0);
1298 
1299 	levels.resize(subresource.levelCount);
1300 
1301 	for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1302 	{
1303 		const tcu::ConstPixelBufferAccess& srcLevel = tex2D ? tex2D->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx)
1304 															: tex2DArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx);
1305 
1306 		levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer, srcLevel.getWidth(), srcLevel.getHeight(), 1);
1307 	}
1308 
1309 	return MovePtr<tcu::Texture2DView>(new tcu::Texture2DView((int)levels.size(), &levels[0]));
1310 }
1311 
getTexture2DArrayView(const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)1312 MovePtr<tcu::Texture2DArrayView> getTexture2DArrayView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1313 {
1314 	const TestTexture2D*		tex2D		= dynamic_cast<const TestTexture2D*>(&testTexture);
1315 	const TestTexture2DArray*	tex2DArray	= dynamic_cast<const TestTexture2DArray*>(&testTexture);
1316 
1317 	DE_ASSERT(!!tex2D != !!tex2DArray);
1318 	DE_ASSERT(tex2DArray || subresource.baseArrayLayer == 0);
1319 
1320 	levels.resize(subresource.levelCount);
1321 
1322 	for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1323 	{
1324 		const tcu::ConstPixelBufferAccess& srcLevel = tex2D ? tex2D->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx)
1325 															: tex2DArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx);
1326 
1327 		levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer, srcLevel.getWidth(), srcLevel.getHeight(), (int)subresource.layerCount);
1328 	}
1329 
1330 	return MovePtr<tcu::Texture2DArrayView>(new tcu::Texture2DArrayView((int)levels.size(), &levels[0]));
1331 }
1332 
getTextureCubeView(const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)1333 MovePtr<tcu::TextureCubeView> getTextureCubeView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1334 {
1335 	const static tcu::CubeFace s_faceMap[tcu::CUBEFACE_LAST] =
1336 	{
1337 		tcu::CUBEFACE_POSITIVE_X,
1338 		tcu::CUBEFACE_NEGATIVE_X,
1339 		tcu::CUBEFACE_POSITIVE_Y,
1340 		tcu::CUBEFACE_NEGATIVE_Y,
1341 		tcu::CUBEFACE_POSITIVE_Z,
1342 		tcu::CUBEFACE_NEGATIVE_Z
1343 	};
1344 
1345 	const TestTextureCube*		texCube			= dynamic_cast<const TestTextureCube*>(&testTexture);
1346 	const TestTextureCubeArray*	texCubeArray	= dynamic_cast<const TestTextureCubeArray*>(&testTexture);
1347 
1348 	DE_ASSERT(!!texCube != !!texCubeArray);
1349 	DE_ASSERT(subresource.layerCount == 6);
1350 	DE_ASSERT(texCubeArray || subresource.baseArrayLayer == 0);
1351 
1352 	levels.resize(subresource.levelCount*tcu::CUBEFACE_LAST);
1353 
1354 	for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
1355 	{
1356 		for (int levelNdx = 0; levelNdx < (int)subresource.levelCount; ++levelNdx)
1357 		{
1358 			const tcu::ConstPixelBufferAccess& srcLevel = texCubeArray ? texCubeArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx)
1359 																	   : texCube->getTexture().getLevelFace(levelNdx, s_faceMap[faceNdx]);
1360 
1361 			levels[faceNdx*subresource.levelCount + levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer + (texCubeArray ? faceNdx : 0), srcLevel.getWidth(), srcLevel.getHeight(), 1);
1362 		}
1363 	}
1364 
1365 	{
1366 		const tcu::ConstPixelBufferAccess*	reordered[tcu::CUBEFACE_LAST];
1367 
1368 		for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
1369 			reordered[s_faceMap[faceNdx]] = &levels[faceNdx*subresource.levelCount];
1370 
1371 		return MovePtr<tcu::TextureCubeView>(new tcu::TextureCubeView((int)subresource.levelCount, reordered));
1372 	}
1373 }
1374 
getTextureCubeArrayView(const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)1375 MovePtr<tcu::TextureCubeArrayView> getTextureCubeArrayView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1376 {
1377 	const TestTextureCubeArray*	texCubeArray	= dynamic_cast<const TestTextureCubeArray*>(&testTexture);
1378 
1379 	DE_ASSERT(texCubeArray);
1380 	DE_ASSERT(subresource.layerCount%6 == 0);
1381 
1382 	levels.resize(subresource.levelCount);
1383 
1384 	for (int levelNdx = 0; levelNdx < (int)subresource.levelCount; ++levelNdx)
1385 	{
1386 		const tcu::ConstPixelBufferAccess& srcLevel = texCubeArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx);
1387 
1388 		levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer, srcLevel.getWidth(), srcLevel.getHeight(), (int)subresource.layerCount);
1389 	}
1390 
1391 	return MovePtr<tcu::TextureCubeArrayView>(new tcu::TextureCubeArrayView((int)levels.size(), &levels[0]));
1392 }
1393 
getTexture3DView(const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)1394 MovePtr<tcu::Texture3DView> getTexture3DView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels)
1395 {
1396 	DE_ASSERT(subresource.baseArrayLayer == 0 && subresource.layerCount == 1);
1397 
1398 	levels.resize(subresource.levelCount);
1399 
1400 	for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx)
1401 		levels[levelNdx] = testTexture.getLevel((int)subresource.baseMipLevel+levelNdx, subresource.baseArrayLayer);
1402 
1403 	return MovePtr<tcu::Texture3DView>(new tcu::Texture3DView((int)levels.size(), &levels[0]));
1404 }
1405 
validateResultImage(const TestTexture& texture, const VkImageViewType imageViewType, const VkImageSubresourceRange& subresource, const tcu::Sampler& sampler, const vk::VkComponentMapping& componentMapping, const tcu::ConstPixelBufferAccess& coordAccess, const tcu::Vec2& lodBounds, const tcu::LookupPrecision& lookupPrecision, const tcu::Vec4& lookupScale, const tcu::Vec4& lookupBias, const tcu::ConstPixelBufferAccess& resultAccess, const tcu::PixelBufferAccess& errorAccess)1406 bool validateResultImage (const TestTexture&					texture,
1407 						  const VkImageViewType					imageViewType,
1408 						  const VkImageSubresourceRange&		subresource,
1409 						  const tcu::Sampler&					sampler,
1410 						  const vk::VkComponentMapping&			componentMapping,
1411 						  const tcu::ConstPixelBufferAccess&	coordAccess,
1412 						  const tcu::Vec2&						lodBounds,
1413 						  const tcu::LookupPrecision&			lookupPrecision,
1414 						  const tcu::Vec4&						lookupScale,
1415 						  const tcu::Vec4&						lookupBias,
1416 						  const tcu::ConstPixelBufferAccess&	resultAccess,
1417 						  const tcu::PixelBufferAccess&			errorAccess)
1418 {
1419 	std::vector<tcu::ConstPixelBufferAccess>	levels;
1420 
1421 	switch (imageViewType)
1422 	{
1423 		case VK_IMAGE_VIEW_TYPE_1D:
1424 		{
1425 			UniquePtr<tcu::Texture1DView>			texView(getTexture1DView(texture, subresource, levels));
1426 
1427 			return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1428 		}
1429 
1430 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1431 		{
1432 			UniquePtr<tcu::Texture1DArrayView>		texView(getTexture1DArrayView(texture, subresource, levels));
1433 
1434 			return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1435 		}
1436 
1437 		case VK_IMAGE_VIEW_TYPE_2D:
1438 		{
1439 			UniquePtr<tcu::Texture2DView>			texView(getTexture2DView(texture, subresource, levels));
1440 
1441 			return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1442 		}
1443 
1444 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
1445 		{
1446 			UniquePtr<tcu::Texture2DArrayView>		texView(getTexture2DArrayView(texture, subresource, levels));
1447 
1448 			return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1449 		}
1450 
1451 		case VK_IMAGE_VIEW_TYPE_CUBE:
1452 		{
1453 			UniquePtr<tcu::TextureCubeView>			texView(getTextureCubeView(texture, subresource, levels));
1454 
1455 			return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1456 		}
1457 
1458 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
1459 		{
1460 			UniquePtr<tcu::TextureCubeArrayView>	texView(getTextureCubeArrayView(texture, subresource, levels));
1461 
1462 			return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1463 		}
1464 
1465 		case VK_IMAGE_VIEW_TYPE_3D:
1466 		{
1467 			UniquePtr<tcu::Texture3DView>			texView(getTexture3DView(texture, subresource, levels));
1468 
1469 			return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess);
1470 		}
1471 
1472 		default:
1473 			DE_ASSERT(false);
1474 			return false;
1475 	}
1476 }
1477 
1478 } // anonymous
1479 
verifyImage(void)1480 tcu::TestStatus ImageSamplingInstance::verifyImage (void)
1481 {
1482 	const VkPhysicalDeviceLimits&		limits					= m_context.getDeviceProperties().limits;
1483 	// \note Color buffer is used to capture coordinates - not sampled texture values
1484 	const tcu::TextureFormat			colorFormat				(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
1485 	const tcu::TextureFormat			depthStencilFormat;		// Undefined depth/stencil format.
1486 	const CoordinateCaptureProgram		coordCaptureProgram;
1487 	const rr::Program					rrProgram				= coordCaptureProgram.getReferenceProgram();
1488 	ReferenceRenderer					refRenderer				(m_renderSize.x(), m_renderSize.y(), 1, colorFormat, depthStencilFormat, &rrProgram);
1489 	const bool							useStencilAspect		= (m_subresourceRange.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT);
1490 
1491 	bool								compareOkAll			= true;
1492 
1493 	tcu::Vec4							lookupScale				(1.0f);
1494 	tcu::Vec4							lookupBias				(0.0f);
1495 
1496 	getLookupScaleBias(m_imageFormat, lookupScale, lookupBias, useStencilAspect);
1497 
1498 	// Render out coordinates
1499 	{
1500 		const rr::RenderState renderState(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
1501 		refRenderer.draw(renderState, rr::PRIMITIVETYPE_TRIANGLES, m_vertices);
1502 	}
1503 
1504 	// Verify results
1505 	{
1506 		const tcu::Sampler					sampler			= mapVkSampler(m_samplerParams);
1507 		const float							referenceLod	= de::clamp(m_samplerParams.mipLodBias + m_samplerLod, m_samplerParams.minLod, m_samplerParams.maxLod);
1508 		const float							lodError		= 1.0f / static_cast<float>((1u << limits.mipmapPrecisionBits) - 1u);
1509 		const tcu::Vec2						lodBounds		(referenceLod - lodError, referenceLod + lodError);
1510 		const vk::VkImageSubresourceRange	subresource		= resolveSubresourceRange(*m_texture, m_subresourceRange);
1511 
1512 		const tcu::ConstPixelBufferAccess	coordAccess		= refRenderer.getAccess();
1513 		tcu::TextureLevel					errorMask		(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), (int)m_renderSize.x(), (int)m_renderSize.y());
1514 		const tcu::PixelBufferAccess		errorAccess		= errorMask.getAccess();
1515 
1516 		const bool							isNearestOnly	= (m_samplerParams.minFilter == VK_FILTER_NEAREST && m_samplerParams.magFilter == VK_FILTER_NEAREST);
1517 
1518 		tcu::LookupPrecision				lookupPrecision;
1519 
1520 		// Set precision requirements - very low for these tests as
1521 		// the point of the test is not to validate accuracy.
1522 		lookupPrecision.coordBits		= tcu::IVec3(17, 17, 17);
1523 		lookupPrecision.uvwBits			= tcu::IVec3(5, 5, 5);
1524 		lookupPrecision.colorMask		= m_componentMask;
1525 		lookupPrecision.colorThreshold	= tcu::computeFixedPointThreshold(max((tcu::IVec4(8, 8, 8, 8) - (isNearestOnly ? 1 : 2)), tcu::IVec4(0))) / swizzleScaleBias(lookupScale, m_componentMapping, 1.0f);
1526 
1527 		if (m_imageFormat == VK_FORMAT_BC5_UNORM_BLOCK || m_imageFormat == VK_FORMAT_BC5_SNORM_BLOCK)
1528 			lookupPrecision.colorThreshold = tcu::Vec4(0.06f, 0.06f, 0.06f, 0.06f);
1529 		if (tcu::isSRGB(m_texture->getTextureFormat()))
1530 			lookupPrecision.colorThreshold += tcu::Vec4(4.f / 255.f);
1531 
1532 		de::MovePtr<TestTexture>			textureCopy;
1533 		TestTexture*						texture			= DE_NULL;
1534 
1535 		if (isCombinedDepthStencilType(m_texture->getTextureFormat().type))
1536 		{
1537 			// Verification loop does not support reading from combined depth stencil texture levels.
1538 			// Get rid of stencil component.
1539 
1540 			tcu::TextureFormat::ChannelOrder	channelOrder	= tcu::TextureFormat::CHANNELORDER_LAST;
1541 			tcu::TextureFormat::ChannelType		channelType		= tcu::TextureFormat::CHANNELTYPE_LAST;
1542 
1543 			if (subresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
1544 			{
1545 				channelOrder	= tcu::TextureFormat::S;
1546 				channelType		= tcu::TextureFormat::UNSIGNED_INT8;
1547 			}
1548 			else
1549 			{
1550 				channelOrder = tcu::TextureFormat::D;
1551 
1552 				switch (m_texture->getTextureFormat().type)
1553 				{
1554 				case tcu::TextureFormat::UNSIGNED_INT_16_8_8:
1555 					channelType = tcu::TextureFormat::UNORM_INT16;
1556 					break;
1557 				case tcu::TextureFormat::UNSIGNED_INT_24_8:
1558 				case tcu::TextureFormat::UNSIGNED_INT_24_8_REV:
1559 					channelType = tcu::TextureFormat::UNORM_INT24;
1560 					break;
1561 				case tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
1562 					channelType = tcu::TextureFormat::FLOAT;
1563 					break;
1564 				default:
1565 					DE_FATAL("Unhandled texture format type in switch");
1566 				}
1567 			}
1568 
1569 			textureCopy	= m_texture->copy(tcu::TextureFormat(channelOrder, channelType));
1570 			texture		= textureCopy.get();
1571 		}
1572 		else
1573 		{
1574 			texture		= m_texture.get();
1575 		}
1576 
1577 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1578 		{
1579 			// Read back result image
1580 			UniquePtr<tcu::TextureLevel>		result			(readColorAttachment(m_context.getDeviceInterface(),
1581 																					 m_context.getDevice(),
1582 																					 m_context.getUniversalQueue(),
1583 																					 m_context.getUniversalQueueFamilyIndex(),
1584 																					 m_context.getDefaultAllocator(),
1585 																					 **m_colorImages[imgNdx],
1586 																					 m_colorFormat,
1587 																					 m_renderSize));
1588 			const tcu::ConstPixelBufferAccess	resultAccess	= result->getAccess();
1589 			bool								compareOk		= validateResultImage(*texture,
1590 																					  m_imageViewType,
1591 																					  subresource,
1592 																					  sampler,
1593 																					  m_componentMapping,
1594 																					  coordAccess,
1595 																					  lodBounds,
1596 																					  lookupPrecision,
1597 																					  lookupScale,
1598 																					  lookupBias,
1599 																					  resultAccess,
1600 																					  errorAccess);
1601 			if (!compareOk)
1602 				m_context.getTestContext().getLog()
1603 				<< tcu::TestLog::Image("Result", "Result Image", resultAccess)
1604 				<< tcu::TestLog::Image("ErrorMask", "Error Mask", errorAccess);
1605 
1606 			compareOkAll = compareOkAll && compareOk;
1607 		}
1608 	}
1609 
1610 	if (compareOkAll)
1611 		return tcu::TestStatus::pass("Result image matches reference");
1612 	else
1613 		return tcu::TestStatus::fail("Image mismatch");
1614 }
1615 
1616 } // pipeline
1617 } // vkt
1618