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 
34 namespace vkt
35 {
36 namespace pipeline
37 {
38 
39 using namespace vk;
40 
41 /*! Gets the next multiple of a given divisor */
getNextMultiple(deUint32 divisor,deUint32 value)42 static 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 */
getNextMultiple(const std::vector<deUint32> & divisors,deUint32 value)52 static 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 
isSupportedSamplableFormat(const InstanceInterface & instanceInterface,VkPhysicalDevice device,VkFormat format)74 bool 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.
107 enum
108 {
109 	VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000,
110 };
111 
isLinearFilteringSupported(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkFormat format,VkImageTiling tiling)112 bool 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 
getFormatBorderColor(BorderColor color,VkFormat format)138 VkBorderColor 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 
readColorAttachment(const vk::DeviceInterface & vk,vk::VkDevice device,vk::VkQueue queue,deUint32 queueFamilyIndex,vk::Allocator & allocator,vk::VkImage image,vk::VkFormat format,const tcu::UVec2 & renderSize)167 de::MovePtr<tcu::TextureLevel> readColorAttachment (const vk::DeviceInterface&	vk,
168 													vk::VkDevice				device,
169 													vk::VkQueue					queue,
170 													deUint32					queueFamilyIndex,
171 													vk::Allocator&				allocator,
172 													vk::VkImage					image,
173 													vk::VkFormat				format,
174 													const tcu::UVec2&			renderSize)
175 {
176 	Move<VkBuffer>					buffer;
177 	de::MovePtr<Allocation>			bufferAlloc;
178 	Move<VkCommandPool>				cmdPool;
179 	Move<VkCommandBuffer>			cmdBuffer;
180 	Move<VkFence>					fence;
181 	const tcu::TextureFormat		tcuFormat		= mapVkFormat(format);
182 	const VkDeviceSize				pixelDataSize	= renderSize.x() * renderSize.y() * tcuFormat.getPixelSize();
183 	de::MovePtr<tcu::TextureLevel>	resultLevel		(new tcu::TextureLevel(tcuFormat, renderSize.x(), renderSize.y()));
184 
185 	// Create destination buffer
186 	{
187 		const VkBufferCreateInfo bufferParams =
188 		{
189 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
190 			DE_NULL,									// const void*			pNext;
191 			0u,											// VkBufferCreateFlags	flags;
192 			pixelDataSize,								// VkDeviceSize			size;
193 			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// VkBufferUsageFlags	usage;
194 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
195 			0u,											// deUint32				queueFamilyIndexCount;
196 			DE_NULL										// const deUint32*		pQueueFamilyIndices;
197 		};
198 
199 		buffer		= createBuffer(vk, device, &bufferParams);
200 		bufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *buffer), MemoryRequirement::HostVisible);
201 		VK_CHECK(vk.bindBufferMemory(device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
202 	}
203 
204 	// Create command pool and buffer
205 	{
206 		const VkCommandPoolCreateInfo cmdPoolParams =
207 		{
208 			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,		// VkStructureType		sType;
209 			DE_NULL,										// const void*			pNext;
210 			VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// VkCmdPoolCreateFlags	flags;
211 			queueFamilyIndex,								// deUint32				queueFamilyIndex;
212 		};
213 
214 		cmdPool = createCommandPool(vk, device, &cmdPoolParams);
215 
216 		const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
217 		{
218 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
219 			DE_NULL,										// const void*				pNext;
220 			*cmdPool,										// VkCommandPool			commandPool;
221 			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
222 			1u												// deUint32					bufferCount;
223 		};
224 
225 		cmdBuffer = allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo);
226 	}
227 
228 	// Create fence
229 	{
230 		const VkFenceCreateInfo fenceParams =
231 		{
232 			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,		// VkStructureType		sType;
233 			DE_NULL,									// const void*			pNext;
234 			0u											// VkFenceCreateFlags	flags;
235 		};
236 
237 		fence = createFence(vk, device, &fenceParams);
238 	}
239 
240 	// Barriers for copying image to buffer
241 
242 	const VkImageMemoryBarrier imageBarrier =
243 	{
244 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
245 		DE_NULL,									// const void*				pNext;
246 		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			srcAccessMask;
247 		VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask;
248 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			oldLayout;
249 		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// VkImageLayout			newLayout;
250 		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
251 		VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
252 		image,										// VkImage					image;
253 		{											// VkImageSubresourceRange	subresourceRange;
254 			VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
255 			0u,							// deUint32				baseMipLevel;
256 			1u,							// deUint32				mipLevels;
257 			0u,							// deUint32				baseArraySlice;
258 			1u							// deUint32				arraySize;
259 		}
260 	};
261 
262 	const VkBufferMemoryBarrier bufferBarrier =
263 	{
264 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
265 		DE_NULL,									// const void*		pNext;
266 		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
267 		VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask;
268 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
269 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
270 		*buffer,									// VkBuffer			buffer;
271 		0u,											// VkDeviceSize		offset;
272 		pixelDataSize								// VkDeviceSize		size;
273 	};
274 
275 	const VkCommandBufferBeginInfo cmdBufferBeginInfo =
276 	{
277 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,			// VkStructureType					sType;
278 		DE_NULL,												// const void*						pNext;
279 		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,			// VkCommandBufferUsageFlags		flags;
280 		(const VkCommandBufferInheritanceInfo*)DE_NULL,
281 	};
282 
283 	// Copy image to buffer
284 
285 	const VkBufferImageCopy copyRegion =
286 	{
287 		0u,												// VkDeviceSize				bufferOffset;
288 		(deUint32)renderSize.x(),						// deUint32					bufferRowLength;
289 		(deUint32)renderSize.y(),						// deUint32					bufferImageHeight;
290 		{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u },		// VkImageSubresourceLayers	imageSubresource;
291 		{ 0, 0, 0 },									// VkOffset3D				imageOffset;
292 		{ renderSize.x(), renderSize.y(), 1u }			// VkExtent3D				imageExtent;
293 	};
294 
295 	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
296 	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);
297 	vk.cmdCopyImageToBuffer(*cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *buffer, 1, &copyRegion);
298 	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);
299 	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
300 
301 	const VkSubmitInfo submitInfo =
302 	{
303 		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
304 		DE_NULL,						// const void*				pNext;
305 		0u,								// deUint32					waitSemaphoreCount;
306 		DE_NULL,						// const VkSemaphore*		pWaitSemaphores;
307 		DE_NULL,
308 		1u,								// deUint32					commandBufferCount;
309 		&cmdBuffer.get(),				// const VkCommandBuffer*	pCommandBuffers;
310 		0u,								// deUint32					signalSemaphoreCount;
311 		DE_NULL							// const VkSemaphore*		pSignalSemaphores;
312 	};
313 
314 	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
315 	VK_CHECK(vk.waitForFences(device, 1, &fence.get(), 0, ~(0ull) /* infinity */));
316 
317 	// Read buffer data
318 	invalidateMappedMemoryRange(vk, device, bufferAlloc->getMemory(), bufferAlloc->getOffset(), pixelDataSize);
319 	tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), bufferAlloc->getHostPtr()));
320 
321 	return resultLevel;
322 }
323 
uploadTestTexture(const DeviceInterface & vk,VkDevice device,VkQueue queue,deUint32 queueFamilyIndex,Allocator & allocator,const TestTexture & srcTexture,VkImage destImage)324 void uploadTestTexture (const DeviceInterface&			vk,
325 						VkDevice						device,
326 						VkQueue							queue,
327 						deUint32						queueFamilyIndex,
328 						Allocator&						allocator,
329 						const TestTexture&				srcTexture,
330 						VkImage							destImage)
331 {
332 	deUint32						bufferSize;
333 	Move<VkBuffer>					buffer;
334 	de::MovePtr<Allocation>			bufferAlloc;
335 	Move<VkCommandPool>				cmdPool;
336 	Move<VkCommandBuffer>			cmdBuffer;
337 	Move<VkFence>					fence;
338 	std::vector<deUint32>			levelDataSizes;
339 
340 	// Calculate buffer size
341 	bufferSize =  (srcTexture.isCompressed())? srcTexture.getCompressedSize(): srcTexture.getSize();
342 
343 	// Create source buffer
344 	{
345 		const VkBufferCreateInfo bufferParams =
346 		{
347 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
348 			DE_NULL,									// const void*			pNext;
349 			0u,											// VkBufferCreateFlags	flags;
350 			bufferSize,									// VkDeviceSize			size;
351 			VK_BUFFER_USAGE_TRANSFER_SRC_BIT,			// VkBufferUsageFlags	usage;
352 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
353 			0u,											// deUint32				queueFamilyIndexCount;
354 			DE_NULL,									// const deUint32*		pQueueFamilyIndices;
355 		};
356 
357 		buffer		= createBuffer(vk, device, &bufferParams);
358 		bufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *buffer), MemoryRequirement::HostVisible);
359 		VK_CHECK(vk.bindBufferMemory(device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
360 	}
361 
362 	// Create command pool and buffer
363 	{
364 		const VkCommandPoolCreateInfo cmdPoolParams =
365 		{
366 			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,		// VkStructureType			sType;
367 			DE_NULL,										// const void*				pNext;
368 			VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// VkCommandPoolCreateFlags	flags;
369 			queueFamilyIndex,								// deUint32					queueFamilyIndex;
370 		};
371 
372 		cmdPool = createCommandPool(vk, device, &cmdPoolParams);
373 
374 		const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
375 		{
376 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
377 			DE_NULL,										// const void*				pNext;
378 			*cmdPool,										// VkCommandPool			commandPool;
379 			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
380 			1u,												// deUint32					bufferCount;
381 		};
382 
383 		cmdBuffer = allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo);
384 	}
385 
386 	// Create fence
387 	{
388 		const VkFenceCreateInfo fenceParams =
389 		{
390 			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,		// VkStructureType		sType;
391 			DE_NULL,									// const void*			pNext;
392 			0u											// VkFenceCreateFlags	flags;
393 		};
394 
395 		fence = createFence(vk, device, &fenceParams);
396 	}
397 
398 	// Barriers for copying buffer to image
399 	const VkBufferMemoryBarrier preBufferBarrier =
400 	{
401 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
402 		DE_NULL,									// const void*		pNext;
403 		VK_ACCESS_HOST_WRITE_BIT,					// VkAccessFlags	srcAccessMask;
404 		VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags	dstAccessMask;
405 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
406 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
407 		*buffer,									// VkBuffer			buffer;
408 		0u,											// VkDeviceSize		offset;
409 		bufferSize									// VkDeviceSize		size;
410 	};
411 
412 	const VkImageMemoryBarrier preImageBarrier =
413 	{
414 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
415 		DE_NULL,										// const void*				pNext;
416 		0u,												// VkAccessFlags			srcAccessMask;
417 		VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			dstAccessMask;
418 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
419 		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout			newLayout;
420 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
421 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
422 		destImage,										// VkImage					image;
423 		{												// VkImageSubresourceRange	subresourceRange;
424 			VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspect	aspect;
425 			0u,										// deUint32			baseMipLevel;
426 			(deUint32)srcTexture.getNumLevels(),	// deUint32			mipLevels;
427 			0u,										// deUint32			baseArraySlice;
428 			(deUint32)srcTexture.getArraySize(),	// deUint32			arraySize;
429 		}
430 	};
431 
432 	const VkImageMemoryBarrier postImageBarrier =
433 	{
434 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
435 		DE_NULL,										// const void*				pNext;
436 		VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			srcAccessMask;
437 		VK_ACCESS_SHADER_READ_BIT,						// VkAccessFlags			dstAccessMask;
438 		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout			oldLayout;
439 		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,		// VkImageLayout			newLayout;
440 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
441 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
442 		destImage,										// VkImage					image;
443 		{												// VkImageSubresourceRange	subresourceRange;
444 			VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspect	aspect;
445 			0u,										// deUint32			baseMipLevel;
446 			(deUint32)srcTexture.getNumLevels(),	// deUint32			mipLevels;
447 			0u,										// deUint32			baseArraySlice;
448 			(deUint32)srcTexture.getArraySize(),	// deUint32			arraySize;
449 		}
450 	};
451 
452 	const VkCommandBufferBeginInfo cmdBufferBeginInfo =
453 	{
454 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType;
455 		DE_NULL,										// const void*						pNext;
456 		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// VkCommandBufferUsageFlags		flags;
457 		(const VkCommandBufferInheritanceInfo*)DE_NULL,
458 	};
459 
460 	const std::vector<VkBufferImageCopy>	copyRegions		= srcTexture.getBufferCopyRegions();
461 
462 	// Write buffer data
463 	srcTexture.write(reinterpret_cast<deUint8*>(bufferAlloc->getHostPtr()));
464 	flushMappedMemoryRange(vk, device, bufferAlloc->getMemory(), bufferAlloc->getOffset(), bufferSize);
465 
466 	// Copy buffer to image
467 	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
468 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &preBufferBarrier, 1, &preImageBarrier);
469 	vk.cmdCopyBufferToImage(*cmdBuffer, *buffer, destImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32)copyRegions.size(), copyRegions.data());
470 	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);
471 
472 	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
473 
474 	const VkSubmitInfo submitInfo =
475 	{
476 		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
477 		DE_NULL,						// const void*				pNext;
478 		0u,								// deUint32					waitSemaphoreCount;
479 		DE_NULL,						// const VkSemaphore*		pWaitSemaphores;
480 		DE_NULL,
481 		1u,								// deUint32					commandBufferCount;
482 		&cmdBuffer.get(),				// const VkCommandBuffer*	pCommandBuffers;
483 		0u,								// deUint32					signalSemaphoreCount;
484 		DE_NULL							// const VkSemaphore*		pSignalSemaphores;
485 	};
486 
487 	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
488 	VK_CHECK(vk.waitForFences(device, 1, &fence.get(), true, ~(0ull) /* infinity */));
489 }
490 
491 
492 // Utilities for test textures
493 
494 template<typename TcuTextureType>
allocateLevels(TcuTextureType & texture)495 void allocateLevels (TcuTextureType& texture)
496 {
497 	for (int levelNdx = 0; levelNdx < texture.getNumLevels(); levelNdx++)
498 		texture.allocLevel(levelNdx);
499 }
500 
501 template<typename TcuTextureType>
getLevelsVector(const TcuTextureType & texture)502 std::vector<tcu::PixelBufferAccess> getLevelsVector (const TcuTextureType& texture)
503 {
504 	std::vector<tcu::PixelBufferAccess> levels(texture.getNumLevels());
505 
506 	for (int levelNdx = 0; levelNdx < texture.getNumLevels(); levelNdx++)
507 		levels[levelNdx] = *reinterpret_cast<const tcu::PixelBufferAccess*>(&texture.getLevel(levelNdx));
508 
509 	return levels;
510 }
511 
512 
513 // TestTexture
514 
TestTexture(const tcu::TextureFormat & format,int width,int height,int depth)515 TestTexture::TestTexture (const tcu::TextureFormat& format, int width, int height, int depth)
516 {
517 	DE_ASSERT(width >= 1);
518 	DE_ASSERT(height >= 1);
519 	DE_ASSERT(depth >= 1);
520 
521 	DE_UNREF(format);
522 	DE_UNREF(width);
523 	DE_UNREF(height);
524 	DE_UNREF(depth);
525 }
526 
TestTexture(const tcu::CompressedTexFormat & format,int width,int height,int depth)527 TestTexture::TestTexture (const tcu::CompressedTexFormat& format, int width, int height, int depth)
528 {
529 	DE_ASSERT(width >= 1);
530 	DE_ASSERT(height >= 1);
531 	DE_ASSERT(depth >= 1);
532 
533 	DE_UNREF(format);
534 	DE_UNREF(width);
535 	DE_UNREF(height);
536 	DE_UNREF(depth);
537 }
538 
~TestTexture(void)539 TestTexture::~TestTexture (void)
540 {
541 	for (size_t levelNdx = 0; levelNdx < m_compressedLevels.size(); levelNdx++)
542 		delete m_compressedLevels[levelNdx];
543 }
544 
getSize(void) const545 deUint32 TestTexture::getSize (void) const
546 {
547 	std::vector<deUint32>	offsetMultiples;
548 	deUint32				textureSize = 0;
549 
550 	offsetMultiples.push_back(4);
551 	offsetMultiples.push_back(getLevel(0, 0).getFormat().getPixelSize());
552 
553 	for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
554 	{
555 		for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
556 		{
557 			const tcu::ConstPixelBufferAccess level = getLevel(levelNdx, layerNdx);
558 			textureSize = getNextMultiple(offsetMultiples, textureSize);
559 			textureSize += level.getWidth() * level.getHeight() * level.getDepth() * level.getFormat().getPixelSize();
560 		}
561 	}
562 
563 	return textureSize;
564 }
565 
getCompressedSize(void) const566 deUint32 TestTexture::getCompressedSize (void) const
567 {
568 	if (!isCompressed())
569 		throw tcu::InternalError("Texture is not compressed");
570 
571 	std::vector<deUint32>	offsetMultiples;
572 	deUint32				textureSize			= 0;
573 
574 	offsetMultiples.push_back(4);
575 	offsetMultiples.push_back(tcu::getBlockSize(getCompressedLevel(0, 0).getFormat()));
576 
577 	for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
578 	{
579 		for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
580 		{
581 			textureSize = getNextMultiple(offsetMultiples, textureSize);
582 			textureSize += getCompressedLevel(levelNdx, layerNdx).getDataSize();
583 		}
584 	}
585 
586 	return textureSize;
587 }
588 
getCompressedLevel(int level,int layer)589 tcu::CompressedTexture& TestTexture::getCompressedLevel (int level, int layer)
590 {
591 	DE_ASSERT(level >= 0 && level < getNumLevels());
592 	DE_ASSERT(layer >= 0 && layer < getArraySize());
593 
594 	return *m_compressedLevels[level * getArraySize() + layer];
595 }
596 
getCompressedLevel(int level,int layer) const597 const tcu::CompressedTexture& TestTexture::getCompressedLevel (int level, int layer) const
598 {
599 	DE_ASSERT(level >= 0 && level < getNumLevels());
600 	DE_ASSERT(layer >= 0 && layer < getArraySize());
601 
602 	return *m_compressedLevels[level * getArraySize() + layer];
603 }
604 
getBufferCopyRegions(void) const605 std::vector<VkBufferImageCopy> TestTexture::getBufferCopyRegions (void) const
606 {
607 	std::vector<deUint32>			offsetMultiples;
608 	std::vector<VkBufferImageCopy>	regions;
609 	deUint32						layerDataOffset	= 0;
610 
611 	offsetMultiples.push_back(4);
612 
613 	if (isCompressed())
614 	{
615 		offsetMultiples.push_back(tcu::getBlockSize(getCompressedLevel(0, 0).getFormat()));
616 
617 		for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
618 		{
619 			for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
620 			{
621 				const tcu::CompressedTexture& level = getCompressedLevel(levelNdx, layerNdx);
622 				tcu::IVec3 blockPixelSize			= getBlockPixelSize(level.getFormat());
623 				layerDataOffset						= getNextMultiple(offsetMultiples, layerDataOffset);
624 
625 				const VkBufferImageCopy layerRegion =
626 				{
627 					layerDataOffset,													// VkDeviceSize				bufferOffset;
628 					(deUint32)getNextMultiple(blockPixelSize.x(), level.getWidth()),	// deUint32					bufferRowLength;
629 					(deUint32)getNextMultiple(blockPixelSize.y(), level.getHeight()),	// deUint32					bufferImageHeight;
630 					{																	// VkImageSubresourceLayers	imageSubresource;
631 						VK_IMAGE_ASPECT_COLOR_BIT,
632 						(deUint32)levelNdx,
633 						(deUint32)layerNdx,
634 						1u
635 					},
636 					{ 0u, 0u, 0u },							// VkOffset3D				imageOffset;
637 					{										// VkExtent3D				imageExtent;
638 						(deUint32)level.getWidth(),
639 						(deUint32)level.getHeight(),
640 						(deUint32)level.getDepth()
641 					}
642 				};
643 
644 				regions.push_back(layerRegion);
645 				layerDataOffset += level.getDataSize();
646 			}
647 		}
648 	}
649 	else
650 	{
651 		offsetMultiples.push_back(getLevel(0, 0).getFormat().getPixelSize());
652 
653 		for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
654 		{
655 			for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
656 			{
657 				const tcu::ConstPixelBufferAccess level = getLevel(levelNdx, layerNdx);
658 
659 				layerDataOffset = getNextMultiple(offsetMultiples, layerDataOffset);
660 
661 				const VkBufferImageCopy layerRegion =
662 				{
663 					layerDataOffset,						// VkDeviceSize				bufferOffset;
664 					(deUint32)level.getWidth(),				// deUint32					bufferRowLength;
665 					(deUint32)level.getHeight(),			// deUint32					bufferImageHeight;
666 					{										// VkImageSubresourceLayers	imageSubresource;
667 						VK_IMAGE_ASPECT_COLOR_BIT,
668 						(deUint32)levelNdx,
669 						(deUint32)layerNdx,
670 						1u
671 					},
672 					{ 0u, 0u, 0u },							// VkOffset3D			imageOffset;
673 					{										// VkExtent3D			imageExtent;
674 						(deUint32)level.getWidth(),
675 						(deUint32)level.getHeight(),
676 						(deUint32)level.getDepth()
677 					}
678 				};
679 
680 				regions.push_back(layerRegion);
681 				layerDataOffset += level.getWidth() * level.getHeight() * level.getDepth() * level.getFormat().getPixelSize();
682 			}
683 		}
684 	}
685 
686 	return regions;
687 }
688 
write(deUint8 * destPtr) const689 void TestTexture::write (deUint8* destPtr) const
690 {
691 	std::vector<deUint32>	offsetMultiples;
692 	deUint32				levelOffset		= 0;
693 
694 	offsetMultiples.push_back(4);
695 
696 	if (isCompressed())
697 	{
698 		offsetMultiples.push_back(tcu::getBlockSize(getCompressedLevel(0, 0).getFormat()));
699 
700 		for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
701 		{
702 			for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
703 			{
704 				levelOffset = getNextMultiple(offsetMultiples, levelOffset);
705 
706 				const tcu::CompressedTexture&		compressedTex	= getCompressedLevel(levelNdx, layerNdx);
707 
708 				deMemcpy(destPtr + levelOffset, compressedTex.getData(), compressedTex.getDataSize());
709 				levelOffset += compressedTex.getDataSize();
710 			}
711 		}
712 	}
713 	else
714 	{
715 		offsetMultiples.push_back(getLevel(0, 0).getFormat().getPixelSize());
716 
717 		for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
718 		{
719 			for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
720 			{
721 				levelOffset = getNextMultiple(offsetMultiples, levelOffset);
722 
723 				const tcu::ConstPixelBufferAccess	srcAccess		= getLevel(levelNdx, layerNdx);
724 				const tcu::PixelBufferAccess		destAccess		(srcAccess.getFormat(), srcAccess.getSize(), srcAccess.getPitch(), destPtr + levelOffset);
725 
726 				tcu::copy(destAccess, srcAccess);
727 				levelOffset += srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
728 			}
729 		}
730 	}
731 }
732 
populateLevels(const std::vector<tcu::PixelBufferAccess> & levels)733 void TestTexture::populateLevels (const std::vector<tcu::PixelBufferAccess>& levels)
734 {
735 	for (size_t levelNdx = 0; levelNdx < levels.size(); levelNdx++)
736 		TestTexture::fillWithGradient(levels[levelNdx]);
737 }
738 
populateCompressedLevels(tcu::CompressedTexFormat format,const std::vector<tcu::PixelBufferAccess> & decompressedLevels)739 void TestTexture::populateCompressedLevels (tcu::CompressedTexFormat format, const std::vector<tcu::PixelBufferAccess>& decompressedLevels)
740 {
741 	// Generate random compressed data and update decompressed data
742 
743 	de::Random random(123);
744 
745 	for (size_t levelNdx = 0; levelNdx < decompressedLevels.size(); levelNdx++)
746 	{
747 		const tcu::PixelBufferAccess	level				= decompressedLevels[levelNdx];
748 		tcu::CompressedTexture*			compressedLevel		= new tcu::CompressedTexture(format, level.getWidth(), level.getHeight(), level.getDepth());
749 		deUint8* const					compressedData		= (deUint8*)compressedLevel->getData();
750 
751 		if (tcu::isAstcFormat(format))
752 		{
753 			// \todo [2016-01-20 pyry] Comparison doesn't currently handle invalid blocks correctly so we use only valid blocks
754 			tcu::astc::generateRandomValidBlocks(compressedData, compressedLevel->getDataSize()/tcu::astc::BLOCK_SIZE_BYTES,
755 												 format, tcu::TexDecompressionParams::ASTCMODE_LDR, random.getUint32());
756 		}
757 		else
758 		{
759 			// Generate random compressed data
760 			for (int byteNdx = 0; byteNdx < compressedLevel->getDataSize(); byteNdx++)
761 				compressedData[byteNdx] = 0xFF & random.getUint32();
762 		}
763 
764 		m_compressedLevels.push_back(compressedLevel);
765 
766 		// Store decompressed data
767 		compressedLevel->decompress(level, tcu::TexDecompressionParams(tcu::TexDecompressionParams::ASTCMODE_LDR));
768 	}
769 }
770 
fillWithGradient(const tcu::PixelBufferAccess & levelAccess)771 void TestTexture::fillWithGradient (const tcu::PixelBufferAccess& levelAccess)
772 {
773 	const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(levelAccess.getFormat());
774 	tcu::fillWithComponentGradients(levelAccess, formatInfo.valueMin, formatInfo.valueMax);
775 }
776 
777 // TestTexture1D
778 
TestTexture1D(const tcu::TextureFormat & format,int width)779 TestTexture1D::TestTexture1D (const tcu::TextureFormat& format, int width)
780 	: TestTexture	(format, width, 1, 1)
781 	, m_texture		(format, width)
782 {
783 	allocateLevels(m_texture);
784 	TestTexture::populateLevels(getLevelsVector(m_texture));
785 }
786 
TestTexture1D(const tcu::CompressedTexFormat & format,int width)787 TestTexture1D::TestTexture1D (const tcu::CompressedTexFormat& format, int width)
788 	: TestTexture	(format, width, 1, 1)
789 	, m_texture		(tcu::getUncompressedFormat(format), width)
790 {
791 	allocateLevels(m_texture);
792 	TestTexture::populateCompressedLevels(format, getLevelsVector(m_texture));
793 }
794 
~TestTexture1D(void)795 TestTexture1D::~TestTexture1D (void)
796 {
797 }
798 
getNumLevels(void) const799 int TestTexture1D::getNumLevels (void) const
800 {
801 	return m_texture.getNumLevels();
802 }
803 
getLevel(int level,int layer)804 tcu::PixelBufferAccess TestTexture1D::getLevel (int level, int layer)
805 {
806 	DE_ASSERT(layer == 0);
807 	DE_UNREF(layer);
808 	return m_texture.getLevel(level);
809 }
810 
getLevel(int level,int layer) const811 const tcu::ConstPixelBufferAccess TestTexture1D::getLevel (int level, int layer) const
812 {
813 	DE_ASSERT(layer == 0);
814 	DE_UNREF(layer);
815 	return m_texture.getLevel(level);
816 }
817 
getTexture(void) const818 const tcu::Texture1D& TestTexture1D::getTexture (void) const
819 {
820 	return m_texture;
821 }
822 
823 
824 // TestTexture1DArray
825 
TestTexture1DArray(const tcu::TextureFormat & format,int width,int arraySize)826 TestTexture1DArray::TestTexture1DArray (const tcu::TextureFormat& format, int width, int arraySize)
827 	: TestTexture	(format, width, 1, arraySize)
828 	, m_texture		(format, width, arraySize)
829 {
830 	allocateLevels(m_texture);
831 	TestTexture::populateLevels(getLevelsVector(m_texture));
832 }
833 
TestTexture1DArray(const tcu::CompressedTexFormat & format,int width,int arraySize)834 TestTexture1DArray::TestTexture1DArray (const tcu::CompressedTexFormat& format, int width, int arraySize)
835 	: TestTexture	(format, width, 1, arraySize)
836 	, m_texture		(tcu::getUncompressedFormat(format), width, arraySize)
837 {
838 	allocateLevels(m_texture);
839 
840 	std::vector<tcu::PixelBufferAccess> layers;
841 	for (int levelNdx = 0; levelNdx < m_texture.getNumLevels(); levelNdx++)
842 		for (int layerNdx = 0; layerNdx < m_texture.getNumLayers(); layerNdx++)
843 			layers.push_back(getLevel(levelNdx, layerNdx));
844 
845 	TestTexture::populateCompressedLevels(format, layers);
846 }
847 
~TestTexture1DArray(void)848 TestTexture1DArray::~TestTexture1DArray (void)
849 {
850 }
851 
getNumLevels(void) const852 int TestTexture1DArray::getNumLevels (void) const
853 {
854 	return m_texture.getNumLevels();
855 }
856 
getLevel(int level,int layer)857 tcu::PixelBufferAccess TestTexture1DArray::getLevel (int level, int layer)
858 {
859 	const tcu::PixelBufferAccess	levelLayers	= m_texture.getLevel(level);
860 	const deUint32					layerSize	= levelLayers.getWidth() * levelLayers.getFormat().getPixelSize();
861 	const deUint32					layerOffset	= layerSize * layer;
862 
863 	return tcu::PixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), 1, 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
864 }
865 
getLevel(int level,int layer) const866 const tcu::ConstPixelBufferAccess TestTexture1DArray::getLevel (int level, int layer) const
867 {
868 	const tcu::ConstPixelBufferAccess	levelLayers	= m_texture.getLevel(level);
869 	const deUint32						layerSize	= levelLayers.getWidth() * levelLayers.getFormat().getPixelSize();
870 	const deUint32						layerOffset	= layerSize * layer;
871 
872 	return tcu::ConstPixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), 1, 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
873 }
874 
getTexture(void) const875 const tcu::Texture1DArray& TestTexture1DArray::getTexture (void) const
876 {
877 	return m_texture;
878 }
879 
getArraySize(void) const880 int TestTexture1DArray::getArraySize (void) const
881 {
882 	return m_texture.getNumLayers();
883 }
884 
885 
886 // TestTexture2D
887 
TestTexture2D(const tcu::TextureFormat & format,int width,int height)888 TestTexture2D::TestTexture2D (const tcu::TextureFormat& format, int width, int height)
889 	: TestTexture	(format, width, height, 1)
890 	, m_texture		(format, width, height)
891 {
892 	allocateLevels(m_texture);
893 	TestTexture::populateLevels(getLevelsVector(m_texture));
894 }
895 
TestTexture2D(const tcu::CompressedTexFormat & format,int width,int height)896 TestTexture2D::TestTexture2D (const tcu::CompressedTexFormat& format, int width, int height)
897 	: TestTexture	(format, width, height, 1)
898 	, m_texture		(tcu::getUncompressedFormat(format), width, height)
899 {
900 	allocateLevels(m_texture);
901 	TestTexture::populateCompressedLevels(format, getLevelsVector(m_texture));
902 }
903 
~TestTexture2D(void)904 TestTexture2D::~TestTexture2D (void)
905 {
906 }
907 
getNumLevels(void) const908 int TestTexture2D::getNumLevels (void) const
909 {
910 	return m_texture.getNumLevels();
911 }
912 
getLevel(int level,int layer)913 tcu::PixelBufferAccess TestTexture2D::getLevel (int level, int layer)
914 {
915 	DE_ASSERT(layer == 0);
916 	DE_UNREF(layer);
917 	return m_texture.getLevel(level);
918 }
919 
getLevel(int level,int layer) const920 const tcu::ConstPixelBufferAccess TestTexture2D::getLevel (int level, int layer) const
921 {
922 	DE_ASSERT(layer == 0);
923 	DE_UNREF(layer);
924 	return m_texture.getLevel(level);
925 }
926 
getTexture(void) const927 const tcu::Texture2D& TestTexture2D::getTexture (void) const
928 {
929 	return m_texture;
930 }
931 
932 
933 // TestTexture2DArray
934 
TestTexture2DArray(const tcu::TextureFormat & format,int width,int height,int arraySize)935 TestTexture2DArray::TestTexture2DArray (const tcu::TextureFormat& format, int width, int height, int arraySize)
936 	: TestTexture	(format, width, height, arraySize)
937 	, m_texture		(format, width, height, arraySize)
938 {
939 	allocateLevels(m_texture);
940 	TestTexture::populateLevels(getLevelsVector(m_texture));
941 }
942 
TestTexture2DArray(const tcu::CompressedTexFormat & format,int width,int height,int arraySize)943 TestTexture2DArray::TestTexture2DArray (const tcu::CompressedTexFormat& format, int width, int height, int arraySize)
944 	: TestTexture	(format, width, height, arraySize)
945 	, m_texture		(tcu::getUncompressedFormat(format), width, height, arraySize)
946 {
947 	allocateLevels(m_texture);
948 
949 	std::vector<tcu::PixelBufferAccess> layers;
950 	for (int levelNdx = 0; levelNdx < m_texture.getNumLevels(); levelNdx++)
951 		for (int layerNdx = 0; layerNdx < m_texture.getNumLayers(); layerNdx++)
952 			layers.push_back(getLevel(levelNdx, layerNdx));
953 
954 	TestTexture::populateCompressedLevels(format, layers);
955 }
956 
~TestTexture2DArray(void)957 TestTexture2DArray::~TestTexture2DArray (void)
958 {
959 }
960 
getNumLevels(void) const961 int TestTexture2DArray::getNumLevels (void) const
962 {
963 	return m_texture.getNumLevels();
964 }
965 
getLevel(int level,int layer)966 tcu::PixelBufferAccess TestTexture2DArray::getLevel (int level, int layer)
967 {
968 	const tcu::PixelBufferAccess	levelLayers	= m_texture.getLevel(level);
969 	const deUint32					layerSize	= levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
970 	const deUint32					layerOffset	= layerSize * layer;
971 
972 	return tcu::PixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
973 }
974 
getLevel(int level,int layer) const975 const tcu::ConstPixelBufferAccess TestTexture2DArray::getLevel (int level, int layer) const
976 {
977 	const tcu::ConstPixelBufferAccess	levelLayers	= m_texture.getLevel(level);
978 	const deUint32						layerSize	= levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
979 	const deUint32						layerOffset	= layerSize * layer;
980 
981 	return tcu::ConstPixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
982 }
983 
getTexture(void) const984 const tcu::Texture2DArray& TestTexture2DArray::getTexture (void) const
985 {
986 	return m_texture;
987 }
988 
getArraySize(void) const989 int TestTexture2DArray::getArraySize (void) const
990 {
991 	return m_texture.getNumLayers();
992 }
993 
994 
995 // TestTexture3D
996 
TestTexture3D(const tcu::TextureFormat & format,int width,int height,int depth)997 TestTexture3D::TestTexture3D (const tcu::TextureFormat& format, int width, int height, int depth)
998 	: TestTexture	(format, width, height, depth)
999 	, m_texture		(format, width, height, depth)
1000 {
1001 	allocateLevels(m_texture);
1002 	TestTexture::populateLevels(getLevelsVector(m_texture));
1003 }
1004 
TestTexture3D(const tcu::CompressedTexFormat & format,int width,int height,int depth)1005 TestTexture3D::TestTexture3D (const tcu::CompressedTexFormat& format, int width, int height, int depth)
1006 	: TestTexture	(format, width, height, depth)
1007 	, m_texture		(tcu::getUncompressedFormat(format), width, height, depth)
1008 {
1009 	allocateLevels(m_texture);
1010 	TestTexture::populateCompressedLevels(format, getLevelsVector(m_texture));
1011 }
1012 
~TestTexture3D(void)1013 TestTexture3D::~TestTexture3D (void)
1014 {
1015 }
1016 
getNumLevels(void) const1017 int TestTexture3D::getNumLevels (void) const
1018 {
1019 	return m_texture.getNumLevels();
1020 }
1021 
getLevel(int level,int layer)1022 tcu::PixelBufferAccess TestTexture3D::getLevel (int level, int layer)
1023 {
1024 	DE_ASSERT(layer == 0);
1025 	DE_UNREF(layer);
1026 	return m_texture.getLevel(level);
1027 }
1028 
getLevel(int level,int layer) const1029 const tcu::ConstPixelBufferAccess TestTexture3D::getLevel (int level, int layer) const
1030 {
1031 	DE_ASSERT(layer == 0);
1032 	DE_UNREF(layer);
1033 	return m_texture.getLevel(level);
1034 }
1035 
getTexture(void) const1036 const tcu::Texture3D& TestTexture3D::getTexture (void) const
1037 {
1038 	return m_texture;
1039 }
1040 
1041 
1042 // TestTextureCube
1043 
1044 const static tcu::CubeFace tcuFaceMapping[tcu::CUBEFACE_LAST] =
1045 {
1046 	tcu::CUBEFACE_POSITIVE_X,
1047 	tcu::CUBEFACE_NEGATIVE_X,
1048 	tcu::CUBEFACE_POSITIVE_Y,
1049 	tcu::CUBEFACE_NEGATIVE_Y,
1050 	tcu::CUBEFACE_POSITIVE_Z,
1051 	tcu::CUBEFACE_NEGATIVE_Z
1052 };
1053 
TestTextureCube(const tcu::TextureFormat & format,int size)1054 TestTextureCube::TestTextureCube (const tcu::TextureFormat& format, int size)
1055 	: TestTexture	(format, size, size, 1)
1056 	, m_texture		(format, size)
1057 {
1058 	for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
1059 	{
1060 		for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
1061 		{
1062 			m_texture.allocLevel(tcuFaceMapping[faceNdx], levelNdx);
1063 			TestTexture::fillWithGradient(m_texture.getLevelFace(levelNdx, tcuFaceMapping[faceNdx]));
1064 		}
1065 	}
1066 }
1067 
TestTextureCube(const tcu::CompressedTexFormat & format,int size)1068 TestTextureCube::TestTextureCube (const tcu::CompressedTexFormat& format, int size)
1069 	: TestTexture	(format, size, size, 1)
1070 	, m_texture		(tcu::getUncompressedFormat(format), size)
1071 {
1072 	std::vector<tcu::PixelBufferAccess> levels(m_texture.getNumLevels() * tcu::CUBEFACE_LAST);
1073 
1074 	for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
1075 	{
1076 		for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
1077 		{
1078 			m_texture.allocLevel(tcuFaceMapping[faceNdx], levelNdx);
1079 			levels[levelNdx * tcu::CUBEFACE_LAST + faceNdx] = m_texture.getLevelFace(levelNdx, tcuFaceMapping[faceNdx]);
1080 		}
1081 	}
1082 
1083 	TestTexture::populateCompressedLevels(format, levels);
1084 }
1085 
~TestTextureCube(void)1086 TestTextureCube::~TestTextureCube (void)
1087 {
1088 }
1089 
getNumLevels(void) const1090 int TestTextureCube::getNumLevels (void) const
1091 {
1092 	return m_texture.getNumLevels();
1093 }
1094 
getLevel(int level,int face)1095 tcu::PixelBufferAccess TestTextureCube::getLevel (int level, int face)
1096 {
1097 	return m_texture.getLevelFace(level, (tcu::CubeFace)face);
1098 }
1099 
getLevel(int level,int face) const1100 const tcu::ConstPixelBufferAccess TestTextureCube::getLevel (int level, int face) const
1101 {
1102 	return m_texture.getLevelFace(level, (tcu::CubeFace)face);
1103 }
1104 
getArraySize(void) const1105 int TestTextureCube::getArraySize (void) const
1106 {
1107 	return (int)tcu::CUBEFACE_LAST;
1108 }
1109 
getTexture(void) const1110 const tcu::TextureCube& TestTextureCube::getTexture (void) const
1111 {
1112 	return m_texture;
1113 }
1114 
1115 // TestTextureCubeArray
1116 
TestTextureCubeArray(const tcu::TextureFormat & format,int size,int arraySize)1117 TestTextureCubeArray::TestTextureCubeArray (const tcu::TextureFormat& format, int size, int arraySize)
1118 	: TestTexture	(format, size, size, arraySize)
1119 	, m_texture		(format, size, arraySize)
1120 {
1121 	allocateLevels(m_texture);
1122 	TestTexture::populateLevels(getLevelsVector(m_texture));
1123 }
1124 
TestTextureCubeArray(const tcu::CompressedTexFormat & format,int size,int arraySize)1125 TestTextureCubeArray::TestTextureCubeArray (const tcu::CompressedTexFormat& format, int size, int arraySize)
1126 	: TestTexture	(format, size, size, arraySize)
1127 	, m_texture		(tcu::getUncompressedFormat(format), size, arraySize)
1128 {
1129 	DE_ASSERT(arraySize % 6 == 0);
1130 
1131 	allocateLevels(m_texture);
1132 
1133 	std::vector<tcu::PixelBufferAccess> layers;
1134 	for (int levelNdx = 0; levelNdx < m_texture.getNumLevels(); levelNdx++)
1135 		for (int layerNdx = 0; layerNdx < m_texture.getDepth(); layerNdx++)
1136 			layers.push_back(getLevel(levelNdx, layerNdx));
1137 
1138 	TestTexture::populateCompressedLevels(format, layers);
1139 }
1140 
~TestTextureCubeArray(void)1141 TestTextureCubeArray::~TestTextureCubeArray (void)
1142 {
1143 }
1144 
getNumLevels(void) const1145 int TestTextureCubeArray::getNumLevels (void) const
1146 {
1147 	return m_texture.getNumLevels();
1148 }
1149 
getLevel(int level,int layer)1150 tcu::PixelBufferAccess TestTextureCubeArray::getLevel (int level, int layer)
1151 {
1152 	const tcu::PixelBufferAccess	levelLayers	= m_texture.getLevel(level);
1153 	const deUint32					layerSize	= levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
1154 	const deUint32					layerOffset	= layerSize * layer;
1155 
1156 	return tcu::PixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
1157 }
1158 
getLevel(int level,int layer) const1159 const tcu::ConstPixelBufferAccess TestTextureCubeArray::getLevel (int level, int layer) const
1160 {
1161 	const tcu::ConstPixelBufferAccess	levelLayers	= m_texture.getLevel(level);
1162 	const deUint32						layerSize	= levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
1163 	const deUint32						layerOffset	= layerSize * layer;
1164 
1165 	return tcu::ConstPixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
1166 }
1167 
getArraySize(void) const1168 int TestTextureCubeArray::getArraySize (void) const
1169 {
1170 	return m_texture.getDepth();
1171 }
1172 
getTexture(void) const1173 const tcu::TextureCubeArray& TestTextureCubeArray::getTexture (void) const
1174 {
1175 	return m_texture;
1176 }
1177 
1178 } // pipeline
1179 } // vkt
1180