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