xref: /aosp_15_r20/external/swiftshader/src/Vulkan/VkImage.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2018 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker //    http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker 
15*03ce13f7SAndroid Build Coastguard Worker #include "VkImage.hpp"
16*03ce13f7SAndroid Build Coastguard Worker 
17*03ce13f7SAndroid Build Coastguard Worker #include "VkBuffer.hpp"
18*03ce13f7SAndroid Build Coastguard Worker #include "VkDevice.hpp"
19*03ce13f7SAndroid Build Coastguard Worker #include "VkDeviceMemory.hpp"
20*03ce13f7SAndroid Build Coastguard Worker #include "VkImageView.hpp"
21*03ce13f7SAndroid Build Coastguard Worker #include "VkStringify.hpp"
22*03ce13f7SAndroid Build Coastguard Worker #include "VkStructConversion.hpp"
23*03ce13f7SAndroid Build Coastguard Worker #include "Device/ASTC_Decoder.hpp"
24*03ce13f7SAndroid Build Coastguard Worker #include "Device/BC_Decoder.hpp"
25*03ce13f7SAndroid Build Coastguard Worker #include "Device/Blitter.hpp"
26*03ce13f7SAndroid Build Coastguard Worker #include "Device/ETC_Decoder.hpp"
27*03ce13f7SAndroid Build Coastguard Worker 
28*03ce13f7SAndroid Build Coastguard Worker #ifdef __ANDROID__
29*03ce13f7SAndroid Build Coastguard Worker #	include <vndk/hardware_buffer.h>
30*03ce13f7SAndroid Build Coastguard Worker 
31*03ce13f7SAndroid Build Coastguard Worker #	include "VkDeviceMemoryExternalAndroid.hpp"
32*03ce13f7SAndroid Build Coastguard Worker #endif
33*03ce13f7SAndroid Build Coastguard Worker 
34*03ce13f7SAndroid Build Coastguard Worker #include <cstring>
35*03ce13f7SAndroid Build Coastguard Worker 
36*03ce13f7SAndroid Build Coastguard Worker namespace {
37*03ce13f7SAndroid Build Coastguard Worker 
GetInputType(const vk::Format & format)38*03ce13f7SAndroid Build Coastguard Worker ETC_Decoder::InputType GetInputType(const vk::Format &format)
39*03ce13f7SAndroid Build Coastguard Worker {
40*03ce13f7SAndroid Build Coastguard Worker 	switch(format)
41*03ce13f7SAndroid Build Coastguard Worker 	{
42*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_EAC_R11_UNORM_BLOCK:
43*03ce13f7SAndroid Build Coastguard Worker 		return ETC_Decoder::ETC_R_UNSIGNED;
44*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_EAC_R11_SNORM_BLOCK:
45*03ce13f7SAndroid Build Coastguard Worker 		return ETC_Decoder::ETC_R_SIGNED;
46*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_EAC_R11G11_UNORM_BLOCK:
47*03ce13f7SAndroid Build Coastguard Worker 		return ETC_Decoder::ETC_RG_UNSIGNED;
48*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
49*03ce13f7SAndroid Build Coastguard Worker 		return ETC_Decoder::ETC_RG_SIGNED;
50*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
51*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
52*03ce13f7SAndroid Build Coastguard Worker 		return ETC_Decoder::ETC_RGB;
53*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:
54*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
55*03ce13f7SAndroid Build Coastguard Worker 		return ETC_Decoder::ETC_RGB_PUNCHTHROUGH_ALPHA;
56*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
57*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
58*03ce13f7SAndroid Build Coastguard Worker 		return ETC_Decoder::ETC_RGBA;
59*03ce13f7SAndroid Build Coastguard Worker 	default:
60*03ce13f7SAndroid Build Coastguard Worker 		UNSUPPORTED("format: %d", int(format));
61*03ce13f7SAndroid Build Coastguard Worker 		return ETC_Decoder::ETC_RGBA;
62*03ce13f7SAndroid Build Coastguard Worker 	}
63*03ce13f7SAndroid Build Coastguard Worker }
64*03ce13f7SAndroid Build Coastguard Worker 
GetBCn(const vk::Format & format)65*03ce13f7SAndroid Build Coastguard Worker int GetBCn(const vk::Format &format)
66*03ce13f7SAndroid Build Coastguard Worker {
67*03ce13f7SAndroid Build Coastguard Worker 	switch(format)
68*03ce13f7SAndroid Build Coastguard Worker 	{
69*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
70*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
71*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
72*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
73*03ce13f7SAndroid Build Coastguard Worker 		return 1;
74*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC2_UNORM_BLOCK:
75*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC2_SRGB_BLOCK:
76*03ce13f7SAndroid Build Coastguard Worker 		return 2;
77*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC3_UNORM_BLOCK:
78*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC3_SRGB_BLOCK:
79*03ce13f7SAndroid Build Coastguard Worker 		return 3;
80*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC4_UNORM_BLOCK:
81*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC4_SNORM_BLOCK:
82*03ce13f7SAndroid Build Coastguard Worker 		return 4;
83*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC5_UNORM_BLOCK:
84*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC5_SNORM_BLOCK:
85*03ce13f7SAndroid Build Coastguard Worker 		return 5;
86*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC6H_UFLOAT_BLOCK:
87*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC6H_SFLOAT_BLOCK:
88*03ce13f7SAndroid Build Coastguard Worker 		return 6;
89*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC7_UNORM_BLOCK:
90*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC7_SRGB_BLOCK:
91*03ce13f7SAndroid Build Coastguard Worker 		return 7;
92*03ce13f7SAndroid Build Coastguard Worker 	default:
93*03ce13f7SAndroid Build Coastguard Worker 		UNSUPPORTED("format: %d", int(format));
94*03ce13f7SAndroid Build Coastguard Worker 		return 0;
95*03ce13f7SAndroid Build Coastguard Worker 	}
96*03ce13f7SAndroid Build Coastguard Worker }
97*03ce13f7SAndroid Build Coastguard Worker 
98*03ce13f7SAndroid Build Coastguard Worker // Returns true for BC1 if we have an RGB format, false for RGBA
99*03ce13f7SAndroid Build Coastguard Worker // Returns true for BC4, BC5, BC6H if we have an unsigned format, false for signed
100*03ce13f7SAndroid Build Coastguard Worker // Ignored by BC2, BC3, and BC7
GetNoAlphaOrUnsigned(const vk::Format & format)101*03ce13f7SAndroid Build Coastguard Worker bool GetNoAlphaOrUnsigned(const vk::Format &format)
102*03ce13f7SAndroid Build Coastguard Worker {
103*03ce13f7SAndroid Build Coastguard Worker 	switch(format)
104*03ce13f7SAndroid Build Coastguard Worker 	{
105*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
106*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
107*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC4_UNORM_BLOCK:
108*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC5_UNORM_BLOCK:
109*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC6H_UFLOAT_BLOCK:
110*03ce13f7SAndroid Build Coastguard Worker 		return true;
111*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
112*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
113*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC2_UNORM_BLOCK:
114*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC2_SRGB_BLOCK:
115*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC3_UNORM_BLOCK:
116*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC3_SRGB_BLOCK:
117*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC4_SNORM_BLOCK:
118*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC5_SNORM_BLOCK:
119*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC6H_SFLOAT_BLOCK:
120*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC7_SRGB_BLOCK:
121*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC7_UNORM_BLOCK:
122*03ce13f7SAndroid Build Coastguard Worker 		return false;
123*03ce13f7SAndroid Build Coastguard Worker 	default:
124*03ce13f7SAndroid Build Coastguard Worker 		UNSUPPORTED("format: %d", int(format));
125*03ce13f7SAndroid Build Coastguard Worker 		return false;
126*03ce13f7SAndroid Build Coastguard Worker 	}
127*03ce13f7SAndroid Build Coastguard Worker }
128*03ce13f7SAndroid Build Coastguard Worker 
GetImageFormat(const VkImageCreateInfo * pCreateInfo)129*03ce13f7SAndroid Build Coastguard Worker VkFormat GetImageFormat(const VkImageCreateInfo *pCreateInfo)
130*03ce13f7SAndroid Build Coastguard Worker {
131*03ce13f7SAndroid Build Coastguard Worker 	const auto *nextInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
132*03ce13f7SAndroid Build Coastguard Worker 	while(nextInfo)
133*03ce13f7SAndroid Build Coastguard Worker 	{
134*03ce13f7SAndroid Build Coastguard Worker 		// Casting to an int since some structures, such as VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID and
135*03ce13f7SAndroid Build Coastguard Worker 		// VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID, are not enumerated in the official Vulkan headers.
136*03ce13f7SAndroid Build Coastguard Worker 		switch((int)(nextInfo->sType))
137*03ce13f7SAndroid Build Coastguard Worker 		{
138*03ce13f7SAndroid Build Coastguard Worker #ifdef __ANDROID__
139*03ce13f7SAndroid Build Coastguard Worker 		case VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID:
140*03ce13f7SAndroid Build Coastguard Worker 			{
141*03ce13f7SAndroid Build Coastguard Worker 				const VkExternalFormatANDROID *externalFormatAndroid = reinterpret_cast<const VkExternalFormatANDROID *>(nextInfo);
142*03ce13f7SAndroid Build Coastguard Worker 
143*03ce13f7SAndroid Build Coastguard Worker 				// VkExternalFormatANDROID: "If externalFormat is zero, the effect is as if the VkExternalFormatANDROID structure was not present."
144*03ce13f7SAndroid Build Coastguard Worker 				if(externalFormatAndroid->externalFormat == 0)
145*03ce13f7SAndroid Build Coastguard Worker 				{
146*03ce13f7SAndroid Build Coastguard Worker 					break;
147*03ce13f7SAndroid Build Coastguard Worker 				}
148*03ce13f7SAndroid Build Coastguard Worker 
149*03ce13f7SAndroid Build Coastguard Worker 				const VkFormat correspondingVkFormat = AHardwareBufferExternalMemory::GetVkFormatFromAHBFormat(externalFormatAndroid->externalFormat);
150*03ce13f7SAndroid Build Coastguard Worker 				ASSERT(pCreateInfo->format == VK_FORMAT_UNDEFINED || pCreateInfo->format == correspondingVkFormat);
151*03ce13f7SAndroid Build Coastguard Worker 				return correspondingVkFormat;
152*03ce13f7SAndroid Build Coastguard Worker 			}
153*03ce13f7SAndroid Build Coastguard Worker 			break;
154*03ce13f7SAndroid Build Coastguard Worker 		case VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID:
155*03ce13f7SAndroid Build Coastguard Worker 			break;
156*03ce13f7SAndroid Build Coastguard Worker 		case VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID:
157*03ce13f7SAndroid Build Coastguard Worker 			break;
158*03ce13f7SAndroid Build Coastguard Worker #endif
159*03ce13f7SAndroid Build Coastguard Worker 		// We support these extensions, but they don't affect the image format.
160*03ce13f7SAndroid Build Coastguard Worker 		case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO:
161*03ce13f7SAndroid Build Coastguard Worker 		case VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR:
162*03ce13f7SAndroid Build Coastguard Worker 		case VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO:
163*03ce13f7SAndroid Build Coastguard Worker 		case VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO:
164*03ce13f7SAndroid Build Coastguard Worker 			break;
165*03ce13f7SAndroid Build Coastguard Worker 		case VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT:
166*03ce13f7SAndroid Build Coastguard Worker 			{
167*03ce13f7SAndroid Build Coastguard Worker 				// Explicitly ignored, since VK_EXT_image_drm_format_modifier is not supported
168*03ce13f7SAndroid Build Coastguard Worker 			}
169*03ce13f7SAndroid Build Coastguard Worker 			break;
170*03ce13f7SAndroid Build Coastguard Worker 		case VK_STRUCTURE_TYPE_MAX_ENUM:
171*03ce13f7SAndroid Build Coastguard Worker 			// dEQP tests that this value is ignored.
172*03ce13f7SAndroid Build Coastguard Worker 			break;
173*03ce13f7SAndroid Build Coastguard Worker 		default:
174*03ce13f7SAndroid Build Coastguard Worker 			UNSUPPORTED("pCreateInfo->pNext->sType = %s", vk::Stringify(nextInfo->sType).c_str());
175*03ce13f7SAndroid Build Coastguard Worker 			break;
176*03ce13f7SAndroid Build Coastguard Worker 		}
177*03ce13f7SAndroid Build Coastguard Worker 
178*03ce13f7SAndroid Build Coastguard Worker 		nextInfo = nextInfo->pNext;
179*03ce13f7SAndroid Build Coastguard Worker 	}
180*03ce13f7SAndroid Build Coastguard Worker 
181*03ce13f7SAndroid Build Coastguard Worker 	return pCreateInfo->format;
182*03ce13f7SAndroid Build Coastguard Worker }
183*03ce13f7SAndroid Build Coastguard Worker 
184*03ce13f7SAndroid Build Coastguard Worker }  // anonymous namespace
185*03ce13f7SAndroid Build Coastguard Worker 
186*03ce13f7SAndroid Build Coastguard Worker namespace vk {
187*03ce13f7SAndroid Build Coastguard Worker 
Image(const VkImageCreateInfo * pCreateInfo,void * mem,Device * device)188*03ce13f7SAndroid Build Coastguard Worker Image::Image(const VkImageCreateInfo *pCreateInfo, void *mem, Device *device)
189*03ce13f7SAndroid Build Coastguard Worker     : device(device)
190*03ce13f7SAndroid Build Coastguard Worker     , flags(pCreateInfo->flags)
191*03ce13f7SAndroid Build Coastguard Worker     , imageType(pCreateInfo->imageType)
192*03ce13f7SAndroid Build Coastguard Worker     , format(GetImageFormat(pCreateInfo))
193*03ce13f7SAndroid Build Coastguard Worker     , extent(pCreateInfo->extent)
194*03ce13f7SAndroid Build Coastguard Worker     , mipLevels(pCreateInfo->mipLevels)
195*03ce13f7SAndroid Build Coastguard Worker     , arrayLayers(pCreateInfo->arrayLayers)
196*03ce13f7SAndroid Build Coastguard Worker     , samples(pCreateInfo->samples)
197*03ce13f7SAndroid Build Coastguard Worker     , tiling(pCreateInfo->tiling)
198*03ce13f7SAndroid Build Coastguard Worker     , usage(pCreateInfo->usage)
199*03ce13f7SAndroid Build Coastguard Worker {
200*03ce13f7SAndroid Build Coastguard Worker 	if(format.isCompressed())
201*03ce13f7SAndroid Build Coastguard Worker 	{
202*03ce13f7SAndroid Build Coastguard Worker 		VkImageCreateInfo compressedImageCreateInfo = *pCreateInfo;
203*03ce13f7SAndroid Build Coastguard Worker 		compressedImageCreateInfo.format = format.getDecompressedFormat();
204*03ce13f7SAndroid Build Coastguard Worker 		decompressedImage = new(mem) Image(&compressedImageCreateInfo, nullptr, device);
205*03ce13f7SAndroid Build Coastguard Worker 	}
206*03ce13f7SAndroid Build Coastguard Worker 
207*03ce13f7SAndroid Build Coastguard Worker 	const auto *externalInfo = GetExtendedStruct<VkExternalMemoryImageCreateInfo>(pCreateInfo->pNext, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO);
208*03ce13f7SAndroid Build Coastguard Worker 	if(externalInfo)
209*03ce13f7SAndroid Build Coastguard Worker 	{
210*03ce13f7SAndroid Build Coastguard Worker 		supportedExternalMemoryHandleTypes = externalInfo->handleTypes;
211*03ce13f7SAndroid Build Coastguard Worker 	}
212*03ce13f7SAndroid Build Coastguard Worker }
213*03ce13f7SAndroid Build Coastguard Worker 
destroy(const VkAllocationCallbacks * pAllocator)214*03ce13f7SAndroid Build Coastguard Worker void Image::destroy(const VkAllocationCallbacks *pAllocator)
215*03ce13f7SAndroid Build Coastguard Worker {
216*03ce13f7SAndroid Build Coastguard Worker 	if(decompressedImage)
217*03ce13f7SAndroid Build Coastguard Worker 	{
218*03ce13f7SAndroid Build Coastguard Worker 		vk::freeHostMemory(decompressedImage, pAllocator);
219*03ce13f7SAndroid Build Coastguard Worker 	}
220*03ce13f7SAndroid Build Coastguard Worker }
221*03ce13f7SAndroid Build Coastguard Worker 
ComputeRequiredAllocationSize(const VkImageCreateInfo * pCreateInfo)222*03ce13f7SAndroid Build Coastguard Worker size_t Image::ComputeRequiredAllocationSize(const VkImageCreateInfo *pCreateInfo)
223*03ce13f7SAndroid Build Coastguard Worker {
224*03ce13f7SAndroid Build Coastguard Worker 	return Format(pCreateInfo->format).isCompressed() ? sizeof(Image) : 0;
225*03ce13f7SAndroid Build Coastguard Worker }
226*03ce13f7SAndroid Build Coastguard Worker 
getMemoryRequirements() const227*03ce13f7SAndroid Build Coastguard Worker const VkMemoryRequirements Image::getMemoryRequirements() const
228*03ce13f7SAndroid Build Coastguard Worker {
229*03ce13f7SAndroid Build Coastguard Worker 	VkMemoryRequirements memoryRequirements;
230*03ce13f7SAndroid Build Coastguard Worker 	memoryRequirements.alignment = vk::MEMORY_REQUIREMENTS_OFFSET_ALIGNMENT;
231*03ce13f7SAndroid Build Coastguard Worker 	memoryRequirements.memoryTypeBits = vk::MEMORY_TYPE_GENERIC_BIT;
232*03ce13f7SAndroid Build Coastguard Worker 	memoryRequirements.size = getStorageSize(format.getAspects()) +
233*03ce13f7SAndroid Build Coastguard Worker 	                          (decompressedImage ? decompressedImage->getStorageSize(decompressedImage->format.getAspects()) : 0);
234*03ce13f7SAndroid Build Coastguard Worker 	return memoryRequirements;
235*03ce13f7SAndroid Build Coastguard Worker }
236*03ce13f7SAndroid Build Coastguard Worker 
getMemoryRequirements(VkMemoryRequirements2 * pMemoryRequirements) const237*03ce13f7SAndroid Build Coastguard Worker void Image::getMemoryRequirements(VkMemoryRequirements2 *pMemoryRequirements) const
238*03ce13f7SAndroid Build Coastguard Worker {
239*03ce13f7SAndroid Build Coastguard Worker 	VkBaseOutStructure *extensionRequirements = reinterpret_cast<VkBaseOutStructure *>(pMemoryRequirements->pNext);
240*03ce13f7SAndroid Build Coastguard Worker 	while(extensionRequirements)
241*03ce13f7SAndroid Build Coastguard Worker 	{
242*03ce13f7SAndroid Build Coastguard Worker 		switch(extensionRequirements->sType)
243*03ce13f7SAndroid Build Coastguard Worker 		{
244*03ce13f7SAndroid Build Coastguard Worker 		case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS:
245*03ce13f7SAndroid Build Coastguard Worker 			{
246*03ce13f7SAndroid Build Coastguard Worker 				auto *requirements = reinterpret_cast<VkMemoryDedicatedRequirements *>(extensionRequirements);
247*03ce13f7SAndroid Build Coastguard Worker 				device->getRequirements(requirements);
248*03ce13f7SAndroid Build Coastguard Worker #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
249*03ce13f7SAndroid Build Coastguard Worker 				if(getSupportedExternalMemoryHandleTypes() == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
250*03ce13f7SAndroid Build Coastguard Worker 				{
251*03ce13f7SAndroid Build Coastguard Worker 					requirements->prefersDedicatedAllocation = VK_TRUE;
252*03ce13f7SAndroid Build Coastguard Worker 					requirements->requiresDedicatedAllocation = VK_TRUE;
253*03ce13f7SAndroid Build Coastguard Worker 				}
254*03ce13f7SAndroid Build Coastguard Worker #endif
255*03ce13f7SAndroid Build Coastguard Worker 			}
256*03ce13f7SAndroid Build Coastguard Worker 			break;
257*03ce13f7SAndroid Build Coastguard Worker 		default:
258*03ce13f7SAndroid Build Coastguard Worker 			UNSUPPORTED("pMemoryRequirements->pNext sType = %s", vk::Stringify(extensionRequirements->sType).c_str());
259*03ce13f7SAndroid Build Coastguard Worker 			break;
260*03ce13f7SAndroid Build Coastguard Worker 		}
261*03ce13f7SAndroid Build Coastguard Worker 
262*03ce13f7SAndroid Build Coastguard Worker 		extensionRequirements = extensionRequirements->pNext;
263*03ce13f7SAndroid Build Coastguard Worker 	}
264*03ce13f7SAndroid Build Coastguard Worker 
265*03ce13f7SAndroid Build Coastguard Worker 	pMemoryRequirements->memoryRequirements = getMemoryRequirements();
266*03ce13f7SAndroid Build Coastguard Worker }
267*03ce13f7SAndroid Build Coastguard Worker 
getSizeInBytes(const VkImageSubresourceRange & subresourceRange) const268*03ce13f7SAndroid Build Coastguard Worker size_t Image::getSizeInBytes(const VkImageSubresourceRange &subresourceRange) const
269*03ce13f7SAndroid Build Coastguard Worker {
270*03ce13f7SAndroid Build Coastguard Worker 	size_t size = 0;
271*03ce13f7SAndroid Build Coastguard Worker 	uint32_t lastLayer = getLastLayerIndex(subresourceRange);
272*03ce13f7SAndroid Build Coastguard Worker 	uint32_t lastMipLevel = getLastMipLevel(subresourceRange);
273*03ce13f7SAndroid Build Coastguard Worker 	uint32_t layerCount = lastLayer - subresourceRange.baseArrayLayer + 1;
274*03ce13f7SAndroid Build Coastguard Worker 	uint32_t mipLevelCount = lastMipLevel - subresourceRange.baseMipLevel + 1;
275*03ce13f7SAndroid Build Coastguard Worker 
276*03ce13f7SAndroid Build Coastguard Worker 	auto aspect = static_cast<VkImageAspectFlagBits>(subresourceRange.aspectMask);
277*03ce13f7SAndroid Build Coastguard Worker 
278*03ce13f7SAndroid Build Coastguard Worker 	if(layerCount > 1)
279*03ce13f7SAndroid Build Coastguard Worker 	{
280*03ce13f7SAndroid Build Coastguard Worker 		if(mipLevelCount < mipLevels)  // Compute size for all layers except the last one, then add relevant mip level sizes only for last layer
281*03ce13f7SAndroid Build Coastguard Worker 		{
282*03ce13f7SAndroid Build Coastguard Worker 			size = (layerCount - 1) * getLayerSize(aspect);
283*03ce13f7SAndroid Build Coastguard Worker 			for(uint32_t mipLevel = subresourceRange.baseMipLevel; mipLevel <= lastMipLevel; ++mipLevel)
284*03ce13f7SAndroid Build Coastguard Worker 			{
285*03ce13f7SAndroid Build Coastguard Worker 				size += getMultiSampledLevelSize(aspect, mipLevel);
286*03ce13f7SAndroid Build Coastguard Worker 			}
287*03ce13f7SAndroid Build Coastguard Worker 		}
288*03ce13f7SAndroid Build Coastguard Worker 		else  // All mip levels used, compute full layer sizes
289*03ce13f7SAndroid Build Coastguard Worker 		{
290*03ce13f7SAndroid Build Coastguard Worker 			size = layerCount * getLayerSize(aspect);
291*03ce13f7SAndroid Build Coastguard Worker 		}
292*03ce13f7SAndroid Build Coastguard Worker 	}
293*03ce13f7SAndroid Build Coastguard Worker 	else  // Single layer, add all mip levels in the subresource range
294*03ce13f7SAndroid Build Coastguard Worker 	{
295*03ce13f7SAndroid Build Coastguard Worker 		for(uint32_t mipLevel = subresourceRange.baseMipLevel; mipLevel <= lastMipLevel; ++mipLevel)
296*03ce13f7SAndroid Build Coastguard Worker 		{
297*03ce13f7SAndroid Build Coastguard Worker 			size += getMultiSampledLevelSize(aspect, mipLevel);
298*03ce13f7SAndroid Build Coastguard Worker 		}
299*03ce13f7SAndroid Build Coastguard Worker 	}
300*03ce13f7SAndroid Build Coastguard Worker 
301*03ce13f7SAndroid Build Coastguard Worker 	return size;
302*03ce13f7SAndroid Build Coastguard Worker }
303*03ce13f7SAndroid Build Coastguard Worker 
canBindToMemory(DeviceMemory * pDeviceMemory) const304*03ce13f7SAndroid Build Coastguard Worker bool Image::canBindToMemory(DeviceMemory *pDeviceMemory) const
305*03ce13f7SAndroid Build Coastguard Worker {
306*03ce13f7SAndroid Build Coastguard Worker 	return pDeviceMemory->checkExternalMemoryHandleType(supportedExternalMemoryHandleTypes);
307*03ce13f7SAndroid Build Coastguard Worker }
308*03ce13f7SAndroid Build Coastguard Worker 
bind(DeviceMemory * pDeviceMemory,VkDeviceSize pMemoryOffset)309*03ce13f7SAndroid Build Coastguard Worker void Image::bind(DeviceMemory *pDeviceMemory, VkDeviceSize pMemoryOffset)
310*03ce13f7SAndroid Build Coastguard Worker {
311*03ce13f7SAndroid Build Coastguard Worker 	deviceMemory = pDeviceMemory;
312*03ce13f7SAndroid Build Coastguard Worker 	memoryOffset = pMemoryOffset;
313*03ce13f7SAndroid Build Coastguard Worker 	if(decompressedImage)
314*03ce13f7SAndroid Build Coastguard Worker 	{
315*03ce13f7SAndroid Build Coastguard Worker 		decompressedImage->deviceMemory = deviceMemory;
316*03ce13f7SAndroid Build Coastguard Worker 		decompressedImage->memoryOffset = memoryOffset + getStorageSize(format.getAspects());
317*03ce13f7SAndroid Build Coastguard Worker 	}
318*03ce13f7SAndroid Build Coastguard Worker }
319*03ce13f7SAndroid Build Coastguard Worker 
320*03ce13f7SAndroid Build Coastguard Worker #ifdef __ANDROID__
prepareForExternalUseANDROID() const321*03ce13f7SAndroid Build Coastguard Worker VkResult Image::prepareForExternalUseANDROID() const
322*03ce13f7SAndroid Build Coastguard Worker {
323*03ce13f7SAndroid Build Coastguard Worker 	VkExtent3D extent = getMipLevelExtent(VK_IMAGE_ASPECT_COLOR_BIT, 0);
324*03ce13f7SAndroid Build Coastguard Worker 
325*03ce13f7SAndroid Build Coastguard Worker 	AHardwareBuffer_Desc ahbDesc = {};
326*03ce13f7SAndroid Build Coastguard Worker 	ahbDesc.width = extent.width;
327*03ce13f7SAndroid Build Coastguard Worker 	ahbDesc.height = extent.height;
328*03ce13f7SAndroid Build Coastguard Worker 	ahbDesc.layers = 1;
329*03ce13f7SAndroid Build Coastguard Worker 	ahbDesc.format = static_cast<uint32_t>(backingMemory.nativeBufferInfo.format);
330*03ce13f7SAndroid Build Coastguard Worker 	ahbDesc.usage = static_cast<uint64_t>(backingMemory.nativeBufferInfo.usage);
331*03ce13f7SAndroid Build Coastguard Worker 	ahbDesc.stride = static_cast<uint32_t>(backingMemory.nativeBufferInfo.stride);
332*03ce13f7SAndroid Build Coastguard Worker 
333*03ce13f7SAndroid Build Coastguard Worker 	AHardwareBuffer *ahb = nullptr;
334*03ce13f7SAndroid Build Coastguard Worker 	if(AHardwareBuffer_createFromHandle(&ahbDesc, backingMemory.nativeBufferInfo.handle, AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE, &ahb) != 0)
335*03ce13f7SAndroid Build Coastguard Worker 	{
336*03ce13f7SAndroid Build Coastguard Worker 		return VK_ERROR_OUT_OF_DATE_KHR;
337*03ce13f7SAndroid Build Coastguard Worker 	}
338*03ce13f7SAndroid Build Coastguard Worker 	if(!ahb)
339*03ce13f7SAndroid Build Coastguard Worker 	{
340*03ce13f7SAndroid Build Coastguard Worker 		return VK_ERROR_OUT_OF_DATE_KHR;
341*03ce13f7SAndroid Build Coastguard Worker 	}
342*03ce13f7SAndroid Build Coastguard Worker 
343*03ce13f7SAndroid Build Coastguard Worker 	ARect ahbRect = {};
344*03ce13f7SAndroid Build Coastguard Worker 	ahbRect.left = 0;
345*03ce13f7SAndroid Build Coastguard Worker 	ahbRect.top = 0;
346*03ce13f7SAndroid Build Coastguard Worker 	ahbRect.right = static_cast<int32_t>(extent.width);
347*03ce13f7SAndroid Build Coastguard Worker 	ahbRect.bottom = static_cast<int32_t>(extent.height);
348*03ce13f7SAndroid Build Coastguard Worker 
349*03ce13f7SAndroid Build Coastguard Worker 	AHardwareBuffer_Planes ahbPlanes = {};
350*03ce13f7SAndroid Build Coastguard Worker 	if(AHardwareBuffer_lockPlanes(ahb, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, /*fence=*/-1, &ahbRect, &ahbPlanes) != 0)
351*03ce13f7SAndroid Build Coastguard Worker 	{
352*03ce13f7SAndroid Build Coastguard Worker 		return VK_ERROR_OUT_OF_DATE_KHR;
353*03ce13f7SAndroid Build Coastguard Worker 	}
354*03ce13f7SAndroid Build Coastguard Worker 
355*03ce13f7SAndroid Build Coastguard Worker 	int imageRowBytes = rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
356*03ce13f7SAndroid Build Coastguard Worker 	int bufferRowBytes = backingMemory.nativeBufferInfo.stride * getFormat().bytes();
357*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(imageRowBytes <= bufferRowBytes);
358*03ce13f7SAndroid Build Coastguard Worker 
359*03ce13f7SAndroid Build Coastguard Worker 	uint8_t *srcBuffer = static_cast<uint8_t *>(deviceMemory->getOffsetPointer(0));
360*03ce13f7SAndroid Build Coastguard Worker 	uint8_t *dstBuffer = static_cast<uint8_t *>(ahbPlanes.planes[0].data);
361*03ce13f7SAndroid Build Coastguard Worker 	for(uint32_t i = 0; i < extent.height; i++)
362*03ce13f7SAndroid Build Coastguard Worker 	{
363*03ce13f7SAndroid Build Coastguard Worker 		memcpy(dstBuffer + (i * bufferRowBytes), srcBuffer + (i * imageRowBytes), imageRowBytes);
364*03ce13f7SAndroid Build Coastguard Worker 	}
365*03ce13f7SAndroid Build Coastguard Worker 
366*03ce13f7SAndroid Build Coastguard Worker 	AHardwareBuffer_unlock(ahb, /*fence=*/nullptr);
367*03ce13f7SAndroid Build Coastguard Worker 	AHardwareBuffer_release(ahb);
368*03ce13f7SAndroid Build Coastguard Worker 
369*03ce13f7SAndroid Build Coastguard Worker 	return VK_SUCCESS;
370*03ce13f7SAndroid Build Coastguard Worker }
371*03ce13f7SAndroid Build Coastguard Worker 
getExternalMemory() const372*03ce13f7SAndroid Build Coastguard Worker VkDeviceMemory Image::getExternalMemory() const
373*03ce13f7SAndroid Build Coastguard Worker {
374*03ce13f7SAndroid Build Coastguard Worker 	return backingMemory.externalMemory ? *deviceMemory : VkDeviceMemory{ VK_NULL_HANDLE };
375*03ce13f7SAndroid Build Coastguard Worker }
376*03ce13f7SAndroid Build Coastguard Worker #endif
377*03ce13f7SAndroid Build Coastguard Worker 
getSubresourceLayout(const VkImageSubresource * pSubresource,VkSubresourceLayout * pLayout) const378*03ce13f7SAndroid Build Coastguard Worker void Image::getSubresourceLayout(const VkImageSubresource *pSubresource, VkSubresourceLayout *pLayout) const
379*03ce13f7SAndroid Build Coastguard Worker {
380*03ce13f7SAndroid Build Coastguard Worker 	// By spec, aspectMask has a single bit set.
381*03ce13f7SAndroid Build Coastguard Worker 	if(!((pSubresource->aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
382*03ce13f7SAndroid Build Coastguard Worker 	     (pSubresource->aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
383*03ce13f7SAndroid Build Coastguard Worker 	     (pSubresource->aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT) ||
384*03ce13f7SAndroid Build Coastguard Worker 	     (pSubresource->aspectMask == VK_IMAGE_ASPECT_PLANE_0_BIT) ||
385*03ce13f7SAndroid Build Coastguard Worker 	     (pSubresource->aspectMask == VK_IMAGE_ASPECT_PLANE_1_BIT) ||
386*03ce13f7SAndroid Build Coastguard Worker 	     (pSubresource->aspectMask == VK_IMAGE_ASPECT_PLANE_2_BIT)))
387*03ce13f7SAndroid Build Coastguard Worker 	{
388*03ce13f7SAndroid Build Coastguard Worker 		UNSUPPORTED("aspectMask %X", pSubresource->aspectMask);
389*03ce13f7SAndroid Build Coastguard Worker 	}
390*03ce13f7SAndroid Build Coastguard Worker 
391*03ce13f7SAndroid Build Coastguard Worker 	auto aspect = static_cast<VkImageAspectFlagBits>(pSubresource->aspectMask);
392*03ce13f7SAndroid Build Coastguard Worker 	pLayout->offset = getSubresourceOffset(aspect, pSubresource->mipLevel, pSubresource->arrayLayer);
393*03ce13f7SAndroid Build Coastguard Worker 	pLayout->size = getMultiSampledLevelSize(aspect, pSubresource->mipLevel);
394*03ce13f7SAndroid Build Coastguard Worker 	pLayout->rowPitch = rowPitchBytes(aspect, pSubresource->mipLevel);
395*03ce13f7SAndroid Build Coastguard Worker 	pLayout->depthPitch = slicePitchBytes(aspect, pSubresource->mipLevel);
396*03ce13f7SAndroid Build Coastguard Worker 	pLayout->arrayPitch = getLayerSize(aspect);
397*03ce13f7SAndroid Build Coastguard Worker }
398*03ce13f7SAndroid Build Coastguard Worker 
copyTo(Image * dstImage,const VkImageCopy2KHR & region) const399*03ce13f7SAndroid Build Coastguard Worker void Image::copyTo(Image *dstImage, const VkImageCopy2KHR &region) const
400*03ce13f7SAndroid Build Coastguard Worker {
401*03ce13f7SAndroid Build Coastguard Worker 	static constexpr VkImageAspectFlags CombinedDepthStencilAspects =
402*03ce13f7SAndroid Build Coastguard Worker 	    VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
403*03ce13f7SAndroid Build Coastguard Worker 	if((region.srcSubresource.aspectMask == CombinedDepthStencilAspects) &&
404*03ce13f7SAndroid Build Coastguard Worker 	   (region.dstSubresource.aspectMask == CombinedDepthStencilAspects))
405*03ce13f7SAndroid Build Coastguard Worker 	{
406*03ce13f7SAndroid Build Coastguard Worker 		// Depth and stencil can be specified together, copy each separately
407*03ce13f7SAndroid Build Coastguard Worker 		VkImageCopy2KHR singleAspectRegion = region;
408*03ce13f7SAndroid Build Coastguard Worker 		singleAspectRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
409*03ce13f7SAndroid Build Coastguard Worker 		singleAspectRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
410*03ce13f7SAndroid Build Coastguard Worker 		copySingleAspectTo(dstImage, singleAspectRegion);
411*03ce13f7SAndroid Build Coastguard Worker 		singleAspectRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
412*03ce13f7SAndroid Build Coastguard Worker 		singleAspectRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
413*03ce13f7SAndroid Build Coastguard Worker 		copySingleAspectTo(dstImage, singleAspectRegion);
414*03ce13f7SAndroid Build Coastguard Worker 		return;
415*03ce13f7SAndroid Build Coastguard Worker 	}
416*03ce13f7SAndroid Build Coastguard Worker 
417*03ce13f7SAndroid Build Coastguard Worker 	copySingleAspectTo(dstImage, region);
418*03ce13f7SAndroid Build Coastguard Worker }
419*03ce13f7SAndroid Build Coastguard Worker 
copySingleAspectTo(Image * dstImage,const VkImageCopy2KHR & region) const420*03ce13f7SAndroid Build Coastguard Worker void Image::copySingleAspectTo(Image *dstImage, const VkImageCopy2KHR &region) const
421*03ce13f7SAndroid Build Coastguard Worker {
422*03ce13f7SAndroid Build Coastguard Worker 	// Image copy does not perform any conversion, it simply copies memory from
423*03ce13f7SAndroid Build Coastguard Worker 	// an image to another image that has the same number of bytes per pixel.
424*03ce13f7SAndroid Build Coastguard Worker 
425*03ce13f7SAndroid Build Coastguard Worker 	if(!((region.srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
426*03ce13f7SAndroid Build Coastguard Worker 	     (region.srcSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
427*03ce13f7SAndroid Build Coastguard Worker 	     (region.srcSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT) ||
428*03ce13f7SAndroid Build Coastguard Worker 	     (region.srcSubresource.aspectMask == VK_IMAGE_ASPECT_PLANE_0_BIT) ||
429*03ce13f7SAndroid Build Coastguard Worker 	     (region.srcSubresource.aspectMask == VK_IMAGE_ASPECT_PLANE_1_BIT) ||
430*03ce13f7SAndroid Build Coastguard Worker 	     (region.srcSubresource.aspectMask == VK_IMAGE_ASPECT_PLANE_2_BIT)))
431*03ce13f7SAndroid Build Coastguard Worker 	{
432*03ce13f7SAndroid Build Coastguard Worker 		UNSUPPORTED("srcSubresource.aspectMask %X", region.srcSubresource.aspectMask);
433*03ce13f7SAndroid Build Coastguard Worker 	}
434*03ce13f7SAndroid Build Coastguard Worker 
435*03ce13f7SAndroid Build Coastguard Worker 	if(!((region.dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
436*03ce13f7SAndroid Build Coastguard Worker 	     (region.dstSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
437*03ce13f7SAndroid Build Coastguard Worker 	     (region.dstSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT) ||
438*03ce13f7SAndroid Build Coastguard Worker 	     (region.dstSubresource.aspectMask == VK_IMAGE_ASPECT_PLANE_0_BIT) ||
439*03ce13f7SAndroid Build Coastguard Worker 	     (region.dstSubresource.aspectMask == VK_IMAGE_ASPECT_PLANE_1_BIT) ||
440*03ce13f7SAndroid Build Coastguard Worker 	     (region.dstSubresource.aspectMask == VK_IMAGE_ASPECT_PLANE_2_BIT)))
441*03ce13f7SAndroid Build Coastguard Worker 	{
442*03ce13f7SAndroid Build Coastguard Worker 		UNSUPPORTED("dstSubresource.aspectMask %X", region.dstSubresource.aspectMask);
443*03ce13f7SAndroid Build Coastguard Worker 	}
444*03ce13f7SAndroid Build Coastguard Worker 
445*03ce13f7SAndroid Build Coastguard Worker 	VkImageAspectFlagBits srcAspect = static_cast<VkImageAspectFlagBits>(region.srcSubresource.aspectMask);
446*03ce13f7SAndroid Build Coastguard Worker 	VkImageAspectFlagBits dstAspect = static_cast<VkImageAspectFlagBits>(region.dstSubresource.aspectMask);
447*03ce13f7SAndroid Build Coastguard Worker 
448*03ce13f7SAndroid Build Coastguard Worker 	Format srcFormat = getFormat(srcAspect);
449*03ce13f7SAndroid Build Coastguard Worker 	Format dstFormat = dstImage->getFormat(dstAspect);
450*03ce13f7SAndroid Build Coastguard Worker 	int bytesPerBlock = srcFormat.bytesPerBlock();
451*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(bytesPerBlock == dstFormat.bytesPerBlock());
452*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(samples == dstImage->samples);
453*03ce13f7SAndroid Build Coastguard Worker 
454*03ce13f7SAndroid Build Coastguard Worker 	VkExtent3D srcExtent = getMipLevelExtent(srcAspect, region.srcSubresource.mipLevel);
455*03ce13f7SAndroid Build Coastguard Worker 	VkExtent3D dstExtent = dstImage->getMipLevelExtent(dstAspect, region.dstSubresource.mipLevel);
456*03ce13f7SAndroid Build Coastguard Worker 	VkExtent3D copyExtent = imageExtentInBlocks(region.extent, srcAspect);
457*03ce13f7SAndroid Build Coastguard Worker 
458*03ce13f7SAndroid Build Coastguard Worker 	VkImageType srcImageType = imageType;
459*03ce13f7SAndroid Build Coastguard Worker 	VkImageType dstImageType = dstImage->getImageType();
460*03ce13f7SAndroid Build Coastguard Worker 	bool one3D = (srcImageType == VK_IMAGE_TYPE_3D) != (dstImageType == VK_IMAGE_TYPE_3D);
461*03ce13f7SAndroid Build Coastguard Worker 	bool both3D = (srcImageType == VK_IMAGE_TYPE_3D) && (dstImageType == VK_IMAGE_TYPE_3D);
462*03ce13f7SAndroid Build Coastguard Worker 
463*03ce13f7SAndroid Build Coastguard Worker 	// Texel layout pitches, using the VkSubresourceLayout nomenclature.
464*03ce13f7SAndroid Build Coastguard Worker 	int srcRowPitch = rowPitchBytes(srcAspect, region.srcSubresource.mipLevel);
465*03ce13f7SAndroid Build Coastguard Worker 	int srcDepthPitch = slicePitchBytes(srcAspect, region.srcSubresource.mipLevel);
466*03ce13f7SAndroid Build Coastguard Worker 	int dstRowPitch = dstImage->rowPitchBytes(dstAspect, region.dstSubresource.mipLevel);
467*03ce13f7SAndroid Build Coastguard Worker 	int dstDepthPitch = dstImage->slicePitchBytes(dstAspect, region.dstSubresource.mipLevel);
468*03ce13f7SAndroid Build Coastguard Worker 	VkDeviceSize srcArrayPitch = getLayerSize(srcAspect);
469*03ce13f7SAndroid Build Coastguard Worker 	VkDeviceSize dstArrayPitch = dstImage->getLayerSize(dstAspect);
470*03ce13f7SAndroid Build Coastguard Worker 
471*03ce13f7SAndroid Build Coastguard Worker 	// These are the pitches used when iterating over the layers that are being copied by the
472*03ce13f7SAndroid Build Coastguard Worker 	// vkCmdCopyImage command. They can differ from the above array piches because the spec states that:
473*03ce13f7SAndroid Build Coastguard Worker 	// "If one image is VK_IMAGE_TYPE_3D and the other image is VK_IMAGE_TYPE_2D with multiple
474*03ce13f7SAndroid Build Coastguard Worker 	//  layers, then each slice is copied to or from a different layer."
475*03ce13f7SAndroid Build Coastguard Worker 	VkDeviceSize srcLayerPitch = (srcImageType == VK_IMAGE_TYPE_3D) ? srcDepthPitch : srcArrayPitch;
476*03ce13f7SAndroid Build Coastguard Worker 	VkDeviceSize dstLayerPitch = (dstImageType == VK_IMAGE_TYPE_3D) ? dstDepthPitch : dstArrayPitch;
477*03ce13f7SAndroid Build Coastguard Worker 
478*03ce13f7SAndroid Build Coastguard Worker 	// If one image is 3D, extent.depth must match the layer count. If both images are 2D,
479*03ce13f7SAndroid Build Coastguard Worker 	// depth is 1 but the source and destination subresource layer count must match.
480*03ce13f7SAndroid Build Coastguard Worker 	uint32_t layerCount = one3D ? copyExtent.depth : region.srcSubresource.layerCount;
481*03ce13f7SAndroid Build Coastguard Worker 
482*03ce13f7SAndroid Build Coastguard Worker 	// Copies between 2D and 3D images are treated as layers, so only use depth as the slice count when
483*03ce13f7SAndroid Build Coastguard Worker 	// both images are 3D.
484*03ce13f7SAndroid Build Coastguard Worker 	// Multisample images are currently implemented similar to 3D images by storing one sample per slice.
485*03ce13f7SAndroid Build Coastguard Worker 	// TODO(b/160600347): Store samples consecutively.
486*03ce13f7SAndroid Build Coastguard Worker 	uint32_t sliceCount = both3D ? copyExtent.depth : samples;
487*03ce13f7SAndroid Build Coastguard Worker 
488*03ce13f7SAndroid Build Coastguard Worker 	bool isSingleSlice = (sliceCount == 1);
489*03ce13f7SAndroid Build Coastguard Worker 	bool isSingleRow = (copyExtent.height == 1) && isSingleSlice;
490*03ce13f7SAndroid Build Coastguard Worker 	// In order to copy multiple rows using a single memcpy call, we
491*03ce13f7SAndroid Build Coastguard Worker 	// have to make sure that we need to copy the entire row and that
492*03ce13f7SAndroid Build Coastguard Worker 	// both source and destination rows have the same size in bytes
493*03ce13f7SAndroid Build Coastguard Worker 	bool isEntireRow = (region.extent.width == srcExtent.width) &&
494*03ce13f7SAndroid Build Coastguard Worker 	                   (region.extent.width == dstExtent.width) &&
495*03ce13f7SAndroid Build Coastguard Worker 	                   // For non-compressed formats, blockWidth is 1. For compressed
496*03ce13f7SAndroid Build Coastguard Worker 	                   // formats, rowPitchBytes returns the number of bytes for a row of
497*03ce13f7SAndroid Build Coastguard Worker 	                   // blocks, so we have to divide by the block height, which means:
498*03ce13f7SAndroid Build Coastguard Worker 	                   // srcRowPitchBytes / srcBlockWidth == dstRowPitchBytes / dstBlockWidth
499*03ce13f7SAndroid Build Coastguard Worker 	                   // And, to avoid potential non exact integer division, for example if a
500*03ce13f7SAndroid Build Coastguard Worker 	                   // block has 16 bytes and represents 5 rows, we change the equation to:
501*03ce13f7SAndroid Build Coastguard Worker 	                   // srcRowPitchBytes * dstBlockWidth == dstRowPitchBytes * srcBlockWidth
502*03ce13f7SAndroid Build Coastguard Worker 	                   ((srcRowPitch * dstFormat.blockWidth()) ==
503*03ce13f7SAndroid Build Coastguard Worker 	                    (dstRowPitch * srcFormat.blockWidth()));
504*03ce13f7SAndroid Build Coastguard Worker 	// In order to copy multiple slices using a single memcpy call, we
505*03ce13f7SAndroid Build Coastguard Worker 	// have to make sure that we need to copy the entire slice and that
506*03ce13f7SAndroid Build Coastguard Worker 	// both source and destination slices have the same size in bytes
507*03ce13f7SAndroid Build Coastguard Worker 	bool isEntireSlice = isEntireRow &&
508*03ce13f7SAndroid Build Coastguard Worker 	                     (copyExtent.height == srcExtent.height) &&
509*03ce13f7SAndroid Build Coastguard Worker 	                     (copyExtent.height == dstExtent.height) &&
510*03ce13f7SAndroid Build Coastguard Worker 	                     (srcDepthPitch == dstDepthPitch);
511*03ce13f7SAndroid Build Coastguard Worker 
512*03ce13f7SAndroid Build Coastguard Worker 	const uint8_t *srcLayer = static_cast<const uint8_t *>(getTexelPointer(region.srcOffset, ImageSubresource(region.srcSubresource)));
513*03ce13f7SAndroid Build Coastguard Worker 	uint8_t *dstLayer = static_cast<uint8_t *>(dstImage->getTexelPointer(region.dstOffset, ImageSubresource(region.dstSubresource)));
514*03ce13f7SAndroid Build Coastguard Worker 
515*03ce13f7SAndroid Build Coastguard Worker 	for(uint32_t layer = 0; layer < layerCount; layer++)
516*03ce13f7SAndroid Build Coastguard Worker 	{
517*03ce13f7SAndroid Build Coastguard Worker 		if(isSingleRow)  // Copy one row
518*03ce13f7SAndroid Build Coastguard Worker 		{
519*03ce13f7SAndroid Build Coastguard Worker 			size_t copySize = copyExtent.width * bytesPerBlock;
520*03ce13f7SAndroid Build Coastguard Worker 			ASSERT((srcLayer + copySize) < end());
521*03ce13f7SAndroid Build Coastguard Worker 			ASSERT((dstLayer + copySize) < dstImage->end());
522*03ce13f7SAndroid Build Coastguard Worker 			memcpy(dstLayer, srcLayer, copySize);
523*03ce13f7SAndroid Build Coastguard Worker 		}
524*03ce13f7SAndroid Build Coastguard Worker 		else if(isEntireRow && isSingleSlice)  // Copy one slice
525*03ce13f7SAndroid Build Coastguard Worker 		{
526*03ce13f7SAndroid Build Coastguard Worker 			size_t copySize = copyExtent.height * srcRowPitch;
527*03ce13f7SAndroid Build Coastguard Worker 			ASSERT((srcLayer + copySize) < end());
528*03ce13f7SAndroid Build Coastguard Worker 			ASSERT((dstLayer + copySize) < dstImage->end());
529*03ce13f7SAndroid Build Coastguard Worker 			memcpy(dstLayer, srcLayer, copySize);
530*03ce13f7SAndroid Build Coastguard Worker 		}
531*03ce13f7SAndroid Build Coastguard Worker 		else if(isEntireSlice)  // Copy multiple slices
532*03ce13f7SAndroid Build Coastguard Worker 		{
533*03ce13f7SAndroid Build Coastguard Worker 			size_t copySize = sliceCount * srcDepthPitch;
534*03ce13f7SAndroid Build Coastguard Worker 			ASSERT((srcLayer + copySize) < end());
535*03ce13f7SAndroid Build Coastguard Worker 			ASSERT((dstLayer + copySize) < dstImage->end());
536*03ce13f7SAndroid Build Coastguard Worker 			memcpy(dstLayer, srcLayer, copySize);
537*03ce13f7SAndroid Build Coastguard Worker 		}
538*03ce13f7SAndroid Build Coastguard Worker 		else if(isEntireRow)  // Copy slice by slice
539*03ce13f7SAndroid Build Coastguard Worker 		{
540*03ce13f7SAndroid Build Coastguard Worker 			size_t sliceSize = copyExtent.height * srcRowPitch;
541*03ce13f7SAndroid Build Coastguard Worker 			const uint8_t *srcSlice = srcLayer;
542*03ce13f7SAndroid Build Coastguard Worker 			uint8_t *dstSlice = dstLayer;
543*03ce13f7SAndroid Build Coastguard Worker 
544*03ce13f7SAndroid Build Coastguard Worker 			for(uint32_t z = 0; z < sliceCount; z++)
545*03ce13f7SAndroid Build Coastguard Worker 			{
546*03ce13f7SAndroid Build Coastguard Worker 				ASSERT((srcSlice + sliceSize) < end());
547*03ce13f7SAndroid Build Coastguard Worker 				ASSERT((dstSlice + sliceSize) < dstImage->end());
548*03ce13f7SAndroid Build Coastguard Worker 
549*03ce13f7SAndroid Build Coastguard Worker 				memcpy(dstSlice, srcSlice, sliceSize);
550*03ce13f7SAndroid Build Coastguard Worker 
551*03ce13f7SAndroid Build Coastguard Worker 				dstSlice += dstDepthPitch;
552*03ce13f7SAndroid Build Coastguard Worker 				srcSlice += srcDepthPitch;
553*03ce13f7SAndroid Build Coastguard Worker 			}
554*03ce13f7SAndroid Build Coastguard Worker 		}
555*03ce13f7SAndroid Build Coastguard Worker 		else  // Copy row by row
556*03ce13f7SAndroid Build Coastguard Worker 		{
557*03ce13f7SAndroid Build Coastguard Worker 			size_t rowSize = copyExtent.width * bytesPerBlock;
558*03ce13f7SAndroid Build Coastguard Worker 			const uint8_t *srcSlice = srcLayer;
559*03ce13f7SAndroid Build Coastguard Worker 			uint8_t *dstSlice = dstLayer;
560*03ce13f7SAndroid Build Coastguard Worker 
561*03ce13f7SAndroid Build Coastguard Worker 			for(uint32_t z = 0; z < sliceCount; z++)
562*03ce13f7SAndroid Build Coastguard Worker 			{
563*03ce13f7SAndroid Build Coastguard Worker 				const uint8_t *srcRow = srcSlice;
564*03ce13f7SAndroid Build Coastguard Worker 				uint8_t *dstRow = dstSlice;
565*03ce13f7SAndroid Build Coastguard Worker 
566*03ce13f7SAndroid Build Coastguard Worker 				for(uint32_t y = 0; y < copyExtent.height; y++)
567*03ce13f7SAndroid Build Coastguard Worker 				{
568*03ce13f7SAndroid Build Coastguard Worker 					ASSERT((srcRow + rowSize) < end());
569*03ce13f7SAndroid Build Coastguard Worker 					ASSERT((dstRow + rowSize) < dstImage->end());
570*03ce13f7SAndroid Build Coastguard Worker 
571*03ce13f7SAndroid Build Coastguard Worker 					memcpy(dstRow, srcRow, rowSize);
572*03ce13f7SAndroid Build Coastguard Worker 
573*03ce13f7SAndroid Build Coastguard Worker 					srcRow += srcRowPitch;
574*03ce13f7SAndroid Build Coastguard Worker 					dstRow += dstRowPitch;
575*03ce13f7SAndroid Build Coastguard Worker 				}
576*03ce13f7SAndroid Build Coastguard Worker 
577*03ce13f7SAndroid Build Coastguard Worker 				srcSlice += srcDepthPitch;
578*03ce13f7SAndroid Build Coastguard Worker 				dstSlice += dstDepthPitch;
579*03ce13f7SAndroid Build Coastguard Worker 			}
580*03ce13f7SAndroid Build Coastguard Worker 		}
581*03ce13f7SAndroid Build Coastguard Worker 
582*03ce13f7SAndroid Build Coastguard Worker 		srcLayer += srcLayerPitch;
583*03ce13f7SAndroid Build Coastguard Worker 		dstLayer += dstLayerPitch;
584*03ce13f7SAndroid Build Coastguard Worker 	}
585*03ce13f7SAndroid Build Coastguard Worker 
586*03ce13f7SAndroid Build Coastguard Worker 	dstImage->contentsChanged(ImageSubresourceRange(region.dstSubresource));
587*03ce13f7SAndroid Build Coastguard Worker }
588*03ce13f7SAndroid Build Coastguard Worker 
copy(const void * srcCopyMemory,void * dstCopyMemory,uint32_t rowLength,uint32_t imageHeight,const VkImageSubresourceLayers & imageSubresource,const VkOffset3D & imageCopyOffset,const VkExtent3D & imageCopyExtent)589*03ce13f7SAndroid Build Coastguard Worker void Image::copy(const void *srcCopyMemory,
590*03ce13f7SAndroid Build Coastguard Worker                  void *dstCopyMemory,
591*03ce13f7SAndroid Build Coastguard Worker                  uint32_t rowLength,
592*03ce13f7SAndroid Build Coastguard Worker                  uint32_t imageHeight,
593*03ce13f7SAndroid Build Coastguard Worker                  const VkImageSubresourceLayers &imageSubresource,
594*03ce13f7SAndroid Build Coastguard Worker                  const VkOffset3D &imageCopyOffset,
595*03ce13f7SAndroid Build Coastguard Worker                  const VkExtent3D &imageCopyExtent)
596*03ce13f7SAndroid Build Coastguard Worker {
597*03ce13f7SAndroid Build Coastguard Worker 	// Decide on whether copying from buffer/memory or to buffer/memory
598*03ce13f7SAndroid Build Coastguard Worker 	ASSERT((srcCopyMemory == nullptr) != (dstCopyMemory == nullptr));
599*03ce13f7SAndroid Build Coastguard Worker 	const bool memoryIsSource = srcCopyMemory != nullptr;
600*03ce13f7SAndroid Build Coastguard Worker 
601*03ce13f7SAndroid Build Coastguard Worker 	switch(imageSubresource.aspectMask)
602*03ce13f7SAndroid Build Coastguard Worker 	{
603*03ce13f7SAndroid Build Coastguard Worker 	case VK_IMAGE_ASPECT_COLOR_BIT:
604*03ce13f7SAndroid Build Coastguard Worker 	case VK_IMAGE_ASPECT_DEPTH_BIT:
605*03ce13f7SAndroid Build Coastguard Worker 	case VK_IMAGE_ASPECT_STENCIL_BIT:
606*03ce13f7SAndroid Build Coastguard Worker 	case VK_IMAGE_ASPECT_PLANE_0_BIT:
607*03ce13f7SAndroid Build Coastguard Worker 	case VK_IMAGE_ASPECT_PLANE_1_BIT:
608*03ce13f7SAndroid Build Coastguard Worker 	case VK_IMAGE_ASPECT_PLANE_2_BIT:
609*03ce13f7SAndroid Build Coastguard Worker 		break;
610*03ce13f7SAndroid Build Coastguard Worker 	default:
611*03ce13f7SAndroid Build Coastguard Worker 		UNSUPPORTED("aspectMask %x", int(imageSubresource.aspectMask));
612*03ce13f7SAndroid Build Coastguard Worker 		break;
613*03ce13f7SAndroid Build Coastguard Worker 	}
614*03ce13f7SAndroid Build Coastguard Worker 
615*03ce13f7SAndroid Build Coastguard Worker 	auto aspect = static_cast<VkImageAspectFlagBits>(imageSubresource.aspectMask);
616*03ce13f7SAndroid Build Coastguard Worker 	Format copyFormat = getFormat(aspect);
617*03ce13f7SAndroid Build Coastguard Worker 
618*03ce13f7SAndroid Build Coastguard Worker 	VkExtent3D imageExtent = imageExtentInBlocks(imageCopyExtent, aspect);
619*03ce13f7SAndroid Build Coastguard Worker 
620*03ce13f7SAndroid Build Coastguard Worker 	if(imageExtent.width == 0 || imageExtent.height == 0 || imageExtent.depth == 0)
621*03ce13f7SAndroid Build Coastguard Worker 	{
622*03ce13f7SAndroid Build Coastguard Worker 		return;
623*03ce13f7SAndroid Build Coastguard Worker 	}
624*03ce13f7SAndroid Build Coastguard Worker 
625*03ce13f7SAndroid Build Coastguard Worker 	VkExtent2D extent = bufferExtentInBlocks(Extent2D(imageExtent), rowLength, imageHeight, imageSubresource, imageCopyOffset);
626*03ce13f7SAndroid Build Coastguard Worker 	int bytesPerBlock = copyFormat.bytesPerBlock();
627*03ce13f7SAndroid Build Coastguard Worker 	int memoryRowPitchBytes = extent.width * bytesPerBlock;
628*03ce13f7SAndroid Build Coastguard Worker 	int memorySlicePitchBytes = extent.height * memoryRowPitchBytes;
629*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(samples == 1);
630*03ce13f7SAndroid Build Coastguard Worker 
631*03ce13f7SAndroid Build Coastguard Worker 	uint8_t *imageMemory = static_cast<uint8_t *>(getTexelPointer(imageCopyOffset, ImageSubresource(imageSubresource)));
632*03ce13f7SAndroid Build Coastguard Worker 	const uint8_t *srcMemory = memoryIsSource ? static_cast<const uint8_t *>(srcCopyMemory) : imageMemory;
633*03ce13f7SAndroid Build Coastguard Worker 	uint8_t *dstMemory = memoryIsSource ? imageMemory : static_cast<uint8_t *>(dstCopyMemory);
634*03ce13f7SAndroid Build Coastguard Worker 	int imageRowPitchBytes = rowPitchBytes(aspect, imageSubresource.mipLevel);
635*03ce13f7SAndroid Build Coastguard Worker 	int imageSlicePitchBytes = slicePitchBytes(aspect, imageSubresource.mipLevel);
636*03ce13f7SAndroid Build Coastguard Worker 
637*03ce13f7SAndroid Build Coastguard Worker 	int srcSlicePitchBytes = memoryIsSource ? memorySlicePitchBytes : imageSlicePitchBytes;
638*03ce13f7SAndroid Build Coastguard Worker 	int dstSlicePitchBytes = memoryIsSource ? imageSlicePitchBytes : memorySlicePitchBytes;
639*03ce13f7SAndroid Build Coastguard Worker 	int srcRowPitchBytes = memoryIsSource ? memoryRowPitchBytes : imageRowPitchBytes;
640*03ce13f7SAndroid Build Coastguard Worker 	int dstRowPitchBytes = memoryIsSource ? imageRowPitchBytes : memoryRowPitchBytes;
641*03ce13f7SAndroid Build Coastguard Worker 
642*03ce13f7SAndroid Build Coastguard Worker 	VkDeviceSize copySize = imageExtent.width * bytesPerBlock;
643*03ce13f7SAndroid Build Coastguard Worker 
644*03ce13f7SAndroid Build Coastguard Worker 	VkDeviceSize imageLayerSize = getLayerSize(aspect);
645*03ce13f7SAndroid Build Coastguard Worker 	VkDeviceSize srcLayerSize = memoryIsSource ? memorySlicePitchBytes : imageLayerSize;
646*03ce13f7SAndroid Build Coastguard Worker 	VkDeviceSize dstLayerSize = memoryIsSource ? imageLayerSize : memorySlicePitchBytes;
647*03ce13f7SAndroid Build Coastguard Worker 
648*03ce13f7SAndroid Build Coastguard Worker 	for(uint32_t i = 0; i < imageSubresource.layerCount; i++)
649*03ce13f7SAndroid Build Coastguard Worker 	{
650*03ce13f7SAndroid Build Coastguard Worker 		const uint8_t *srcLayerMemory = srcMemory;
651*03ce13f7SAndroid Build Coastguard Worker 		uint8_t *dstLayerMemory = dstMemory;
652*03ce13f7SAndroid Build Coastguard Worker 		for(uint32_t z = 0; z < imageExtent.depth; z++)
653*03ce13f7SAndroid Build Coastguard Worker 		{
654*03ce13f7SAndroid Build Coastguard Worker 			const uint8_t *srcSliceMemory = srcLayerMemory;
655*03ce13f7SAndroid Build Coastguard Worker 			uint8_t *dstSliceMemory = dstLayerMemory;
656*03ce13f7SAndroid Build Coastguard Worker 			for(uint32_t y = 0; y < imageExtent.height; y++)
657*03ce13f7SAndroid Build Coastguard Worker 			{
658*03ce13f7SAndroid Build Coastguard Worker 				ASSERT(((memoryIsSource ? dstSliceMemory : srcSliceMemory) + copySize) < end());
659*03ce13f7SAndroid Build Coastguard Worker 				memcpy(dstSliceMemory, srcSliceMemory, copySize);
660*03ce13f7SAndroid Build Coastguard Worker 				srcSliceMemory += srcRowPitchBytes;
661*03ce13f7SAndroid Build Coastguard Worker 				dstSliceMemory += dstRowPitchBytes;
662*03ce13f7SAndroid Build Coastguard Worker 			}
663*03ce13f7SAndroid Build Coastguard Worker 			srcLayerMemory += srcSlicePitchBytes;
664*03ce13f7SAndroid Build Coastguard Worker 			dstLayerMemory += dstSlicePitchBytes;
665*03ce13f7SAndroid Build Coastguard Worker 		}
666*03ce13f7SAndroid Build Coastguard Worker 
667*03ce13f7SAndroid Build Coastguard Worker 		srcMemory += srcLayerSize;
668*03ce13f7SAndroid Build Coastguard Worker 		dstMemory += dstLayerSize;
669*03ce13f7SAndroid Build Coastguard Worker 	}
670*03ce13f7SAndroid Build Coastguard Worker 
671*03ce13f7SAndroid Build Coastguard Worker 	if(memoryIsSource)
672*03ce13f7SAndroid Build Coastguard Worker 	{
673*03ce13f7SAndroid Build Coastguard Worker 		contentsChanged(ImageSubresourceRange(imageSubresource));
674*03ce13f7SAndroid Build Coastguard Worker 	}
675*03ce13f7SAndroid Build Coastguard Worker }
676*03ce13f7SAndroid Build Coastguard Worker 
copyTo(Buffer * dstBuffer,const VkBufferImageCopy2KHR & region)677*03ce13f7SAndroid Build Coastguard Worker void Image::copyTo(Buffer *dstBuffer, const VkBufferImageCopy2KHR &region)
678*03ce13f7SAndroid Build Coastguard Worker {
679*03ce13f7SAndroid Build Coastguard Worker 	copy(nullptr, dstBuffer->getOffsetPointer(region.bufferOffset), region.bufferRowLength, region.bufferImageHeight, region.imageSubresource, region.imageOffset, region.imageExtent);
680*03ce13f7SAndroid Build Coastguard Worker }
681*03ce13f7SAndroid Build Coastguard Worker 
copyFrom(Buffer * srcBuffer,const VkBufferImageCopy2KHR & region)682*03ce13f7SAndroid Build Coastguard Worker void Image::copyFrom(Buffer *srcBuffer, const VkBufferImageCopy2KHR &region)
683*03ce13f7SAndroid Build Coastguard Worker {
684*03ce13f7SAndroid Build Coastguard Worker 	copy(srcBuffer->getOffsetPointer(region.bufferOffset), nullptr, region.bufferRowLength, region.bufferImageHeight, region.imageSubresource, region.imageOffset, region.imageExtent);
685*03ce13f7SAndroid Build Coastguard Worker }
686*03ce13f7SAndroid Build Coastguard Worker 
copyToMemory(const VkImageToMemoryCopyEXT & region)687*03ce13f7SAndroid Build Coastguard Worker void Image::copyToMemory(const VkImageToMemoryCopyEXT &region)
688*03ce13f7SAndroid Build Coastguard Worker {
689*03ce13f7SAndroid Build Coastguard Worker 	copy(nullptr, region.pHostPointer, region.memoryRowLength, region.memoryImageHeight, region.imageSubresource, region.imageOffset, region.imageExtent);
690*03ce13f7SAndroid Build Coastguard Worker }
691*03ce13f7SAndroid Build Coastguard Worker 
copyFromMemory(const VkMemoryToImageCopyEXT & region)692*03ce13f7SAndroid Build Coastguard Worker void Image::copyFromMemory(const VkMemoryToImageCopyEXT &region)
693*03ce13f7SAndroid Build Coastguard Worker {
694*03ce13f7SAndroid Build Coastguard Worker 	copy(region.pHostPointer, nullptr, region.memoryRowLength, region.memoryImageHeight, region.imageSubresource, region.imageOffset, region.imageExtent);
695*03ce13f7SAndroid Build Coastguard Worker }
696*03ce13f7SAndroid Build Coastguard Worker 
getTexelPointer(const VkOffset3D & offset,const VkImageSubresource & subresource) const697*03ce13f7SAndroid Build Coastguard Worker void *Image::getTexelPointer(const VkOffset3D &offset, const VkImageSubresource &subresource) const
698*03ce13f7SAndroid Build Coastguard Worker {
699*03ce13f7SAndroid Build Coastguard Worker 	VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(subresource.aspectMask);
700*03ce13f7SAndroid Build Coastguard Worker 	return deviceMemory->getOffsetPointer(getMemoryOffset(aspect) +
701*03ce13f7SAndroid Build Coastguard Worker 	                                      texelOffsetBytesInStorage(offset, subresource) +
702*03ce13f7SAndroid Build Coastguard Worker 	                                      getSubresourceOffset(aspect, subresource.mipLevel, subresource.arrayLayer));
703*03ce13f7SAndroid Build Coastguard Worker }
704*03ce13f7SAndroid Build Coastguard Worker 
imageExtentInBlocks(const VkExtent3D & extent,VkImageAspectFlagBits aspect) const705*03ce13f7SAndroid Build Coastguard Worker VkExtent3D Image::imageExtentInBlocks(const VkExtent3D &extent, VkImageAspectFlagBits aspect) const
706*03ce13f7SAndroid Build Coastguard Worker {
707*03ce13f7SAndroid Build Coastguard Worker 	VkExtent3D adjustedExtent = extent;
708*03ce13f7SAndroid Build Coastguard Worker 	Format usedFormat = getFormat(aspect);
709*03ce13f7SAndroid Build Coastguard Worker 	if(usedFormat.isCompressed())
710*03ce13f7SAndroid Build Coastguard Worker 	{
711*03ce13f7SAndroid Build Coastguard Worker 		// When using a compressed format, we use the block as the base unit, instead of the texel
712*03ce13f7SAndroid Build Coastguard Worker 		int blockWidth = usedFormat.blockWidth();
713*03ce13f7SAndroid Build Coastguard Worker 		int blockHeight = usedFormat.blockHeight();
714*03ce13f7SAndroid Build Coastguard Worker 
715*03ce13f7SAndroid Build Coastguard Worker 		// Mip level allocations will round up to the next block for compressed texture
716*03ce13f7SAndroid Build Coastguard Worker 		adjustedExtent.width = ((adjustedExtent.width + blockWidth - 1) / blockWidth);
717*03ce13f7SAndroid Build Coastguard Worker 		adjustedExtent.height = ((adjustedExtent.height + blockHeight - 1) / blockHeight);
718*03ce13f7SAndroid Build Coastguard Worker 	}
719*03ce13f7SAndroid Build Coastguard Worker 	return adjustedExtent;
720*03ce13f7SAndroid Build Coastguard Worker }
721*03ce13f7SAndroid Build Coastguard Worker 
imageOffsetInBlocks(const VkOffset3D & offset,VkImageAspectFlagBits aspect) const722*03ce13f7SAndroid Build Coastguard Worker VkOffset3D Image::imageOffsetInBlocks(const VkOffset3D &offset, VkImageAspectFlagBits aspect) const
723*03ce13f7SAndroid Build Coastguard Worker {
724*03ce13f7SAndroid Build Coastguard Worker 	VkOffset3D adjustedOffset = offset;
725*03ce13f7SAndroid Build Coastguard Worker 	Format usedFormat = getFormat(aspect);
726*03ce13f7SAndroid Build Coastguard Worker 	if(usedFormat.isCompressed())
727*03ce13f7SAndroid Build Coastguard Worker 	{
728*03ce13f7SAndroid Build Coastguard Worker 		// When using a compressed format, we use the block as the base unit, instead of the texel
729*03ce13f7SAndroid Build Coastguard Worker 		int blockWidth = usedFormat.blockWidth();
730*03ce13f7SAndroid Build Coastguard Worker 		int blockHeight = usedFormat.blockHeight();
731*03ce13f7SAndroid Build Coastguard Worker 
732*03ce13f7SAndroid Build Coastguard Worker 		ASSERT(((offset.x % blockWidth) == 0) && ((offset.y % blockHeight) == 0));  // We can't offset within a block
733*03ce13f7SAndroid Build Coastguard Worker 
734*03ce13f7SAndroid Build Coastguard Worker 		adjustedOffset.x /= blockWidth;
735*03ce13f7SAndroid Build Coastguard Worker 		adjustedOffset.y /= blockHeight;
736*03ce13f7SAndroid Build Coastguard Worker 	}
737*03ce13f7SAndroid Build Coastguard Worker 	return adjustedOffset;
738*03ce13f7SAndroid Build Coastguard Worker }
739*03ce13f7SAndroid Build Coastguard Worker 
bufferExtentInBlocks(const VkExtent2D & extent,uint32_t rowLength,uint32_t imageHeight,const VkImageSubresourceLayers & imageSubresource,const VkOffset3D & imageOffset) const740*03ce13f7SAndroid Build Coastguard Worker VkExtent2D Image::bufferExtentInBlocks(const VkExtent2D &extent, uint32_t rowLength, uint32_t imageHeight, const VkImageSubresourceLayers &imageSubresource, const VkOffset3D &imageOffset) const
741*03ce13f7SAndroid Build Coastguard Worker {
742*03ce13f7SAndroid Build Coastguard Worker 	VkExtent2D adjustedExtent = extent;
743*03ce13f7SAndroid Build Coastguard Worker 	VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(imageSubresource.aspectMask);
744*03ce13f7SAndroid Build Coastguard Worker 	Format usedFormat = getFormat(aspect);
745*03ce13f7SAndroid Build Coastguard Worker 
746*03ce13f7SAndroid Build Coastguard Worker 	if(rowLength != 0)
747*03ce13f7SAndroid Build Coastguard Worker 	{
748*03ce13f7SAndroid Build Coastguard Worker 		adjustedExtent.width = rowLength;
749*03ce13f7SAndroid Build Coastguard Worker 
750*03ce13f7SAndroid Build Coastguard Worker 		if(usedFormat.isCompressed())
751*03ce13f7SAndroid Build Coastguard Worker 		{
752*03ce13f7SAndroid Build Coastguard Worker 			int blockWidth = usedFormat.blockWidth();
753*03ce13f7SAndroid Build Coastguard Worker 			ASSERT((adjustedExtent.width % blockWidth == 0) || (adjustedExtent.width + imageOffset.x == extent.width));
754*03ce13f7SAndroid Build Coastguard Worker 			adjustedExtent.width = (rowLength + blockWidth - 1) / blockWidth;
755*03ce13f7SAndroid Build Coastguard Worker 		}
756*03ce13f7SAndroid Build Coastguard Worker 	}
757*03ce13f7SAndroid Build Coastguard Worker 
758*03ce13f7SAndroid Build Coastguard Worker 	if(imageHeight != 0)
759*03ce13f7SAndroid Build Coastguard Worker 	{
760*03ce13f7SAndroid Build Coastguard Worker 		adjustedExtent.height = imageHeight;
761*03ce13f7SAndroid Build Coastguard Worker 
762*03ce13f7SAndroid Build Coastguard Worker 		if(usedFormat.isCompressed())
763*03ce13f7SAndroid Build Coastguard Worker 		{
764*03ce13f7SAndroid Build Coastguard Worker 			int blockHeight = usedFormat.blockHeight();
765*03ce13f7SAndroid Build Coastguard Worker 			ASSERT((adjustedExtent.height % blockHeight == 0) || (adjustedExtent.height + imageOffset.y == extent.height));
766*03ce13f7SAndroid Build Coastguard Worker 			adjustedExtent.height = (imageHeight + blockHeight - 1) / blockHeight;
767*03ce13f7SAndroid Build Coastguard Worker 		}
768*03ce13f7SAndroid Build Coastguard Worker 	}
769*03ce13f7SAndroid Build Coastguard Worker 
770*03ce13f7SAndroid Build Coastguard Worker 	return adjustedExtent;
771*03ce13f7SAndroid Build Coastguard Worker }
772*03ce13f7SAndroid Build Coastguard Worker 
borderSize() const773*03ce13f7SAndroid Build Coastguard Worker int Image::borderSize() const
774*03ce13f7SAndroid Build Coastguard Worker {
775*03ce13f7SAndroid Build Coastguard Worker 	// We won't add a border to compressed cube textures, we'll add it when we decompress the texture
776*03ce13f7SAndroid Build Coastguard Worker 	return (isCubeCompatible() && !format.isCompressed()) ? 1 : 0;
777*03ce13f7SAndroid Build Coastguard Worker }
778*03ce13f7SAndroid Build Coastguard Worker 
texelOffsetBytesInStorage(const VkOffset3D & offset,const VkImageSubresource & subresource) const779*03ce13f7SAndroid Build Coastguard Worker VkDeviceSize Image::texelOffsetBytesInStorage(const VkOffset3D &offset, const VkImageSubresource &subresource) const
780*03ce13f7SAndroid Build Coastguard Worker {
781*03ce13f7SAndroid Build Coastguard Worker 	VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(subresource.aspectMask);
782*03ce13f7SAndroid Build Coastguard Worker 	VkOffset3D adjustedOffset = imageOffsetInBlocks(offset, aspect);
783*03ce13f7SAndroid Build Coastguard Worker 	int border = borderSize();
784*03ce13f7SAndroid Build Coastguard Worker 	return adjustedOffset.z * slicePitchBytes(aspect, subresource.mipLevel) +
785*03ce13f7SAndroid Build Coastguard Worker 	       (adjustedOffset.y + border) * rowPitchBytes(aspect, subresource.mipLevel) +
786*03ce13f7SAndroid Build Coastguard Worker 	       (adjustedOffset.x + border) * getFormat(aspect).bytesPerBlock();
787*03ce13f7SAndroid Build Coastguard Worker }
788*03ce13f7SAndroid Build Coastguard Worker 
getMipLevelExtent(VkImageAspectFlagBits aspect,uint32_t mipLevel) const789*03ce13f7SAndroid Build Coastguard Worker VkExtent3D Image::getMipLevelExtent(VkImageAspectFlagBits aspect, uint32_t mipLevel) const
790*03ce13f7SAndroid Build Coastguard Worker {
791*03ce13f7SAndroid Build Coastguard Worker 	VkExtent3D mipLevelExtent;
792*03ce13f7SAndroid Build Coastguard Worker 	mipLevelExtent.width = extent.width >> mipLevel;
793*03ce13f7SAndroid Build Coastguard Worker 	mipLevelExtent.height = extent.height >> mipLevel;
794*03ce13f7SAndroid Build Coastguard Worker 	mipLevelExtent.depth = extent.depth >> mipLevel;
795*03ce13f7SAndroid Build Coastguard Worker 
796*03ce13f7SAndroid Build Coastguard Worker 	if(mipLevelExtent.width == 0) { mipLevelExtent.width = 1; }
797*03ce13f7SAndroid Build Coastguard Worker 	if(mipLevelExtent.height == 0) { mipLevelExtent.height = 1; }
798*03ce13f7SAndroid Build Coastguard Worker 	if(mipLevelExtent.depth == 0) { mipLevelExtent.depth = 1; }
799*03ce13f7SAndroid Build Coastguard Worker 
800*03ce13f7SAndroid Build Coastguard Worker 	switch(aspect)
801*03ce13f7SAndroid Build Coastguard Worker 	{
802*03ce13f7SAndroid Build Coastguard Worker 	case VK_IMAGE_ASPECT_COLOR_BIT:
803*03ce13f7SAndroid Build Coastguard Worker 	case VK_IMAGE_ASPECT_DEPTH_BIT:
804*03ce13f7SAndroid Build Coastguard Worker 	case VK_IMAGE_ASPECT_STENCIL_BIT:
805*03ce13f7SAndroid Build Coastguard Worker 	case VK_IMAGE_ASPECT_PLANE_0_BIT:  // Vulkan 1.1 Table 31. Plane Format Compatibility Table: plane 0 of all defined formats is full resolution.
806*03ce13f7SAndroid Build Coastguard Worker 		break;
807*03ce13f7SAndroid Build Coastguard Worker 	case VK_IMAGE_ASPECT_PLANE_1_BIT:
808*03ce13f7SAndroid Build Coastguard Worker 	case VK_IMAGE_ASPECT_PLANE_2_BIT:
809*03ce13f7SAndroid Build Coastguard Worker 		switch(format)
810*03ce13f7SAndroid Build Coastguard Worker 		{
811*03ce13f7SAndroid Build Coastguard Worker 		case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
812*03ce13f7SAndroid Build Coastguard Worker 		case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
813*03ce13f7SAndroid Build Coastguard Worker 		case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
814*03ce13f7SAndroid Build Coastguard Worker 			ASSERT(mipLevelExtent.width % 2 == 0 && mipLevelExtent.height % 2 == 0);  // Vulkan 1.1: "Images in this format must be defined with a width and height that is a multiple of two."
815*03ce13f7SAndroid Build Coastguard Worker 			// Vulkan 1.1 Table 31. Plane Format Compatibility Table:
816*03ce13f7SAndroid Build Coastguard Worker 			// Half-resolution U and V planes.
817*03ce13f7SAndroid Build Coastguard Worker 			mipLevelExtent.width /= 2;
818*03ce13f7SAndroid Build Coastguard Worker 			mipLevelExtent.height /= 2;
819*03ce13f7SAndroid Build Coastguard Worker 			break;
820*03ce13f7SAndroid Build Coastguard Worker 		default:
821*03ce13f7SAndroid Build Coastguard Worker 			UNSUPPORTED("format %d", int(format));
822*03ce13f7SAndroid Build Coastguard Worker 		}
823*03ce13f7SAndroid Build Coastguard Worker 		break;
824*03ce13f7SAndroid Build Coastguard Worker 	default:
825*03ce13f7SAndroid Build Coastguard Worker 		UNSUPPORTED("aspect %x", int(aspect));
826*03ce13f7SAndroid Build Coastguard Worker 	}
827*03ce13f7SAndroid Build Coastguard Worker 
828*03ce13f7SAndroid Build Coastguard Worker 	return mipLevelExtent;
829*03ce13f7SAndroid Build Coastguard Worker }
830*03ce13f7SAndroid Build Coastguard Worker 
rowPitchBytes(VkImageAspectFlagBits aspect,uint32_t mipLevel) const831*03ce13f7SAndroid Build Coastguard Worker size_t Image::rowPitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const
832*03ce13f7SAndroid Build Coastguard Worker {
833*03ce13f7SAndroid Build Coastguard Worker 	if(deviceMemory && deviceMemory->hasExternalImagePlanes())
834*03ce13f7SAndroid Build Coastguard Worker 	{
835*03ce13f7SAndroid Build Coastguard Worker 		return deviceMemory->externalImageRowPitchBytes(aspect);
836*03ce13f7SAndroid Build Coastguard Worker 	}
837*03ce13f7SAndroid Build Coastguard Worker 
838*03ce13f7SAndroid Build Coastguard Worker 	// Depth and Stencil pitch should be computed separately
839*03ce13f7SAndroid Build Coastguard Worker 	ASSERT((aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) !=
840*03ce13f7SAndroid Build Coastguard Worker 	       (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT));
841*03ce13f7SAndroid Build Coastguard Worker 
842*03ce13f7SAndroid Build Coastguard Worker 	VkExtent3D mipLevelExtent = getMipLevelExtent(aspect, mipLevel);
843*03ce13f7SAndroid Build Coastguard Worker 	Format usedFormat = getFormat(aspect);
844*03ce13f7SAndroid Build Coastguard Worker 	if(usedFormat.isCompressed())
845*03ce13f7SAndroid Build Coastguard Worker 	{
846*03ce13f7SAndroid Build Coastguard Worker 		VkExtent3D extentInBlocks = imageExtentInBlocks(mipLevelExtent, aspect);
847*03ce13f7SAndroid Build Coastguard Worker 		return extentInBlocks.width * usedFormat.bytesPerBlock();
848*03ce13f7SAndroid Build Coastguard Worker 	}
849*03ce13f7SAndroid Build Coastguard Worker 
850*03ce13f7SAndroid Build Coastguard Worker 	return usedFormat.pitchB(mipLevelExtent.width, borderSize());
851*03ce13f7SAndroid Build Coastguard Worker }
852*03ce13f7SAndroid Build Coastguard Worker 
slicePitchBytes(VkImageAspectFlagBits aspect,uint32_t mipLevel) const853*03ce13f7SAndroid Build Coastguard Worker size_t Image::slicePitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel) const
854*03ce13f7SAndroid Build Coastguard Worker {
855*03ce13f7SAndroid Build Coastguard Worker 	// Depth and Stencil slice should be computed separately
856*03ce13f7SAndroid Build Coastguard Worker 	ASSERT((aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) !=
857*03ce13f7SAndroid Build Coastguard Worker 	       (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT));
858*03ce13f7SAndroid Build Coastguard Worker 
859*03ce13f7SAndroid Build Coastguard Worker 	VkExtent3D mipLevelExtent = getMipLevelExtent(aspect, mipLevel);
860*03ce13f7SAndroid Build Coastguard Worker 	Format usedFormat = getFormat(aspect);
861*03ce13f7SAndroid Build Coastguard Worker 	if(usedFormat.isCompressed())
862*03ce13f7SAndroid Build Coastguard Worker 	{
863*03ce13f7SAndroid Build Coastguard Worker 		VkExtent3D extentInBlocks = imageExtentInBlocks(mipLevelExtent, aspect);
864*03ce13f7SAndroid Build Coastguard Worker 		return extentInBlocks.height * extentInBlocks.width * usedFormat.bytesPerBlock();
865*03ce13f7SAndroid Build Coastguard Worker 	}
866*03ce13f7SAndroid Build Coastguard Worker 
867*03ce13f7SAndroid Build Coastguard Worker 	return usedFormat.sliceB(mipLevelExtent.width, mipLevelExtent.height, borderSize());
868*03ce13f7SAndroid Build Coastguard Worker }
869*03ce13f7SAndroid Build Coastguard Worker 
getFormat(VkImageAspectFlagBits aspect) const870*03ce13f7SAndroid Build Coastguard Worker Format Image::getFormat(VkImageAspectFlagBits aspect) const
871*03ce13f7SAndroid Build Coastguard Worker {
872*03ce13f7SAndroid Build Coastguard Worker 	return format.getAspectFormat(aspect);
873*03ce13f7SAndroid Build Coastguard Worker }
874*03ce13f7SAndroid Build Coastguard Worker 
isCubeCompatible() const875*03ce13f7SAndroid Build Coastguard Worker bool Image::isCubeCompatible() const
876*03ce13f7SAndroid Build Coastguard Worker {
877*03ce13f7SAndroid Build Coastguard Worker 	bool cubeCompatible = (flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT);
878*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(!cubeCompatible || (imageType == VK_IMAGE_TYPE_2D));  // VUID-VkImageCreateInfo-flags-00949
879*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(!cubeCompatible || (arrayLayers >= 6));               // VUID-VkImageCreateInfo-imageType-00954
880*03ce13f7SAndroid Build Coastguard Worker 
881*03ce13f7SAndroid Build Coastguard Worker 	return cubeCompatible;
882*03ce13f7SAndroid Build Coastguard Worker }
883*03ce13f7SAndroid Build Coastguard Worker 
end() const884*03ce13f7SAndroid Build Coastguard Worker uint8_t *Image::end() const
885*03ce13f7SAndroid Build Coastguard Worker {
886*03ce13f7SAndroid Build Coastguard Worker 	return reinterpret_cast<uint8_t *>(deviceMemory->getOffsetPointer(deviceMemory->getCommittedMemoryInBytes() + 1));
887*03ce13f7SAndroid Build Coastguard Worker }
888*03ce13f7SAndroid Build Coastguard Worker 
getMemoryOffset(VkImageAspectFlagBits aspect) const889*03ce13f7SAndroid Build Coastguard Worker VkDeviceSize Image::getMemoryOffset(VkImageAspectFlagBits aspect) const
890*03ce13f7SAndroid Build Coastguard Worker {
891*03ce13f7SAndroid Build Coastguard Worker 	if(deviceMemory && deviceMemory->hasExternalImagePlanes())
892*03ce13f7SAndroid Build Coastguard Worker 	{
893*03ce13f7SAndroid Build Coastguard Worker 		return deviceMemory->externalImageMemoryOffset(aspect);
894*03ce13f7SAndroid Build Coastguard Worker 	}
895*03ce13f7SAndroid Build Coastguard Worker 
896*03ce13f7SAndroid Build Coastguard Worker 	return memoryOffset;
897*03ce13f7SAndroid Build Coastguard Worker }
898*03ce13f7SAndroid Build Coastguard Worker 
getAspectOffset(VkImageAspectFlagBits aspect) const899*03ce13f7SAndroid Build Coastguard Worker VkDeviceSize Image::getAspectOffset(VkImageAspectFlagBits aspect) const
900*03ce13f7SAndroid Build Coastguard Worker {
901*03ce13f7SAndroid Build Coastguard Worker 	switch(format)
902*03ce13f7SAndroid Build Coastguard Worker 	{
903*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_D16_UNORM_S8_UINT:
904*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_D24_UNORM_S8_UINT:
905*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_D32_SFLOAT_S8_UINT:
906*03ce13f7SAndroid Build Coastguard Worker 		if(aspect == VK_IMAGE_ASPECT_STENCIL_BIT)
907*03ce13f7SAndroid Build Coastguard Worker 		{
908*03ce13f7SAndroid Build Coastguard Worker 			// Offset by depth buffer to get to stencil buffer
909*03ce13f7SAndroid Build Coastguard Worker 			return getStorageSize(VK_IMAGE_ASPECT_DEPTH_BIT);
910*03ce13f7SAndroid Build Coastguard Worker 		}
911*03ce13f7SAndroid Build Coastguard Worker 		break;
912*03ce13f7SAndroid Build Coastguard Worker 
913*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
914*03ce13f7SAndroid Build Coastguard Worker 		if(aspect == VK_IMAGE_ASPECT_PLANE_2_BIT)
915*03ce13f7SAndroid Build Coastguard Worker 		{
916*03ce13f7SAndroid Build Coastguard Worker 			return getStorageSize(VK_IMAGE_ASPECT_PLANE_1_BIT) + getStorageSize(VK_IMAGE_ASPECT_PLANE_0_BIT);
917*03ce13f7SAndroid Build Coastguard Worker 		}
918*03ce13f7SAndroid Build Coastguard Worker 		// Fall through to 2PLANE case:
919*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
920*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
921*03ce13f7SAndroid Build Coastguard Worker 		if(aspect == VK_IMAGE_ASPECT_PLANE_1_BIT)
922*03ce13f7SAndroid Build Coastguard Worker 		{
923*03ce13f7SAndroid Build Coastguard Worker 			return getStorageSize(VK_IMAGE_ASPECT_PLANE_0_BIT);
924*03ce13f7SAndroid Build Coastguard Worker 		}
925*03ce13f7SAndroid Build Coastguard Worker 		else
926*03ce13f7SAndroid Build Coastguard Worker 		{
927*03ce13f7SAndroid Build Coastguard Worker 			ASSERT(aspect == VK_IMAGE_ASPECT_PLANE_0_BIT);
928*03ce13f7SAndroid Build Coastguard Worker 
929*03ce13f7SAndroid Build Coastguard Worker 			return 0;
930*03ce13f7SAndroid Build Coastguard Worker 		}
931*03ce13f7SAndroid Build Coastguard Worker 		break;
932*03ce13f7SAndroid Build Coastguard Worker 
933*03ce13f7SAndroid Build Coastguard Worker 	default:
934*03ce13f7SAndroid Build Coastguard Worker 		break;
935*03ce13f7SAndroid Build Coastguard Worker 	}
936*03ce13f7SAndroid Build Coastguard Worker 
937*03ce13f7SAndroid Build Coastguard Worker 	return 0;
938*03ce13f7SAndroid Build Coastguard Worker }
939*03ce13f7SAndroid Build Coastguard Worker 
getSubresourceOffset(VkImageAspectFlagBits aspect,uint32_t mipLevel,uint32_t layer) const940*03ce13f7SAndroid Build Coastguard Worker VkDeviceSize Image::getSubresourceOffset(VkImageAspectFlagBits aspect, uint32_t mipLevel, uint32_t layer) const
941*03ce13f7SAndroid Build Coastguard Worker {
942*03ce13f7SAndroid Build Coastguard Worker 	// "If the image is disjoint, then the offset is relative to the base address of the plane.
943*03ce13f7SAndroid Build Coastguard Worker 	//  If the image is non-disjoint, then the offset is relative to the base address of the image."
944*03ce13f7SAndroid Build Coastguard Worker 	// Multi-plane external images are essentially disjoint.
945*03ce13f7SAndroid Build Coastguard Worker 	bool disjoint = (flags & VK_IMAGE_CREATE_DISJOINT_BIT) || (deviceMemory && deviceMemory->hasExternalImagePlanes());
946*03ce13f7SAndroid Build Coastguard Worker 	VkDeviceSize offset = !disjoint ? getAspectOffset(aspect) : 0;
947*03ce13f7SAndroid Build Coastguard Worker 
948*03ce13f7SAndroid Build Coastguard Worker 	for(uint32_t i = 0; i < mipLevel; i++)
949*03ce13f7SAndroid Build Coastguard Worker 	{
950*03ce13f7SAndroid Build Coastguard Worker 		offset += getMultiSampledLevelSize(aspect, i);
951*03ce13f7SAndroid Build Coastguard Worker 	}
952*03ce13f7SAndroid Build Coastguard Worker 
953*03ce13f7SAndroid Build Coastguard Worker 	return offset + layer * getLayerOffset(aspect, mipLevel);
954*03ce13f7SAndroid Build Coastguard Worker }
955*03ce13f7SAndroid Build Coastguard Worker 
getMipLevelSize(VkImageAspectFlagBits aspect,uint32_t mipLevel) const956*03ce13f7SAndroid Build Coastguard Worker VkDeviceSize Image::getMipLevelSize(VkImageAspectFlagBits aspect, uint32_t mipLevel) const
957*03ce13f7SAndroid Build Coastguard Worker {
958*03ce13f7SAndroid Build Coastguard Worker 	return slicePitchBytes(aspect, mipLevel) * getMipLevelExtent(aspect, mipLevel).depth;
959*03ce13f7SAndroid Build Coastguard Worker }
960*03ce13f7SAndroid Build Coastguard Worker 
getMultiSampledLevelSize(VkImageAspectFlagBits aspect,uint32_t mipLevel) const961*03ce13f7SAndroid Build Coastguard Worker VkDeviceSize Image::getMultiSampledLevelSize(VkImageAspectFlagBits aspect, uint32_t mipLevel) const
962*03ce13f7SAndroid Build Coastguard Worker {
963*03ce13f7SAndroid Build Coastguard Worker 	return getMipLevelSize(aspect, mipLevel) * samples;
964*03ce13f7SAndroid Build Coastguard Worker }
965*03ce13f7SAndroid Build Coastguard Worker 
is3DSlice() const966*03ce13f7SAndroid Build Coastguard Worker bool Image::is3DSlice() const
967*03ce13f7SAndroid Build Coastguard Worker {
968*03ce13f7SAndroid Build Coastguard Worker 	return ((imageType == VK_IMAGE_TYPE_3D) && (flags & VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT));
969*03ce13f7SAndroid Build Coastguard Worker }
970*03ce13f7SAndroid Build Coastguard Worker 
getLayerOffset(VkImageAspectFlagBits aspect,uint32_t mipLevel) const971*03ce13f7SAndroid Build Coastguard Worker VkDeviceSize Image::getLayerOffset(VkImageAspectFlagBits aspect, uint32_t mipLevel) const
972*03ce13f7SAndroid Build Coastguard Worker {
973*03ce13f7SAndroid Build Coastguard Worker 	if(is3DSlice())
974*03ce13f7SAndroid Build Coastguard Worker 	{
975*03ce13f7SAndroid Build Coastguard Worker 		// When the VkImageSubresourceRange structure is used to select a subset of the slices of a 3D
976*03ce13f7SAndroid Build Coastguard Worker 		// image's mip level in order to create a 2D or 2D array image view of a 3D image created with
977*03ce13f7SAndroid Build Coastguard Worker 		// VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT, baseArrayLayer and layerCount specify the first
978*03ce13f7SAndroid Build Coastguard Worker 		// slice index and the number of slices to include in the created image view.
979*03ce13f7SAndroid Build Coastguard Worker 		ASSERT(samples == VK_SAMPLE_COUNT_1_BIT);
980*03ce13f7SAndroid Build Coastguard Worker 
981*03ce13f7SAndroid Build Coastguard Worker 		// Offset to the proper slice of the 3D image's mip level
982*03ce13f7SAndroid Build Coastguard Worker 		return slicePitchBytes(aspect, mipLevel);
983*03ce13f7SAndroid Build Coastguard Worker 	}
984*03ce13f7SAndroid Build Coastguard Worker 
985*03ce13f7SAndroid Build Coastguard Worker 	return getLayerSize(aspect);
986*03ce13f7SAndroid Build Coastguard Worker }
987*03ce13f7SAndroid Build Coastguard Worker 
getLayerSize(VkImageAspectFlagBits aspect) const988*03ce13f7SAndroid Build Coastguard Worker VkDeviceSize Image::getLayerSize(VkImageAspectFlagBits aspect) const
989*03ce13f7SAndroid Build Coastguard Worker {
990*03ce13f7SAndroid Build Coastguard Worker 	VkDeviceSize layerSize = 0;
991*03ce13f7SAndroid Build Coastguard Worker 
992*03ce13f7SAndroid Build Coastguard Worker 	for(uint32_t mipLevel = 0; mipLevel < mipLevels; ++mipLevel)
993*03ce13f7SAndroid Build Coastguard Worker 	{
994*03ce13f7SAndroid Build Coastguard Worker 		layerSize += getMultiSampledLevelSize(aspect, mipLevel);
995*03ce13f7SAndroid Build Coastguard Worker 	}
996*03ce13f7SAndroid Build Coastguard Worker 
997*03ce13f7SAndroid Build Coastguard Worker 	return layerSize;
998*03ce13f7SAndroid Build Coastguard Worker }
999*03ce13f7SAndroid Build Coastguard Worker 
getStorageSize(VkImageAspectFlags aspectMask) const1000*03ce13f7SAndroid Build Coastguard Worker VkDeviceSize Image::getStorageSize(VkImageAspectFlags aspectMask) const
1001*03ce13f7SAndroid Build Coastguard Worker {
1002*03ce13f7SAndroid Build Coastguard Worker 	if((aspectMask & ~(VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT |
1003*03ce13f7SAndroid Build Coastguard Worker 	                   VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT | VK_IMAGE_ASPECT_PLANE_2_BIT)) != 0)
1004*03ce13f7SAndroid Build Coastguard Worker 	{
1005*03ce13f7SAndroid Build Coastguard Worker 		UNSUPPORTED("aspectMask %x", int(aspectMask));
1006*03ce13f7SAndroid Build Coastguard Worker 	}
1007*03ce13f7SAndroid Build Coastguard Worker 
1008*03ce13f7SAndroid Build Coastguard Worker 	VkDeviceSize storageSize = 0;
1009*03ce13f7SAndroid Build Coastguard Worker 
1010*03ce13f7SAndroid Build Coastguard Worker 	if(aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) storageSize += getLayerSize(VK_IMAGE_ASPECT_COLOR_BIT);
1011*03ce13f7SAndroid Build Coastguard Worker 	if(aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) storageSize += getLayerSize(VK_IMAGE_ASPECT_DEPTH_BIT);
1012*03ce13f7SAndroid Build Coastguard Worker 	if(aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) storageSize += getLayerSize(VK_IMAGE_ASPECT_STENCIL_BIT);
1013*03ce13f7SAndroid Build Coastguard Worker 	if(aspectMask & VK_IMAGE_ASPECT_PLANE_0_BIT) storageSize += getLayerSize(VK_IMAGE_ASPECT_PLANE_0_BIT);
1014*03ce13f7SAndroid Build Coastguard Worker 	if(aspectMask & VK_IMAGE_ASPECT_PLANE_1_BIT) storageSize += getLayerSize(VK_IMAGE_ASPECT_PLANE_1_BIT);
1015*03ce13f7SAndroid Build Coastguard Worker 	if(aspectMask & VK_IMAGE_ASPECT_PLANE_2_BIT) storageSize += getLayerSize(VK_IMAGE_ASPECT_PLANE_2_BIT);
1016*03ce13f7SAndroid Build Coastguard Worker 
1017*03ce13f7SAndroid Build Coastguard Worker 	return arrayLayers * storageSize;
1018*03ce13f7SAndroid Build Coastguard Worker }
1019*03ce13f7SAndroid Build Coastguard Worker 
getSampledImage(const vk::Format & imageViewFormat) const1020*03ce13f7SAndroid Build Coastguard Worker const Image *Image::getSampledImage(const vk::Format &imageViewFormat) const
1021*03ce13f7SAndroid Build Coastguard Worker {
1022*03ce13f7SAndroid Build Coastguard Worker 	bool isImageViewCompressed = imageViewFormat.isCompressed();
1023*03ce13f7SAndroid Build Coastguard Worker 	if(decompressedImage && !isImageViewCompressed)
1024*03ce13f7SAndroid Build Coastguard Worker 	{
1025*03ce13f7SAndroid Build Coastguard Worker 		ASSERT(flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT);
1026*03ce13f7SAndroid Build Coastguard Worker 		ASSERT(format.bytesPerBlock() == imageViewFormat.bytesPerBlock());
1027*03ce13f7SAndroid Build Coastguard Worker 	}
1028*03ce13f7SAndroid Build Coastguard Worker 	// If the ImageView's format is compressed, then we do need to decompress the image so that
1029*03ce13f7SAndroid Build Coastguard Worker 	// it may be sampled properly by texture sampling functions, which don't support compressed
1030*03ce13f7SAndroid Build Coastguard Worker 	// textures. If the ImageView's format is NOT compressed, then we reinterpret cast the
1031*03ce13f7SAndroid Build Coastguard Worker 	// compressed image into the ImageView's format, so we must return the compressed image as is.
1032*03ce13f7SAndroid Build Coastguard Worker 	return (decompressedImage && isImageViewCompressed) ? decompressedImage : this;
1033*03ce13f7SAndroid Build Coastguard Worker }
1034*03ce13f7SAndroid Build Coastguard Worker 
blitTo(Image * dstImage,const VkImageBlit2KHR & region,VkFilter filter) const1035*03ce13f7SAndroid Build Coastguard Worker void Image::blitTo(Image *dstImage, const VkImageBlit2KHR &region, VkFilter filter) const
1036*03ce13f7SAndroid Build Coastguard Worker {
1037*03ce13f7SAndroid Build Coastguard Worker 	prepareForSampling(ImageSubresourceRange(region.srcSubresource));
1038*03ce13f7SAndroid Build Coastguard Worker 	device->getBlitter()->blit(decompressedImage ? decompressedImage : this, dstImage, region, filter);
1039*03ce13f7SAndroid Build Coastguard Worker }
1040*03ce13f7SAndroid Build Coastguard Worker 
copyTo(uint8_t * dst,unsigned int dstPitch) const1041*03ce13f7SAndroid Build Coastguard Worker void Image::copyTo(uint8_t *dst, unsigned int dstPitch) const
1042*03ce13f7SAndroid Build Coastguard Worker {
1043*03ce13f7SAndroid Build Coastguard Worker 	device->getBlitter()->copy(this, dst, dstPitch);
1044*03ce13f7SAndroid Build Coastguard Worker }
1045*03ce13f7SAndroid Build Coastguard Worker 
resolveTo(Image * dstImage,const VkImageResolve2KHR & region) const1046*03ce13f7SAndroid Build Coastguard Worker void Image::resolveTo(Image *dstImage, const VkImageResolve2KHR &region) const
1047*03ce13f7SAndroid Build Coastguard Worker {
1048*03ce13f7SAndroid Build Coastguard Worker 	device->getBlitter()->resolve(this, dstImage, region);
1049*03ce13f7SAndroid Build Coastguard Worker }
1050*03ce13f7SAndroid Build Coastguard Worker 
resolveDepthStencilTo(const ImageView * src,ImageView * dst,VkResolveModeFlagBits depthResolveMode,VkResolveModeFlagBits stencilResolveMode) const1051*03ce13f7SAndroid Build Coastguard Worker void Image::resolveDepthStencilTo(const ImageView *src, ImageView *dst, VkResolveModeFlagBits depthResolveMode, VkResolveModeFlagBits stencilResolveMode) const
1052*03ce13f7SAndroid Build Coastguard Worker {
1053*03ce13f7SAndroid Build Coastguard Worker 	device->getBlitter()->resolveDepthStencil(src, dst, depthResolveMode, stencilResolveMode);
1054*03ce13f7SAndroid Build Coastguard Worker }
1055*03ce13f7SAndroid Build Coastguard Worker 
getLastLayerIndex(const VkImageSubresourceRange & subresourceRange) const1056*03ce13f7SAndroid Build Coastguard Worker uint32_t Image::getLastLayerIndex(const VkImageSubresourceRange &subresourceRange) const
1057*03ce13f7SAndroid Build Coastguard Worker {
1058*03ce13f7SAndroid Build Coastguard Worker 	return ((subresourceRange.layerCount == VK_REMAINING_ARRAY_LAYERS) ? arrayLayers : (subresourceRange.baseArrayLayer + subresourceRange.layerCount)) - 1;
1059*03ce13f7SAndroid Build Coastguard Worker }
1060*03ce13f7SAndroid Build Coastguard Worker 
getLastMipLevel(const VkImageSubresourceRange & subresourceRange) const1061*03ce13f7SAndroid Build Coastguard Worker uint32_t Image::getLastMipLevel(const VkImageSubresourceRange &subresourceRange) const
1062*03ce13f7SAndroid Build Coastguard Worker {
1063*03ce13f7SAndroid Build Coastguard Worker 	return ((subresourceRange.levelCount == VK_REMAINING_MIP_LEVELS) ? mipLevels : (subresourceRange.baseMipLevel + subresourceRange.levelCount)) - 1;
1064*03ce13f7SAndroid Build Coastguard Worker }
1065*03ce13f7SAndroid Build Coastguard Worker 
clear(const void * pixelData,VkFormat pixelFormat,const vk::Format & viewFormat,const VkImageSubresourceRange & subresourceRange,const VkRect2D * renderArea)1066*03ce13f7SAndroid Build Coastguard Worker void Image::clear(const void *pixelData, VkFormat pixelFormat, const vk::Format &viewFormat, const VkImageSubresourceRange &subresourceRange, const VkRect2D *renderArea)
1067*03ce13f7SAndroid Build Coastguard Worker {
1068*03ce13f7SAndroid Build Coastguard Worker 	device->getBlitter()->clear(pixelData, pixelFormat, this, viewFormat, subresourceRange, renderArea);
1069*03ce13f7SAndroid Build Coastguard Worker }
1070*03ce13f7SAndroid Build Coastguard Worker 
clear(const VkClearColorValue & color,const VkImageSubresourceRange & subresourceRange)1071*03ce13f7SAndroid Build Coastguard Worker void Image::clear(const VkClearColorValue &color, const VkImageSubresourceRange &subresourceRange)
1072*03ce13f7SAndroid Build Coastguard Worker {
1073*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(subresourceRange.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
1074*03ce13f7SAndroid Build Coastguard Worker 
1075*03ce13f7SAndroid Build Coastguard Worker 	clear(color.float32, format.getClearFormat(), format, subresourceRange, nullptr);
1076*03ce13f7SAndroid Build Coastguard Worker }
1077*03ce13f7SAndroid Build Coastguard Worker 
clear(const VkClearDepthStencilValue & color,const VkImageSubresourceRange & subresourceRange)1078*03ce13f7SAndroid Build Coastguard Worker void Image::clear(const VkClearDepthStencilValue &color, const VkImageSubresourceRange &subresourceRange)
1079*03ce13f7SAndroid Build Coastguard Worker {
1080*03ce13f7SAndroid Build Coastguard Worker 	ASSERT((subresourceRange.aspectMask & ~(VK_IMAGE_ASPECT_DEPTH_BIT |
1081*03ce13f7SAndroid Build Coastguard Worker 	                                        VK_IMAGE_ASPECT_STENCIL_BIT)) == 0);
1082*03ce13f7SAndroid Build Coastguard Worker 
1083*03ce13f7SAndroid Build Coastguard Worker 	if(subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)
1084*03ce13f7SAndroid Build Coastguard Worker 	{
1085*03ce13f7SAndroid Build Coastguard Worker 		VkImageSubresourceRange depthSubresourceRange = subresourceRange;
1086*03ce13f7SAndroid Build Coastguard Worker 		depthSubresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
1087*03ce13f7SAndroid Build Coastguard Worker 		clear(&color.depth, VK_FORMAT_D32_SFLOAT, format, depthSubresourceRange, nullptr);
1088*03ce13f7SAndroid Build Coastguard Worker 	}
1089*03ce13f7SAndroid Build Coastguard Worker 
1090*03ce13f7SAndroid Build Coastguard Worker 	if(subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)
1091*03ce13f7SAndroid Build Coastguard Worker 	{
1092*03ce13f7SAndroid Build Coastguard Worker 		VkImageSubresourceRange stencilSubresourceRange = subresourceRange;
1093*03ce13f7SAndroid Build Coastguard Worker 		stencilSubresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
1094*03ce13f7SAndroid Build Coastguard Worker 		clear(&color.stencil, VK_FORMAT_S8_UINT, format, stencilSubresourceRange, nullptr);
1095*03ce13f7SAndroid Build Coastguard Worker 	}
1096*03ce13f7SAndroid Build Coastguard Worker }
1097*03ce13f7SAndroid Build Coastguard Worker 
clear(const VkClearValue & clearValue,const vk::Format & viewFormat,const VkRect2D & renderArea,const VkImageSubresourceRange & subresourceRange)1098*03ce13f7SAndroid Build Coastguard Worker void Image::clear(const VkClearValue &clearValue, const vk::Format &viewFormat, const VkRect2D &renderArea, const VkImageSubresourceRange &subresourceRange)
1099*03ce13f7SAndroid Build Coastguard Worker {
1100*03ce13f7SAndroid Build Coastguard Worker 	ASSERT((subresourceRange.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
1101*03ce13f7SAndroid Build Coastguard Worker 	       (subresourceRange.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT |
1102*03ce13f7SAndroid Build Coastguard Worker 	                                       VK_IMAGE_ASPECT_STENCIL_BIT)));
1103*03ce13f7SAndroid Build Coastguard Worker 
1104*03ce13f7SAndroid Build Coastguard Worker 	if(subresourceRange.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT)
1105*03ce13f7SAndroid Build Coastguard Worker 	{
1106*03ce13f7SAndroid Build Coastguard Worker 		clear(clearValue.color.float32, viewFormat.getClearFormat(), viewFormat, subresourceRange, &renderArea);
1107*03ce13f7SAndroid Build Coastguard Worker 	}
1108*03ce13f7SAndroid Build Coastguard Worker 	else
1109*03ce13f7SAndroid Build Coastguard Worker 	{
1110*03ce13f7SAndroid Build Coastguard Worker 		if(subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)
1111*03ce13f7SAndroid Build Coastguard Worker 		{
1112*03ce13f7SAndroid Build Coastguard Worker 			VkImageSubresourceRange depthSubresourceRange = subresourceRange;
1113*03ce13f7SAndroid Build Coastguard Worker 			depthSubresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
1114*03ce13f7SAndroid Build Coastguard Worker 			clear(&clearValue.depthStencil.depth, VK_FORMAT_D32_SFLOAT, viewFormat, depthSubresourceRange, &renderArea);
1115*03ce13f7SAndroid Build Coastguard Worker 		}
1116*03ce13f7SAndroid Build Coastguard Worker 
1117*03ce13f7SAndroid Build Coastguard Worker 		if(subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)
1118*03ce13f7SAndroid Build Coastguard Worker 		{
1119*03ce13f7SAndroid Build Coastguard Worker 			VkImageSubresourceRange stencilSubresourceRange = subresourceRange;
1120*03ce13f7SAndroid Build Coastguard Worker 			stencilSubresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
1121*03ce13f7SAndroid Build Coastguard Worker 			clear(&clearValue.depthStencil.stencil, VK_FORMAT_S8_UINT, viewFormat, stencilSubresourceRange, &renderArea);
1122*03ce13f7SAndroid Build Coastguard Worker 		}
1123*03ce13f7SAndroid Build Coastguard Worker 	}
1124*03ce13f7SAndroid Build Coastguard Worker }
1125*03ce13f7SAndroid Build Coastguard Worker 
requiresPreprocessing() const1126*03ce13f7SAndroid Build Coastguard Worker bool Image::requiresPreprocessing() const
1127*03ce13f7SAndroid Build Coastguard Worker {
1128*03ce13f7SAndroid Build Coastguard Worker 	return isCubeCompatible() || decompressedImage;
1129*03ce13f7SAndroid Build Coastguard Worker }
1130*03ce13f7SAndroid Build Coastguard Worker 
contentsChanged(const VkImageSubresourceRange & subresourceRange,ContentsChangedContext contentsChangedContext)1131*03ce13f7SAndroid Build Coastguard Worker void Image::contentsChanged(const VkImageSubresourceRange &subresourceRange, ContentsChangedContext contentsChangedContext)
1132*03ce13f7SAndroid Build Coastguard Worker {
1133*03ce13f7SAndroid Build Coastguard Worker 	// If this function is called after (possibly) writing to this image from a shader,
1134*03ce13f7SAndroid Build Coastguard Worker 	// this must have the VK_IMAGE_USAGE_STORAGE_BIT set for the write operation to be
1135*03ce13f7SAndroid Build Coastguard Worker 	// valid. Otherwise, we can't have legally written to this image, so we know we can
1136*03ce13f7SAndroid Build Coastguard Worker 	// skip updating dirtyResources.
1137*03ce13f7SAndroid Build Coastguard Worker 	if((contentsChangedContext == USING_STORAGE) && !(usage & VK_IMAGE_USAGE_STORAGE_BIT))
1138*03ce13f7SAndroid Build Coastguard Worker 	{
1139*03ce13f7SAndroid Build Coastguard Worker 		return;
1140*03ce13f7SAndroid Build Coastguard Worker 	}
1141*03ce13f7SAndroid Build Coastguard Worker 
1142*03ce13f7SAndroid Build Coastguard Worker 	// If this isn't a cube or a compressed image, we'll never need dirtyResources,
1143*03ce13f7SAndroid Build Coastguard Worker 	// so we can skip updating dirtyResources
1144*03ce13f7SAndroid Build Coastguard Worker 	if(!requiresPreprocessing())
1145*03ce13f7SAndroid Build Coastguard Worker 	{
1146*03ce13f7SAndroid Build Coastguard Worker 		return;
1147*03ce13f7SAndroid Build Coastguard Worker 	}
1148*03ce13f7SAndroid Build Coastguard Worker 
1149*03ce13f7SAndroid Build Coastguard Worker 	uint32_t lastLayer = getLastLayerIndex(subresourceRange);
1150*03ce13f7SAndroid Build Coastguard Worker 	uint32_t lastMipLevel = getLastMipLevel(subresourceRange);
1151*03ce13f7SAndroid Build Coastguard Worker 
1152*03ce13f7SAndroid Build Coastguard Worker 	VkImageSubresource subresource = {
1153*03ce13f7SAndroid Build Coastguard Worker 		subresourceRange.aspectMask,
1154*03ce13f7SAndroid Build Coastguard Worker 		subresourceRange.baseMipLevel,
1155*03ce13f7SAndroid Build Coastguard Worker 		subresourceRange.baseArrayLayer
1156*03ce13f7SAndroid Build Coastguard Worker 	};
1157*03ce13f7SAndroid Build Coastguard Worker 
1158*03ce13f7SAndroid Build Coastguard Worker 	marl::lock lock(mutex);
1159*03ce13f7SAndroid Build Coastguard Worker 	for(subresource.arrayLayer = subresourceRange.baseArrayLayer;
1160*03ce13f7SAndroid Build Coastguard Worker 	    subresource.arrayLayer <= lastLayer;
1161*03ce13f7SAndroid Build Coastguard Worker 	    subresource.arrayLayer++)
1162*03ce13f7SAndroid Build Coastguard Worker 	{
1163*03ce13f7SAndroid Build Coastguard Worker 		for(subresource.mipLevel = subresourceRange.baseMipLevel;
1164*03ce13f7SAndroid Build Coastguard Worker 		    subresource.mipLevel <= lastMipLevel;
1165*03ce13f7SAndroid Build Coastguard Worker 		    subresource.mipLevel++)
1166*03ce13f7SAndroid Build Coastguard Worker 		{
1167*03ce13f7SAndroid Build Coastguard Worker 			dirtySubresources.insert(subresource);
1168*03ce13f7SAndroid Build Coastguard Worker 		}
1169*03ce13f7SAndroid Build Coastguard Worker 	}
1170*03ce13f7SAndroid Build Coastguard Worker }
1171*03ce13f7SAndroid Build Coastguard Worker 
prepareForSampling(const VkImageSubresourceRange & subresourceRange) const1172*03ce13f7SAndroid Build Coastguard Worker void Image::prepareForSampling(const VkImageSubresourceRange &subresourceRange) const
1173*03ce13f7SAndroid Build Coastguard Worker {
1174*03ce13f7SAndroid Build Coastguard Worker 	// If this isn't a cube or a compressed image, there's nothing to do
1175*03ce13f7SAndroid Build Coastguard Worker 	if(!requiresPreprocessing())
1176*03ce13f7SAndroid Build Coastguard Worker 	{
1177*03ce13f7SAndroid Build Coastguard Worker 		return;
1178*03ce13f7SAndroid Build Coastguard Worker 	}
1179*03ce13f7SAndroid Build Coastguard Worker 
1180*03ce13f7SAndroid Build Coastguard Worker 	uint32_t lastLayer = getLastLayerIndex(subresourceRange);
1181*03ce13f7SAndroid Build Coastguard Worker 	uint32_t lastMipLevel = getLastMipLevel(subresourceRange);
1182*03ce13f7SAndroid Build Coastguard Worker 
1183*03ce13f7SAndroid Build Coastguard Worker 	VkImageSubresource subresource = {
1184*03ce13f7SAndroid Build Coastguard Worker 		subresourceRange.aspectMask,
1185*03ce13f7SAndroid Build Coastguard Worker 		subresourceRange.baseMipLevel,
1186*03ce13f7SAndroid Build Coastguard Worker 		subresourceRange.baseArrayLayer
1187*03ce13f7SAndroid Build Coastguard Worker 	};
1188*03ce13f7SAndroid Build Coastguard Worker 
1189*03ce13f7SAndroid Build Coastguard Worker 	marl::lock lock(mutex);
1190*03ce13f7SAndroid Build Coastguard Worker 
1191*03ce13f7SAndroid Build Coastguard Worker 	if(dirtySubresources.empty())
1192*03ce13f7SAndroid Build Coastguard Worker 	{
1193*03ce13f7SAndroid Build Coastguard Worker 		return;
1194*03ce13f7SAndroid Build Coastguard Worker 	}
1195*03ce13f7SAndroid Build Coastguard Worker 
1196*03ce13f7SAndroid Build Coastguard Worker 	// First, decompress all relevant dirty subregions
1197*03ce13f7SAndroid Build Coastguard Worker 	if(decompressedImage)
1198*03ce13f7SAndroid Build Coastguard Worker 	{
1199*03ce13f7SAndroid Build Coastguard Worker 		for(subresource.mipLevel = subresourceRange.baseMipLevel;
1200*03ce13f7SAndroid Build Coastguard Worker 		    subresource.mipLevel <= lastMipLevel;
1201*03ce13f7SAndroid Build Coastguard Worker 		    subresource.mipLevel++)
1202*03ce13f7SAndroid Build Coastguard Worker 		{
1203*03ce13f7SAndroid Build Coastguard Worker 			for(subresource.arrayLayer = subresourceRange.baseArrayLayer;
1204*03ce13f7SAndroid Build Coastguard Worker 			    subresource.arrayLayer <= lastLayer;
1205*03ce13f7SAndroid Build Coastguard Worker 			    subresource.arrayLayer++)
1206*03ce13f7SAndroid Build Coastguard Worker 			{
1207*03ce13f7SAndroid Build Coastguard Worker 				auto it = dirtySubresources.find(subresource);
1208*03ce13f7SAndroid Build Coastguard Worker 				if(it != dirtySubresources.end())
1209*03ce13f7SAndroid Build Coastguard Worker 				{
1210*03ce13f7SAndroid Build Coastguard Worker 					decompress(subresource);
1211*03ce13f7SAndroid Build Coastguard Worker 				}
1212*03ce13f7SAndroid Build Coastguard Worker 			}
1213*03ce13f7SAndroid Build Coastguard Worker 		}
1214*03ce13f7SAndroid Build Coastguard Worker 	}
1215*03ce13f7SAndroid Build Coastguard Worker 
1216*03ce13f7SAndroid Build Coastguard Worker 	// Second, update cubemap borders
1217*03ce13f7SAndroid Build Coastguard Worker 	if(isCubeCompatible())
1218*03ce13f7SAndroid Build Coastguard Worker 	{
1219*03ce13f7SAndroid Build Coastguard Worker 		for(subresource.mipLevel = subresourceRange.baseMipLevel;
1220*03ce13f7SAndroid Build Coastguard Worker 		    subresource.mipLevel <= lastMipLevel;
1221*03ce13f7SAndroid Build Coastguard Worker 		    subresource.mipLevel++)
1222*03ce13f7SAndroid Build Coastguard Worker 		{
1223*03ce13f7SAndroid Build Coastguard Worker 			for(subresource.arrayLayer = subresourceRange.baseArrayLayer;
1224*03ce13f7SAndroid Build Coastguard Worker 			    subresource.arrayLayer <= lastLayer;
1225*03ce13f7SAndroid Build Coastguard Worker 			    subresource.arrayLayer++)
1226*03ce13f7SAndroid Build Coastguard Worker 			{
1227*03ce13f7SAndroid Build Coastguard Worker 				auto it = dirtySubresources.find(subresource);
1228*03ce13f7SAndroid Build Coastguard Worker 				if(it != dirtySubresources.end())
1229*03ce13f7SAndroid Build Coastguard Worker 				{
1230*03ce13f7SAndroid Build Coastguard Worker 					// Since cube faces affect each other's borders, we update all 6 layers.
1231*03ce13f7SAndroid Build Coastguard Worker 
1232*03ce13f7SAndroid Build Coastguard Worker 					subresource.arrayLayer -= subresource.arrayLayer % 6;  // Round down to a multiple of 6.
1233*03ce13f7SAndroid Build Coastguard Worker 
1234*03ce13f7SAndroid Build Coastguard Worker 					if(subresource.arrayLayer + 5 <= lastLayer)
1235*03ce13f7SAndroid Build Coastguard Worker 					{
1236*03ce13f7SAndroid Build Coastguard Worker 						device->getBlitter()->updateBorders(decompressedImage ? decompressedImage : this, subresource);
1237*03ce13f7SAndroid Build Coastguard Worker 					}
1238*03ce13f7SAndroid Build Coastguard Worker 
1239*03ce13f7SAndroid Build Coastguard Worker 					subresource.arrayLayer += 5;  // Together with the loop increment, advances to the next cube.
1240*03ce13f7SAndroid Build Coastguard Worker 				}
1241*03ce13f7SAndroid Build Coastguard Worker 			}
1242*03ce13f7SAndroid Build Coastguard Worker 		}
1243*03ce13f7SAndroid Build Coastguard Worker 	}
1244*03ce13f7SAndroid Build Coastguard Worker 
1245*03ce13f7SAndroid Build Coastguard Worker 	// Finally, mark all updated subregions clean
1246*03ce13f7SAndroid Build Coastguard Worker 	for(subresource.mipLevel = subresourceRange.baseMipLevel;
1247*03ce13f7SAndroid Build Coastguard Worker 	    subresource.mipLevel <= lastMipLevel;
1248*03ce13f7SAndroid Build Coastguard Worker 	    subresource.mipLevel++)
1249*03ce13f7SAndroid Build Coastguard Worker 	{
1250*03ce13f7SAndroid Build Coastguard Worker 		for(subresource.arrayLayer = subresourceRange.baseArrayLayer;
1251*03ce13f7SAndroid Build Coastguard Worker 		    subresource.arrayLayer <= lastLayer;
1252*03ce13f7SAndroid Build Coastguard Worker 		    subresource.arrayLayer++)
1253*03ce13f7SAndroid Build Coastguard Worker 		{
1254*03ce13f7SAndroid Build Coastguard Worker 			auto it = dirtySubresources.find(subresource);
1255*03ce13f7SAndroid Build Coastguard Worker 			if(it != dirtySubresources.end())
1256*03ce13f7SAndroid Build Coastguard Worker 			{
1257*03ce13f7SAndroid Build Coastguard Worker 				dirtySubresources.erase(it);
1258*03ce13f7SAndroid Build Coastguard Worker 			}
1259*03ce13f7SAndroid Build Coastguard Worker 		}
1260*03ce13f7SAndroid Build Coastguard Worker 	}
1261*03ce13f7SAndroid Build Coastguard Worker }
1262*03ce13f7SAndroid Build Coastguard Worker 
decompress(const VkImageSubresource & subresource) const1263*03ce13f7SAndroid Build Coastguard Worker void Image::decompress(const VkImageSubresource &subresource) const
1264*03ce13f7SAndroid Build Coastguard Worker {
1265*03ce13f7SAndroid Build Coastguard Worker 	switch(format)
1266*03ce13f7SAndroid Build Coastguard Worker 	{
1267*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_EAC_R11_UNORM_BLOCK:
1268*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_EAC_R11_SNORM_BLOCK:
1269*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_EAC_R11G11_UNORM_BLOCK:
1270*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
1271*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
1272*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
1273*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:
1274*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
1275*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
1276*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
1277*03ce13f7SAndroid Build Coastguard Worker 		decodeETC2(subresource);
1278*03ce13f7SAndroid Build Coastguard Worker 		break;
1279*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
1280*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
1281*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
1282*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
1283*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC2_UNORM_BLOCK:
1284*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC2_SRGB_BLOCK:
1285*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC3_UNORM_BLOCK:
1286*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC3_SRGB_BLOCK:
1287*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC4_UNORM_BLOCK:
1288*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC4_SNORM_BLOCK:
1289*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC5_UNORM_BLOCK:
1290*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC5_SNORM_BLOCK:
1291*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC6H_UFLOAT_BLOCK:
1292*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC6H_SFLOAT_BLOCK:
1293*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC7_UNORM_BLOCK:
1294*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_BC7_SRGB_BLOCK:
1295*03ce13f7SAndroid Build Coastguard Worker 		decodeBC(subresource);
1296*03ce13f7SAndroid Build Coastguard Worker 		break;
1297*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
1298*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
1299*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
1300*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
1301*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
1302*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
1303*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
1304*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
1305*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
1306*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
1307*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
1308*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
1309*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
1310*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
1311*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
1312*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
1313*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
1314*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
1315*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
1316*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
1317*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
1318*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
1319*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
1320*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
1321*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
1322*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
1323*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
1324*03ce13f7SAndroid Build Coastguard Worker 	case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
1325*03ce13f7SAndroid Build Coastguard Worker 		decodeASTC(subresource);
1326*03ce13f7SAndroid Build Coastguard Worker 		break;
1327*03ce13f7SAndroid Build Coastguard Worker 	default:
1328*03ce13f7SAndroid Build Coastguard Worker 		UNSUPPORTED("Compressed format %d", (VkFormat)format);
1329*03ce13f7SAndroid Build Coastguard Worker 		break;
1330*03ce13f7SAndroid Build Coastguard Worker 	}
1331*03ce13f7SAndroid Build Coastguard Worker }
1332*03ce13f7SAndroid Build Coastguard Worker 
decodeETC2(const VkImageSubresource & subresource) const1333*03ce13f7SAndroid Build Coastguard Worker void Image::decodeETC2(const VkImageSubresource &subresource) const
1334*03ce13f7SAndroid Build Coastguard Worker {
1335*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(decompressedImage);
1336*03ce13f7SAndroid Build Coastguard Worker 
1337*03ce13f7SAndroid Build Coastguard Worker 	ETC_Decoder::InputType inputType = GetInputType(format);
1338*03ce13f7SAndroid Build Coastguard Worker 
1339*03ce13f7SAndroid Build Coastguard Worker 	int bytes = decompressedImage->format.bytes();
1340*03ce13f7SAndroid Build Coastguard Worker 	bool fakeAlpha = (format == VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK) || (format == VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK);
1341*03ce13f7SAndroid Build Coastguard Worker 	size_t sizeToWrite = 0;
1342*03ce13f7SAndroid Build Coastguard Worker 
1343*03ce13f7SAndroid Build Coastguard Worker 	VkExtent3D mipLevelExtent = getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresource.aspectMask), subresource.mipLevel);
1344*03ce13f7SAndroid Build Coastguard Worker 
1345*03ce13f7SAndroid Build Coastguard Worker 	int pitchB = decompressedImage->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresource.mipLevel);
1346*03ce13f7SAndroid Build Coastguard Worker 
1347*03ce13f7SAndroid Build Coastguard Worker 	if(fakeAlpha)
1348*03ce13f7SAndroid Build Coastguard Worker 	{
1349*03ce13f7SAndroid Build Coastguard Worker 		// To avoid overflow in case of cube textures, which are offset in memory to account for the border,
1350*03ce13f7SAndroid Build Coastguard Worker 		// compute the size from the first pixel to the last pixel, excluding any padding or border before
1351*03ce13f7SAndroid Build Coastguard Worker 		// the first pixel or after the last pixel.
1352*03ce13f7SAndroid Build Coastguard Worker 		sizeToWrite = ((mipLevelExtent.height - 1) * pitchB) + (mipLevelExtent.width * bytes);
1353*03ce13f7SAndroid Build Coastguard Worker 	}
1354*03ce13f7SAndroid Build Coastguard Worker 
1355*03ce13f7SAndroid Build Coastguard Worker 	for(int32_t depth = 0; depth < static_cast<int32_t>(mipLevelExtent.depth); depth++)
1356*03ce13f7SAndroid Build Coastguard Worker 	{
1357*03ce13f7SAndroid Build Coastguard Worker 		uint8_t *source = static_cast<uint8_t *>(getTexelPointer({ 0, 0, depth }, subresource));
1358*03ce13f7SAndroid Build Coastguard Worker 		uint8_t *dest = static_cast<uint8_t *>(decompressedImage->getTexelPointer({ 0, 0, depth }, subresource));
1359*03ce13f7SAndroid Build Coastguard Worker 
1360*03ce13f7SAndroid Build Coastguard Worker 		if(fakeAlpha)
1361*03ce13f7SAndroid Build Coastguard Worker 		{
1362*03ce13f7SAndroid Build Coastguard Worker 			ASSERT((dest + sizeToWrite) < decompressedImage->end());
1363*03ce13f7SAndroid Build Coastguard Worker 			memset(dest, 0xFF, sizeToWrite);
1364*03ce13f7SAndroid Build Coastguard Worker 		}
1365*03ce13f7SAndroid Build Coastguard Worker 
1366*03ce13f7SAndroid Build Coastguard Worker 		ETC_Decoder::Decode(source, dest, mipLevelExtent.width, mipLevelExtent.height,
1367*03ce13f7SAndroid Build Coastguard Worker 		                    pitchB, bytes, inputType);
1368*03ce13f7SAndroid Build Coastguard Worker 	}
1369*03ce13f7SAndroid Build Coastguard Worker }
1370*03ce13f7SAndroid Build Coastguard Worker 
decodeBC(const VkImageSubresource & subresource) const1371*03ce13f7SAndroid Build Coastguard Worker void Image::decodeBC(const VkImageSubresource &subresource) const
1372*03ce13f7SAndroid Build Coastguard Worker {
1373*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(decompressedImage);
1374*03ce13f7SAndroid Build Coastguard Worker 
1375*03ce13f7SAndroid Build Coastguard Worker 	int n = GetBCn(format);
1376*03ce13f7SAndroid Build Coastguard Worker 	int noAlphaU = GetNoAlphaOrUnsigned(format);
1377*03ce13f7SAndroid Build Coastguard Worker 
1378*03ce13f7SAndroid Build Coastguard Worker 	int bytes = decompressedImage->format.bytes();
1379*03ce13f7SAndroid Build Coastguard Worker 
1380*03ce13f7SAndroid Build Coastguard Worker 	VkExtent3D mipLevelExtent = getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresource.aspectMask), subresource.mipLevel);
1381*03ce13f7SAndroid Build Coastguard Worker 
1382*03ce13f7SAndroid Build Coastguard Worker 	int pitchB = decompressedImage->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresource.mipLevel);
1383*03ce13f7SAndroid Build Coastguard Worker 
1384*03ce13f7SAndroid Build Coastguard Worker 	for(int32_t depth = 0; depth < static_cast<int32_t>(mipLevelExtent.depth); depth++)
1385*03ce13f7SAndroid Build Coastguard Worker 	{
1386*03ce13f7SAndroid Build Coastguard Worker 		uint8_t *source = static_cast<uint8_t *>(getTexelPointer({ 0, 0, depth }, subresource));
1387*03ce13f7SAndroid Build Coastguard Worker 		uint8_t *dest = static_cast<uint8_t *>(decompressedImage->getTexelPointer({ 0, 0, depth }, subresource));
1388*03ce13f7SAndroid Build Coastguard Worker 
1389*03ce13f7SAndroid Build Coastguard Worker 		BC_Decoder::Decode(source, dest, mipLevelExtent.width, mipLevelExtent.height,
1390*03ce13f7SAndroid Build Coastguard Worker 		                   pitchB, bytes, n, noAlphaU);
1391*03ce13f7SAndroid Build Coastguard Worker 	}
1392*03ce13f7SAndroid Build Coastguard Worker }
1393*03ce13f7SAndroid Build Coastguard Worker 
decodeASTC(const VkImageSubresource & subresource) const1394*03ce13f7SAndroid Build Coastguard Worker void Image::decodeASTC(const VkImageSubresource &subresource) const
1395*03ce13f7SAndroid Build Coastguard Worker {
1396*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(decompressedImage);
1397*03ce13f7SAndroid Build Coastguard Worker 
1398*03ce13f7SAndroid Build Coastguard Worker 	int xBlockSize = format.blockWidth();
1399*03ce13f7SAndroid Build Coastguard Worker 	int yBlockSize = format.blockHeight();
1400*03ce13f7SAndroid Build Coastguard Worker 	int zBlockSize = 1;
1401*03ce13f7SAndroid Build Coastguard Worker 	bool isUnsigned = format.isUnsignedComponent(0);
1402*03ce13f7SAndroid Build Coastguard Worker 
1403*03ce13f7SAndroid Build Coastguard Worker 	int bytes = decompressedImage->format.bytes();
1404*03ce13f7SAndroid Build Coastguard Worker 
1405*03ce13f7SAndroid Build Coastguard Worker 	VkExtent3D mipLevelExtent = getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresource.aspectMask), subresource.mipLevel);
1406*03ce13f7SAndroid Build Coastguard Worker 
1407*03ce13f7SAndroid Build Coastguard Worker 	int xblocks = (mipLevelExtent.width + xBlockSize - 1) / xBlockSize;
1408*03ce13f7SAndroid Build Coastguard Worker 	int yblocks = (mipLevelExtent.height + yBlockSize - 1) / yBlockSize;
1409*03ce13f7SAndroid Build Coastguard Worker 	int zblocks = (zBlockSize > 1) ? (mipLevelExtent.depth + zBlockSize - 1) / zBlockSize : 1;
1410*03ce13f7SAndroid Build Coastguard Worker 
1411*03ce13f7SAndroid Build Coastguard Worker 	if(xblocks <= 0 || yblocks <= 0 || zblocks <= 0)
1412*03ce13f7SAndroid Build Coastguard Worker 	{
1413*03ce13f7SAndroid Build Coastguard Worker 		return;
1414*03ce13f7SAndroid Build Coastguard Worker 	}
1415*03ce13f7SAndroid Build Coastguard Worker 
1416*03ce13f7SAndroid Build Coastguard Worker 	int pitchB = decompressedImage->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresource.mipLevel);
1417*03ce13f7SAndroid Build Coastguard Worker 	int sliceB = decompressedImage->slicePitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, subresource.mipLevel);
1418*03ce13f7SAndroid Build Coastguard Worker 
1419*03ce13f7SAndroid Build Coastguard Worker 	for(int32_t depth = 0; depth < static_cast<int32_t>(mipLevelExtent.depth); depth++)
1420*03ce13f7SAndroid Build Coastguard Worker 	{
1421*03ce13f7SAndroid Build Coastguard Worker 		uint8_t *source = static_cast<uint8_t *>(getTexelPointer({ 0, 0, depth }, subresource));
1422*03ce13f7SAndroid Build Coastguard Worker 		uint8_t *dest = static_cast<uint8_t *>(decompressedImage->getTexelPointer({ 0, 0, depth }, subresource));
1423*03ce13f7SAndroid Build Coastguard Worker 
1424*03ce13f7SAndroid Build Coastguard Worker 		ASTC_Decoder::Decode(source, dest, mipLevelExtent.width, mipLevelExtent.height, mipLevelExtent.depth, bytes, pitchB, sliceB,
1425*03ce13f7SAndroid Build Coastguard Worker 		                     xBlockSize, yBlockSize, zBlockSize, xblocks, yblocks, zblocks, isUnsigned);
1426*03ce13f7SAndroid Build Coastguard Worker 	}
1427*03ce13f7SAndroid Build Coastguard Worker }
1428*03ce13f7SAndroid Build Coastguard Worker 
1429*03ce13f7SAndroid Build Coastguard Worker }  // namespace vk
1430