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