Home | History | Annotate | Download | only in pipeline
      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 Utilities for images.
     23  *//*--------------------------------------------------------------------*/
     24 
     25 #include "vktPipelineImageUtil.hpp"
     26 #include "vkImageUtil.hpp"
     27 #include "vkMemUtil.hpp"
     28 #include "vkQueryUtil.hpp"
     29 #include "vkRefUtil.hpp"
     30 #include "vkCmdUtil.hpp"
     31 #include "tcuTextureUtil.hpp"
     32 #include "tcuAstcUtil.hpp"
     33 #include "deRandom.hpp"
     34 #include "deSharedPtr.hpp"
     35 
     36 namespace vkt
     37 {
     38 namespace pipeline
     39 {
     40 
     41 using namespace vk;
     42 
     43 /*! Gets the next multiple of a given divisor */
     44 static deUint32 getNextMultiple (deUint32 divisor, deUint32 value)
     45 {
     46 	if (value % divisor == 0)
     47 	{
     48 		return value;
     49 	}
     50 	return value + divisor - (value % divisor);
     51 }
     52 
     53 /*! Gets the next value that is multiple of all given divisors */
     54 static deUint32 getNextMultiple (const std::vector<deUint32>& divisors, deUint32 value)
     55 {
     56 	deUint32	nextMultiple		= value;
     57 	bool		nextMultipleFound	= false;
     58 
     59 	while (true)
     60 	{
     61 		nextMultipleFound = true;
     62 
     63 		for (size_t divNdx = 0; divNdx < divisors.size(); divNdx++)
     64 			nextMultipleFound = nextMultipleFound && (nextMultiple % divisors[divNdx] == 0);
     65 
     66 		if (nextMultipleFound)
     67 			break;
     68 
     69 		DE_ASSERT(nextMultiple < ~((deUint32)0u));
     70 		nextMultiple = getNextMultiple(divisors[0], nextMultiple + 1);
     71 	}
     72 
     73 	return nextMultiple;
     74 }
     75 
     76 bool isSupportedSamplableFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
     77 {
     78 	if (isCompressedFormat(format))
     79 	{
     80 		VkPhysicalDeviceFeatures		physicalFeatures;
     81 		const tcu::CompressedTexFormat	compressedFormat	= mapVkCompressedFormat(format);
     82 
     83 		instanceInterface.getPhysicalDeviceFeatures(device, &physicalFeatures);
     84 
     85 		if (tcu::isAstcFormat(compressedFormat))
     86 		{
     87 			if (!physicalFeatures.textureCompressionASTC_LDR)
     88 				return false;
     89 		}
     90 		else if (tcu::isEtcFormat(compressedFormat))
     91 		{
     92 			if (!physicalFeatures.textureCompressionETC2)
     93 				return false;
     94 		}
     95 		else
     96 		{
     97 			DE_FATAL("Unsupported compressed format");
     98 		}
     99 	}
    100 
    101 	VkFormatProperties	formatProps;
    102 	instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
    103 
    104 	return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u;
    105 }
    106 
    107 bool isLinearFilteringSupported (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkFormat format, VkImageTiling tiling)
    108 {
    109 	const VkFormatProperties	formatProperties	= getPhysicalDeviceFormatProperties(vki, physicalDevice, format);
    110 	const VkFormatFeatureFlags	formatFeatures		= tiling == VK_IMAGE_TILING_LINEAR
    111 													? formatProperties.linearTilingFeatures
    112 													: formatProperties.optimalTilingFeatures;
    113 
    114 	return (formatFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) != 0;
    115 }
    116 
    117 bool isMinMaxFilteringSupported (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkFormat format, VkImageTiling tiling)
    118 {
    119 	const VkFormatProperties	formatProperties	= getPhysicalDeviceFormatProperties(vki, physicalDevice, format);
    120 	const VkFormatFeatureFlags	formatFeatures		= tiling == VK_IMAGE_TILING_LINEAR
    121 													? formatProperties.linearTilingFeatures
    122 													: formatProperties.optimalTilingFeatures;
    123 
    124 	return (formatFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT) != 0;
    125 }
    126 
    127 VkBorderColor getFormatBorderColor (BorderColor color, VkFormat format)
    128 {
    129 	if (!isCompressedFormat(format) && (isIntFormat(format) || isUintFormat(format)))
    130 	{
    131 		switch (color)
    132 		{
    133 			case BORDER_COLOR_OPAQUE_BLACK:			return VK_BORDER_COLOR_INT_OPAQUE_BLACK;
    134 			case BORDER_COLOR_OPAQUE_WHITE:			return VK_BORDER_COLOR_INT_OPAQUE_WHITE;
    135 			case BORDER_COLOR_TRANSPARENT_BLACK:	return VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
    136 			default:
    137 				break;
    138 		}
    139 	}
    140 	else
    141 	{
    142 		switch (color)
    143 		{
    144 			case BORDER_COLOR_OPAQUE_BLACK:			return VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
    145 			case BORDER_COLOR_OPAQUE_WHITE:			return VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
    146 			case BORDER_COLOR_TRANSPARENT_BLACK:	return VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
    147 			default:
    148 				break;
    149 		}
    150 	}
    151 
    152 	DE_ASSERT(false);
    153 	return VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
    154 }
    155 
    156 void getLookupScaleBias (vk::VkFormat format, tcu::Vec4& lookupScale, tcu::Vec4& lookupBias)
    157 {
    158 	if (!isCompressedFormat(format))
    159 	{
    160 		const tcu::TextureFormatInfo	fmtInfo	= tcu::getTextureFormatInfo(mapVkFormat(format));
    161 
    162 		// Needed to normalize various formats to 0..1 range for writing into RT
    163 		lookupScale	= fmtInfo.lookupScale;
    164 		lookupBias	= fmtInfo.lookupBias;
    165 	}
    166 	else
    167 	{
    168 		switch (format)
    169 		{
    170 			case VK_FORMAT_EAC_R11_SNORM_BLOCK:
    171 				lookupScale	= tcu::Vec4(0.5f, 1.0f, 1.0f, 1.0f);
    172 				lookupBias	= tcu::Vec4(0.5f, 0.0f, 0.0f, 0.0f);
    173 				break;
    174 
    175 			case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
    176 				lookupScale	= tcu::Vec4(0.5f, 0.5f, 1.0f, 1.0f);
    177 				lookupBias	= tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f);
    178 				break;
    179 
    180 			default:
    181 				// else: All supported compressed formats are fine with no normalization.
    182 				//		 ASTC LDR blocks decompress to f16 so querying normalization parameters
    183 				//		 based on uncompressed formats would actually lead to massive precision loss
    184 				//		 and complete lack of coverage in case of R8G8B8A8_UNORM RT.
    185 				lookupScale	= tcu::Vec4(1.0f);
    186 				lookupBias	= tcu::Vec4(0.0f);
    187 				break;
    188 		}
    189 	}
    190 }
    191 
    192 de::MovePtr<tcu::TextureLevel> readColorAttachment (const vk::DeviceInterface&	vk,
    193 													vk::VkDevice				device,
    194 													vk::VkQueue					queue,
    195 													deUint32					queueFamilyIndex,
    196 													vk::Allocator&				allocator,
    197 													vk::VkImage					image,
    198 													vk::VkFormat				format,
    199 													const tcu::UVec2&			renderSize)
    200 {
    201 	Move<VkBuffer>					buffer;
    202 	de::MovePtr<Allocation>			bufferAlloc;
    203 	Move<VkCommandPool>				cmdPool;
    204 	Move<VkCommandBuffer>			cmdBuffer;
    205 	Move<VkFence>					fence;
    206 	const tcu::TextureFormat		tcuFormat		= mapVkFormat(format);
    207 	const VkDeviceSize				pixelDataSize	= renderSize.x() * renderSize.y() * tcuFormat.getPixelSize();
    208 	de::MovePtr<tcu::TextureLevel>	resultLevel		(new tcu::TextureLevel(tcuFormat, renderSize.x(), renderSize.y()));
    209 
    210 	// Create destination buffer
    211 	{
    212 		const VkBufferCreateInfo bufferParams =
    213 		{
    214 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
    215 			DE_NULL,									// const void*			pNext;
    216 			0u,											// VkBufferCreateFlags	flags;
    217 			pixelDataSize,								// VkDeviceSize			size;
    218 			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// VkBufferUsageFlags	usage;
    219 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
    220 			0u,											// deUint32				queueFamilyIndexCount;
    221 			DE_NULL										// const deUint32*		pQueueFamilyIndices;
    222 		};
    223 
    224 		buffer		= createBuffer(vk, device, &bufferParams);
    225 		bufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *buffer), MemoryRequirement::HostVisible);
    226 		VK_CHECK(vk.bindBufferMemory(device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
    227 	}
    228 
    229 	// Create command pool and buffer
    230 	cmdPool		= createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
    231 	cmdBuffer	= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
    232 
    233 	// Create fence
    234 	fence = createFence(vk, device);
    235 
    236 	beginCommandBuffer(vk, *cmdBuffer);
    237 	copyImageToBuffer(vk, *cmdBuffer, image, *buffer, tcu::IVec2(renderSize.x(), renderSize.y()));
    238 	endCommandBuffer(vk, *cmdBuffer);
    239 
    240 	submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
    241 
    242 	// Read buffer data
    243 	invalidateAlloc(vk, device, *bufferAlloc);
    244 	tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), bufferAlloc->getHostPtr()));
    245 
    246 	return resultLevel;
    247 }
    248 
    249 void uploadTestTextureInternal (const DeviceInterface&	vk,
    250 								VkDevice				device,
    251 								VkQueue					queue,
    252 								deUint32				queueFamilyIndex,
    253 								Allocator&				allocator,
    254 								const TestTexture&		srcTexture,
    255 								const TestTexture*		srcStencilTexture,
    256 								tcu::TextureFormat		format,
    257 								VkImage					destImage)
    258 {
    259 	Move<VkBuffer>					buffer;
    260 	de::MovePtr<Allocation>			bufferAlloc;
    261 	Move<VkCommandPool>				cmdPool;
    262 	Move<VkCommandBuffer>			cmdBuffer;
    263 	const VkImageAspectFlags		imageAspectFlags	= getImageAspectFlags(format);
    264 	deUint32						stencilOffset		= 0u;
    265 	std::vector<VkBufferImageCopy>	copyRegions			= srcTexture.getBufferCopyRegions();
    266 	deUint32						bufferSize			= (srcTexture.isCompressed())? srcTexture.getCompressedSize(): srcTexture.getSize();
    267 
    268 	// Stencil-only texture should be provided if (and only if) the image has a combined DS format
    269 	DE_ASSERT((tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order)) == (srcStencilTexture != DE_NULL));
    270 
    271 	if (srcStencilTexture != DE_NULL)
    272 	{
    273 		stencilOffset	= static_cast<deUint32>(deAlign32(static_cast<deInt32>(bufferSize), 4));
    274 		bufferSize		= stencilOffset + srcStencilTexture->getSize();
    275 	}
    276 
    277 	// Create source buffer
    278 	{
    279 		const VkBufferCreateInfo bufferParams =
    280 		{
    281 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType      sType;
    282 			DE_NULL,								// const void*          pNext;
    283 			0u,										// VkBufferCreateFlags  flags;
    284 			bufferSize,								// VkDeviceSize         size;
    285 			VK_BUFFER_USAGE_TRANSFER_SRC_BIT,		// VkBufferUsageFlags   usage;
    286 			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode        sharingMode;
    287 			0u,										// deUint32             queueFamilyIndexCount;
    288 			DE_NULL,								// const deUint32*      pQueueFamilyIndices;
    289 		};
    290 
    291 		buffer		= createBuffer(vk, device, &bufferParams);
    292 		bufferAlloc	= allocator.allocate(getBufferMemoryRequirements(vk, device, *buffer), MemoryRequirement::HostVisible);
    293 		VK_CHECK(vk.bindBufferMemory(device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
    294 	}
    295 
    296 	// Write buffer data
    297 	{
    298 		srcTexture.write(reinterpret_cast<deUint8*>(bufferAlloc->getHostPtr()));
    299 
    300 		if (srcStencilTexture != DE_NULL)
    301 		{
    302 			DE_ASSERT(stencilOffset != 0u);
    303 
    304 			srcStencilTexture->write(reinterpret_cast<deUint8*>(bufferAlloc->getHostPtr()) + stencilOffset);
    305 
    306 			std::vector<VkBufferImageCopy>	stencilCopyRegions = srcStencilTexture->getBufferCopyRegions();
    307 			for (size_t regionIdx = 0; regionIdx < stencilCopyRegions.size(); regionIdx++)
    308 			{
    309 				VkBufferImageCopy region = stencilCopyRegions[regionIdx];
    310 				region.bufferOffset += stencilOffset;
    311 
    312 				copyRegions.push_back(region);
    313 			}
    314 		}
    315 
    316 		flushAlloc(vk, device, *bufferAlloc);
    317 	}
    318 
    319 	copyBufferToImage(vk, device, queue, queueFamilyIndex, *buffer, bufferSize, copyRegions, DE_NULL, imageAspectFlags, srcTexture.getNumLevels(), srcTexture.getArraySize(), destImage);
    320 }
    321 
    322 bool checkSparseImageFormatSupport (const VkPhysicalDevice		physicalDevice,
    323 									const InstanceInterface&	instance,
    324 									const VkImageCreateInfo&	imageCreateInfo)
    325 {
    326 	const std::vector<VkSparseImageFormatProperties> sparseImageFormatPropVec =
    327 		getPhysicalDeviceSparseImageFormatProperties(instance, physicalDevice, imageCreateInfo.format, imageCreateInfo.imageType, imageCreateInfo.samples, imageCreateInfo.usage, imageCreateInfo.tiling);
    328 
    329 	return (sparseImageFormatPropVec.size() != 0);
    330 }
    331 
    332 void uploadTestTextureInternalSparse (const DeviceInterface&					vk,
    333 									  VkDevice									device,
    334 									  const VkPhysicalDevice					physicalDevice,
    335 									  const InstanceInterface&					instance,
    336 									  const VkImageCreateInfo&					imageCreateInfo,
    337 									  VkQueue									universalQueue,
    338 									  deUint32									universalQueueFamilyIndex,
    339 									  VkQueue									sparseQueue,
    340 									  Allocator&								allocator,
    341 									  std::vector<de::SharedPtr<Allocation> >&	allocations,
    342 									  const TestTexture&						srcTexture,
    343 									  const TestTexture*						srcStencilTexture,
    344 									  tcu::TextureFormat						format,
    345 									  VkImage									destImage)
    346 {
    347 	deUint32						bufferSize				= (srcTexture.isCompressed()) ? srcTexture.getCompressedSize(): srcTexture.getSize();
    348 	const VkImageAspectFlags		imageAspectFlags		= getImageAspectFlags(format);
    349 	deUint32						stencilOffset			= 0u;
    350 	const Unique<VkSemaphore>		imageMemoryBindSemaphore(createSemaphore(vk, device));
    351 	Move<VkCommandPool>				cmdPool					= createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, universalQueueFamilyIndex);
    352 	Move<VkCommandBuffer>			cmdBuffer				= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
    353 	Move<VkFence>					fence					= createFence(vk, device);
    354 	std::vector<VkBufferImageCopy>	copyRegions				= srcTexture.getBufferCopyRegions();
    355 	Move<VkBuffer>					buffer;
    356 	de::MovePtr<Allocation>			bufferAlloc;
    357 
    358 	// Stencil-only texture should be provided if (and only if) the image has a combined DS format
    359 	DE_ASSERT((tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order)) == (srcStencilTexture != DE_NULL));
    360 
    361 	if (srcStencilTexture != DE_NULL)
    362 	{
    363 		stencilOffset	= static_cast<deUint32>(deAlign32(static_cast<deInt32>(bufferSize), 4));
    364 		bufferSize		= stencilOffset + srcStencilTexture->getSize();
    365 	}
    366 
    367 	allocateAndBindSparseImage (vk, device, physicalDevice, instance, imageCreateInfo, imageMemoryBindSemaphore.get(), sparseQueue, allocator, allocations, format, destImage);
    368 
    369 	{
    370 		// Create source buffer
    371 		const VkBufferCreateInfo bufferParams =
    372 		{
    373 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
    374 			DE_NULL,									// const void*			pNext;
    375 			0u,											// VkBufferCreateFlags	flags;
    376 			bufferSize,									// VkDeviceSize			size;
    377 			VK_BUFFER_USAGE_TRANSFER_SRC_BIT,			// VkBufferUsageFlags	usage;
    378 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
    379 			0u,											// deUint32				queueFamilyIndexCount;
    380 			DE_NULL,									// const deUint32*		pQueueFamilyIndices;
    381 		};
    382 
    383 		buffer		= createBuffer(vk, device, &bufferParams);
    384 		bufferAlloc	= allocator.allocate(getBufferMemoryRequirements(vk, device, *buffer), MemoryRequirement::HostVisible);
    385 
    386 		VK_CHECK(vk.bindBufferMemory(device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
    387 	}
    388 
    389 	{
    390 		// Write buffer data
    391 		srcTexture.write(reinterpret_cast<deUint8*>(bufferAlloc->getHostPtr()));
    392 
    393 		if (srcStencilTexture != DE_NULL)
    394 		{
    395 			DE_ASSERT(stencilOffset != 0u);
    396 
    397 			srcStencilTexture->write(reinterpret_cast<deUint8*>(bufferAlloc->getHostPtr()) + stencilOffset);
    398 
    399 			std::vector<VkBufferImageCopy>	stencilCopyRegions = srcStencilTexture->getBufferCopyRegions();
    400 			for (size_t regionIdx = 0; regionIdx < stencilCopyRegions.size(); regionIdx++)
    401 			{
    402 				VkBufferImageCopy region = stencilCopyRegions[regionIdx];
    403 				region.bufferOffset += stencilOffset;
    404 
    405 				copyRegions.push_back(region);
    406 			}
    407 		}
    408 
    409 		flushAlloc(vk, device, *bufferAlloc);
    410 	}
    411 
    412 	copyBufferToImage(vk, device, universalQueue, universalQueueFamilyIndex, *buffer, bufferSize, copyRegions, &(*imageMemoryBindSemaphore), imageAspectFlags, imageCreateInfo.mipLevels, imageCreateInfo.arrayLayers, destImage);
    413 }
    414 
    415 void uploadTestTexture (const DeviceInterface&			vk,
    416 						VkDevice						device,
    417 						VkQueue							queue,
    418 						deUint32						queueFamilyIndex,
    419 						Allocator&						allocator,
    420 						const TestTexture&				srcTexture,
    421 						VkImage							destImage)
    422 {
    423 	if (tcu::isCombinedDepthStencilType(srcTexture.getTextureFormat().type))
    424 	{
    425 		de::MovePtr<TestTexture> srcDepthTexture;
    426 		de::MovePtr<TestTexture> srcStencilTexture;
    427 
    428 		if (tcu::hasDepthComponent(srcTexture.getTextureFormat().order))
    429 		{
    430 			tcu::TextureFormat format;
    431 			switch (srcTexture.getTextureFormat().type)
    432 			{
    433 				case tcu::TextureFormat::UNSIGNED_INT_16_8_8:
    434 					format = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
    435 					break;
    436 				case tcu::TextureFormat::UNSIGNED_INT_24_8_REV:
    437 					format = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNSIGNED_INT_24_8_REV);
    438 					break;
    439 				case tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
    440 					format = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT);
    441 					break;
    442 				default:
    443 					DE_FATAL("Unexpected source texture format.");
    444 					break;
    445 			}
    446 			srcDepthTexture = srcTexture.copy(format);
    447 		}
    448 
    449 		if (tcu::hasStencilComponent(srcTexture.getTextureFormat().order))
    450 			srcStencilTexture = srcTexture.copy(tcu::getEffectiveDepthStencilTextureFormat(srcTexture.getTextureFormat(), tcu::Sampler::MODE_STENCIL));
    451 
    452 		uploadTestTextureInternal(vk, device, queue, queueFamilyIndex, allocator, *srcDepthTexture, srcStencilTexture.get(), srcTexture.getTextureFormat(), destImage);
    453 	}
    454 	else
    455 		uploadTestTextureInternal(vk, device, queue, queueFamilyIndex, allocator, srcTexture, DE_NULL, srcTexture.getTextureFormat(), destImage);
    456 }
    457 
    458 void uploadTestTextureSparse (const DeviceInterface&					vk,
    459 							  VkDevice									device,
    460 							  const VkPhysicalDevice					physicalDevice,
    461 							  const InstanceInterface&					instance,
    462 							  const VkImageCreateInfo&					imageCreateInfo,
    463 							  VkQueue									universalQueue,
    464 							  deUint32									universalQueueFamilyIndex,
    465 							  VkQueue									sparseQueue,
    466 							  Allocator&								allocator,
    467 							  std::vector<de::SharedPtr<Allocation> >&	allocations,
    468 							  const TestTexture&						srcTexture,
    469 							  VkImage									destImage)
    470 {
    471 	if (tcu::isCombinedDepthStencilType(srcTexture.getTextureFormat().type))
    472 	{
    473 		de::MovePtr<TestTexture> srcDepthTexture;
    474 		de::MovePtr<TestTexture> srcStencilTexture;
    475 
    476 		if (tcu::hasDepthComponent(srcTexture.getTextureFormat().order))
    477 		{
    478 			tcu::TextureFormat format;
    479 			switch (srcTexture.getTextureFormat().type)
    480 			{
    481 				case tcu::TextureFormat::UNSIGNED_INT_16_8_8:
    482 					format = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
    483 					break;
    484 				case tcu::TextureFormat::UNSIGNED_INT_24_8_REV:
    485 					format = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNSIGNED_INT_24_8_REV);
    486 					break;
    487 				case tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
    488 					format = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT);
    489 					break;
    490 				default:
    491 					DE_FATAL("Unexpected source texture format.");
    492 					break;
    493 			}
    494 			srcDepthTexture = srcTexture.copy(format);
    495 		}
    496 
    497 		if (tcu::hasStencilComponent(srcTexture.getTextureFormat().order))
    498 			srcStencilTexture = srcTexture.copy(tcu::getEffectiveDepthStencilTextureFormat(srcTexture.getTextureFormat(), tcu::Sampler::MODE_STENCIL));
    499 
    500 		uploadTestTextureInternalSparse	(vk,
    501 										 device,
    502 										 physicalDevice,
    503 										 instance,
    504 										 imageCreateInfo,
    505 										 universalQueue,
    506 										 universalQueueFamilyIndex,
    507 										 sparseQueue,
    508 										 allocator,
    509 										 allocations,
    510 										 *srcDepthTexture,
    511 										 srcStencilTexture.get(),
    512 										 srcTexture.getTextureFormat(),
    513 										 destImage);
    514 	}
    515 	else
    516 	{
    517 		uploadTestTextureInternalSparse	(vk,
    518 										 device,
    519 										 physicalDevice,
    520 										 instance,
    521 										 imageCreateInfo,
    522 										 universalQueue,
    523 										 universalQueueFamilyIndex,
    524 										 sparseQueue,
    525 										 allocator,
    526 										 allocations,
    527 										 srcTexture,
    528 										 DE_NULL,
    529 										 srcTexture.getTextureFormat(),
    530 										 destImage);
    531 	}
    532 }
    533 
    534 // Utilities for test textures
    535 
    536 template<typename TcuTextureType>
    537 void allocateLevels (TcuTextureType& texture)
    538 {
    539 	for (int levelNdx = 0; levelNdx < texture.getNumLevels(); levelNdx++)
    540 		texture.allocLevel(levelNdx);
    541 }
    542 
    543 template<typename TcuTextureType>
    544 std::vector<tcu::PixelBufferAccess> getLevelsVector (const TcuTextureType& texture)
    545 {
    546 	std::vector<tcu::PixelBufferAccess> levels(texture.getNumLevels());
    547 
    548 	for (int levelNdx = 0; levelNdx < texture.getNumLevels(); levelNdx++)
    549 		levels[levelNdx] = *reinterpret_cast<const tcu::PixelBufferAccess*>(&texture.getLevel(levelNdx));
    550 
    551 	return levels;
    552 }
    553 
    554 // TestTexture
    555 
    556 TestTexture::TestTexture (const tcu::TextureFormat& format, int width, int height, int depth)
    557 {
    558 	DE_ASSERT(width >= 1);
    559 	DE_ASSERT(height >= 1);
    560 	DE_ASSERT(depth >= 1);
    561 
    562 	DE_UNREF(format);
    563 	DE_UNREF(width);
    564 	DE_UNREF(height);
    565 	DE_UNREF(depth);
    566 }
    567 
    568 TestTexture::TestTexture (const tcu::CompressedTexFormat& format, int width, int height, int depth)
    569 {
    570 	DE_ASSERT(width >= 1);
    571 	DE_ASSERT(height >= 1);
    572 	DE_ASSERT(depth >= 1);
    573 
    574 	DE_UNREF(format);
    575 	DE_UNREF(width);
    576 	DE_UNREF(height);
    577 	DE_UNREF(depth);
    578 }
    579 
    580 TestTexture::~TestTexture (void)
    581 {
    582 	for (size_t levelNdx = 0; levelNdx < m_compressedLevels.size(); levelNdx++)
    583 		delete m_compressedLevels[levelNdx];
    584 }
    585 
    586 deUint32 TestTexture::getSize (void) const
    587 {
    588 	std::vector<deUint32>	offsetMultiples;
    589 	deUint32				textureSize = 0;
    590 
    591 	offsetMultiples.push_back(4);
    592 	offsetMultiples.push_back(getLevel(0, 0).getFormat().getPixelSize());
    593 
    594 	for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
    595 	{
    596 		for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
    597 		{
    598 			const tcu::ConstPixelBufferAccess level = getLevel(levelNdx, layerNdx);
    599 			textureSize = getNextMultiple(offsetMultiples, textureSize);
    600 			textureSize += level.getWidth() * level.getHeight() * level.getDepth() * level.getFormat().getPixelSize();
    601 		}
    602 	}
    603 
    604 	return textureSize;
    605 }
    606 
    607 deUint32 TestTexture::getCompressedSize (void) const
    608 {
    609 	if (!isCompressed())
    610 		throw tcu::InternalError("Texture is not compressed");
    611 
    612 	std::vector<deUint32>	offsetMultiples;
    613 	deUint32				textureSize			= 0;
    614 
    615 	offsetMultiples.push_back(4);
    616 	offsetMultiples.push_back(tcu::getBlockSize(getCompressedLevel(0, 0).getFormat()));
    617 
    618 	for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
    619 	{
    620 		for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
    621 		{
    622 			textureSize = getNextMultiple(offsetMultiples, textureSize);
    623 			textureSize += getCompressedLevel(levelNdx, layerNdx).getDataSize();
    624 		}
    625 	}
    626 
    627 	return textureSize;
    628 }
    629 
    630 tcu::CompressedTexture& TestTexture::getCompressedLevel (int level, int layer)
    631 {
    632 	DE_ASSERT(level >= 0 && level < getNumLevels());
    633 	DE_ASSERT(layer >= 0 && layer < getArraySize());
    634 
    635 	return *m_compressedLevels[level * getArraySize() + layer];
    636 }
    637 
    638 const tcu::CompressedTexture& TestTexture::getCompressedLevel (int level, int layer) const
    639 {
    640 	DE_ASSERT(level >= 0 && level < getNumLevels());
    641 	DE_ASSERT(layer >= 0 && layer < getArraySize());
    642 
    643 	return *m_compressedLevels[level * getArraySize() + layer];
    644 }
    645 
    646 std::vector<VkBufferImageCopy> TestTexture::getBufferCopyRegions (void) const
    647 {
    648 	std::vector<deUint32>			offsetMultiples;
    649 	std::vector<VkBufferImageCopy>	regions;
    650 	deUint32						layerDataOffset = 0;
    651 
    652 	offsetMultiples.push_back(4);
    653 
    654 	if (isCompressed())
    655 	{
    656 		offsetMultiples.push_back(tcu::getBlockSize(getCompressedLevel(0, 0).getFormat()));
    657 
    658 		for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
    659 		{
    660 			for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
    661 			{
    662 				const tcu::CompressedTexture& level = getCompressedLevel(levelNdx, layerNdx);
    663 				tcu::IVec3 blockPixelSize			= getBlockPixelSize(level.getFormat());
    664 				layerDataOffset						= getNextMultiple(offsetMultiples, layerDataOffset);
    665 
    666 				const VkBufferImageCopy layerRegion =
    667 				{
    668 					layerDataOffset,													// VkDeviceSize				bufferOffset;
    669 					(deUint32)getNextMultiple(blockPixelSize.x(), level.getWidth()),	// deUint32					bufferRowLength;
    670 					(deUint32)getNextMultiple(blockPixelSize.y(), level.getHeight()),	// deUint32					bufferImageHeight;
    671 					{																	// VkImageSubresourceLayers	imageSubresource;
    672 						VK_IMAGE_ASPECT_COLOR_BIT,
    673 						(deUint32)levelNdx,
    674 						(deUint32)layerNdx,
    675 						1u
    676 					},
    677 					{ 0u, 0u, 0u },							// VkOffset3D				imageOffset;
    678 					{										// VkExtent3D				imageExtent;
    679 						(deUint32)level.getWidth(),
    680 						(deUint32)level.getHeight(),
    681 						(deUint32)level.getDepth()
    682 					}
    683 				};
    684 
    685 				regions.push_back(layerRegion);
    686 				layerDataOffset += level.getDataSize();
    687 			}
    688 		}
    689 	}
    690 	else
    691 	{
    692 		std::vector<VkImageAspectFlags>	imageAspects;
    693 		tcu::TextureFormat				textureFormat	= getTextureFormat();
    694 
    695 		if (tcu::hasDepthComponent(textureFormat.order))
    696 			imageAspects.push_back(VK_IMAGE_ASPECT_DEPTH_BIT);
    697 
    698 		if (tcu::hasStencilComponent(textureFormat.order))
    699 			imageAspects.push_back(VK_IMAGE_ASPECT_STENCIL_BIT);
    700 
    701 		if (imageAspects.empty())
    702 			imageAspects.push_back(VK_IMAGE_ASPECT_COLOR_BIT);
    703 
    704 		offsetMultiples.push_back(getLevel(0, 0).getFormat().getPixelSize());
    705 
    706 		for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
    707 		{
    708 			for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
    709 			{
    710 				const tcu::ConstPixelBufferAccess level = getLevel(levelNdx, layerNdx);
    711 
    712 				layerDataOffset = getNextMultiple(offsetMultiples, layerDataOffset);
    713 
    714 				for (size_t aspectIndex = 0; aspectIndex < imageAspects.size(); ++aspectIndex)
    715 				{
    716 					const VkBufferImageCopy layerRegion =
    717 					{
    718 						layerDataOffset,						// VkDeviceSize				bufferOffset;
    719 						(deUint32)level.getWidth(),				// deUint32					bufferRowLength;
    720 						(deUint32)level.getHeight(),			// deUint32					bufferImageHeight;
    721 						{										// VkImageSubresourceLayers	imageSubresource;
    722 							imageAspects[aspectIndex],
    723 							(deUint32)levelNdx,
    724 							(deUint32)layerNdx,
    725 							1u
    726 						},
    727 						{ 0u, 0u, 0u },							// VkOffset3D			imageOffset;
    728 						{										// VkExtent3D			imageExtent;
    729 							(deUint32)level.getWidth(),
    730 							(deUint32)level.getHeight(),
    731 							(deUint32)level.getDepth()
    732 						}
    733 					};
    734 
    735 					regions.push_back(layerRegion);
    736 				}
    737 				layerDataOffset += level.getWidth() * level.getHeight() * level.getDepth() * level.getFormat().getPixelSize();
    738 			}
    739 		}
    740 	}
    741 
    742 	return regions;
    743 }
    744 
    745 void TestTexture::write (deUint8* destPtr) const
    746 {
    747 	std::vector<deUint32>	offsetMultiples;
    748 	deUint32				levelOffset		= 0;
    749 
    750 	offsetMultiples.push_back(4);
    751 
    752 	if (isCompressed())
    753 	{
    754 		offsetMultiples.push_back(tcu::getBlockSize(getCompressedLevel(0, 0).getFormat()));
    755 
    756 		for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
    757 		{
    758 			for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
    759 			{
    760 				levelOffset = getNextMultiple(offsetMultiples, levelOffset);
    761 
    762 				const tcu::CompressedTexture&		compressedTex	= getCompressedLevel(levelNdx, layerNdx);
    763 
    764 				deMemcpy(destPtr + levelOffset, compressedTex.getData(), compressedTex.getDataSize());
    765 				levelOffset += compressedTex.getDataSize();
    766 			}
    767 		}
    768 	}
    769 	else
    770 	{
    771 		offsetMultiples.push_back(getLevel(0, 0).getFormat().getPixelSize());
    772 
    773 		for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
    774 		{
    775 			for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
    776 			{
    777 				levelOffset = getNextMultiple(offsetMultiples, levelOffset);
    778 
    779 				const tcu::ConstPixelBufferAccess	srcAccess		= getLevel(levelNdx, layerNdx);
    780 				const tcu::PixelBufferAccess		destAccess		(srcAccess.getFormat(), srcAccess.getSize(), srcAccess.getPitch(), destPtr + levelOffset);
    781 
    782 				tcu::copy(destAccess, srcAccess);
    783 				levelOffset += srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
    784 			}
    785 		}
    786 	}
    787 }
    788 
    789 void TestTexture::copyToTexture (TestTexture& destTexture) const
    790 {
    791 	for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
    792 		for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
    793 			tcu::copy(destTexture.getLevel(levelNdx, layerNdx), getLevel(levelNdx, layerNdx));
    794 }
    795 
    796 void TestTexture::populateLevels (const std::vector<tcu::PixelBufferAccess>& levels)
    797 {
    798 	for (size_t levelNdx = 0; levelNdx < levels.size(); levelNdx++)
    799 		TestTexture::fillWithGradient(levels[levelNdx]);
    800 }
    801 
    802 void TestTexture::populateCompressedLevels (tcu::CompressedTexFormat format, const std::vector<tcu::PixelBufferAccess>& decompressedLevels)
    803 {
    804 	// Generate random compressed data and update decompressed data
    805 
    806 	de::Random random(123);
    807 
    808 	for (size_t levelNdx = 0; levelNdx < decompressedLevels.size(); levelNdx++)
    809 	{
    810 		const tcu::PixelBufferAccess	level				= decompressedLevels[levelNdx];
    811 		tcu::CompressedTexture*			compressedLevel		= new tcu::CompressedTexture(format, level.getWidth(), level.getHeight(), level.getDepth());
    812 		deUint8* const					compressedData		= (deUint8*)compressedLevel->getData();
    813 
    814 		if (tcu::isAstcFormat(format))
    815 		{
    816 			// \todo [2016-01-20 pyry] Comparison doesn't currently handle invalid blocks correctly so we use only valid blocks
    817 			tcu::astc::generateRandomValidBlocks(compressedData, compressedLevel->getDataSize()/tcu::astc::BLOCK_SIZE_BYTES,
    818 												 format, tcu::TexDecompressionParams::ASTCMODE_LDR, random.getUint32());
    819 		}
    820 		else
    821 		{
    822 			// Generate random compressed data
    823 			// Random initial values cause assertion during the decompression in case of COMPRESSEDTEXFORMAT_ETC1_RGB8 format
    824 			if (format != tcu::COMPRESSEDTEXFORMAT_ETC1_RGB8)
    825 				for (int byteNdx = 0; byteNdx < compressedLevel->getDataSize(); byteNdx++)
    826 					compressedData[byteNdx] = 0xFF & random.getUint32();
    827 		}
    828 
    829 		m_compressedLevels.push_back(compressedLevel);
    830 
    831 		// Store decompressed data
    832 		compressedLevel->decompress(level, tcu::TexDecompressionParams(tcu::TexDecompressionParams::ASTCMODE_LDR));
    833 	}
    834 }
    835 
    836 void TestTexture::fillWithGradient (const tcu::PixelBufferAccess& levelAccess)
    837 {
    838 	const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(levelAccess.getFormat());
    839 	tcu::fillWithComponentGradients(levelAccess, formatInfo.valueMin, formatInfo.valueMax);
    840 }
    841 
    842 // TestTexture1D
    843 
    844 TestTexture1D::TestTexture1D (const tcu::TextureFormat& format, int width)
    845 	: TestTexture	(format, width, 1, 1)
    846 	, m_texture		(format, width)
    847 {
    848 	allocateLevels(m_texture);
    849 	TestTexture::populateLevels(getLevelsVector(m_texture));
    850 }
    851 
    852 TestTexture1D::TestTexture1D (const tcu::CompressedTexFormat& format, int width)
    853 	: TestTexture	(format, width, 1, 1)
    854 	, m_texture		(tcu::getUncompressedFormat(format), width)
    855 {
    856 	allocateLevels(m_texture);
    857 	TestTexture::populateCompressedLevels(format, getLevelsVector(m_texture));
    858 }
    859 
    860 TestTexture1D::~TestTexture1D (void)
    861 {
    862 }
    863 
    864 int TestTexture1D::getNumLevels (void) const
    865 {
    866 	return m_texture.getNumLevels();
    867 }
    868 
    869 tcu::PixelBufferAccess TestTexture1D::getLevel (int level, int layer)
    870 {
    871 	DE_ASSERT(layer == 0);
    872 	DE_UNREF(layer);
    873 	return m_texture.getLevel(level);
    874 }
    875 
    876 const tcu::ConstPixelBufferAccess TestTexture1D::getLevel (int level, int layer) const
    877 {
    878 	DE_ASSERT(layer == 0);
    879 	DE_UNREF(layer);
    880 	return m_texture.getLevel(level);
    881 }
    882 
    883 const tcu::Texture1D& TestTexture1D::getTexture (void) const
    884 {
    885 	return m_texture;
    886 }
    887 
    888 tcu::Texture1D& TestTexture1D::getTexture (void)
    889 {
    890 	return m_texture;
    891 }
    892 
    893 de::MovePtr<TestTexture> TestTexture1D::copy(const tcu::TextureFormat format) const
    894 {
    895 	DE_ASSERT(!isCompressed());
    896 
    897 	de::MovePtr<TestTexture>	texture	(new TestTexture1D(format, m_texture.getWidth()));
    898 
    899 	copyToTexture(*texture);
    900 
    901 	return texture;
    902 }
    903 
    904 // TestTexture1DArray
    905 
    906 TestTexture1DArray::TestTexture1DArray (const tcu::TextureFormat& format, int width, int arraySize)
    907 	: TestTexture	(format, width, 1, arraySize)
    908 	, m_texture		(format, width, arraySize)
    909 {
    910 	allocateLevels(m_texture);
    911 	TestTexture::populateLevels(getLevelsVector(m_texture));
    912 }
    913 
    914 TestTexture1DArray::TestTexture1DArray (const tcu::CompressedTexFormat& format, int width, int arraySize)
    915 	: TestTexture	(format, width, 1, arraySize)
    916 	, m_texture		(tcu::getUncompressedFormat(format), width, arraySize)
    917 {
    918 	allocateLevels(m_texture);
    919 
    920 	std::vector<tcu::PixelBufferAccess> layers;
    921 	for (int levelNdx = 0; levelNdx < m_texture.getNumLevels(); levelNdx++)
    922 		for (int layerNdx = 0; layerNdx < m_texture.getNumLayers(); layerNdx++)
    923 			layers.push_back(getLevel(levelNdx, layerNdx));
    924 
    925 	TestTexture::populateCompressedLevels(format, layers);
    926 }
    927 
    928 TestTexture1DArray::~TestTexture1DArray (void)
    929 {
    930 }
    931 
    932 int TestTexture1DArray::getNumLevels (void) const
    933 {
    934 	return m_texture.getNumLevels();
    935 }
    936 
    937 tcu::PixelBufferAccess TestTexture1DArray::getLevel (int level, int layer)
    938 {
    939 	const tcu::PixelBufferAccess	levelLayers	= m_texture.getLevel(level);
    940 	const deUint32					layerSize	= levelLayers.getWidth() * levelLayers.getFormat().getPixelSize();
    941 	const deUint32					layerOffset	= layerSize * layer;
    942 
    943 	return tcu::PixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), 1, 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
    944 }
    945 
    946 const tcu::ConstPixelBufferAccess TestTexture1DArray::getLevel (int level, int layer) const
    947 {
    948 	const tcu::ConstPixelBufferAccess	levelLayers	= m_texture.getLevel(level);
    949 	const deUint32						layerSize	= levelLayers.getWidth() * levelLayers.getFormat().getPixelSize();
    950 	const deUint32						layerOffset	= layerSize * layer;
    951 
    952 	return tcu::ConstPixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), 1, 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
    953 }
    954 
    955 const tcu::Texture1DArray& TestTexture1DArray::getTexture (void) const
    956 {
    957 	return m_texture;
    958 }
    959 
    960 tcu::Texture1DArray& TestTexture1DArray::getTexture (void)
    961 {
    962 	return m_texture;
    963 }
    964 
    965 int TestTexture1DArray::getArraySize (void) const
    966 {
    967 	return m_texture.getNumLayers();
    968 }
    969 
    970 de::MovePtr<TestTexture> TestTexture1DArray::copy(const tcu::TextureFormat format) const
    971 {
    972 	DE_ASSERT(!isCompressed());
    973 
    974 	de::MovePtr<TestTexture>	texture	(new TestTexture1DArray(format, m_texture.getWidth(), getArraySize()));
    975 
    976 	copyToTexture(*texture);
    977 
    978 	return texture;
    979 }
    980 
    981 // TestTexture2D
    982 
    983 TestTexture2D::TestTexture2D (const tcu::TextureFormat& format, int width, int height)
    984 	: TestTexture	(format, width, height, 1)
    985 	, m_texture		(format, width, height)
    986 {
    987 	allocateLevels(m_texture);
    988 	TestTexture::populateLevels(getLevelsVector(m_texture));
    989 }
    990 
    991 TestTexture2D::TestTexture2D (const tcu::TextureFormat& format, int width, int height, int miplevels)
    992 	: TestTexture(format, width, height, 1)
    993 	, m_texture(format, width, height, miplevels)
    994 {
    995 	allocateLevels(m_texture);
    996 	TestTexture::populateLevels(getLevelsVector(m_texture));
    997 }
    998 
    999 
   1000 TestTexture2D::TestTexture2D (const tcu::CompressedTexFormat& format, int width, int height)
   1001 	: TestTexture	(format, width, height, 1)
   1002 	, m_texture		(tcu::getUncompressedFormat(format), width, height)
   1003 {
   1004 	allocateLevels(m_texture);
   1005 	TestTexture::populateCompressedLevels(format, getLevelsVector(m_texture));
   1006 }
   1007 
   1008 TestTexture2D::~TestTexture2D (void)
   1009 {
   1010 }
   1011 
   1012 int TestTexture2D::getNumLevels (void) const
   1013 {
   1014 	return m_texture.getNumLevels();
   1015 }
   1016 
   1017 tcu::PixelBufferAccess TestTexture2D::getLevel (int level, int layer)
   1018 {
   1019 	DE_ASSERT(layer == 0);
   1020 	DE_UNREF(layer);
   1021 	return m_texture.getLevel(level);
   1022 }
   1023 
   1024 const tcu::ConstPixelBufferAccess TestTexture2D::getLevel (int level, int layer) const
   1025 {
   1026 	DE_ASSERT(layer == 0);
   1027 	DE_UNREF(layer);
   1028 	return m_texture.getLevel(level);
   1029 }
   1030 
   1031 const tcu::Texture2D& TestTexture2D::getTexture (void) const
   1032 {
   1033 	return m_texture;
   1034 }
   1035 
   1036 tcu::Texture2D& TestTexture2D::getTexture (void)
   1037 {
   1038 	return m_texture;
   1039 }
   1040 
   1041 de::MovePtr<TestTexture> TestTexture2D::copy(const tcu::TextureFormat format) const
   1042 {
   1043 	DE_ASSERT(!isCompressed());
   1044 
   1045 	de::MovePtr<TestTexture>	texture	(new TestTexture2D(format, m_texture.getWidth(), m_texture.getHeight()));
   1046 
   1047 	copyToTexture(*texture);
   1048 
   1049 	return texture;
   1050 }
   1051 
   1052 // TestTexture2DArray
   1053 
   1054 TestTexture2DArray::TestTexture2DArray (const tcu::TextureFormat& format, int width, int height, int arraySize)
   1055 	: TestTexture	(format, width, height, arraySize)
   1056 	, m_texture		(format, width, height, arraySize)
   1057 {
   1058 	allocateLevels(m_texture);
   1059 	TestTexture::populateLevels(getLevelsVector(m_texture));
   1060 }
   1061 
   1062 TestTexture2DArray::TestTexture2DArray (const tcu::CompressedTexFormat& format, int width, int height, int arraySize)
   1063 	: TestTexture	(format, width, height, arraySize)
   1064 	, m_texture		(tcu::getUncompressedFormat(format), width, height, arraySize)
   1065 {
   1066 	allocateLevels(m_texture);
   1067 
   1068 	std::vector<tcu::PixelBufferAccess> layers;
   1069 	for (int levelNdx = 0; levelNdx < m_texture.getNumLevels(); levelNdx++)
   1070 		for (int layerNdx = 0; layerNdx < m_texture.getNumLayers(); layerNdx++)
   1071 			layers.push_back(getLevel(levelNdx, layerNdx));
   1072 
   1073 	TestTexture::populateCompressedLevels(format, layers);
   1074 }
   1075 
   1076 TestTexture2DArray::~TestTexture2DArray (void)
   1077 {
   1078 }
   1079 
   1080 int TestTexture2DArray::getNumLevels (void) const
   1081 {
   1082 	return m_texture.getNumLevels();
   1083 }
   1084 
   1085 tcu::PixelBufferAccess TestTexture2DArray::getLevel (int level, int layer)
   1086 {
   1087 	const tcu::PixelBufferAccess	levelLayers	= m_texture.getLevel(level);
   1088 	const deUint32					layerSize	= levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
   1089 	const deUint32					layerOffset	= layerSize * layer;
   1090 
   1091 	return tcu::PixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
   1092 }
   1093 
   1094 const tcu::ConstPixelBufferAccess TestTexture2DArray::getLevel (int level, int layer) const
   1095 {
   1096 	const tcu::ConstPixelBufferAccess	levelLayers	= m_texture.getLevel(level);
   1097 	const deUint32						layerSize	= levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
   1098 	const deUint32						layerOffset	= layerSize * layer;
   1099 
   1100 	return tcu::ConstPixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
   1101 }
   1102 
   1103 const tcu::Texture2DArray& TestTexture2DArray::getTexture (void) const
   1104 {
   1105 	return m_texture;
   1106 }
   1107 
   1108 tcu::Texture2DArray& TestTexture2DArray::getTexture (void)
   1109 {
   1110 	return m_texture;
   1111 }
   1112 
   1113 int TestTexture2DArray::getArraySize (void) const
   1114 {
   1115 	return m_texture.getNumLayers();
   1116 }
   1117 
   1118 de::MovePtr<TestTexture> TestTexture2DArray::copy(const tcu::TextureFormat format) const
   1119 {
   1120 	DE_ASSERT(!isCompressed());
   1121 
   1122 	de::MovePtr<TestTexture>	texture	(new TestTexture2DArray(format, m_texture.getWidth(), m_texture.getHeight(), getArraySize()));
   1123 
   1124 	copyToTexture(*texture);
   1125 
   1126 	return texture;
   1127 }
   1128 
   1129 // TestTexture3D
   1130 
   1131 TestTexture3D::TestTexture3D (const tcu::TextureFormat& format, int width, int height, int depth)
   1132 	: TestTexture	(format, width, height, depth)
   1133 	, m_texture		(format, width, height, depth)
   1134 {
   1135 	allocateLevels(m_texture);
   1136 	TestTexture::populateLevels(getLevelsVector(m_texture));
   1137 }
   1138 
   1139 TestTexture3D::TestTexture3D (const tcu::CompressedTexFormat& format, int width, int height, int depth)
   1140 	: TestTexture	(format, width, height, depth)
   1141 	, m_texture		(tcu::getUncompressedFormat(format), width, height, depth)
   1142 {
   1143 	allocateLevels(m_texture);
   1144 	TestTexture::populateCompressedLevels(format, getLevelsVector(m_texture));
   1145 }
   1146 
   1147 TestTexture3D::~TestTexture3D (void)
   1148 {
   1149 }
   1150 
   1151 int TestTexture3D::getNumLevels (void) const
   1152 {
   1153 	return m_texture.getNumLevels();
   1154 }
   1155 
   1156 tcu::PixelBufferAccess TestTexture3D::getLevel (int level, int layer)
   1157 {
   1158 	DE_ASSERT(layer == 0);
   1159 	DE_UNREF(layer);
   1160 	return m_texture.getLevel(level);
   1161 }
   1162 
   1163 const tcu::ConstPixelBufferAccess TestTexture3D::getLevel (int level, int layer) const
   1164 {
   1165 	DE_ASSERT(layer == 0);
   1166 	DE_UNREF(layer);
   1167 	return m_texture.getLevel(level);
   1168 }
   1169 
   1170 const tcu::Texture3D& TestTexture3D::getTexture (void) const
   1171 {
   1172 	return m_texture;
   1173 }
   1174 
   1175 tcu::Texture3D& TestTexture3D::getTexture (void)
   1176 {
   1177 	return m_texture;
   1178 }
   1179 
   1180 de::MovePtr<TestTexture> TestTexture3D::copy(const tcu::TextureFormat format) const
   1181 {
   1182 	DE_ASSERT(!isCompressed());
   1183 
   1184 	de::MovePtr<TestTexture>	texture	(new TestTexture3D(format, m_texture.getWidth(), m_texture.getHeight(), m_texture.getDepth()));
   1185 
   1186 	copyToTexture(*texture);
   1187 
   1188 	return texture;
   1189 }
   1190 
   1191 // TestTextureCube
   1192 
   1193 const static tcu::CubeFace tcuFaceMapping[tcu::CUBEFACE_LAST] =
   1194 {
   1195 	tcu::CUBEFACE_POSITIVE_X,
   1196 	tcu::CUBEFACE_NEGATIVE_X,
   1197 	tcu::CUBEFACE_POSITIVE_Y,
   1198 	tcu::CUBEFACE_NEGATIVE_Y,
   1199 	tcu::CUBEFACE_POSITIVE_Z,
   1200 	tcu::CUBEFACE_NEGATIVE_Z
   1201 };
   1202 
   1203 TestTextureCube::TestTextureCube (const tcu::TextureFormat& format, int size)
   1204 	: TestTexture	(format, size, size, 1)
   1205 	, m_texture		(format, size)
   1206 {
   1207 	for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
   1208 	{
   1209 		for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
   1210 		{
   1211 			m_texture.allocLevel(tcuFaceMapping[faceNdx], levelNdx);
   1212 			TestTexture::fillWithGradient(m_texture.getLevelFace(levelNdx, tcuFaceMapping[faceNdx]));
   1213 		}
   1214 	}
   1215 }
   1216 
   1217 TestTextureCube::TestTextureCube (const tcu::CompressedTexFormat& format, int size)
   1218 	: TestTexture	(format, size, size, 1)
   1219 	, m_texture		(tcu::getUncompressedFormat(format), size)
   1220 {
   1221 	std::vector<tcu::PixelBufferAccess> levels(m_texture.getNumLevels() * tcu::CUBEFACE_LAST);
   1222 
   1223 	for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
   1224 	{
   1225 		for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
   1226 		{
   1227 			m_texture.allocLevel(tcuFaceMapping[faceNdx], levelNdx);
   1228 			levels[levelNdx * tcu::CUBEFACE_LAST + faceNdx] = m_texture.getLevelFace(levelNdx, tcuFaceMapping[faceNdx]);
   1229 		}
   1230 	}
   1231 
   1232 	TestTexture::populateCompressedLevels(format, levels);
   1233 }
   1234 
   1235 TestTextureCube::~TestTextureCube (void)
   1236 {
   1237 }
   1238 
   1239 int TestTextureCube::getNumLevels (void) const
   1240 {
   1241 	return m_texture.getNumLevels();
   1242 }
   1243 
   1244 tcu::PixelBufferAccess TestTextureCube::getLevel (int level, int layer)
   1245 {
   1246 	return m_texture.getLevelFace(level, tcuFaceMapping[layer]);
   1247 }
   1248 
   1249 const tcu::ConstPixelBufferAccess TestTextureCube::getLevel (int level, int layer) const
   1250 {
   1251 	return m_texture.getLevelFace(level, tcuFaceMapping[layer]);
   1252 }
   1253 
   1254 int TestTextureCube::getArraySize (void) const
   1255 {
   1256 	return (int)tcu::CUBEFACE_LAST;
   1257 }
   1258 
   1259 const tcu::TextureCube& TestTextureCube::getTexture (void) const
   1260 {
   1261 	return m_texture;
   1262 }
   1263 
   1264 tcu::TextureCube& TestTextureCube::getTexture (void)
   1265 {
   1266 	return m_texture;
   1267 }
   1268 
   1269 de::MovePtr<TestTexture> TestTextureCube::copy(const tcu::TextureFormat format) const
   1270 {
   1271 	DE_ASSERT(!isCompressed());
   1272 
   1273 	de::MovePtr<TestTexture>	texture	(new TestTextureCube(format, m_texture.getSize()));
   1274 
   1275 	copyToTexture(*texture);
   1276 
   1277 	return texture;
   1278 }
   1279 
   1280 // TestTextureCubeArray
   1281 
   1282 TestTextureCubeArray::TestTextureCubeArray (const tcu::TextureFormat& format, int size, int arraySize)
   1283 	: TestTexture	(format, size, size, arraySize)
   1284 	, m_texture		(format, size, arraySize)
   1285 {
   1286 	allocateLevels(m_texture);
   1287 	TestTexture::populateLevels(getLevelsVector(m_texture));
   1288 }
   1289 
   1290 TestTextureCubeArray::TestTextureCubeArray (const tcu::CompressedTexFormat& format, int size, int arraySize)
   1291 	: TestTexture	(format, size, size, arraySize)
   1292 	, m_texture		(tcu::getUncompressedFormat(format), size, arraySize)
   1293 {
   1294 	DE_ASSERT(arraySize % 6 == 0);
   1295 
   1296 	allocateLevels(m_texture);
   1297 
   1298 	std::vector<tcu::PixelBufferAccess> layers;
   1299 	for (int levelNdx = 0; levelNdx < m_texture.getNumLevels(); levelNdx++)
   1300 		for (int layerNdx = 0; layerNdx < m_texture.getDepth(); layerNdx++)
   1301 			layers.push_back(getLevel(levelNdx, layerNdx));
   1302 
   1303 	TestTexture::populateCompressedLevels(format, layers);
   1304 }
   1305 
   1306 TestTextureCubeArray::~TestTextureCubeArray (void)
   1307 {
   1308 }
   1309 
   1310 int TestTextureCubeArray::getNumLevels (void) const
   1311 {
   1312 	return m_texture.getNumLevels();
   1313 }
   1314 
   1315 tcu::PixelBufferAccess TestTextureCubeArray::getLevel (int level, int layer)
   1316 {
   1317 	const tcu::PixelBufferAccess	levelLayers	= m_texture.getLevel(level);
   1318 	const deUint32					layerSize	= levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
   1319 	const deUint32					layerOffset	= layerSize * layer;
   1320 
   1321 	return tcu::PixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
   1322 }
   1323 
   1324 const tcu::ConstPixelBufferAccess TestTextureCubeArray::getLevel (int level, int layer) const
   1325 {
   1326 	const tcu::ConstPixelBufferAccess	levelLayers	= m_texture.getLevel(level);
   1327 	const deUint32						layerSize	= levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
   1328 	const deUint32						layerOffset	= layerSize * layer;
   1329 
   1330 	return tcu::ConstPixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
   1331 }
   1332 
   1333 int TestTextureCubeArray::getArraySize (void) const
   1334 {
   1335 	return m_texture.getDepth();
   1336 }
   1337 
   1338 const tcu::TextureCubeArray& TestTextureCubeArray::getTexture (void) const
   1339 {
   1340 	return m_texture;
   1341 }
   1342 
   1343 tcu::TextureCubeArray& TestTextureCubeArray::getTexture (void)
   1344 {
   1345 	return m_texture;
   1346 }
   1347 
   1348 de::MovePtr<TestTexture> TestTextureCubeArray::copy(const tcu::TextureFormat format) const
   1349 {
   1350 	DE_ASSERT(!isCompressed());
   1351 
   1352 	de::MovePtr<TestTexture>	texture	(new TestTextureCubeArray(format, m_texture.getSize(), getArraySize()));
   1353 
   1354 	copyToTexture(*texture);
   1355 
   1356 	return texture;
   1357 }
   1358 
   1359 } // pipeline
   1360 } // vkt
   1361