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 ®ion) 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 ®ion) 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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion, 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 ®ion) 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