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