xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // TextureVk.cpp:
7*8975f5c5SAndroid Build Coastguard Worker //    Implements the class methods for TextureVk.
8*8975f5c5SAndroid Build Coastguard Worker //
9*8975f5c5SAndroid Build Coastguard Worker 
10*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/TextureVk.h"
11*8975f5c5SAndroid Build Coastguard Worker #include <vulkan/vulkan.h>
12*8975f5c5SAndroid Build Coastguard Worker 
13*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "image_util/generatemip.inc"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Config.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Image.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/MemoryObject.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Surface.h"
20*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/renderer_utils.h"
21*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/ContextVk.h"
22*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/FramebufferVk.h"
23*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/ImageVk.h"
24*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/MemoryObjectVk.h"
25*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/RenderbufferVk.h"
26*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/SurfaceVk.h"
27*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/UtilsVk.h"
28*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/vk_format_utils.h"
29*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/vk_helpers.h"
30*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/vk_renderer.h"
31*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/vk_utils.h"
32*8975f5c5SAndroid Build Coastguard Worker 
33*8975f5c5SAndroid Build Coastguard Worker namespace rx
34*8975f5c5SAndroid Build Coastguard Worker {
35*8975f5c5SAndroid Build Coastguard Worker namespace
36*8975f5c5SAndroid Build Coastguard Worker {
37*8975f5c5SAndroid Build Coastguard Worker constexpr VkImageUsageFlags kTransferImageFlags =
38*8975f5c5SAndroid Build Coastguard Worker     VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
39*8975f5c5SAndroid Build Coastguard Worker 
40*8975f5c5SAndroid Build Coastguard Worker constexpr VkImageUsageFlags kColorAttachmentImageFlags =
41*8975f5c5SAndroid Build Coastguard Worker     VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
42*8975f5c5SAndroid Build Coastguard Worker 
43*8975f5c5SAndroid Build Coastguard Worker constexpr VkImageUsageFlags kDrawStagingImageFlags =
44*8975f5c5SAndroid Build Coastguard Worker     kTransferImageFlags | kColorAttachmentImageFlags;
45*8975f5c5SAndroid Build Coastguard Worker 
46*8975f5c5SAndroid Build Coastguard Worker constexpr VkFormatFeatureFlags kBlitFeatureFlags =
47*8975f5c5SAndroid Build Coastguard Worker     VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
48*8975f5c5SAndroid Build Coastguard Worker 
49*8975f5c5SAndroid Build Coastguard Worker constexpr VkImageAspectFlags kDepthStencilAspects =
50*8975f5c5SAndroid Build Coastguard Worker     VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT;
51*8975f5c5SAndroid Build Coastguard Worker 
52*8975f5c5SAndroid Build Coastguard Worker constexpr angle::SubjectIndex kTextureImageSubjectIndex = 0;
53*8975f5c5SAndroid Build Coastguard Worker 
54*8975f5c5SAndroid Build Coastguard Worker // Test whether a texture level is within the range of levels for which the current image is
55*8975f5c5SAndroid Build Coastguard Worker // allocated.  This is used to ensure out-of-range updates are staged in the image, and not
56*8975f5c5SAndroid Build Coastguard Worker // attempted to be directly applied.
IsTextureLevelInAllocatedImage(const vk::ImageHelper & image,gl::LevelIndex textureLevelIndexGL)57*8975f5c5SAndroid Build Coastguard Worker bool IsTextureLevelInAllocatedImage(const vk::ImageHelper &image,
58*8975f5c5SAndroid Build Coastguard Worker                                     gl::LevelIndex textureLevelIndexGL)
59*8975f5c5SAndroid Build Coastguard Worker {
60*8975f5c5SAndroid Build Coastguard Worker     gl::LevelIndex imageFirstAllocateLevel = image.getFirstAllocatedLevel();
61*8975f5c5SAndroid Build Coastguard Worker     if (textureLevelIndexGL < imageFirstAllocateLevel)
62*8975f5c5SAndroid Build Coastguard Worker     {
63*8975f5c5SAndroid Build Coastguard Worker         return false;
64*8975f5c5SAndroid Build Coastguard Worker     }
65*8975f5c5SAndroid Build Coastguard Worker 
66*8975f5c5SAndroid Build Coastguard Worker     vk::LevelIndex imageLevelIndexVk = image.toVkLevel(textureLevelIndexGL);
67*8975f5c5SAndroid Build Coastguard Worker     return imageLevelIndexVk < vk::LevelIndex(image.getLevelCount());
68*8975f5c5SAndroid Build Coastguard Worker }
69*8975f5c5SAndroid Build Coastguard Worker 
70*8975f5c5SAndroid Build Coastguard Worker // Test whether a redefined texture level is compatible with the currently allocated image.  Returns
71*8975f5c5SAndroid Build Coastguard Worker // true if the given size and format match the corresponding mip in the allocated image (taking
72*8975f5c5SAndroid Build Coastguard Worker // base level into account).  This could return false when:
73*8975f5c5SAndroid Build Coastguard Worker //
74*8975f5c5SAndroid Build Coastguard Worker // - Defining a texture level that is outside the range of the image levels.  In this case, changes
75*8975f5c5SAndroid Build Coastguard Worker //   to this level should remain staged until the texture is redefined to include this level.
76*8975f5c5SAndroid Build Coastguard Worker // - Redefining a texture level that is within the range of the image levels, but has a different
77*8975f5c5SAndroid Build Coastguard Worker //   size or format.  In this case too, changes to this level should remain staged as the texture
78*8975f5c5SAndroid Build Coastguard Worker //   is no longer complete as is.
IsTextureLevelDefinitionCompatibleWithImage(const vk::ImageHelper & image,gl::LevelIndex textureLevelIndexGL,const gl::Extents & size,angle::FormatID intendedFormatID,angle::FormatID actualFormatID)79*8975f5c5SAndroid Build Coastguard Worker bool IsTextureLevelDefinitionCompatibleWithImage(const vk::ImageHelper &image,
80*8975f5c5SAndroid Build Coastguard Worker                                                  gl::LevelIndex textureLevelIndexGL,
81*8975f5c5SAndroid Build Coastguard Worker                                                  const gl::Extents &size,
82*8975f5c5SAndroid Build Coastguard Worker                                                  angle::FormatID intendedFormatID,
83*8975f5c5SAndroid Build Coastguard Worker                                                  angle::FormatID actualFormatID)
84*8975f5c5SAndroid Build Coastguard Worker {
85*8975f5c5SAndroid Build Coastguard Worker     if (!IsTextureLevelInAllocatedImage(image, textureLevelIndexGL))
86*8975f5c5SAndroid Build Coastguard Worker     {
87*8975f5c5SAndroid Build Coastguard Worker         return false;
88*8975f5c5SAndroid Build Coastguard Worker     }
89*8975f5c5SAndroid Build Coastguard Worker 
90*8975f5c5SAndroid Build Coastguard Worker     vk::LevelIndex imageLevelIndexVk = image.toVkLevel(textureLevelIndexGL);
91*8975f5c5SAndroid Build Coastguard Worker     return size == image.getLevelExtents(imageLevelIndexVk) &&
92*8975f5c5SAndroid Build Coastguard Worker            intendedFormatID == image.getIntendedFormatID() &&
93*8975f5c5SAndroid Build Coastguard Worker            actualFormatID == image.getActualFormatID();
94*8975f5c5SAndroid Build Coastguard Worker }
95*8975f5c5SAndroid Build Coastguard Worker 
CanCopyWithTransferForTexImage(vk::Renderer * renderer,angle::FormatID srcIntendedFormatID,angle::FormatID srcActualFormatID,VkImageTiling srcTilingMode,angle::FormatID dstIntendedFormatID,angle::FormatID dstActualFormatID,VkImageTiling dstTilingMode,bool isViewportFlipY)96*8975f5c5SAndroid Build Coastguard Worker bool CanCopyWithTransferForTexImage(vk::Renderer *renderer,
97*8975f5c5SAndroid Build Coastguard Worker                                     angle::FormatID srcIntendedFormatID,
98*8975f5c5SAndroid Build Coastguard Worker                                     angle::FormatID srcActualFormatID,
99*8975f5c5SAndroid Build Coastguard Worker                                     VkImageTiling srcTilingMode,
100*8975f5c5SAndroid Build Coastguard Worker                                     angle::FormatID dstIntendedFormatID,
101*8975f5c5SAndroid Build Coastguard Worker                                     angle::FormatID dstActualFormatID,
102*8975f5c5SAndroid Build Coastguard Worker                                     VkImageTiling dstTilingMode,
103*8975f5c5SAndroid Build Coastguard Worker                                     bool isViewportFlipY)
104*8975f5c5SAndroid Build Coastguard Worker {
105*8975f5c5SAndroid Build Coastguard Worker     // For glTex[Sub]Image, only accept same-format transfers.
106*8975f5c5SAndroid Build Coastguard Worker     // There are cases that two images' actual format is the same, but intended formats are
107*8975f5c5SAndroid Build Coastguard Worker     // different due to one is using the fallback format (for example, RGB fallback to RGBA). In
108*8975f5c5SAndroid Build Coastguard Worker     // these situations CanCopyWithTransfer will say yes. But if we use transfer to do copy, the
109*8975f5c5SAndroid Build Coastguard Worker     // alpha channel will be also be copied with source data which is wrong.
110*8975f5c5SAndroid Build Coastguard Worker     bool isFormatCompatible =
111*8975f5c5SAndroid Build Coastguard Worker         srcIntendedFormatID == dstIntendedFormatID && srcActualFormatID == dstActualFormatID;
112*8975f5c5SAndroid Build Coastguard Worker 
113*8975f5c5SAndroid Build Coastguard Worker     return !isViewportFlipY && isFormatCompatible &&
114*8975f5c5SAndroid Build Coastguard Worker            vk::CanCopyWithTransfer(renderer, srcActualFormatID, srcTilingMode, dstActualFormatID,
115*8975f5c5SAndroid Build Coastguard Worker                                    dstTilingMode);
116*8975f5c5SAndroid Build Coastguard Worker }
117*8975f5c5SAndroid Build Coastguard Worker 
CanCopyWithTransferForCopyTexture(vk::Renderer * renderer,const vk::ImageHelper & srcImage,VkImageTiling srcTilingMode,angle::FormatID destIntendedFormatID,angle::FormatID destActualFormatID,VkImageTiling destTilingMode,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha)118*8975f5c5SAndroid Build Coastguard Worker bool CanCopyWithTransferForCopyTexture(vk::Renderer *renderer,
119*8975f5c5SAndroid Build Coastguard Worker                                        const vk::ImageHelper &srcImage,
120*8975f5c5SAndroid Build Coastguard Worker                                        VkImageTiling srcTilingMode,
121*8975f5c5SAndroid Build Coastguard Worker                                        angle::FormatID destIntendedFormatID,
122*8975f5c5SAndroid Build Coastguard Worker                                        angle::FormatID destActualFormatID,
123*8975f5c5SAndroid Build Coastguard Worker                                        VkImageTiling destTilingMode,
124*8975f5c5SAndroid Build Coastguard Worker                                        bool unpackFlipY,
125*8975f5c5SAndroid Build Coastguard Worker                                        bool unpackPremultiplyAlpha,
126*8975f5c5SAndroid Build Coastguard Worker                                        bool unpackUnmultiplyAlpha)
127*8975f5c5SAndroid Build Coastguard Worker {
128*8975f5c5SAndroid Build Coastguard Worker     if (unpackFlipY || unpackPremultiplyAlpha || unpackUnmultiplyAlpha)
129*8975f5c5SAndroid Build Coastguard Worker     {
130*8975f5c5SAndroid Build Coastguard Worker         return false;
131*8975f5c5SAndroid Build Coastguard Worker     }
132*8975f5c5SAndroid Build Coastguard Worker 
133*8975f5c5SAndroid Build Coastguard Worker     if (!vk::CanCopyWithTransfer(renderer, srcImage.getActualFormatID(), srcTilingMode,
134*8975f5c5SAndroid Build Coastguard Worker                                  destActualFormatID, destTilingMode))
135*8975f5c5SAndroid Build Coastguard Worker     {
136*8975f5c5SAndroid Build Coastguard Worker         return false;
137*8975f5c5SAndroid Build Coastguard Worker     }
138*8975f5c5SAndroid Build Coastguard Worker 
139*8975f5c5SAndroid Build Coastguard Worker     // If the formats are identical, we can always transfer between them.
140*8975f5c5SAndroid Build Coastguard Worker     if (srcImage.getIntendedFormatID() == destIntendedFormatID &&
141*8975f5c5SAndroid Build Coastguard Worker         srcImage.getActualFormatID() == destActualFormatID)
142*8975f5c5SAndroid Build Coastguard Worker     {
143*8975f5c5SAndroid Build Coastguard Worker         return true;
144*8975f5c5SAndroid Build Coastguard Worker     }
145*8975f5c5SAndroid Build Coastguard Worker 
146*8975f5c5SAndroid Build Coastguard Worker     // If either format is emulated, cannot transfer.
147*8975f5c5SAndroid Build Coastguard Worker     if (srcImage.hasEmulatedImageFormat() ||
148*8975f5c5SAndroid Build Coastguard Worker         vk::HasEmulatedImageFormat(destIntendedFormatID, destActualFormatID))
149*8975f5c5SAndroid Build Coastguard Worker     {
150*8975f5c5SAndroid Build Coastguard Worker         return false;
151*8975f5c5SAndroid Build Coastguard Worker     }
152*8975f5c5SAndroid Build Coastguard Worker 
153*8975f5c5SAndroid Build Coastguard Worker     // Otherwise, allow transfer between compatible formats.  This is derived from the specification
154*8975f5c5SAndroid Build Coastguard Worker     // of CHROMIUM_copy_texture.
155*8975f5c5SAndroid Build Coastguard Worker     const angle::Format &srcAngleFormat  = srcImage.getActualFormat();
156*8975f5c5SAndroid Build Coastguard Worker     const angle::Format &destAngleFormat = angle::Format::Get(destActualFormatID);
157*8975f5c5SAndroid Build Coastguard Worker 
158*8975f5c5SAndroid Build Coastguard Worker     const bool srcIsBGRA   = srcAngleFormat.isBGRA();
159*8975f5c5SAndroid Build Coastguard Worker     const bool srcHasR8    = srcAngleFormat.redBits == 8;
160*8975f5c5SAndroid Build Coastguard Worker     const bool srcHasG8    = srcAngleFormat.greenBits == 8;
161*8975f5c5SAndroid Build Coastguard Worker     const bool srcHasB8    = srcAngleFormat.blueBits == 8;
162*8975f5c5SAndroid Build Coastguard Worker     const bool srcHasA8    = srcAngleFormat.alphaBits == 8;
163*8975f5c5SAndroid Build Coastguard Worker     const bool srcIsSigned = srcAngleFormat.isSnorm() || srcAngleFormat.isSint();
164*8975f5c5SAndroid Build Coastguard Worker 
165*8975f5c5SAndroid Build Coastguard Worker     const bool destIsBGRA   = destAngleFormat.isBGRA();
166*8975f5c5SAndroid Build Coastguard Worker     const bool destHasR8    = destAngleFormat.redBits == 8;
167*8975f5c5SAndroid Build Coastguard Worker     const bool destHasG8    = destAngleFormat.greenBits == 8;
168*8975f5c5SAndroid Build Coastguard Worker     const bool destHasB8    = destAngleFormat.blueBits == 8;
169*8975f5c5SAndroid Build Coastguard Worker     const bool destHasA8    = destAngleFormat.alphaBits == 8;
170*8975f5c5SAndroid Build Coastguard Worker     const bool destIsSigned = destAngleFormat.isSnorm() || destAngleFormat.isSint();
171*8975f5c5SAndroid Build Coastguard Worker 
172*8975f5c5SAndroid Build Coastguard Worker     // Copy is allowed as long as they have the same number, ordering and sign of (8-bit) channels.
173*8975f5c5SAndroid Build Coastguard Worker     // CHROMIUM_copy_texture expects verbatim copy between these format, so this copy is done
174*8975f5c5SAndroid Build Coastguard Worker     // regardless of sRGB, normalized, etc.
175*8975f5c5SAndroid Build Coastguard Worker     return srcIsBGRA == destIsBGRA && srcHasR8 == destHasR8 && srcHasG8 == destHasG8 &&
176*8975f5c5SAndroid Build Coastguard Worker            srcHasB8 == destHasB8 && srcHasA8 == destHasA8 && srcIsSigned == destIsSigned;
177*8975f5c5SAndroid Build Coastguard Worker }
178*8975f5c5SAndroid Build Coastguard Worker 
CanCopyWithDraw(vk::Renderer * renderer,const angle::FormatID srcFormatID,VkImageTiling srcTilingMode,const angle::FormatID dstFormatID,VkImageTiling destTilingMode)179*8975f5c5SAndroid Build Coastguard Worker bool CanCopyWithDraw(vk::Renderer *renderer,
180*8975f5c5SAndroid Build Coastguard Worker                      const angle::FormatID srcFormatID,
181*8975f5c5SAndroid Build Coastguard Worker                      VkImageTiling srcTilingMode,
182*8975f5c5SAndroid Build Coastguard Worker                      const angle::FormatID dstFormatID,
183*8975f5c5SAndroid Build Coastguard Worker                      VkImageTiling destTilingMode)
184*8975f5c5SAndroid Build Coastguard Worker {
185*8975f5c5SAndroid Build Coastguard Worker     // Checks that the formats in copy by drawing have the appropriate feature bits
186*8975f5c5SAndroid Build Coastguard Worker     bool srcFormatHasNecessaryFeature = vk::FormatHasNecessaryFeature(
187*8975f5c5SAndroid Build Coastguard Worker         renderer, srcFormatID, srcTilingMode, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
188*8975f5c5SAndroid Build Coastguard Worker     bool dstFormatHasNecessaryFeature = vk::FormatHasNecessaryFeature(
189*8975f5c5SAndroid Build Coastguard Worker         renderer, dstFormatID, destTilingMode, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
190*8975f5c5SAndroid Build Coastguard Worker 
191*8975f5c5SAndroid Build Coastguard Worker     return srcFormatHasNecessaryFeature && dstFormatHasNecessaryFeature;
192*8975f5c5SAndroid Build Coastguard Worker }
193*8975f5c5SAndroid Build Coastguard Worker 
CanGenerateMipmapWithCompute(vk::Renderer * renderer,VkImageType imageType,angle::FormatID formatID,GLint samples,bool canBeRespecified)194*8975f5c5SAndroid Build Coastguard Worker bool CanGenerateMipmapWithCompute(vk::Renderer *renderer,
195*8975f5c5SAndroid Build Coastguard Worker                                   VkImageType imageType,
196*8975f5c5SAndroid Build Coastguard Worker                                   angle::FormatID formatID,
197*8975f5c5SAndroid Build Coastguard Worker                                   GLint samples,
198*8975f5c5SAndroid Build Coastguard Worker                                   bool canBeRespecified)
199*8975f5c5SAndroid Build Coastguard Worker {
200*8975f5c5SAndroid Build Coastguard Worker     // Feature needs to be enabled
201*8975f5c5SAndroid Build Coastguard Worker     if (!renderer->getFeatures().allowGenerateMipmapWithCompute.enabled)
202*8975f5c5SAndroid Build Coastguard Worker     {
203*8975f5c5SAndroid Build Coastguard Worker         return false;
204*8975f5c5SAndroid Build Coastguard Worker     }
205*8975f5c5SAndroid Build Coastguard Worker 
206*8975f5c5SAndroid Build Coastguard Worker     // We need to be able to respecify the backing image
207*8975f5c5SAndroid Build Coastguard Worker     if (!canBeRespecified)
208*8975f5c5SAndroid Build Coastguard Worker     {
209*8975f5c5SAndroid Build Coastguard Worker         return false;
210*8975f5c5SAndroid Build Coastguard Worker     }
211*8975f5c5SAndroid Build Coastguard Worker 
212*8975f5c5SAndroid Build Coastguard Worker     const angle::Format &angleFormat = angle::Format::Get(formatID);
213*8975f5c5SAndroid Build Coastguard Worker     // Format must have STORAGE support.
214*8975f5c5SAndroid Build Coastguard Worker     const bool hasStorageSupport =
215*8975f5c5SAndroid Build Coastguard Worker         renderer->hasImageFormatFeatureBits(formatID, VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT);
216*8975f5c5SAndroid Build Coastguard Worker 
217*8975f5c5SAndroid Build Coastguard Worker     // No support for sRGB formats yet.
218*8975f5c5SAndroid Build Coastguard Worker     const bool isSRGB = angleFormat.isSRGB;
219*8975f5c5SAndroid Build Coastguard Worker 
220*8975f5c5SAndroid Build Coastguard Worker     // No support for integer formats yet.
221*8975f5c5SAndroid Build Coastguard Worker     const bool isInt = angleFormat.isInt();
222*8975f5c5SAndroid Build Coastguard Worker 
223*8975f5c5SAndroid Build Coastguard Worker     // Only 2D images are supported.
224*8975f5c5SAndroid Build Coastguard Worker     const bool is2D = imageType == VK_IMAGE_TYPE_2D;
225*8975f5c5SAndroid Build Coastguard Worker 
226*8975f5c5SAndroid Build Coastguard Worker     // No support for multisampled images yet.
227*8975f5c5SAndroid Build Coastguard Worker     const bool isMultisampled = samples > 1;
228*8975f5c5SAndroid Build Coastguard Worker 
229*8975f5c5SAndroid Build Coastguard Worker     // Only color formats are supported.
230*8975f5c5SAndroid Build Coastguard Worker     const bool isColorFormat = !angleFormat.hasDepthOrStencilBits();
231*8975f5c5SAndroid Build Coastguard Worker 
232*8975f5c5SAndroid Build Coastguard Worker     return hasStorageSupport && !isSRGB && !isInt && is2D && !isMultisampled && isColorFormat;
233*8975f5c5SAndroid Build Coastguard Worker }
234*8975f5c5SAndroid Build Coastguard Worker 
GetRenderTargetLayerCountAndIndex(vk::ImageHelper * image,const gl::ImageIndex & index,GLuint * layerIndex,GLuint * layerCount,GLuint * imageLayerCount)235*8975f5c5SAndroid Build Coastguard Worker void GetRenderTargetLayerCountAndIndex(vk::ImageHelper *image,
236*8975f5c5SAndroid Build Coastguard Worker                                        const gl::ImageIndex &index,
237*8975f5c5SAndroid Build Coastguard Worker                                        GLuint *layerIndex,
238*8975f5c5SAndroid Build Coastguard Worker                                        GLuint *layerCount,
239*8975f5c5SAndroid Build Coastguard Worker                                        GLuint *imageLayerCount)
240*8975f5c5SAndroid Build Coastguard Worker {
241*8975f5c5SAndroid Build Coastguard Worker     *layerIndex = index.hasLayer() ? index.getLayerIndex() : 0;
242*8975f5c5SAndroid Build Coastguard Worker     *layerCount = index.getLayerCount();
243*8975f5c5SAndroid Build Coastguard Worker 
244*8975f5c5SAndroid Build Coastguard Worker     switch (index.getType())
245*8975f5c5SAndroid Build Coastguard Worker     {
246*8975f5c5SAndroid Build Coastguard Worker         case gl::TextureType::_2D:
247*8975f5c5SAndroid Build Coastguard Worker         case gl::TextureType::_2DMultisample:
248*8975f5c5SAndroid Build Coastguard Worker         case gl::TextureType::External:
249*8975f5c5SAndroid Build Coastguard Worker             ASSERT(*layerIndex == 0 &&
250*8975f5c5SAndroid Build Coastguard Worker                    (*layerCount == 1 ||
251*8975f5c5SAndroid Build Coastguard Worker                     *layerCount == static_cast<GLuint>(gl::ImageIndex::kEntireLevel)));
252*8975f5c5SAndroid Build Coastguard Worker             *imageLayerCount = 1;
253*8975f5c5SAndroid Build Coastguard Worker             break;
254*8975f5c5SAndroid Build Coastguard Worker 
255*8975f5c5SAndroid Build Coastguard Worker         case gl::TextureType::CubeMap:
256*8975f5c5SAndroid Build Coastguard Worker             ASSERT(!index.hasLayer() ||
257*8975f5c5SAndroid Build Coastguard Worker                    *layerIndex == static_cast<GLuint>(index.cubeMapFaceIndex()));
258*8975f5c5SAndroid Build Coastguard Worker             *imageLayerCount = gl::kCubeFaceCount;
259*8975f5c5SAndroid Build Coastguard Worker             break;
260*8975f5c5SAndroid Build Coastguard Worker 
261*8975f5c5SAndroid Build Coastguard Worker         case gl::TextureType::_3D:
262*8975f5c5SAndroid Build Coastguard Worker         {
263*8975f5c5SAndroid Build Coastguard Worker             gl::LevelIndex levelGL(index.getLevelIndex());
264*8975f5c5SAndroid Build Coastguard Worker             *imageLayerCount = image->getLevelExtents(image->toVkLevel(levelGL)).depth;
265*8975f5c5SAndroid Build Coastguard Worker             break;
266*8975f5c5SAndroid Build Coastguard Worker         }
267*8975f5c5SAndroid Build Coastguard Worker 
268*8975f5c5SAndroid Build Coastguard Worker         case gl::TextureType::_2DArray:
269*8975f5c5SAndroid Build Coastguard Worker         case gl::TextureType::_2DMultisampleArray:
270*8975f5c5SAndroid Build Coastguard Worker         case gl::TextureType::CubeMapArray:
271*8975f5c5SAndroid Build Coastguard Worker             *imageLayerCount = image->getLayerCount();
272*8975f5c5SAndroid Build Coastguard Worker             break;
273*8975f5c5SAndroid Build Coastguard Worker 
274*8975f5c5SAndroid Build Coastguard Worker         default:
275*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
276*8975f5c5SAndroid Build Coastguard Worker     }
277*8975f5c5SAndroid Build Coastguard Worker 
278*8975f5c5SAndroid Build Coastguard Worker     if (*layerCount == static_cast<GLuint>(gl::ImageIndex::kEntireLevel))
279*8975f5c5SAndroid Build Coastguard Worker     {
280*8975f5c5SAndroid Build Coastguard Worker         ASSERT(*layerIndex == 0);
281*8975f5c5SAndroid Build Coastguard Worker         *layerCount = *imageLayerCount;
282*8975f5c5SAndroid Build Coastguard Worker     }
283*8975f5c5SAndroid Build Coastguard Worker }
284*8975f5c5SAndroid Build Coastguard Worker 
Set3DBaseArrayLayerAndLayerCount(VkImageSubresourceLayers * Subresource)285*8975f5c5SAndroid Build Coastguard Worker void Set3DBaseArrayLayerAndLayerCount(VkImageSubresourceLayers *Subresource)
286*8975f5c5SAndroid Build Coastguard Worker {
287*8975f5c5SAndroid Build Coastguard Worker     // If the srcImage/dstImage parameters are of VkImageType VK_IMAGE_TYPE_3D, the baseArrayLayer
288*8975f5c5SAndroid Build Coastguard Worker     // and layerCount members of the corresponding subresource must be 0 and 1, respectively.
289*8975f5c5SAndroid Build Coastguard Worker     Subresource->baseArrayLayer = 0;
290*8975f5c5SAndroid Build Coastguard Worker     Subresource->layerCount     = 1;
291*8975f5c5SAndroid Build Coastguard Worker }
292*8975f5c5SAndroid Build Coastguard Worker 
AdjustStorageViewFormatPerWorkarounds(vk::Renderer * renderer,const vk::Format * intended,vk::ImageAccess access)293*8975f5c5SAndroid Build Coastguard Worker const vk::Format *AdjustStorageViewFormatPerWorkarounds(vk::Renderer *renderer,
294*8975f5c5SAndroid Build Coastguard Worker                                                         const vk::Format *intended,
295*8975f5c5SAndroid Build Coastguard Worker                                                         vk::ImageAccess access)
296*8975f5c5SAndroid Build Coastguard Worker {
297*8975f5c5SAndroid Build Coastguard Worker     // r32f images are emulated with r32ui.
298*8975f5c5SAndroid Build Coastguard Worker     if (renderer->getFeatures().emulateR32fImageAtomicExchange.enabled &&
299*8975f5c5SAndroid Build Coastguard Worker         intended->getActualImageFormatID(access) == angle::FormatID::R32_FLOAT)
300*8975f5c5SAndroid Build Coastguard Worker     {
301*8975f5c5SAndroid Build Coastguard Worker         return &renderer->getFormat(angle::FormatID::R32_UINT);
302*8975f5c5SAndroid Build Coastguard Worker     }
303*8975f5c5SAndroid Build Coastguard Worker 
304*8975f5c5SAndroid Build Coastguard Worker     return intended;
305*8975f5c5SAndroid Build Coastguard Worker }
306*8975f5c5SAndroid Build Coastguard Worker 
AdjustViewFormatForSampler(vk::Renderer * renderer,const vk::Format * intended,gl::SamplerFormat samplerFormat)307*8975f5c5SAndroid Build Coastguard Worker const vk::Format *AdjustViewFormatForSampler(vk::Renderer *renderer,
308*8975f5c5SAndroid Build Coastguard Worker                                              const vk::Format *intended,
309*8975f5c5SAndroid Build Coastguard Worker                                              gl::SamplerFormat samplerFormat)
310*8975f5c5SAndroid Build Coastguard Worker {
311*8975f5c5SAndroid Build Coastguard Worker     switch (samplerFormat)
312*8975f5c5SAndroid Build Coastguard Worker     {
313*8975f5c5SAndroid Build Coastguard Worker         case gl::SamplerFormat::Float:
314*8975f5c5SAndroid Build Coastguard Worker             switch (intended->getIntendedFormatID())
315*8975f5c5SAndroid Build Coastguard Worker             {
316*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8_UNORM:
317*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16_FLOAT:
318*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32_FLOAT:
319*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8G8_UNORM:
320*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16G16_FLOAT:
321*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32_FLOAT:
322*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32B32_FLOAT:
323*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8G8B8A8_UNORM:
324*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16G16B16A16_FLOAT:
325*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32B32A32_FLOAT:
326*8975f5c5SAndroid Build Coastguard Worker                     return intended;
327*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8_SINT:
328*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8_UINT:
329*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R8_UNORM);
330*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16_SINT:
331*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16_UINT:
332*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R16_FLOAT);
333*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32_SINT:
334*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32_UINT:
335*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R32_FLOAT);
336*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8G8_SINT:
337*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8G8_UINT:
338*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R8G8_UNORM);
339*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16G16_SINT:
340*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16G16_UINT:
341*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R16G16_FLOAT);
342*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32_SINT:
343*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32_UINT:
344*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R32G32_FLOAT);
345*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32B32_SINT:
346*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32B32_UINT:
347*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R32G32B32_FLOAT);
348*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8G8B8A8_SINT:
349*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8G8B8A8_UINT:
350*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R8G8B8A8_UNORM);
351*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16G16B16A16_SINT:
352*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16G16B16A16_UINT:
353*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R16G16B16A16_FLOAT);
354*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32B32A32_SINT:
355*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32B32A32_UINT:
356*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R32G32B32A32_FLOAT);
357*8975f5c5SAndroid Build Coastguard Worker                 default:
358*8975f5c5SAndroid Build Coastguard Worker                     UNREACHABLE();
359*8975f5c5SAndroid Build Coastguard Worker                     return intended;
360*8975f5c5SAndroid Build Coastguard Worker             }
361*8975f5c5SAndroid Build Coastguard Worker         case gl::SamplerFormat::Unsigned:
362*8975f5c5SAndroid Build Coastguard Worker             switch (intended->getIntendedFormatID())
363*8975f5c5SAndroid Build Coastguard Worker             {
364*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8_UINT:
365*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16_UINT:
366*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32_UINT:
367*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8G8_UINT:
368*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16G16_UINT:
369*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32_UINT:
370*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32B32_UINT:
371*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8G8B8A8_UINT:
372*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16G16B16A16_UINT:
373*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32B32A32_UINT:
374*8975f5c5SAndroid Build Coastguard Worker                     return intended;
375*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8_UNORM:
376*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8_SINT:
377*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R8_UINT);
378*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16_FLOAT:
379*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16_SINT:
380*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R16_UINT);
381*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32_FLOAT:
382*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32_SINT:
383*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R32_UINT);
384*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8G8_UNORM:
385*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8G8_SINT:
386*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R8G8_UINT);
387*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16G16_FLOAT:
388*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16G16_SINT:
389*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R16G16_UINT);
390*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32_FLOAT:
391*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32_SINT:
392*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R32G32_UINT);
393*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32B32_FLOAT:
394*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32B32_SINT:
395*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R32G32B32_UINT);
396*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8G8B8A8_UNORM:
397*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8G8B8A8_SINT:
398*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R8G8B8A8_UINT);
399*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16G16B16A16_FLOAT:
400*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16G16B16A16_SINT:
401*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R16G16B16A16_UINT);
402*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32B32A32_FLOAT:
403*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32B32A32_SINT:
404*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R32G32B32A32_UINT);
405*8975f5c5SAndroid Build Coastguard Worker                 default:
406*8975f5c5SAndroid Build Coastguard Worker                     UNREACHABLE();
407*8975f5c5SAndroid Build Coastguard Worker                     return intended;
408*8975f5c5SAndroid Build Coastguard Worker             }
409*8975f5c5SAndroid Build Coastguard Worker         case gl::SamplerFormat::Signed:
410*8975f5c5SAndroid Build Coastguard Worker             switch (intended->getIntendedFormatID())
411*8975f5c5SAndroid Build Coastguard Worker             {
412*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8_SINT:
413*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16_SINT:
414*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32_SINT:
415*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8G8_SINT:
416*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16G16_SINT:
417*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32_SINT:
418*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32B32_SINT:
419*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8G8B8A8_SINT:
420*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16G16B16A16_SINT:
421*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32B32A32_SINT:
422*8975f5c5SAndroid Build Coastguard Worker                     return intended;
423*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8_UNORM:
424*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8_UINT:
425*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R8_SINT);
426*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16_FLOAT:
427*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16_UINT:
428*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R16_SINT);
429*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32_FLOAT:
430*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32_UINT:
431*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R32_SINT);
432*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8G8_UNORM:
433*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8G8_UINT:
434*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R8G8_SINT);
435*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16G16_FLOAT:
436*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16G16_UINT:
437*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R16G16_SINT);
438*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32_FLOAT:
439*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32_UINT:
440*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R32G32_SINT);
441*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32B32_FLOAT:
442*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32B32_UINT:
443*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R32G32B32_SINT);
444*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8G8B8A8_UNORM:
445*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R8G8B8A8_UINT:
446*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R8G8B8A8_SINT);
447*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16G16B16A16_FLOAT:
448*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R16G16B16A16_UINT:
449*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R16G16B16A16_SINT);
450*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32B32A32_FLOAT:
451*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R32G32B32A32_UINT:
452*8975f5c5SAndroid Build Coastguard Worker                     return &renderer->getFormat(angle::FormatID::R32G32B32A32_SINT);
453*8975f5c5SAndroid Build Coastguard Worker                 default:
454*8975f5c5SAndroid Build Coastguard Worker                     UNREACHABLE();
455*8975f5c5SAndroid Build Coastguard Worker                     return intended;
456*8975f5c5SAndroid Build Coastguard Worker             }
457*8975f5c5SAndroid Build Coastguard Worker         default:
458*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
459*8975f5c5SAndroid Build Coastguard Worker             return intended;
460*8975f5c5SAndroid Build Coastguard Worker     }
461*8975f5c5SAndroid Build Coastguard Worker }
462*8975f5c5SAndroid Build Coastguard Worker 
GetRGBAEmulationDstFormat(angle::FormatID srcFormatID)463*8975f5c5SAndroid Build Coastguard Worker angle::FormatID GetRGBAEmulationDstFormat(angle::FormatID srcFormatID)
464*8975f5c5SAndroid Build Coastguard Worker {
465*8975f5c5SAndroid Build Coastguard Worker     switch (srcFormatID)
466*8975f5c5SAndroid Build Coastguard Worker     {
467*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::R32G32B32_UINT:
468*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::R32G32B32A32_UINT;
469*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::R32G32B32_SINT:
470*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::R32G32B32A32_SINT;
471*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::R32G32B32_FLOAT:
472*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::R32G32B32A32_FLOAT;
473*8975f5c5SAndroid Build Coastguard Worker         default:
474*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::NONE;
475*8975f5c5SAndroid Build Coastguard Worker     }
476*8975f5c5SAndroid Build Coastguard Worker }
477*8975f5c5SAndroid Build Coastguard Worker 
NeedsRGBAEmulation(vk::Renderer * renderer,angle::FormatID formatID)478*8975f5c5SAndroid Build Coastguard Worker bool NeedsRGBAEmulation(vk::Renderer *renderer, angle::FormatID formatID)
479*8975f5c5SAndroid Build Coastguard Worker {
480*8975f5c5SAndroid Build Coastguard Worker     if (renderer->hasBufferFormatFeatureBits(formatID, VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))
481*8975f5c5SAndroid Build Coastguard Worker     {
482*8975f5c5SAndroid Build Coastguard Worker         return false;
483*8975f5c5SAndroid Build Coastguard Worker     }
484*8975f5c5SAndroid Build Coastguard Worker     // Vulkan driver support is required for all formats except the ones we emulate.
485*8975f5c5SAndroid Build Coastguard Worker     ASSERT(GetRGBAEmulationDstFormat(formatID) != angle::FormatID::NONE);
486*8975f5c5SAndroid Build Coastguard Worker     return true;
487*8975f5c5SAndroid Build Coastguard Worker }
488*8975f5c5SAndroid Build Coastguard Worker 
489*8975f5c5SAndroid Build Coastguard Worker }  // anonymous namespace
490*8975f5c5SAndroid Build Coastguard Worker 
491*8975f5c5SAndroid Build Coastguard Worker // TextureVk implementation.
TextureVk(const gl::TextureState & state,vk::Renderer * renderer)492*8975f5c5SAndroid Build Coastguard Worker TextureVk::TextureVk(const gl::TextureState &state, vk::Renderer *renderer)
493*8975f5c5SAndroid Build Coastguard Worker     : TextureImpl(state),
494*8975f5c5SAndroid Build Coastguard Worker       mOwnsImage(false),
495*8975f5c5SAndroid Build Coastguard Worker       mRequiresMutableStorage(false),
496*8975f5c5SAndroid Build Coastguard Worker       mRequiredImageAccess(vk::ImageAccess::SampleOnly),
497*8975f5c5SAndroid Build Coastguard Worker       mImmutableSamplerDirty(false),
498*8975f5c5SAndroid Build Coastguard Worker       mEGLImageNativeType(gl::TextureType::InvalidEnum),
499*8975f5c5SAndroid Build Coastguard Worker       mEGLImageLayerOffset(0),
500*8975f5c5SAndroid Build Coastguard Worker       mEGLImageLevelOffset(0),
501*8975f5c5SAndroid Build Coastguard Worker       mImage(nullptr),
502*8975f5c5SAndroid Build Coastguard Worker       mImageUsageFlags(0),
503*8975f5c5SAndroid Build Coastguard Worker       mImageCreateFlags(0),
504*8975f5c5SAndroid Build Coastguard Worker       mImageObserverBinding(this, kTextureImageSubjectIndex),
505*8975f5c5SAndroid Build Coastguard Worker       mCurrentBaseLevel(state.getBaseLevel()),
506*8975f5c5SAndroid Build Coastguard Worker       mCurrentMaxLevel(state.getMaxLevel()),
507*8975f5c5SAndroid Build Coastguard Worker       mCachedImageViewSubresourceSerialSRGBDecode{},
508*8975f5c5SAndroid Build Coastguard Worker       mCachedImageViewSubresourceSerialSkipDecode{}
509*8975f5c5SAndroid Build Coastguard Worker {}
510*8975f5c5SAndroid Build Coastguard Worker 
511*8975f5c5SAndroid Build Coastguard Worker TextureVk::~TextureVk() = default;
512*8975f5c5SAndroid Build Coastguard Worker 
onDestroy(const gl::Context * context)513*8975f5c5SAndroid Build Coastguard Worker void TextureVk::onDestroy(const gl::Context *context)
514*8975f5c5SAndroid Build Coastguard Worker {
515*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
516*8975f5c5SAndroid Build Coastguard Worker 
517*8975f5c5SAndroid Build Coastguard Worker     releaseAndDeleteImageAndViews(contextVk);
518*8975f5c5SAndroid Build Coastguard Worker     resetSampler();
519*8975f5c5SAndroid Build Coastguard Worker }
520*8975f5c5SAndroid Build Coastguard Worker 
setImage(const gl::Context * context,const gl::ImageIndex & index,GLenum internalFormat,const gl::Extents & size,GLenum format,GLenum type,const gl::PixelUnpackState & unpack,gl::Buffer * unpackBuffer,const uint8_t * pixels)521*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setImage(const gl::Context *context,
522*8975f5c5SAndroid Build Coastguard Worker                                   const gl::ImageIndex &index,
523*8975f5c5SAndroid Build Coastguard Worker                                   GLenum internalFormat,
524*8975f5c5SAndroid Build Coastguard Worker                                   const gl::Extents &size,
525*8975f5c5SAndroid Build Coastguard Worker                                   GLenum format,
526*8975f5c5SAndroid Build Coastguard Worker                                   GLenum type,
527*8975f5c5SAndroid Build Coastguard Worker                                   const gl::PixelUnpackState &unpack,
528*8975f5c5SAndroid Build Coastguard Worker                                   gl::Buffer *unpackBuffer,
529*8975f5c5SAndroid Build Coastguard Worker                                   const uint8_t *pixels)
530*8975f5c5SAndroid Build Coastguard Worker {
531*8975f5c5SAndroid Build Coastguard Worker     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
532*8975f5c5SAndroid Build Coastguard Worker 
533*8975f5c5SAndroid Build Coastguard Worker     return setImageImpl(context, index, formatInfo, size, type, unpack, unpackBuffer, pixels);
534*8975f5c5SAndroid Build Coastguard Worker }
535*8975f5c5SAndroid Build Coastguard Worker 
setSubImage(const gl::Context * context,const gl::ImageIndex & index,const gl::Box & area,GLenum format,GLenum type,const gl::PixelUnpackState & unpack,gl::Buffer * unpackBuffer,const uint8_t * pixels)536*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setSubImage(const gl::Context *context,
537*8975f5c5SAndroid Build Coastguard Worker                                      const gl::ImageIndex &index,
538*8975f5c5SAndroid Build Coastguard Worker                                      const gl::Box &area,
539*8975f5c5SAndroid Build Coastguard Worker                                      GLenum format,
540*8975f5c5SAndroid Build Coastguard Worker                                      GLenum type,
541*8975f5c5SAndroid Build Coastguard Worker                                      const gl::PixelUnpackState &unpack,
542*8975f5c5SAndroid Build Coastguard Worker                                      gl::Buffer *unpackBuffer,
543*8975f5c5SAndroid Build Coastguard Worker                                      const uint8_t *pixels)
544*8975f5c5SAndroid Build Coastguard Worker {
545*8975f5c5SAndroid Build Coastguard Worker     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
546*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk                 = vk::GetImpl(context);
547*8975f5c5SAndroid Build Coastguard Worker     const gl::ImageDesc &levelDesc       = mState.getImageDesc(index);
548*8975f5c5SAndroid Build Coastguard Worker     const vk::Format &vkFormat =
549*8975f5c5SAndroid Build Coastguard Worker         contextVk->getRenderer()->getFormat(levelDesc.format.info->sizedInternalFormat);
550*8975f5c5SAndroid Build Coastguard Worker 
551*8975f5c5SAndroid Build Coastguard Worker     return setSubImageImpl(context, index, area, formatInfo, type, unpack, unpackBuffer, pixels,
552*8975f5c5SAndroid Build Coastguard Worker                            vkFormat);
553*8975f5c5SAndroid Build Coastguard Worker }
554*8975f5c5SAndroid Build Coastguard Worker 
isCompressedFormatEmulated(const gl::Context * context,gl::TextureTarget target,GLint level)555*8975f5c5SAndroid Build Coastguard Worker bool TextureVk::isCompressedFormatEmulated(const gl::Context *context,
556*8975f5c5SAndroid Build Coastguard Worker                                            gl::TextureTarget target,
557*8975f5c5SAndroid Build Coastguard Worker                                            GLint level)
558*8975f5c5SAndroid Build Coastguard Worker {
559*8975f5c5SAndroid Build Coastguard Worker     const gl::ImageDesc &levelDesc = mState.getImageDesc(target, level);
560*8975f5c5SAndroid Build Coastguard Worker     if (!levelDesc.format.info->compressed)
561*8975f5c5SAndroid Build Coastguard Worker     {
562*8975f5c5SAndroid Build Coastguard Worker         // If it isn't compressed, the remaining logic won't work
563*8975f5c5SAndroid Build Coastguard Worker         return false;
564*8975f5c5SAndroid Build Coastguard Worker     }
565*8975f5c5SAndroid Build Coastguard Worker 
566*8975f5c5SAndroid Build Coastguard Worker     // Check against the list of formats used to emulate compressed textures
567*8975f5c5SAndroid Build Coastguard Worker     return gl::IsEmulatedCompressedFormat(levelDesc.format.info->sizedInternalFormat);
568*8975f5c5SAndroid Build Coastguard Worker }
569*8975f5c5SAndroid Build Coastguard Worker 
setCompressedImage(const gl::Context * context,const gl::ImageIndex & index,GLenum internalFormat,const gl::Extents & size,const gl::PixelUnpackState & unpack,size_t imageSize,const uint8_t * pixels)570*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setCompressedImage(const gl::Context *context,
571*8975f5c5SAndroid Build Coastguard Worker                                             const gl::ImageIndex &index,
572*8975f5c5SAndroid Build Coastguard Worker                                             GLenum internalFormat,
573*8975f5c5SAndroid Build Coastguard Worker                                             const gl::Extents &size,
574*8975f5c5SAndroid Build Coastguard Worker                                             const gl::PixelUnpackState &unpack,
575*8975f5c5SAndroid Build Coastguard Worker                                             size_t imageSize,
576*8975f5c5SAndroid Build Coastguard Worker                                             const uint8_t *pixels)
577*8975f5c5SAndroid Build Coastguard Worker {
578*8975f5c5SAndroid Build Coastguard Worker     const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
579*8975f5c5SAndroid Build Coastguard Worker 
580*8975f5c5SAndroid Build Coastguard Worker     const gl::State &glState = context->getState();
581*8975f5c5SAndroid Build Coastguard Worker     gl::Buffer *unpackBuffer = glState.getTargetBuffer(gl::BufferBinding::PixelUnpack);
582*8975f5c5SAndroid Build Coastguard Worker 
583*8975f5c5SAndroid Build Coastguard Worker     if (unpackBuffer &&
584*8975f5c5SAndroid Build Coastguard Worker         this->isCompressedFormatEmulated(context, index.getTarget(), index.getLevelIndex()))
585*8975f5c5SAndroid Build Coastguard Worker     {
586*8975f5c5SAndroid Build Coastguard Worker         // TODO (anglebug.com/42265933): Can't populate from a buffer using emulated format
587*8975f5c5SAndroid Build Coastguard Worker         UNIMPLEMENTED();
588*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Stop;
589*8975f5c5SAndroid Build Coastguard Worker     }
590*8975f5c5SAndroid Build Coastguard Worker 
591*8975f5c5SAndroid Build Coastguard Worker     return setImageImpl(context, index, formatInfo, size, GL_UNSIGNED_BYTE, unpack, unpackBuffer,
592*8975f5c5SAndroid Build Coastguard Worker                         pixels);
593*8975f5c5SAndroid Build Coastguard Worker }
594*8975f5c5SAndroid Build Coastguard Worker 
setCompressedSubImage(const gl::Context * context,const gl::ImageIndex & index,const gl::Box & area,GLenum format,const gl::PixelUnpackState & unpack,size_t imageSize,const uint8_t * pixels)595*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setCompressedSubImage(const gl::Context *context,
596*8975f5c5SAndroid Build Coastguard Worker                                                const gl::ImageIndex &index,
597*8975f5c5SAndroid Build Coastguard Worker                                                const gl::Box &area,
598*8975f5c5SAndroid Build Coastguard Worker                                                GLenum format,
599*8975f5c5SAndroid Build Coastguard Worker                                                const gl::PixelUnpackState &unpack,
600*8975f5c5SAndroid Build Coastguard Worker                                                size_t imageSize,
601*8975f5c5SAndroid Build Coastguard Worker                                                const uint8_t *pixels)
602*8975f5c5SAndroid Build Coastguard Worker {
603*8975f5c5SAndroid Build Coastguard Worker 
604*8975f5c5SAndroid Build Coastguard Worker     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, GL_UNSIGNED_BYTE);
605*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk                 = vk::GetImpl(context);
606*8975f5c5SAndroid Build Coastguard Worker     const gl::ImageDesc &levelDesc       = mState.getImageDesc(index);
607*8975f5c5SAndroid Build Coastguard Worker     const vk::Format &vkFormat =
608*8975f5c5SAndroid Build Coastguard Worker         contextVk->getRenderer()->getFormat(levelDesc.format.info->sizedInternalFormat);
609*8975f5c5SAndroid Build Coastguard Worker     const gl::State &glState = contextVk->getState();
610*8975f5c5SAndroid Build Coastguard Worker     gl::Buffer *unpackBuffer = glState.getTargetBuffer(gl::BufferBinding::PixelUnpack);
611*8975f5c5SAndroid Build Coastguard Worker 
612*8975f5c5SAndroid Build Coastguard Worker     if (unpackBuffer &&
613*8975f5c5SAndroid Build Coastguard Worker         this->isCompressedFormatEmulated(context, index.getTarget(), index.getLevelIndex()))
614*8975f5c5SAndroid Build Coastguard Worker     {
615*8975f5c5SAndroid Build Coastguard Worker         // TODO (anglebug.com/42265933): Can't populate from a buffer using emulated format
616*8975f5c5SAndroid Build Coastguard Worker         UNIMPLEMENTED();
617*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Stop;
618*8975f5c5SAndroid Build Coastguard Worker     }
619*8975f5c5SAndroid Build Coastguard Worker 
620*8975f5c5SAndroid Build Coastguard Worker     return setSubImageImpl(context, index, area, formatInfo, GL_UNSIGNED_BYTE, unpack, unpackBuffer,
621*8975f5c5SAndroid Build Coastguard Worker                            pixels, vkFormat);
622*8975f5c5SAndroid Build Coastguard Worker }
623*8975f5c5SAndroid Build Coastguard Worker 
setImageImpl(const gl::Context * context,const gl::ImageIndex & index,const gl::InternalFormat & formatInfo,const gl::Extents & size,GLenum type,const gl::PixelUnpackState & unpack,gl::Buffer * unpackBuffer,const uint8_t * pixels)624*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setImageImpl(const gl::Context *context,
625*8975f5c5SAndroid Build Coastguard Worker                                       const gl::ImageIndex &index,
626*8975f5c5SAndroid Build Coastguard Worker                                       const gl::InternalFormat &formatInfo,
627*8975f5c5SAndroid Build Coastguard Worker                                       const gl::Extents &size,
628*8975f5c5SAndroid Build Coastguard Worker                                       GLenum type,
629*8975f5c5SAndroid Build Coastguard Worker                                       const gl::PixelUnpackState &unpack,
630*8975f5c5SAndroid Build Coastguard Worker                                       gl::Buffer *unpackBuffer,
631*8975f5c5SAndroid Build Coastguard Worker                                       const uint8_t *pixels)
632*8975f5c5SAndroid Build Coastguard Worker {
633*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk   = vk::GetImpl(context);
634*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
635*8975f5c5SAndroid Build Coastguard Worker 
636*8975f5c5SAndroid Build Coastguard Worker     const vk::Format &vkFormat = renderer->getFormat(formatInfo.sizedInternalFormat);
637*8975f5c5SAndroid Build Coastguard Worker 
638*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(redefineLevel(context, index, vkFormat, size));
639*8975f5c5SAndroid Build Coastguard Worker 
640*8975f5c5SAndroid Build Coastguard Worker     // Early-out on empty textures, don't create a zero-sized storage.
641*8975f5c5SAndroid Build Coastguard Worker     if (size.empty())
642*8975f5c5SAndroid Build Coastguard Worker     {
643*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
644*8975f5c5SAndroid Build Coastguard Worker     }
645*8975f5c5SAndroid Build Coastguard Worker 
646*8975f5c5SAndroid Build Coastguard Worker     return setSubImageImpl(context, index, gl::Box(gl::kOffsetZero, size), formatInfo, type, unpack,
647*8975f5c5SAndroid Build Coastguard Worker                            unpackBuffer, pixels, vkFormat);
648*8975f5c5SAndroid Build Coastguard Worker }
649*8975f5c5SAndroid Build Coastguard Worker 
isFastUnpackPossible(const vk::Format & vkFormat,size_t offset,const vk::Format & bufferVkFormat) const650*8975f5c5SAndroid Build Coastguard Worker bool TextureVk::isFastUnpackPossible(const vk::Format &vkFormat,
651*8975f5c5SAndroid Build Coastguard Worker                                      size_t offset,
652*8975f5c5SAndroid Build Coastguard Worker                                      const vk::Format &bufferVkFormat) const
653*8975f5c5SAndroid Build Coastguard Worker {
654*8975f5c5SAndroid Build Coastguard Worker     // Conditions to determine if fast unpacking is possible
655*8975f5c5SAndroid Build Coastguard Worker     // 1. Image must be well defined to unpack directly to it
656*8975f5c5SAndroid Build Coastguard Worker     //    TODO(http://anglebug.com/42262852) Create and stage a temp image instead
657*8975f5c5SAndroid Build Coastguard Worker     // 2. Can't perform a fast copy for depth/stencil, except from non-emulated depth or stencil
658*8975f5c5SAndroid Build Coastguard Worker     //    to emulated depth/stencil.  GL requires depth and stencil data to be packed, while Vulkan
659*8975f5c5SAndroid Build Coastguard Worker     //    requires them to be separate.
660*8975f5c5SAndroid Build Coastguard Worker     // 3. Can't perform a fast copy for emulated formats, except from non-emulated depth or stencil
661*8975f5c5SAndroid Build Coastguard Worker     //    to emulated depth/stencil.
662*8975f5c5SAndroid Build Coastguard Worker     // 4. vkCmdCopyBufferToImage requires byte offset to be a multiple of 4.
663*8975f5c5SAndroid Build Coastguard Worker     // 5. Actual texture format and intended buffer format must match for color formats
664*8975f5c5SAndroid Build Coastguard Worker     const angle::Format &bufferFormat = vkFormat.getActualBufferFormat(false);
665*8975f5c5SAndroid Build Coastguard Worker     const bool isCombinedDepthStencil = bufferFormat.hasDepthAndStencilBits();
666*8975f5c5SAndroid Build Coastguard Worker     const bool isDepthXorStencil = bufferFormat.hasDepthOrStencilBits() && !isCombinedDepthStencil;
667*8975f5c5SAndroid Build Coastguard Worker     const bool isCompatibleDepth = vkFormat.getIntendedFormat().depthBits == bufferFormat.depthBits;
668*8975f5c5SAndroid Build Coastguard Worker     const VkDeviceSize imageCopyAlignment =
669*8975f5c5SAndroid Build Coastguard Worker         vk::GetImageCopyBufferAlignment(mImage->getActualFormatID());
670*8975f5c5SAndroid Build Coastguard Worker     const bool formatsMatch = bufferFormat.hasDepthOrStencilBits() ||
671*8975f5c5SAndroid Build Coastguard Worker                               (vkFormat.getActualImageFormatID(getRequiredImageAccess()) ==
672*8975f5c5SAndroid Build Coastguard Worker                                bufferVkFormat.getIntendedFormatID());
673*8975f5c5SAndroid Build Coastguard Worker 
674*8975f5c5SAndroid Build Coastguard Worker     return mImage->valid() && !isCombinedDepthStencil &&
675*8975f5c5SAndroid Build Coastguard Worker            (vkFormat.getIntendedFormatID() ==
676*8975f5c5SAndroid Build Coastguard Worker                 vkFormat.getActualImageFormatID(getRequiredImageAccess()) ||
677*8975f5c5SAndroid Build Coastguard Worker             (isDepthXorStencil && isCompatibleDepth)) &&
678*8975f5c5SAndroid Build Coastguard Worker            (offset % imageCopyAlignment) == 0 && formatsMatch;
679*8975f5c5SAndroid Build Coastguard Worker }
680*8975f5c5SAndroid Build Coastguard Worker 
isMipImageDescDefined(gl::TextureTarget textureTarget,size_t level)681*8975f5c5SAndroid Build Coastguard Worker bool TextureVk::isMipImageDescDefined(gl::TextureTarget textureTarget, size_t level)
682*8975f5c5SAndroid Build Coastguard Worker {
683*8975f5c5SAndroid Build Coastguard Worker     // A defined image should have defined width, height, and format.
684*8975f5c5SAndroid Build Coastguard Worker     gl::ImageDesc imageDesc = mState.getImageDesc(textureTarget, level);
685*8975f5c5SAndroid Build Coastguard Worker     return imageDesc.size.height != 0 && imageDesc.size.width != 0 &&
686*8975f5c5SAndroid Build Coastguard Worker            imageDesc.format.info->format != GL_NONE;
687*8975f5c5SAndroid Build Coastguard Worker }
688*8975f5c5SAndroid Build Coastguard Worker 
isMutableTextureConsistentlySpecifiedForFlush()689*8975f5c5SAndroid Build Coastguard Worker bool TextureVk::isMutableTextureConsistentlySpecifiedForFlush()
690*8975f5c5SAndroid Build Coastguard Worker {
691*8975f5c5SAndroid Build Coastguard Worker     // Disable optimization if the base level is not 0.
692*8975f5c5SAndroid Build Coastguard Worker     if (mState.getBaseLevel() != 0)
693*8975f5c5SAndroid Build Coastguard Worker     {
694*8975f5c5SAndroid Build Coastguard Worker         return false;
695*8975f5c5SAndroid Build Coastguard Worker     }
696*8975f5c5SAndroid Build Coastguard Worker 
697*8975f5c5SAndroid Build Coastguard Worker     // If the texture is a cubemap, we will have to wait until it is complete.
698*8975f5c5SAndroid Build Coastguard Worker     if (mState.getType() == gl::TextureType::CubeMap && !mState.isCubeComplete())
699*8975f5c5SAndroid Build Coastguard Worker     {
700*8975f5c5SAndroid Build Coastguard Worker         return false;
701*8975f5c5SAndroid Build Coastguard Worker     }
702*8975f5c5SAndroid Build Coastguard Worker 
703*8975f5c5SAndroid Build Coastguard Worker     // Before we initialize the mips, we make sure that the base mip level is properly defined.
704*8975f5c5SAndroid Build Coastguard Worker     gl::TextureTarget textureTarget = (mState.getType() == gl::TextureType::CubeMap)
705*8975f5c5SAndroid Build Coastguard Worker                                           ? gl::kCubeMapTextureTargetMin
706*8975f5c5SAndroid Build Coastguard Worker                                           : gl::TextureTypeToTarget(mState.getType(), 0);
707*8975f5c5SAndroid Build Coastguard Worker     if (!isMipImageDescDefined(textureTarget, 0))
708*8975f5c5SAndroid Build Coastguard Worker     {
709*8975f5c5SAndroid Build Coastguard Worker         return false;
710*8975f5c5SAndroid Build Coastguard Worker     }
711*8975f5c5SAndroid Build Coastguard Worker 
712*8975f5c5SAndroid Build Coastguard Worker     // We do not flush if the texture has been bound as an attachment.
713*8975f5c5SAndroid Build Coastguard Worker     if (mState.hasBeenBoundAsAttachment())
714*8975f5c5SAndroid Build Coastguard Worker     {
715*8975f5c5SAndroid Build Coastguard Worker         return false;
716*8975f5c5SAndroid Build Coastguard Worker     }
717*8975f5c5SAndroid Build Coastguard Worker 
718*8975f5c5SAndroid Build Coastguard Worker     // For performance, flushing is skipped if the number of staged updates in a mip level is not
719*8975f5c5SAndroid Build Coastguard Worker     // one. For a cubemap, this applies to each face of the cube instead.
720*8975f5c5SAndroid Build Coastguard Worker     size_t maxUpdatesPerMipLevel = (mState.getType() == gl::TextureType::CubeMap) ? 6 : 1;
721*8975f5c5SAndroid Build Coastguard Worker     if (mImage->getLevelUpdateCount(gl::LevelIndex(0)) != maxUpdatesPerMipLevel)
722*8975f5c5SAndroid Build Coastguard Worker     {
723*8975f5c5SAndroid Build Coastguard Worker         return false;
724*8975f5c5SAndroid Build Coastguard Worker     }
725*8975f5c5SAndroid Build Coastguard Worker 
726*8975f5c5SAndroid Build Coastguard Worker     // The mip levels that are already defined should have attributes compatible with those of the
727*8975f5c5SAndroid Build Coastguard Worker     // base mip level. For each defined mip level, its size, format, number of samples, and depth
728*8975f5c5SAndroid Build Coastguard Worker     // are checked before flushing the texture updates. For complete cubemaps, there are 6 images
729*8975f5c5SAndroid Build Coastguard Worker     // per mip level. Therefore, mState would have 6 times as many images.
730*8975f5c5SAndroid Build Coastguard Worker     gl::ImageDesc baseImageDesc = mState.getImageDesc(textureTarget, 0);
731*8975f5c5SAndroid Build Coastguard Worker     size_t maxImageMipLevels    = (mState.getType() == gl::TextureType::CubeMap)
732*8975f5c5SAndroid Build Coastguard Worker                                       ? (mState.getImageDescs().size() / 6)
733*8975f5c5SAndroid Build Coastguard Worker                                       : mState.getImageDescs().size();
734*8975f5c5SAndroid Build Coastguard Worker 
735*8975f5c5SAndroid Build Coastguard Worker     for (size_t image = 1; image < maxImageMipLevels; image++)
736*8975f5c5SAndroid Build Coastguard Worker     {
737*8975f5c5SAndroid Build Coastguard Worker         gl::ImageDesc mipImageDesc = mState.getImageDesc(textureTarget, image);
738*8975f5c5SAndroid Build Coastguard Worker         if (!isMipImageDescDefined(textureTarget, image))
739*8975f5c5SAndroid Build Coastguard Worker         {
740*8975f5c5SAndroid Build Coastguard Worker             continue;
741*8975f5c5SAndroid Build Coastguard Worker         }
742*8975f5c5SAndroid Build Coastguard Worker 
743*8975f5c5SAndroid Build Coastguard Worker         // If the texture is 2DArray or 3D, the depths should also be checked according to the mip
744*8975f5c5SAndroid Build Coastguard Worker         // levels. If the texture type is a cube map array, the depth represents the number of
745*8975f5c5SAndroid Build Coastguard Worker         // layer-faces and does not change for mipmaps. Otherwise, we skip the depth comparison.
746*8975f5c5SAndroid Build Coastguard Worker         gl::Extents baseImageDescMipSize;
747*8975f5c5SAndroid Build Coastguard Worker         baseImageDescMipSize.width  = std::max(baseImageDesc.size.width >> image, 1);
748*8975f5c5SAndroid Build Coastguard Worker         baseImageDescMipSize.height = std::max(baseImageDesc.size.height >> image, 1);
749*8975f5c5SAndroid Build Coastguard Worker         baseImageDescMipSize.depth  = std::max(baseImageDesc.size.depth >> image, 1);
750*8975f5c5SAndroid Build Coastguard Worker 
751*8975f5c5SAndroid Build Coastguard Worker         bool isDepthCompatible = (mState.getType() == gl::TextureType::_3D ||
752*8975f5c5SAndroid Build Coastguard Worker                                   mState.getType() == gl::TextureType::_2DArray)
753*8975f5c5SAndroid Build Coastguard Worker                                      ? (baseImageDescMipSize.depth == mipImageDesc.size.depth)
754*8975f5c5SAndroid Build Coastguard Worker                                      : (mState.getType() != gl::TextureType::CubeMapArray ||
755*8975f5c5SAndroid Build Coastguard Worker                                         baseImageDesc.size.depth == mipImageDesc.size.depth);
756*8975f5c5SAndroid Build Coastguard Worker 
757*8975f5c5SAndroid Build Coastguard Worker         bool isSizeCompatible = (baseImageDescMipSize.width == mipImageDesc.size.width) &&
758*8975f5c5SAndroid Build Coastguard Worker                                 (baseImageDescMipSize.height == mipImageDesc.size.height) &&
759*8975f5c5SAndroid Build Coastguard Worker                                 isDepthCompatible;
760*8975f5c5SAndroid Build Coastguard Worker         bool isFormatCompatible          = (baseImageDesc.format.info->sizedInternalFormat ==
761*8975f5c5SAndroid Build Coastguard Worker                                    mipImageDesc.format.info->sizedInternalFormat);
762*8975f5c5SAndroid Build Coastguard Worker         bool isNumberOfSamplesCompatible = (baseImageDesc.samples == mipImageDesc.samples);
763*8975f5c5SAndroid Build Coastguard Worker 
764*8975f5c5SAndroid Build Coastguard Worker         bool isUpdateCompatible =
765*8975f5c5SAndroid Build Coastguard Worker             (mImage->getLevelUpdateCount(gl::LevelIndex(static_cast<GLint>(image))) ==
766*8975f5c5SAndroid Build Coastguard Worker              maxUpdatesPerMipLevel);
767*8975f5c5SAndroid Build Coastguard Worker 
768*8975f5c5SAndroid Build Coastguard Worker         if (!isSizeCompatible || !isFormatCompatible || !isNumberOfSamplesCompatible ||
769*8975f5c5SAndroid Build Coastguard Worker             !isUpdateCompatible)
770*8975f5c5SAndroid Build Coastguard Worker         {
771*8975f5c5SAndroid Build Coastguard Worker             return false;
772*8975f5c5SAndroid Build Coastguard Worker         }
773*8975f5c5SAndroid Build Coastguard Worker     }
774*8975f5c5SAndroid Build Coastguard Worker 
775*8975f5c5SAndroid Build Coastguard Worker     return true;
776*8975f5c5SAndroid Build Coastguard Worker }
777*8975f5c5SAndroid Build Coastguard Worker 
updateMustBeFlushed(gl::LevelIndex textureLevelIndexGL,angle::FormatID dstImageFormatID) const778*8975f5c5SAndroid Build Coastguard Worker bool TextureVk::updateMustBeFlushed(gl::LevelIndex textureLevelIndexGL,
779*8975f5c5SAndroid Build Coastguard Worker                                     angle::FormatID dstImageFormatID) const
780*8975f5c5SAndroid Build Coastguard Worker {
781*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImage);
782*8975f5c5SAndroid Build Coastguard Worker 
783*8975f5c5SAndroid Build Coastguard Worker     // For EGLImages we should never stage the update since staged update is subject to thread
784*8975f5c5SAndroid Build Coastguard Worker     // racing bugs when two textures in different share groups are accessed at same time.
785*8975f5c5SAndroid Build Coastguard Worker     if (!mOwnsImage)
786*8975f5c5SAndroid Build Coastguard Worker     {
787*8975f5c5SAndroid Build Coastguard Worker         // EGLImage is always initialized upon creation and format should always renderable so that
788*8975f5c5SAndroid Build Coastguard Worker         // there is no format upgrade.
789*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mImage->valid());
790*8975f5c5SAndroid Build Coastguard Worker         ASSERT(IsTextureLevelInAllocatedImage(*mImage, textureLevelIndexGL));
791*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!IsTextureLevelRedefined(mRedefinedLevels, mState.getType(), textureLevelIndexGL));
792*8975f5c5SAndroid Build Coastguard Worker         return true;
793*8975f5c5SAndroid Build Coastguard Worker     }
794*8975f5c5SAndroid Build Coastguard Worker     return false;
795*8975f5c5SAndroid Build Coastguard Worker }
796*8975f5c5SAndroid Build Coastguard Worker 
updateMustBeStaged(gl::LevelIndex textureLevelIndexGL,angle::FormatID dstImageFormatID) const797*8975f5c5SAndroid Build Coastguard Worker bool TextureVk::updateMustBeStaged(gl::LevelIndex textureLevelIndexGL,
798*8975f5c5SAndroid Build Coastguard Worker                                    angle::FormatID dstImageFormatID) const
799*8975f5c5SAndroid Build Coastguard Worker {
800*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImage);
801*8975f5c5SAndroid Build Coastguard Worker 
802*8975f5c5SAndroid Build Coastguard Worker     // If we do not have storage yet, there is impossible to immediately do the copy, so just
803*8975f5c5SAndroid Build Coastguard Worker     // stage it. Note that immutable texture will have a valid storage.
804*8975f5c5SAndroid Build Coastguard Worker     if (!mImage->valid())
805*8975f5c5SAndroid Build Coastguard Worker     {
806*8975f5c5SAndroid Build Coastguard Worker         return true;
807*8975f5c5SAndroid Build Coastguard Worker     }
808*8975f5c5SAndroid Build Coastguard Worker 
809*8975f5c5SAndroid Build Coastguard Worker     // If update is outside the range of image levels, it must be staged.
810*8975f5c5SAndroid Build Coastguard Worker     if (!IsTextureLevelInAllocatedImage(*mImage, textureLevelIndexGL))
811*8975f5c5SAndroid Build Coastguard Worker     {
812*8975f5c5SAndroid Build Coastguard Worker         return true;
813*8975f5c5SAndroid Build Coastguard Worker     }
814*8975f5c5SAndroid Build Coastguard Worker 
815*8975f5c5SAndroid Build Coastguard Worker     // During the process of format change, mImage's format may become stale. In that case, we
816*8975f5c5SAndroid Build Coastguard Worker     // must always stage the update and let caller properly release mImage and initExternal and
817*8975f5c5SAndroid Build Coastguard Worker     // flush the update.
818*8975f5c5SAndroid Build Coastguard Worker     if (mImage->getActualFormatID() != dstImageFormatID)
819*8975f5c5SAndroid Build Coastguard Worker     {
820*8975f5c5SAndroid Build Coastguard Worker         return true;
821*8975f5c5SAndroid Build Coastguard Worker     }
822*8975f5c5SAndroid Build Coastguard Worker 
823*8975f5c5SAndroid Build Coastguard Worker     // Otherwise, it can only be directly applied to the image if the level is not previously
824*8975f5c5SAndroid Build Coastguard Worker     // incompatibly redefined.
825*8975f5c5SAndroid Build Coastguard Worker     return IsTextureLevelRedefined(mRedefinedLevels, mState.getType(), textureLevelIndexGL);
826*8975f5c5SAndroid Build Coastguard Worker }
827*8975f5c5SAndroid Build Coastguard Worker 
clearImage(const gl::Context * context,GLint level,GLenum format,GLenum type,const uint8_t * data)828*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::clearImage(const gl::Context *context,
829*8975f5c5SAndroid Build Coastguard Worker                                     GLint level,
830*8975f5c5SAndroid Build Coastguard Worker                                     GLenum format,
831*8975f5c5SAndroid Build Coastguard Worker                                     GLenum type,
832*8975f5c5SAndroid Build Coastguard Worker                                     const uint8_t *data)
833*8975f5c5SAndroid Build Coastguard Worker {
834*8975f5c5SAndroid Build Coastguard Worker     // All defined cubemap faces are expected to have equal width and height.
835*8975f5c5SAndroid Build Coastguard Worker     bool isCubeMap = mState.getType() == gl::TextureType::CubeMap;
836*8975f5c5SAndroid Build Coastguard Worker     gl::TextureTarget textureTarget =
837*8975f5c5SAndroid Build Coastguard Worker         isCubeMap ? gl::kCubeMapTextureTargetMin : gl::TextureTypeToTarget(mState.getType(), 0);
838*8975f5c5SAndroid Build Coastguard Worker     gl::Extents extents = mState.getImageDesc(textureTarget, level).size;
839*8975f5c5SAndroid Build Coastguard Worker 
840*8975f5c5SAndroid Build Coastguard Worker     gl::Box area = gl::Box(gl::kOffsetZero, extents);
841*8975f5c5SAndroid Build Coastguard Worker     if (isCubeMap)
842*8975f5c5SAndroid Build Coastguard Worker     {
843*8975f5c5SAndroid Build Coastguard Worker         // For a cubemap, the depth offset moves between cube faces.
844*8975f5c5SAndroid Build Coastguard Worker         ASSERT(area.depth == 1);
845*8975f5c5SAndroid Build Coastguard Worker         area.depth = 6;
846*8975f5c5SAndroid Build Coastguard Worker     }
847*8975f5c5SAndroid Build Coastguard Worker 
848*8975f5c5SAndroid Build Coastguard Worker     return clearSubImageImpl(context, level, area, vk::ClearTextureMode::FullClear, format, type,
849*8975f5c5SAndroid Build Coastguard Worker                              data);
850*8975f5c5SAndroid Build Coastguard Worker }
851*8975f5c5SAndroid Build Coastguard Worker 
clearSubImage(const gl::Context * context,GLint level,const gl::Box & area,GLenum format,GLenum type,const uint8_t * data)852*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::clearSubImage(const gl::Context *context,
853*8975f5c5SAndroid Build Coastguard Worker                                        GLint level,
854*8975f5c5SAndroid Build Coastguard Worker                                        const gl::Box &area,
855*8975f5c5SAndroid Build Coastguard Worker                                        GLenum format,
856*8975f5c5SAndroid Build Coastguard Worker                                        GLenum type,
857*8975f5c5SAndroid Build Coastguard Worker                                        const uint8_t *data)
858*8975f5c5SAndroid Build Coastguard Worker {
859*8975f5c5SAndroid Build Coastguard Worker     bool isCubeMap = mState.getType() == gl::TextureType::CubeMap;
860*8975f5c5SAndroid Build Coastguard Worker     gl::TextureTarget textureTarget =
861*8975f5c5SAndroid Build Coastguard Worker         isCubeMap ? gl::kCubeMapTextureTargetMin : gl::TextureTypeToTarget(mState.getType(), 0);
862*8975f5c5SAndroid Build Coastguard Worker     gl::Extents extents   = mState.getImageDesc(textureTarget, level).size;
863*8975f5c5SAndroid Build Coastguard Worker     int depthForFullClear = isCubeMap ? 6 : extents.depth;
864*8975f5c5SAndroid Build Coastguard Worker 
865*8975f5c5SAndroid Build Coastguard Worker     vk::ClearTextureMode clearMode = vk::ClearTextureMode::PartialClear;
866*8975f5c5SAndroid Build Coastguard Worker     if (extents.width == area.width && extents.height == area.height &&
867*8975f5c5SAndroid Build Coastguard Worker         depthForFullClear == area.depth)
868*8975f5c5SAndroid Build Coastguard Worker     {
869*8975f5c5SAndroid Build Coastguard Worker         clearMode = vk::ClearTextureMode::FullClear;
870*8975f5c5SAndroid Build Coastguard Worker     }
871*8975f5c5SAndroid Build Coastguard Worker 
872*8975f5c5SAndroid Build Coastguard Worker     return clearSubImageImpl(context, level, area, clearMode, format, type, data);
873*8975f5c5SAndroid Build Coastguard Worker }
874*8975f5c5SAndroid Build Coastguard Worker 
clearSubImageImpl(const gl::Context * context,GLint level,const gl::Box & clearArea,vk::ClearTextureMode clearMode,GLenum format,GLenum type,const uint8_t * data)875*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::clearSubImageImpl(const gl::Context *context,
876*8975f5c5SAndroid Build Coastguard Worker                                            GLint level,
877*8975f5c5SAndroid Build Coastguard Worker                                            const gl::Box &clearArea,
878*8975f5c5SAndroid Build Coastguard Worker                                            vk::ClearTextureMode clearMode,
879*8975f5c5SAndroid Build Coastguard Worker                                            GLenum format,
880*8975f5c5SAndroid Build Coastguard Worker                                            GLenum type,
881*8975f5c5SAndroid Build Coastguard Worker                                            const uint8_t *data)
882*8975f5c5SAndroid Build Coastguard Worker {
883*8975f5c5SAndroid Build Coastguard Worker     // There should be no zero extents in the clear area, since such calls should return before
884*8975f5c5SAndroid Build Coastguard Worker     // entering the backend with no changes to the texture. For 2D textures, depth should be 1.
885*8975f5c5SAndroid Build Coastguard Worker     //
886*8975f5c5SAndroid Build Coastguard Worker     // From the spec: For texture types that do not have certain dimensions, this command treats
887*8975f5c5SAndroid Build Coastguard Worker     // those dimensions as having a size of 1.  For example, to clear a portion of a two-dimensional
888*8975f5c5SAndroid Build Coastguard Worker     // texture, the application would use <zoffset> equal to zero and <depth> equal to one.
889*8975f5c5SAndroid Build Coastguard Worker     ASSERT(clearArea.width != 0 && clearArea.height != 0 && clearArea.depth != 0);
890*8975f5c5SAndroid Build Coastguard Worker 
891*8975f5c5SAndroid Build Coastguard Worker     gl::TextureType textureType = mState.getType();
892*8975f5c5SAndroid Build Coastguard Worker     bool useLayerAsDepth        = textureType == gl::TextureType::CubeMap ||
893*8975f5c5SAndroid Build Coastguard Worker                            textureType == gl::TextureType::CubeMapArray ||
894*8975f5c5SAndroid Build Coastguard Worker                            textureType == gl::TextureType::_2DArray ||
895*8975f5c5SAndroid Build Coastguard Worker                            textureType == gl::TextureType::_2DMultisampleArray;
896*8975f5c5SAndroid Build Coastguard Worker 
897*8975f5c5SAndroid Build Coastguard Worker     // If the texture is renderable (including multisampled), the partial clear can be applied to
898*8975f5c5SAndroid Build Coastguard Worker     // the image simply by opening/closing a render pass with LOAD_OP_CLEAR. Otherwise, a buffer can
899*8975f5c5SAndroid Build Coastguard Worker     // be filled with the given pixel data on the host and staged to the image as a buffer update.
900*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk                 = vk::GetImpl(context);
901*8975f5c5SAndroid Build Coastguard Worker     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
902*8975f5c5SAndroid Build Coastguard Worker     const vk::Format &vkFormat =
903*8975f5c5SAndroid Build Coastguard Worker         contextVk->getRenderer()->getFormat(formatInfo.sizedInternalFormat);
904*8975f5c5SAndroid Build Coastguard Worker     const angle::FormatID &actualFormatID =
905*8975f5c5SAndroid Build Coastguard Worker         vkFormat.getActualImageFormatID(getRequiredImageAccess());
906*8975f5c5SAndroid Build Coastguard Worker     bool usesBufferForClear = false;
907*8975f5c5SAndroid Build Coastguard Worker 
908*8975f5c5SAndroid Build Coastguard Worker     VkFormatFeatureFlags renderableCheckFlag =
909*8975f5c5SAndroid Build Coastguard Worker         clearMode == vk::ClearTextureMode::FullClear ? VK_FORMAT_FEATURE_TRANSFER_DST_BIT
910*8975f5c5SAndroid Build Coastguard Worker         : formatInfo.isDepthOrStencil() ? VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
911*8975f5c5SAndroid Build Coastguard Worker                                         : VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
912*8975f5c5SAndroid Build Coastguard Worker     if (vk::FormatHasNecessaryFeature(contextVk->getRenderer(), actualFormatID, getTilingMode(),
913*8975f5c5SAndroid Build Coastguard Worker                                       renderableCheckFlag))
914*8975f5c5SAndroid Build Coastguard Worker     {
915*8975f5c5SAndroid Build Coastguard Worker         uint32_t baseLayer  = useLayerAsDepth ? clearArea.z : 0;
916*8975f5c5SAndroid Build Coastguard Worker         uint32_t layerCount = useLayerAsDepth ? clearArea.depth : 1;
917*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mImage->stagePartialClear(contextVk, clearArea, clearMode, mState.getType(),
918*8975f5c5SAndroid Build Coastguard Worker                                             level, baseLayer, layerCount, type, formatInfo,
919*8975f5c5SAndroid Build Coastguard Worker                                             vkFormat, getRequiredImageAccess(), data));
920*8975f5c5SAndroid Build Coastguard Worker     }
921*8975f5c5SAndroid Build Coastguard Worker     else
922*8975f5c5SAndroid Build Coastguard Worker     {
923*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mImage->getSamples() <= 1);
924*8975f5c5SAndroid Build Coastguard Worker         bool updateAppliedImmediately = false;
925*8975f5c5SAndroid Build Coastguard Worker         usesBufferForClear            = true;
926*8975f5c5SAndroid Build Coastguard Worker 
927*8975f5c5SAndroid Build Coastguard Worker         auto pixelSize = static_cast<size_t>(formatInfo.pixelBytes);
928*8975f5c5SAndroid Build Coastguard Worker         std::vector<uint8_t> pixelValue(pixelSize, 0);
929*8975f5c5SAndroid Build Coastguard Worker         if (data != nullptr)
930*8975f5c5SAndroid Build Coastguard Worker         {
931*8975f5c5SAndroid Build Coastguard Worker             memcpy(pixelValue.data(), data, pixelSize);
932*8975f5c5SAndroid Build Coastguard Worker         }
933*8975f5c5SAndroid Build Coastguard Worker 
934*8975f5c5SAndroid Build Coastguard Worker         // For a cubemap, each face will be updated separately.
935*8975f5c5SAndroid Build Coastguard Worker         bool isCubeMap = textureType == gl::TextureType::CubeMap;
936*8975f5c5SAndroid Build Coastguard Worker         size_t clearBufferSize =
937*8975f5c5SAndroid Build Coastguard Worker             isCubeMap ? clearArea.width * clearArea.height * pixelSize
938*8975f5c5SAndroid Build Coastguard Worker                       : clearArea.width * clearArea.height * clearArea.depth * pixelSize;
939*8975f5c5SAndroid Build Coastguard Worker 
940*8975f5c5SAndroid Build Coastguard Worker         std::vector<uint8_t> clearBuffer(clearBufferSize, 0);
941*8975f5c5SAndroid Build Coastguard Worker         ASSERT(clearBufferSize % pixelSize == 0);
942*8975f5c5SAndroid Build Coastguard Worker         if (data != nullptr)
943*8975f5c5SAndroid Build Coastguard Worker         {
944*8975f5c5SAndroid Build Coastguard Worker             for (GLuint i = 0; i < clearBufferSize; i += pixelSize)
945*8975f5c5SAndroid Build Coastguard Worker             {
946*8975f5c5SAndroid Build Coastguard Worker                 memcpy(&clearBuffer[i], pixelValue.data(), pixelSize);
947*8975f5c5SAndroid Build Coastguard Worker             }
948*8975f5c5SAndroid Build Coastguard Worker         }
949*8975f5c5SAndroid Build Coastguard Worker 
950*8975f5c5SAndroid Build Coastguard Worker         if (isCubeMap)
951*8975f5c5SAndroid Build Coastguard Worker         {
952*8975f5c5SAndroid Build Coastguard Worker             size_t cubeFaceStart = clearArea.z;
953*8975f5c5SAndroid Build Coastguard Worker             auto cubeFaceEnd     = static_cast<size_t>(clearArea.z + clearArea.depth);
954*8975f5c5SAndroid Build Coastguard Worker 
955*8975f5c5SAndroid Build Coastguard Worker             for (size_t cubeFace = cubeFaceStart; cubeFace < cubeFaceEnd; cubeFace++)
956*8975f5c5SAndroid Build Coastguard Worker             {
957*8975f5c5SAndroid Build Coastguard Worker                 const gl::ImageIndex index = gl::ImageIndex::MakeFromTarget(
958*8975f5c5SAndroid Build Coastguard Worker                     gl::CubeFaceIndexToTextureTarget(cubeFace), level, 0);
959*8975f5c5SAndroid Build Coastguard Worker 
960*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(mImage->stageSubresourceUpdate(
961*8975f5c5SAndroid Build Coastguard Worker                     contextVk, getNativeImageIndex(index),
962*8975f5c5SAndroid Build Coastguard Worker                     gl::Extents(clearArea.width, clearArea.height, 1),
963*8975f5c5SAndroid Build Coastguard Worker                     gl::Offset(clearArea.x, clearArea.y, 0), formatInfo,
964*8975f5c5SAndroid Build Coastguard Worker                     contextVk->getState().getUnpackState(), type, clearBuffer.data(), vkFormat,
965*8975f5c5SAndroid Build Coastguard Worker                     getRequiredImageAccess(), vk::ApplyImageUpdate::Defer,
966*8975f5c5SAndroid Build Coastguard Worker                     &updateAppliedImmediately));
967*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(!updateAppliedImmediately);
968*8975f5c5SAndroid Build Coastguard Worker             }
969*8975f5c5SAndroid Build Coastguard Worker         }
970*8975f5c5SAndroid Build Coastguard Worker         else
971*8975f5c5SAndroid Build Coastguard Worker         {
972*8975f5c5SAndroid Build Coastguard Worker             gl::TextureTarget textureTarget = gl::TextureTypeToTarget(textureType, 0);
973*8975f5c5SAndroid Build Coastguard Worker             uint32_t layerCount             = useLayerAsDepth ? clearArea.depth : 0;
974*8975f5c5SAndroid Build Coastguard Worker             const gl::ImageIndex index =
975*8975f5c5SAndroid Build Coastguard Worker                 gl::ImageIndex::MakeFromTarget(textureTarget, level, layerCount);
976*8975f5c5SAndroid Build Coastguard Worker 
977*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(mImage->stageSubresourceUpdate(
978*8975f5c5SAndroid Build Coastguard Worker                 contextVk, getNativeImageIndex(index),
979*8975f5c5SAndroid Build Coastguard Worker                 gl::Extents(clearArea.width, clearArea.height, clearArea.depth),
980*8975f5c5SAndroid Build Coastguard Worker                 gl::Offset(clearArea.x, clearArea.y, clearArea.z), formatInfo,
981*8975f5c5SAndroid Build Coastguard Worker                 contextVk->getState().getUnpackState(), type, clearBuffer.data(), vkFormat,
982*8975f5c5SAndroid Build Coastguard Worker                 getRequiredImageAccess(), vk::ApplyImageUpdate::Defer, &updateAppliedImmediately));
983*8975f5c5SAndroid Build Coastguard Worker             ASSERT(!updateAppliedImmediately);
984*8975f5c5SAndroid Build Coastguard Worker         }
985*8975f5c5SAndroid Build Coastguard Worker     }
986*8975f5c5SAndroid Build Coastguard Worker 
987*8975f5c5SAndroid Build Coastguard Worker     // Flush the staged updates if needed.
988*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureImageInitializedIfUpdatesNeedStageOrFlush(contextVk, gl::LevelIndex(level),
989*8975f5c5SAndroid Build Coastguard Worker                                                               vkFormat, vk::ApplyImageUpdate::Defer,
990*8975f5c5SAndroid Build Coastguard Worker                                                               usesBufferForClear));
991*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
992*8975f5c5SAndroid Build Coastguard Worker }
993*8975f5c5SAndroid Build Coastguard Worker 
ensureImageInitializedIfUpdatesNeedStageOrFlush(ContextVk * contextVk,gl::LevelIndex level,const vk::Format & vkFormat,vk::ApplyImageUpdate applyUpdate,bool usesBufferForUpdate)994*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::ensureImageInitializedIfUpdatesNeedStageOrFlush(
995*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk,
996*8975f5c5SAndroid Build Coastguard Worker     gl::LevelIndex level,
997*8975f5c5SAndroid Build Coastguard Worker     const vk::Format &vkFormat,
998*8975f5c5SAndroid Build Coastguard Worker     vk::ApplyImageUpdate applyUpdate,
999*8975f5c5SAndroid Build Coastguard Worker     bool usesBufferForUpdate)
1000*8975f5c5SAndroid Build Coastguard Worker {
1001*8975f5c5SAndroid Build Coastguard Worker     bool mustFlush =
1002*8975f5c5SAndroid Build Coastguard Worker         updateMustBeFlushed(level, vkFormat.getActualImageFormatID(getRequiredImageAccess()));
1003*8975f5c5SAndroid Build Coastguard Worker     bool mustStage = applyUpdate == vk::ApplyImageUpdate::Defer;
1004*8975f5c5SAndroid Build Coastguard Worker 
1005*8975f5c5SAndroid Build Coastguard Worker     // If texture has all levels being specified, then do the flush immediately. This tries to avoid
1006*8975f5c5SAndroid Build Coastguard Worker     // issue flush as each level is being provided which may end up flushing out the staged clear
1007*8975f5c5SAndroid Build Coastguard Worker     // that otherwise might able to be removed. It also helps tracking all updates with just one
1008*8975f5c5SAndroid Build Coastguard Worker     // VkEvent instead of one for each level.
1009*8975f5c5SAndroid Build Coastguard Worker     if (mustFlush ||
1010*8975f5c5SAndroid Build Coastguard Worker         (!mustStage && mImage->valid() && mImage->hasBufferSourcedStagedUpdatesInAllLevels()))
1011*8975f5c5SAndroid Build Coastguard Worker     {
1012*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
1013*8975f5c5SAndroid Build Coastguard Worker 
1014*8975f5c5SAndroid Build Coastguard Worker         // If forceSubmitImmutableTextureUpdates is enabled, submit the staged updates as well.
1015*8975f5c5SAndroid Build Coastguard Worker         if (contextVk->getFeatures().forceSubmitImmutableTextureUpdates.enabled)
1016*8975f5c5SAndroid Build Coastguard Worker         {
1017*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(contextVk->submitStagedTextureUpdates());
1018*8975f5c5SAndroid Build Coastguard Worker         }
1019*8975f5c5SAndroid Build Coastguard Worker     }
1020*8975f5c5SAndroid Build Coastguard Worker     else if (usesBufferForUpdate && contextVk->isEligibleForMutableTextureFlush() &&
1021*8975f5c5SAndroid Build Coastguard Worker              !mState.getImmutableFormat())
1022*8975f5c5SAndroid Build Coastguard Worker     {
1023*8975f5c5SAndroid Build Coastguard Worker         // Check if we should flush any mutable textures from before.
1024*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(contextVk->getShareGroup()->onMutableTextureUpload(contextVk, this));
1025*8975f5c5SAndroid Build Coastguard Worker     }
1026*8975f5c5SAndroid Build Coastguard Worker 
1027*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1028*8975f5c5SAndroid Build Coastguard Worker }
1029*8975f5c5SAndroid Build Coastguard Worker 
setSubImageImpl(const gl::Context * context,const gl::ImageIndex & index,const gl::Box & area,const gl::InternalFormat & formatInfo,GLenum type,const gl::PixelUnpackState & unpack,gl::Buffer * unpackBuffer,const uint8_t * pixels,const vk::Format & vkFormat)1030*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setSubImageImpl(const gl::Context *context,
1031*8975f5c5SAndroid Build Coastguard Worker                                          const gl::ImageIndex &index,
1032*8975f5c5SAndroid Build Coastguard Worker                                          const gl::Box &area,
1033*8975f5c5SAndroid Build Coastguard Worker                                          const gl::InternalFormat &formatInfo,
1034*8975f5c5SAndroid Build Coastguard Worker                                          GLenum type,
1035*8975f5c5SAndroid Build Coastguard Worker                                          const gl::PixelUnpackState &unpack,
1036*8975f5c5SAndroid Build Coastguard Worker                                          gl::Buffer *unpackBuffer,
1037*8975f5c5SAndroid Build Coastguard Worker                                          const uint8_t *pixels,
1038*8975f5c5SAndroid Build Coastguard Worker                                          const vk::Format &vkFormat)
1039*8975f5c5SAndroid Build Coastguard Worker {
1040*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
1041*8975f5c5SAndroid Build Coastguard Worker 
1042*8975f5c5SAndroid Build Coastguard Worker     bool mustStage = updateMustBeStaged(gl::LevelIndex(index.getLevelIndex()),
1043*8975f5c5SAndroid Build Coastguard Worker                                         vkFormat.getActualImageFormatID(getRequiredImageAccess()));
1044*8975f5c5SAndroid Build Coastguard Worker 
1045*8975f5c5SAndroid Build Coastguard Worker     vk::ApplyImageUpdate applyUpdate;
1046*8975f5c5SAndroid Build Coastguard Worker     if (mustStage)
1047*8975f5c5SAndroid Build Coastguard Worker     {
1048*8975f5c5SAndroid Build Coastguard Worker         applyUpdate = vk::ApplyImageUpdate::Defer;
1049*8975f5c5SAndroid Build Coastguard Worker     }
1050*8975f5c5SAndroid Build Coastguard Worker     else
1051*8975f5c5SAndroid Build Coastguard Worker     {
1052*8975f5c5SAndroid Build Coastguard Worker         // Cannot defer to unlocked tail call if:
1053*8975f5c5SAndroid Build Coastguard Worker         //
1054*8975f5c5SAndroid Build Coastguard Worker         // - The generate mipmap hint is set: This is because on return the Texture class would
1055*8975f5c5SAndroid Build Coastguard Worker         //   attempt to generate mipmaps, which may reallocate the image, or fall back to software
1056*8975f5c5SAndroid Build Coastguard Worker         //   mipmap generation.
1057*8975f5c5SAndroid Build Coastguard Worker         // - The texture is incomplete: This is because unlocked tail call is disabled on draw
1058*8975f5c5SAndroid Build Coastguard Worker         //   calls, but that is when incomplete textures are created and initialized.
1059*8975f5c5SAndroid Build Coastguard Worker         const bool canDeferToUnlockedTailCall =
1060*8975f5c5SAndroid Build Coastguard Worker             mState.getGenerateMipmapHint() != GL_TRUE && !mState.isInternalIncompleteTexture();
1061*8975f5c5SAndroid Build Coastguard Worker 
1062*8975f5c5SAndroid Build Coastguard Worker         // When possible flush out updates immediately.
1063*8975f5c5SAndroid Build Coastguard Worker         applyUpdate = canDeferToUnlockedTailCall
1064*8975f5c5SAndroid Build Coastguard Worker                           ? vk::ApplyImageUpdate::ImmediatelyInUnlockedTailCall
1065*8975f5c5SAndroid Build Coastguard Worker                           : vk::ApplyImageUpdate::Immediately;
1066*8975f5c5SAndroid Build Coastguard Worker     }
1067*8975f5c5SAndroid Build Coastguard Worker     bool updateAppliedImmediately = false;
1068*8975f5c5SAndroid Build Coastguard Worker 
1069*8975f5c5SAndroid Build Coastguard Worker     if (unpackBuffer)
1070*8975f5c5SAndroid Build Coastguard Worker     {
1071*8975f5c5SAndroid Build Coastguard Worker         BufferVk *unpackBufferVk       = vk::GetImpl(unpackBuffer);
1072*8975f5c5SAndroid Build Coastguard Worker         vk::BufferHelper &bufferHelper = unpackBufferVk->getBuffer();
1073*8975f5c5SAndroid Build Coastguard Worker         VkDeviceSize bufferOffset      = bufferHelper.getOffset();
1074*8975f5c5SAndroid Build Coastguard Worker         uintptr_t offset               = reinterpret_cast<uintptr_t>(pixels);
1075*8975f5c5SAndroid Build Coastguard Worker         GLuint inputRowPitch           = 0;
1076*8975f5c5SAndroid Build Coastguard Worker         GLuint inputDepthPitch         = 0;
1077*8975f5c5SAndroid Build Coastguard Worker         GLuint inputSkipBytes          = 0;
1078*8975f5c5SAndroid Build Coastguard Worker 
1079*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mImage->CalculateBufferInfo(
1080*8975f5c5SAndroid Build Coastguard Worker             contextVk, gl::Extents(area.width, area.height, area.depth), formatInfo, unpack, type,
1081*8975f5c5SAndroid Build Coastguard Worker             index.usesTex3D(), &inputRowPitch, &inputDepthPitch, &inputSkipBytes));
1082*8975f5c5SAndroid Build Coastguard Worker 
1083*8975f5c5SAndroid Build Coastguard Worker         size_t offsetBytes = static_cast<size_t>(bufferOffset + offset + inputSkipBytes);
1084*8975f5c5SAndroid Build Coastguard Worker 
1085*8975f5c5SAndroid Build Coastguard Worker         // Note: cannot directly copy from a depth/stencil PBO.  GL requires depth and stencil data
1086*8975f5c5SAndroid Build Coastguard Worker         // to be packed, while Vulkan requires them to be separate.
1087*8975f5c5SAndroid Build Coastguard Worker         const VkImageAspectFlags aspectFlags =
1088*8975f5c5SAndroid Build Coastguard Worker             vk::GetFormatAspectFlags(vkFormat.getIntendedFormat());
1089*8975f5c5SAndroid Build Coastguard Worker         const vk::Format &bufferVkFormat =
1090*8975f5c5SAndroid Build Coastguard Worker             contextVk->getRenderer()->getFormat(formatInfo.sizedInternalFormat);
1091*8975f5c5SAndroid Build Coastguard Worker 
1092*8975f5c5SAndroid Build Coastguard Worker         if (shouldUpdateBeFlushed(gl::LevelIndex(index.getLevelIndex()),
1093*8975f5c5SAndroid Build Coastguard Worker                                   vkFormat.getActualImageFormatID(getRequiredImageAccess())) &&
1094*8975f5c5SAndroid Build Coastguard Worker             isFastUnpackPossible(vkFormat, offsetBytes, bufferVkFormat))
1095*8975f5c5SAndroid Build Coastguard Worker         {
1096*8975f5c5SAndroid Build Coastguard Worker             GLuint pixelSize   = formatInfo.pixelBytes;
1097*8975f5c5SAndroid Build Coastguard Worker             GLuint blockWidth  = formatInfo.compressedBlockWidth;
1098*8975f5c5SAndroid Build Coastguard Worker             GLuint blockHeight = formatInfo.compressedBlockHeight;
1099*8975f5c5SAndroid Build Coastguard Worker             if (!formatInfo.compressed)
1100*8975f5c5SAndroid Build Coastguard Worker             {
1101*8975f5c5SAndroid Build Coastguard Worker                 pixelSize   = formatInfo.computePixelBytes(type);
1102*8975f5c5SAndroid Build Coastguard Worker                 blockWidth  = 1;
1103*8975f5c5SAndroid Build Coastguard Worker                 blockHeight = 1;
1104*8975f5c5SAndroid Build Coastguard Worker             }
1105*8975f5c5SAndroid Build Coastguard Worker             ASSERT(pixelSize != 0 && inputRowPitch != 0 && blockWidth != 0 && blockHeight != 0);
1106*8975f5c5SAndroid Build Coastguard Worker 
1107*8975f5c5SAndroid Build Coastguard Worker             GLuint rowLengthPixels   = inputRowPitch / pixelSize * blockWidth;
1108*8975f5c5SAndroid Build Coastguard Worker             GLuint imageHeightPixels = inputDepthPitch / inputRowPitch * blockHeight;
1109*8975f5c5SAndroid Build Coastguard Worker 
1110*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(copyBufferDataToImage(contextVk, &bufferHelper, index, rowLengthPixels,
1111*8975f5c5SAndroid Build Coastguard Worker                                             imageHeightPixels, area, offsetBytes, aspectFlags));
1112*8975f5c5SAndroid Build Coastguard Worker         }
1113*8975f5c5SAndroid Build Coastguard Worker         else
1114*8975f5c5SAndroid Build Coastguard Worker         {
1115*8975f5c5SAndroid Build Coastguard Worker             ANGLE_VK_PERF_WARNING(
1116*8975f5c5SAndroid Build Coastguard Worker                 contextVk, GL_DEBUG_SEVERITY_HIGH,
1117*8975f5c5SAndroid Build Coastguard Worker                 "TexSubImage with unpack buffer copied on CPU due to store, format "
1118*8975f5c5SAndroid Build Coastguard Worker                 "or offset restrictions");
1119*8975f5c5SAndroid Build Coastguard Worker 
1120*8975f5c5SAndroid Build Coastguard Worker             void *mapPtr = nullptr;
1121*8975f5c5SAndroid Build Coastguard Worker 
1122*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(unpackBufferVk->mapImpl(contextVk, GL_MAP_READ_BIT, &mapPtr));
1123*8975f5c5SAndroid Build Coastguard Worker 
1124*8975f5c5SAndroid Build Coastguard Worker             const uint8_t *source =
1125*8975f5c5SAndroid Build Coastguard Worker                 static_cast<const uint8_t *>(mapPtr) + reinterpret_cast<ptrdiff_t>(pixels);
1126*8975f5c5SAndroid Build Coastguard Worker 
1127*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(mImage->stageSubresourceUpdateImpl(
1128*8975f5c5SAndroid Build Coastguard Worker                 contextVk, getNativeImageIndex(index),
1129*8975f5c5SAndroid Build Coastguard Worker                 gl::Extents(area.width, area.height, area.depth),
1130*8975f5c5SAndroid Build Coastguard Worker                 gl::Offset(area.x, area.y, area.z), formatInfo, unpack, type, source, vkFormat,
1131*8975f5c5SAndroid Build Coastguard Worker                 getRequiredImageAccess(), inputRowPitch, inputDepthPitch, inputSkipBytes,
1132*8975f5c5SAndroid Build Coastguard Worker                 applyUpdate, &updateAppliedImmediately));
1133*8975f5c5SAndroid Build Coastguard Worker 
1134*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(unpackBufferVk->unmapImpl(contextVk));
1135*8975f5c5SAndroid Build Coastguard Worker         }
1136*8975f5c5SAndroid Build Coastguard Worker     }
1137*8975f5c5SAndroid Build Coastguard Worker     else if (pixels)
1138*8975f5c5SAndroid Build Coastguard Worker     {
1139*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mImage->stageSubresourceUpdate(
1140*8975f5c5SAndroid Build Coastguard Worker             contextVk, getNativeImageIndex(index), gl::Extents(area.width, area.height, area.depth),
1141*8975f5c5SAndroid Build Coastguard Worker             gl::Offset(area.x, area.y, area.z), formatInfo, unpack, type, pixels, vkFormat,
1142*8975f5c5SAndroid Build Coastguard Worker             getRequiredImageAccess(), applyUpdate, &updateAppliedImmediately));
1143*8975f5c5SAndroid Build Coastguard Worker     }
1144*8975f5c5SAndroid Build Coastguard Worker 
1145*8975f5c5SAndroid Build Coastguard Worker     if (updateAppliedImmediately)
1146*8975f5c5SAndroid Build Coastguard Worker     {
1147*8975f5c5SAndroid Build Coastguard Worker         // Return if stageSubresourceUpdate already applied the update
1148*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
1149*8975f5c5SAndroid Build Coastguard Worker     }
1150*8975f5c5SAndroid Build Coastguard Worker 
1151*8975f5c5SAndroid Build Coastguard Worker     // Flush the staged updates if needed.
1152*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureImageInitializedIfUpdatesNeedStageOrFlush(
1153*8975f5c5SAndroid Build Coastguard Worker         contextVk, gl::LevelIndex(index.getLevelIndex()), vkFormat, applyUpdate, true));
1154*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1155*8975f5c5SAndroid Build Coastguard Worker }
1156*8975f5c5SAndroid Build Coastguard Worker 
copyImage(const gl::Context * context,const gl::ImageIndex & index,const gl::Rectangle & sourceArea,GLenum internalFormat,gl::Framebuffer * source)1157*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copyImage(const gl::Context *context,
1158*8975f5c5SAndroid Build Coastguard Worker                                    const gl::ImageIndex &index,
1159*8975f5c5SAndroid Build Coastguard Worker                                    const gl::Rectangle &sourceArea,
1160*8975f5c5SAndroid Build Coastguard Worker                                    GLenum internalFormat,
1161*8975f5c5SAndroid Build Coastguard Worker                                    gl::Framebuffer *source)
1162*8975f5c5SAndroid Build Coastguard Worker {
1163*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk   = vk::GetImpl(context);
1164*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
1165*8975f5c5SAndroid Build Coastguard Worker 
1166*8975f5c5SAndroid Build Coastguard Worker     gl::Extents newImageSize(sourceArea.width, sourceArea.height, 1);
1167*8975f5c5SAndroid Build Coastguard Worker     const gl::InternalFormat &internalFormatInfo =
1168*8975f5c5SAndroid Build Coastguard Worker         gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
1169*8975f5c5SAndroid Build Coastguard Worker     const vk::Format &vkFormat = renderer->getFormat(internalFormatInfo.sizedInternalFormat);
1170*8975f5c5SAndroid Build Coastguard Worker 
1171*8975f5c5SAndroid Build Coastguard Worker     // Fall back to renderable format if copy cannot be done in transfer.  Must be done before
1172*8975f5c5SAndroid Build Coastguard Worker     // the dst format is accessed anywhere (in |redefineLevel| and |copySubImageImpl|).
1173*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureRenderableIfCopyTexImageCannotTransfer(contextVk, internalFormatInfo, source));
1174*8975f5c5SAndroid Build Coastguard Worker 
1175*8975f5c5SAndroid Build Coastguard Worker     // The texture level being redefined might be the same as the one bound to the framebuffer.
1176*8975f5c5SAndroid Build Coastguard Worker     // This _could_ be supported by using a temp image before redefining the level (and potentially
1177*8975f5c5SAndroid Build Coastguard Worker     // discarding the image).  However, this is currently unimplemented.
1178*8975f5c5SAndroid Build Coastguard Worker     FramebufferVk *framebufferVk = vk::GetImpl(source);
1179*8975f5c5SAndroid Build Coastguard Worker     RenderTargetVk *colorReadRT  = framebufferVk->getColorReadRenderTarget();
1180*8975f5c5SAndroid Build Coastguard Worker     vk::ImageHelper *srcImage    = &colorReadRT->getImageForCopy();
1181*8975f5c5SAndroid Build Coastguard Worker     const bool isCubeMap         = index.getType() == gl::TextureType::CubeMap;
1182*8975f5c5SAndroid Build Coastguard Worker     gl::LevelIndex levelIndex(getNativeImageIndex(index).getLevelIndex());
1183*8975f5c5SAndroid Build Coastguard Worker     const uint32_t layerIndex    = index.hasLayer() ? index.getLayerIndex() : 0;
1184*8975f5c5SAndroid Build Coastguard Worker     const uint32_t redefinedFace = isCubeMap ? layerIndex : 0;
1185*8975f5c5SAndroid Build Coastguard Worker     const uint32_t sourceFace    = isCubeMap ? colorReadRT->getLayerIndex() : 0;
1186*8975f5c5SAndroid Build Coastguard Worker     const bool isSelfCopy = mImage == srcImage && levelIndex == colorReadRT->getLevelIndex() &&
1187*8975f5c5SAndroid Build Coastguard Worker                             redefinedFace == sourceFace;
1188*8975f5c5SAndroid Build Coastguard Worker 
1189*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(redefineLevel(context, index, vkFormat, newImageSize));
1190*8975f5c5SAndroid Build Coastguard Worker 
1191*8975f5c5SAndroid Build Coastguard Worker     if (isSelfCopy)
1192*8975f5c5SAndroid Build Coastguard Worker     {
1193*8975f5c5SAndroid Build Coastguard Worker         UNIMPLEMENTED();
1194*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
1195*8975f5c5SAndroid Build Coastguard Worker     }
1196*8975f5c5SAndroid Build Coastguard Worker 
1197*8975f5c5SAndroid Build Coastguard Worker     return copySubImageImpl(context, index, gl::Offset(0, 0, 0), sourceArea, internalFormatInfo,
1198*8975f5c5SAndroid Build Coastguard Worker                             source);
1199*8975f5c5SAndroid Build Coastguard Worker }
1200*8975f5c5SAndroid Build Coastguard Worker 
copySubImage(const gl::Context * context,const gl::ImageIndex & index,const gl::Offset & destOffset,const gl::Rectangle & sourceArea,gl::Framebuffer * source)1201*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copySubImage(const gl::Context *context,
1202*8975f5c5SAndroid Build Coastguard Worker                                       const gl::ImageIndex &index,
1203*8975f5c5SAndroid Build Coastguard Worker                                       const gl::Offset &destOffset,
1204*8975f5c5SAndroid Build Coastguard Worker                                       const gl::Rectangle &sourceArea,
1205*8975f5c5SAndroid Build Coastguard Worker                                       gl::Framebuffer *source)
1206*8975f5c5SAndroid Build Coastguard Worker {
1207*8975f5c5SAndroid Build Coastguard Worker     const gl::InternalFormat &currentFormat = *mState.getImageDesc(index).format.info;
1208*8975f5c5SAndroid Build Coastguard Worker 
1209*8975f5c5SAndroid Build Coastguard Worker     // Fall back to renderable format if copy cannot be done in transfer.  Must be done before
1210*8975f5c5SAndroid Build Coastguard Worker     // the dst format is accessed anywhere (in |redefineLevel| and |copySubImageImpl|).
1211*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(
1212*8975f5c5SAndroid Build Coastguard Worker         ensureRenderableIfCopyTexImageCannotTransfer(vk::GetImpl(context), currentFormat, source));
1213*8975f5c5SAndroid Build Coastguard Worker 
1214*8975f5c5SAndroid Build Coastguard Worker     return copySubImageImpl(context, index, destOffset, sourceArea, currentFormat, source);
1215*8975f5c5SAndroid Build Coastguard Worker }
1216*8975f5c5SAndroid Build Coastguard Worker 
copyTexture(const gl::Context * context,const gl::ImageIndex & index,GLenum internalFormat,GLenum type,GLint sourceLevelGL,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,const gl::Texture * source)1217*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copyTexture(const gl::Context *context,
1218*8975f5c5SAndroid Build Coastguard Worker                                      const gl::ImageIndex &index,
1219*8975f5c5SAndroid Build Coastguard Worker                                      GLenum internalFormat,
1220*8975f5c5SAndroid Build Coastguard Worker                                      GLenum type,
1221*8975f5c5SAndroid Build Coastguard Worker                                      GLint sourceLevelGL,
1222*8975f5c5SAndroid Build Coastguard Worker                                      bool unpackFlipY,
1223*8975f5c5SAndroid Build Coastguard Worker                                      bool unpackPremultiplyAlpha,
1224*8975f5c5SAndroid Build Coastguard Worker                                      bool unpackUnmultiplyAlpha,
1225*8975f5c5SAndroid Build Coastguard Worker                                      const gl::Texture *source)
1226*8975f5c5SAndroid Build Coastguard Worker {
1227*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk   = vk::GetImpl(context);
1228*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
1229*8975f5c5SAndroid Build Coastguard Worker 
1230*8975f5c5SAndroid Build Coastguard Worker     TextureVk *sourceVk = vk::GetImpl(source);
1231*8975f5c5SAndroid Build Coastguard Worker     const gl::ImageDesc &srcImageDesc =
1232*8975f5c5SAndroid Build Coastguard Worker         sourceVk->mState.getImageDesc(NonCubeTextureTypeToTarget(source->getType()), sourceLevelGL);
1233*8975f5c5SAndroid Build Coastguard Worker     gl::Box sourceBox(gl::kOffsetZero, srcImageDesc.size);
1234*8975f5c5SAndroid Build Coastguard Worker     const gl::InternalFormat &dstFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
1235*8975f5c5SAndroid Build Coastguard Worker     const vk::Format &dstVkFormat = renderer->getFormat(dstFormatInfo.sizedInternalFormat);
1236*8975f5c5SAndroid Build Coastguard Worker 
1237*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(sourceVk->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
1238*8975f5c5SAndroid Build Coastguard Worker 
1239*8975f5c5SAndroid Build Coastguard Worker     // Fall back to renderable format if copy cannot be done in transfer.  Must be done before
1240*8975f5c5SAndroid Build Coastguard Worker     // the dst format is accessed anywhere (in |redefineLevel| and |copySubTextureImpl|).
1241*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureRenderableIfCopyTextureCannotTransfer(contextVk, dstFormatInfo, unpackFlipY,
1242*8975f5c5SAndroid Build Coastguard Worker                                                           unpackPremultiplyAlpha,
1243*8975f5c5SAndroid Build Coastguard Worker                                                           unpackUnmultiplyAlpha, sourceVk));
1244*8975f5c5SAndroid Build Coastguard Worker 
1245*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(redefineLevel(context, index, dstVkFormat, srcImageDesc.size));
1246*8975f5c5SAndroid Build Coastguard Worker 
1247*8975f5c5SAndroid Build Coastguard Worker     return copySubTextureImpl(contextVk, index, gl::kOffsetZero, dstFormatInfo,
1248*8975f5c5SAndroid Build Coastguard Worker                               gl::LevelIndex(sourceLevelGL), sourceBox, unpackFlipY,
1249*8975f5c5SAndroid Build Coastguard Worker                               unpackPremultiplyAlpha, unpackUnmultiplyAlpha, sourceVk);
1250*8975f5c5SAndroid Build Coastguard Worker }
1251*8975f5c5SAndroid Build Coastguard Worker 
copySubTexture(const gl::Context * context,const gl::ImageIndex & index,const gl::Offset & dstOffset,GLint srcLevelGL,const gl::Box & sourceBox,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,const gl::Texture * source)1252*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copySubTexture(const gl::Context *context,
1253*8975f5c5SAndroid Build Coastguard Worker                                         const gl::ImageIndex &index,
1254*8975f5c5SAndroid Build Coastguard Worker                                         const gl::Offset &dstOffset,
1255*8975f5c5SAndroid Build Coastguard Worker                                         GLint srcLevelGL,
1256*8975f5c5SAndroid Build Coastguard Worker                                         const gl::Box &sourceBox,
1257*8975f5c5SAndroid Build Coastguard Worker                                         bool unpackFlipY,
1258*8975f5c5SAndroid Build Coastguard Worker                                         bool unpackPremultiplyAlpha,
1259*8975f5c5SAndroid Build Coastguard Worker                                         bool unpackUnmultiplyAlpha,
1260*8975f5c5SAndroid Build Coastguard Worker                                         const gl::Texture *source)
1261*8975f5c5SAndroid Build Coastguard Worker {
1262*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
1263*8975f5c5SAndroid Build Coastguard Worker 
1264*8975f5c5SAndroid Build Coastguard Worker     gl::TextureTarget target = index.getTarget();
1265*8975f5c5SAndroid Build Coastguard Worker     gl::LevelIndex dstLevelGL(index.getLevelIndex());
1266*8975f5c5SAndroid Build Coastguard Worker     const gl::InternalFormat &dstFormatInfo =
1267*8975f5c5SAndroid Build Coastguard Worker         *mState.getImageDesc(target, dstLevelGL.get()).format.info;
1268*8975f5c5SAndroid Build Coastguard Worker 
1269*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(
1270*8975f5c5SAndroid Build Coastguard Worker         vk::GetImpl(source)->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
1271*8975f5c5SAndroid Build Coastguard Worker 
1272*8975f5c5SAndroid Build Coastguard Worker     // Fall back to renderable format if copy cannot be done in transfer.  Must be done before
1273*8975f5c5SAndroid Build Coastguard Worker     // the dst format is accessed anywhere (in |copySubTextureImpl|).
1274*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureRenderableIfCopyTextureCannotTransfer(
1275*8975f5c5SAndroid Build Coastguard Worker         contextVk, dstFormatInfo, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha,
1276*8975f5c5SAndroid Build Coastguard Worker         vk::GetImpl(source)));
1277*8975f5c5SAndroid Build Coastguard Worker 
1278*8975f5c5SAndroid Build Coastguard Worker     return copySubTextureImpl(contextVk, index, dstOffset, dstFormatInfo,
1279*8975f5c5SAndroid Build Coastguard Worker                               gl::LevelIndex(srcLevelGL), sourceBox, unpackFlipY,
1280*8975f5c5SAndroid Build Coastguard Worker                               unpackPremultiplyAlpha, unpackUnmultiplyAlpha, vk::GetImpl(source));
1281*8975f5c5SAndroid Build Coastguard Worker }
1282*8975f5c5SAndroid Build Coastguard Worker 
copyRenderbufferSubData(const gl::Context * context,const gl::Renderbuffer * srcBuffer,GLint srcLevel,GLint srcX,GLint srcY,GLint srcZ,GLint dstLevel,GLint dstX,GLint dstY,GLint dstZ,GLsizei srcWidth,GLsizei srcHeight,GLsizei srcDepth)1283*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copyRenderbufferSubData(const gl::Context *context,
1284*8975f5c5SAndroid Build Coastguard Worker                                                  const gl::Renderbuffer *srcBuffer,
1285*8975f5c5SAndroid Build Coastguard Worker                                                  GLint srcLevel,
1286*8975f5c5SAndroid Build Coastguard Worker                                                  GLint srcX,
1287*8975f5c5SAndroid Build Coastguard Worker                                                  GLint srcY,
1288*8975f5c5SAndroid Build Coastguard Worker                                                  GLint srcZ,
1289*8975f5c5SAndroid Build Coastguard Worker                                                  GLint dstLevel,
1290*8975f5c5SAndroid Build Coastguard Worker                                                  GLint dstX,
1291*8975f5c5SAndroid Build Coastguard Worker                                                  GLint dstY,
1292*8975f5c5SAndroid Build Coastguard Worker                                                  GLint dstZ,
1293*8975f5c5SAndroid Build Coastguard Worker                                                  GLsizei srcWidth,
1294*8975f5c5SAndroid Build Coastguard Worker                                                  GLsizei srcHeight,
1295*8975f5c5SAndroid Build Coastguard Worker                                                  GLsizei srcDepth)
1296*8975f5c5SAndroid Build Coastguard Worker {
1297*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk     = vk::GetImpl(context);
1298*8975f5c5SAndroid Build Coastguard Worker     RenderbufferVk *sourceVk = vk::GetImpl(srcBuffer);
1299*8975f5c5SAndroid Build Coastguard Worker 
1300*8975f5c5SAndroid Build Coastguard Worker     // Make sure the source/destination targets are initialized and all staged updates are flushed.
1301*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(sourceVk->ensureImageInitialized(context));
1302*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
1303*8975f5c5SAndroid Build Coastguard Worker 
1304*8975f5c5SAndroid Build Coastguard Worker     return vk::ImageHelper::CopyImageSubData(context, sourceVk->getImage(), srcLevel, srcX, srcY,
1305*8975f5c5SAndroid Build Coastguard Worker                                              srcZ, mImage, dstLevel, dstX, dstY, dstZ, srcWidth,
1306*8975f5c5SAndroid Build Coastguard Worker                                              srcHeight, srcDepth);
1307*8975f5c5SAndroid Build Coastguard Worker }
1308*8975f5c5SAndroid Build Coastguard Worker 
copyTextureSubData(const gl::Context * context,const gl::Texture * srcTexture,GLint srcLevel,GLint srcX,GLint srcY,GLint srcZ,GLint dstLevel,GLint dstX,GLint dstY,GLint dstZ,GLsizei srcWidth,GLsizei srcHeight,GLsizei srcDepth)1309*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copyTextureSubData(const gl::Context *context,
1310*8975f5c5SAndroid Build Coastguard Worker                                             const gl::Texture *srcTexture,
1311*8975f5c5SAndroid Build Coastguard Worker                                             GLint srcLevel,
1312*8975f5c5SAndroid Build Coastguard Worker                                             GLint srcX,
1313*8975f5c5SAndroid Build Coastguard Worker                                             GLint srcY,
1314*8975f5c5SAndroid Build Coastguard Worker                                             GLint srcZ,
1315*8975f5c5SAndroid Build Coastguard Worker                                             GLint dstLevel,
1316*8975f5c5SAndroid Build Coastguard Worker                                             GLint dstX,
1317*8975f5c5SAndroid Build Coastguard Worker                                             GLint dstY,
1318*8975f5c5SAndroid Build Coastguard Worker                                             GLint dstZ,
1319*8975f5c5SAndroid Build Coastguard Worker                                             GLsizei srcWidth,
1320*8975f5c5SAndroid Build Coastguard Worker                                             GLsizei srcHeight,
1321*8975f5c5SAndroid Build Coastguard Worker                                             GLsizei srcDepth)
1322*8975f5c5SAndroid Build Coastguard Worker {
1323*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
1324*8975f5c5SAndroid Build Coastguard Worker     TextureVk *sourceVk  = vk::GetImpl(srcTexture);
1325*8975f5c5SAndroid Build Coastguard Worker 
1326*8975f5c5SAndroid Build Coastguard Worker     // Make sure the source/destination targets are initialized and all staged updates are flushed.
1327*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(sourceVk->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
1328*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
1329*8975f5c5SAndroid Build Coastguard Worker 
1330*8975f5c5SAndroid Build Coastguard Worker     return vk::ImageHelper::CopyImageSubData(context, &sourceVk->getImage(), srcLevel, srcX, srcY,
1331*8975f5c5SAndroid Build Coastguard Worker                                              srcZ, mImage, dstLevel, dstX, dstY, dstZ, srcWidth,
1332*8975f5c5SAndroid Build Coastguard Worker                                              srcHeight, srcDepth);
1333*8975f5c5SAndroid Build Coastguard Worker }
1334*8975f5c5SAndroid Build Coastguard Worker 
copyCompressedTexture(const gl::Context * context,const gl::Texture * source)1335*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copyCompressedTexture(const gl::Context *context,
1336*8975f5c5SAndroid Build Coastguard Worker                                                const gl::Texture *source)
1337*8975f5c5SAndroid Build Coastguard Worker {
1338*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
1339*8975f5c5SAndroid Build Coastguard Worker     TextureVk *sourceVk  = vk::GetImpl(source);
1340*8975f5c5SAndroid Build Coastguard Worker 
1341*8975f5c5SAndroid Build Coastguard Worker     gl::TextureTarget sourceTarget = NonCubeTextureTypeToTarget(source->getType());
1342*8975f5c5SAndroid Build Coastguard Worker     constexpr GLint sourceLevelGL  = 0;
1343*8975f5c5SAndroid Build Coastguard Worker     constexpr GLint destLevelGL    = 0;
1344*8975f5c5SAndroid Build Coastguard Worker 
1345*8975f5c5SAndroid Build Coastguard Worker     const gl::InternalFormat &internalFormat = *source->getFormat(sourceTarget, sourceLevelGL).info;
1346*8975f5c5SAndroid Build Coastguard Worker     const vk::Format &vkFormat =
1347*8975f5c5SAndroid Build Coastguard Worker         contextVk->getRenderer()->getFormat(internalFormat.sizedInternalFormat);
1348*8975f5c5SAndroid Build Coastguard Worker     const gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevelGL)),
1349*8975f5c5SAndroid Build Coastguard Worker                            static_cast<int>(source->getHeight(sourceTarget, sourceLevelGL)),
1350*8975f5c5SAndroid Build Coastguard Worker                            static_cast<int>(source->getDepth(sourceTarget, sourceLevelGL)));
1351*8975f5c5SAndroid Build Coastguard Worker     const gl::ImageIndex destIndex = gl::ImageIndex::MakeFromTarget(sourceTarget, destLevelGL, 1);
1352*8975f5c5SAndroid Build Coastguard Worker 
1353*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(redefineLevel(context, destIndex, vkFormat, size));
1354*8975f5c5SAndroid Build Coastguard Worker 
1355*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(sourceVk->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
1356*8975f5c5SAndroid Build Coastguard Worker 
1357*8975f5c5SAndroid Build Coastguard Worker     return copySubImageImplWithTransfer(contextVk, destIndex, gl::kOffsetZero, vkFormat,
1358*8975f5c5SAndroid Build Coastguard Worker                                         gl::LevelIndex(sourceLevelGL), 0,
1359*8975f5c5SAndroid Build Coastguard Worker                                         gl::Box(gl::kOffsetZero, size), &sourceVk->getImage());
1360*8975f5c5SAndroid Build Coastguard Worker }
1361*8975f5c5SAndroid Build Coastguard Worker 
copySubImageImpl(const gl::Context * context,const gl::ImageIndex & index,const gl::Offset & destOffset,const gl::Rectangle & sourceArea,const gl::InternalFormat & internalFormat,gl::Framebuffer * source)1362*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copySubImageImpl(const gl::Context *context,
1363*8975f5c5SAndroid Build Coastguard Worker                                           const gl::ImageIndex &index,
1364*8975f5c5SAndroid Build Coastguard Worker                                           const gl::Offset &destOffset,
1365*8975f5c5SAndroid Build Coastguard Worker                                           const gl::Rectangle &sourceArea,
1366*8975f5c5SAndroid Build Coastguard Worker                                           const gl::InternalFormat &internalFormat,
1367*8975f5c5SAndroid Build Coastguard Worker                                           gl::Framebuffer *source)
1368*8975f5c5SAndroid Build Coastguard Worker {
1369*8975f5c5SAndroid Build Coastguard Worker     gl::Extents fbSize = source->getReadColorAttachment()->getSize();
1370*8975f5c5SAndroid Build Coastguard Worker     gl::Rectangle clippedSourceArea;
1371*8975f5c5SAndroid Build Coastguard Worker     if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height),
1372*8975f5c5SAndroid Build Coastguard Worker                        &clippedSourceArea))
1373*8975f5c5SAndroid Build Coastguard Worker     {
1374*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
1375*8975f5c5SAndroid Build Coastguard Worker     }
1376*8975f5c5SAndroid Build Coastguard Worker 
1377*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk         = vk::GetImpl(context);
1378*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer       = contextVk->getRenderer();
1379*8975f5c5SAndroid Build Coastguard Worker     FramebufferVk *framebufferVk = vk::GetImpl(source);
1380*8975f5c5SAndroid Build Coastguard Worker 
1381*8975f5c5SAndroid Build Coastguard Worker     const gl::ImageIndex offsetImageIndex = getNativeImageIndex(index);
1382*8975f5c5SAndroid Build Coastguard Worker 
1383*8975f5c5SAndroid Build Coastguard Worker     // If negative offsets are given, clippedSourceArea ensures we don't read from those offsets.
1384*8975f5c5SAndroid Build Coastguard Worker     // However, that changes the sourceOffset->destOffset mapping.  Here, destOffset is shifted by
1385*8975f5c5SAndroid Build Coastguard Worker     // the same amount as clipped to correct the error.
1386*8975f5c5SAndroid Build Coastguard Worker     VkImageType imageType = gl_vk::GetImageType(mState.getType());
1387*8975f5c5SAndroid Build Coastguard Worker     int zOffset           = (imageType == VK_IMAGE_TYPE_3D) ? destOffset.z : 0;
1388*8975f5c5SAndroid Build Coastguard Worker     const gl::Offset modifiedDestOffset(destOffset.x + clippedSourceArea.x - sourceArea.x,
1389*8975f5c5SAndroid Build Coastguard Worker                                         destOffset.y + clippedSourceArea.y - sourceArea.y, zOffset);
1390*8975f5c5SAndroid Build Coastguard Worker 
1391*8975f5c5SAndroid Build Coastguard Worker     RenderTargetVk *colorReadRT = framebufferVk->getColorReadRenderTarget();
1392*8975f5c5SAndroid Build Coastguard Worker 
1393*8975f5c5SAndroid Build Coastguard Worker     angle::FormatID srcIntendedFormatID = colorReadRT->getImageIntendedFormatID();
1394*8975f5c5SAndroid Build Coastguard Worker     angle::FormatID srcActualFormatID   = colorReadRT->getImageActualFormatID();
1395*8975f5c5SAndroid Build Coastguard Worker     VkImageTiling srcTilingMode         = colorReadRT->getImageForCopy().getTilingMode();
1396*8975f5c5SAndroid Build Coastguard Worker     const vk::Format &dstFormat         = renderer->getFormat(internalFormat.sizedInternalFormat);
1397*8975f5c5SAndroid Build Coastguard Worker     angle::FormatID dstIntendedFormatID = dstFormat.getIntendedFormatID();
1398*8975f5c5SAndroid Build Coastguard Worker     angle::FormatID dstActualFormatID = dstFormat.getActualImageFormatID(getRequiredImageAccess());
1399*8975f5c5SAndroid Build Coastguard Worker     VkImageTiling destTilingMode      = getTilingMode();
1400*8975f5c5SAndroid Build Coastguard Worker 
1401*8975f5c5SAndroid Build Coastguard Worker     bool isViewportFlipY = contextVk->isViewportFlipEnabledForReadFBO();
1402*8975f5c5SAndroid Build Coastguard Worker 
1403*8975f5c5SAndroid Build Coastguard Worker     gl::Box clippedSourceBox(clippedSourceArea.x, clippedSourceArea.y, colorReadRT->getLayerIndex(),
1404*8975f5c5SAndroid Build Coastguard Worker                              clippedSourceArea.width, clippedSourceArea.height, 1);
1405*8975f5c5SAndroid Build Coastguard Worker 
1406*8975f5c5SAndroid Build Coastguard Worker     // If it's possible to perform the copy with a transfer, that's the best option.
1407*8975f5c5SAndroid Build Coastguard Worker     if (CanCopyWithTransferForTexImage(renderer, srcIntendedFormatID, srcActualFormatID,
1408*8975f5c5SAndroid Build Coastguard Worker                                        srcTilingMode, dstIntendedFormatID, dstActualFormatID,
1409*8975f5c5SAndroid Build Coastguard Worker                                        destTilingMode, isViewportFlipY))
1410*8975f5c5SAndroid Build Coastguard Worker     {
1411*8975f5c5SAndroid Build Coastguard Worker         return copySubImageImplWithTransfer(contextVk, offsetImageIndex, modifiedDestOffset,
1412*8975f5c5SAndroid Build Coastguard Worker                                             dstFormat, colorReadRT->getLevelIndex(),
1413*8975f5c5SAndroid Build Coastguard Worker                                             colorReadRT->getLayerIndex(), clippedSourceBox,
1414*8975f5c5SAndroid Build Coastguard Worker                                             &colorReadRT->getImageForCopy());
1415*8975f5c5SAndroid Build Coastguard Worker     }
1416*8975f5c5SAndroid Build Coastguard Worker 
1417*8975f5c5SAndroid Build Coastguard Worker     // If it's possible to perform the copy with a draw call, do that.
1418*8975f5c5SAndroid Build Coastguard Worker     if (CanCopyWithDraw(renderer, srcActualFormatID, srcTilingMode, dstActualFormatID,
1419*8975f5c5SAndroid Build Coastguard Worker                         destTilingMode))
1420*8975f5c5SAndroid Build Coastguard Worker     {
1421*8975f5c5SAndroid Build Coastguard Worker         // Layer count can only be 1 as the source is a framebuffer.
1422*8975f5c5SAndroid Build Coastguard Worker         ASSERT(offsetImageIndex.getLayerCount() == 1);
1423*8975f5c5SAndroid Build Coastguard Worker 
1424*8975f5c5SAndroid Build Coastguard Worker         // Flush the render pass, which may incur a vkQueueSubmit, before taking any views.
1425*8975f5c5SAndroid Build Coastguard Worker         // Otherwise the view serials would not reflect the render pass they are really used in.
1426*8975f5c5SAndroid Build Coastguard Worker         // http://crbug.com/1272266#c22
1427*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(
1428*8975f5c5SAndroid Build Coastguard Worker             contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::PrepareForImageCopy));
1429*8975f5c5SAndroid Build Coastguard Worker 
1430*8975f5c5SAndroid Build Coastguard Worker         const vk::ImageView *copyImageView = nullptr;
1431*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(colorReadRT->getCopyImageView(contextVk, &copyImageView));
1432*8975f5c5SAndroid Build Coastguard Worker 
1433*8975f5c5SAndroid Build Coastguard Worker         return copySubImageImplWithDraw(contextVk, offsetImageIndex, modifiedDestOffset, dstFormat,
1434*8975f5c5SAndroid Build Coastguard Worker                                         colorReadRT->getLevelIndex(), clippedSourceBox,
1435*8975f5c5SAndroid Build Coastguard Worker                                         isViewportFlipY, false, false, false,
1436*8975f5c5SAndroid Build Coastguard Worker                                         &colorReadRT->getImageForCopy(), copyImageView,
1437*8975f5c5SAndroid Build Coastguard Worker                                         contextVk->getRotationReadFramebuffer());
1438*8975f5c5SAndroid Build Coastguard Worker     }
1439*8975f5c5SAndroid Build Coastguard Worker 
1440*8975f5c5SAndroid Build Coastguard Worker     ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_HIGH,
1441*8975f5c5SAndroid Build Coastguard Worker                           "Texture copied on CPU due to format restrictions");
1442*8975f5c5SAndroid Build Coastguard Worker 
1443*8975f5c5SAndroid Build Coastguard Worker     // Do a CPU readback that does the conversion, and then stage the change to the pixel buffer.
1444*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mImage->stageSubresourceUpdateFromFramebuffer(
1445*8975f5c5SAndroid Build Coastguard Worker         context, offsetImageIndex, clippedSourceArea, modifiedDestOffset,
1446*8975f5c5SAndroid Build Coastguard Worker         gl::Extents(clippedSourceArea.width, clippedSourceArea.height, 1), internalFormat,
1447*8975f5c5SAndroid Build Coastguard Worker         getRequiredImageAccess(), framebufferVk));
1448*8975f5c5SAndroid Build Coastguard Worker 
1449*8975f5c5SAndroid Build Coastguard Worker     // Flush out staged update if possible
1450*8975f5c5SAndroid Build Coastguard Worker     if (shouldUpdateBeFlushed(gl::LevelIndex(index.getLevelIndex()), dstActualFormatID))
1451*8975f5c5SAndroid Build Coastguard Worker     {
1452*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(flushImageStagedUpdates(contextVk));
1453*8975f5c5SAndroid Build Coastguard Worker     }
1454*8975f5c5SAndroid Build Coastguard Worker 
1455*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1456*8975f5c5SAndroid Build Coastguard Worker }
1457*8975f5c5SAndroid Build Coastguard Worker 
copySubTextureImpl(ContextVk * contextVk,const gl::ImageIndex & index,const gl::Offset & dstOffset,const gl::InternalFormat & dstFormat,gl::LevelIndex sourceLevelGL,const gl::Box & sourceBox,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,TextureVk * source)1458*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk,
1459*8975f5c5SAndroid Build Coastguard Worker                                             const gl::ImageIndex &index,
1460*8975f5c5SAndroid Build Coastguard Worker                                             const gl::Offset &dstOffset,
1461*8975f5c5SAndroid Build Coastguard Worker                                             const gl::InternalFormat &dstFormat,
1462*8975f5c5SAndroid Build Coastguard Worker                                             gl::LevelIndex sourceLevelGL,
1463*8975f5c5SAndroid Build Coastguard Worker                                             const gl::Box &sourceBox,
1464*8975f5c5SAndroid Build Coastguard Worker                                             bool unpackFlipY,
1465*8975f5c5SAndroid Build Coastguard Worker                                             bool unpackPremultiplyAlpha,
1466*8975f5c5SAndroid Build Coastguard Worker                                             bool unpackUnmultiplyAlpha,
1467*8975f5c5SAndroid Build Coastguard Worker                                             TextureVk *source)
1468*8975f5c5SAndroid Build Coastguard Worker {
1469*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
1470*8975f5c5SAndroid Build Coastguard Worker 
1471*8975f5c5SAndroid Build Coastguard Worker     const angle::Format &srcIntendedFormat = source->getImage().getIntendedFormat();
1472*8975f5c5SAndroid Build Coastguard Worker     angle::FormatID srcFormatID            = source->getImage().getActualFormatID();
1473*8975f5c5SAndroid Build Coastguard Worker     VkImageTiling srcTilingMode            = source->getImage().getTilingMode();
1474*8975f5c5SAndroid Build Coastguard Worker     const vk::Format &dstVkFormat          = renderer->getFormat(dstFormat.sizedInternalFormat);
1475*8975f5c5SAndroid Build Coastguard Worker     angle::FormatID dstFormatID = dstVkFormat.getActualImageFormatID(getRequiredImageAccess());
1476*8975f5c5SAndroid Build Coastguard Worker     VkImageTiling dstTilingMode = getTilingMode();
1477*8975f5c5SAndroid Build Coastguard Worker 
1478*8975f5c5SAndroid Build Coastguard Worker     const gl::ImageIndex offsetImageIndex = getNativeImageIndex(index);
1479*8975f5c5SAndroid Build Coastguard Worker 
1480*8975f5c5SAndroid Build Coastguard Worker     // If it's possible to perform the copy with a transfer, that's the best option.
1481*8975f5c5SAndroid Build Coastguard Worker     if (CanCopyWithTransferForCopyTexture(
1482*8975f5c5SAndroid Build Coastguard Worker             renderer, source->getImage(), srcTilingMode, dstVkFormat.getIntendedFormatID(),
1483*8975f5c5SAndroid Build Coastguard Worker             dstFormatID, dstTilingMode, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha))
1484*8975f5c5SAndroid Build Coastguard Worker     {
1485*8975f5c5SAndroid Build Coastguard Worker         return copySubImageImplWithTransfer(contextVk, offsetImageIndex, dstOffset, dstVkFormat,
1486*8975f5c5SAndroid Build Coastguard Worker                                             sourceLevelGL, sourceBox.z, sourceBox,
1487*8975f5c5SAndroid Build Coastguard Worker                                             &source->getImage());
1488*8975f5c5SAndroid Build Coastguard Worker     }
1489*8975f5c5SAndroid Build Coastguard Worker 
1490*8975f5c5SAndroid Build Coastguard Worker     // If it's possible to perform the copy with a draw call, do that.
1491*8975f5c5SAndroid Build Coastguard Worker     if (CanCopyWithDraw(renderer, srcFormatID, srcTilingMode, dstFormatID, dstTilingMode))
1492*8975f5c5SAndroid Build Coastguard Worker     {
1493*8975f5c5SAndroid Build Coastguard Worker         // Flush the render pass, which may incur a vkQueueSubmit, before taking any views.
1494*8975f5c5SAndroid Build Coastguard Worker         // Otherwise the view serials would not reflect the render pass they are really used in.
1495*8975f5c5SAndroid Build Coastguard Worker         // http://crbug.com/1272266#c22
1496*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(
1497*8975f5c5SAndroid Build Coastguard Worker             contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::PrepareForImageCopy));
1498*8975f5c5SAndroid Build Coastguard Worker 
1499*8975f5c5SAndroid Build Coastguard Worker         return copySubImageImplWithDraw(
1500*8975f5c5SAndroid Build Coastguard Worker             contextVk, offsetImageIndex, dstOffset, dstVkFormat, sourceLevelGL, sourceBox, false,
1501*8975f5c5SAndroid Build Coastguard Worker             unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha, &source->getImage(),
1502*8975f5c5SAndroid Build Coastguard Worker             &source->getCopyImageView(), SurfaceRotation::Identity);
1503*8975f5c5SAndroid Build Coastguard Worker     }
1504*8975f5c5SAndroid Build Coastguard Worker 
1505*8975f5c5SAndroid Build Coastguard Worker     ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_HIGH,
1506*8975f5c5SAndroid Build Coastguard Worker                           "Texture copied on CPU due to format restrictions");
1507*8975f5c5SAndroid Build Coastguard Worker 
1508*8975f5c5SAndroid Build Coastguard Worker     // Read back the requested region of the source texture
1509*8975f5c5SAndroid Build Coastguard Worker     vk::RendererScoped<vk::BufferHelper> bufferHelper(renderer);
1510*8975f5c5SAndroid Build Coastguard Worker     uint8_t *sourceData = nullptr;
1511*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(source->copyImageDataToBufferAndGetData(
1512*8975f5c5SAndroid Build Coastguard Worker         contextVk, sourceLevelGL, sourceBox.depth, sourceBox,
1513*8975f5c5SAndroid Build Coastguard Worker         RenderPassClosureReason::CopyTextureOnCPU, &bufferHelper.get(), &sourceData));
1514*8975f5c5SAndroid Build Coastguard Worker 
1515*8975f5c5SAndroid Build Coastguard Worker     const angle::Format &srcTextureFormat = source->getImage().getActualFormat();
1516*8975f5c5SAndroid Build Coastguard Worker     const angle::Format &dstTextureFormat =
1517*8975f5c5SAndroid Build Coastguard Worker         dstVkFormat.getActualImageFormat(getRequiredImageAccess());
1518*8975f5c5SAndroid Build Coastguard Worker     size_t destinationAllocationSize =
1519*8975f5c5SAndroid Build Coastguard Worker         sourceBox.width * sourceBox.height * sourceBox.depth * dstTextureFormat.pixelBytes;
1520*8975f5c5SAndroid Build Coastguard Worker 
1521*8975f5c5SAndroid Build Coastguard Worker     // Allocate memory in the destination texture for the copy/conversion
1522*8975f5c5SAndroid Build Coastguard Worker     uint32_t stagingBaseLayer =
1523*8975f5c5SAndroid Build Coastguard Worker         offsetImageIndex.hasLayer() ? offsetImageIndex.getLayerIndex() : dstOffset.z;
1524*8975f5c5SAndroid Build Coastguard Worker     uint32_t stagingLayerCount = sourceBox.depth;
1525*8975f5c5SAndroid Build Coastguard Worker     gl::Offset stagingOffset   = dstOffset;
1526*8975f5c5SAndroid Build Coastguard Worker     gl::Extents stagingExtents(sourceBox.width, sourceBox.height, sourceBox.depth);
1527*8975f5c5SAndroid Build Coastguard Worker     bool is3D = gl_vk::GetImageType(mState.getType()) == VK_IMAGE_TYPE_3D;
1528*8975f5c5SAndroid Build Coastguard Worker 
1529*8975f5c5SAndroid Build Coastguard Worker     if (is3D)
1530*8975f5c5SAndroid Build Coastguard Worker     {
1531*8975f5c5SAndroid Build Coastguard Worker         stagingBaseLayer  = 0;
1532*8975f5c5SAndroid Build Coastguard Worker         stagingLayerCount = 1;
1533*8975f5c5SAndroid Build Coastguard Worker     }
1534*8975f5c5SAndroid Build Coastguard Worker     else
1535*8975f5c5SAndroid Build Coastguard Worker     {
1536*8975f5c5SAndroid Build Coastguard Worker         stagingOffset.z      = 0;
1537*8975f5c5SAndroid Build Coastguard Worker         stagingExtents.depth = 1;
1538*8975f5c5SAndroid Build Coastguard Worker     }
1539*8975f5c5SAndroid Build Coastguard Worker 
1540*8975f5c5SAndroid Build Coastguard Worker     const gl::ImageIndex stagingIndex = gl::ImageIndex::Make2DArrayRange(
1541*8975f5c5SAndroid Build Coastguard Worker         offsetImageIndex.getLevelIndex(), stagingBaseLayer, stagingLayerCount);
1542*8975f5c5SAndroid Build Coastguard Worker 
1543*8975f5c5SAndroid Build Coastguard Worker     uint8_t *destData = nullptr;
1544*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mImage->stageSubresourceUpdateAndGetData(contextVk, destinationAllocationSize,
1545*8975f5c5SAndroid Build Coastguard Worker                                                        stagingIndex, stagingExtents, stagingOffset,
1546*8975f5c5SAndroid Build Coastguard Worker                                                        &destData, dstFormatID));
1547*8975f5c5SAndroid Build Coastguard Worker 
1548*8975f5c5SAndroid Build Coastguard Worker     // Source and dst data is tightly packed
1549*8975f5c5SAndroid Build Coastguard Worker     GLuint srcDataRowPitch = sourceBox.width * srcTextureFormat.pixelBytes;
1550*8975f5c5SAndroid Build Coastguard Worker     GLuint dstDataRowPitch = sourceBox.width * dstTextureFormat.pixelBytes;
1551*8975f5c5SAndroid Build Coastguard Worker 
1552*8975f5c5SAndroid Build Coastguard Worker     GLuint srcDataDepthPitch = srcDataRowPitch * sourceBox.height;
1553*8975f5c5SAndroid Build Coastguard Worker     GLuint dstDataDepthPitch = dstDataRowPitch * sourceBox.height;
1554*8975f5c5SAndroid Build Coastguard Worker 
1555*8975f5c5SAndroid Build Coastguard Worker     rx::PixelReadFunction pixelReadFunction   = srcTextureFormat.pixelReadFunction;
1556*8975f5c5SAndroid Build Coastguard Worker     rx::PixelWriteFunction pixelWriteFunction = dstTextureFormat.pixelWriteFunction;
1557*8975f5c5SAndroid Build Coastguard Worker 
1558*8975f5c5SAndroid Build Coastguard Worker     // Fix up the read/write functions for the sake of luminance/alpha that are emulated with
1559*8975f5c5SAndroid Build Coastguard Worker     // formats whose channels don't correspond to the original format (alpha is emulated with red,
1560*8975f5c5SAndroid Build Coastguard Worker     // and luminance/alpha is emulated with red/green).
1561*8975f5c5SAndroid Build Coastguard Worker     if (srcIntendedFormat.isLUMA())
1562*8975f5c5SAndroid Build Coastguard Worker     {
1563*8975f5c5SAndroid Build Coastguard Worker         pixelReadFunction = srcIntendedFormat.pixelReadFunction;
1564*8975f5c5SAndroid Build Coastguard Worker     }
1565*8975f5c5SAndroid Build Coastguard Worker     if (dstVkFormat.getIntendedFormat().isLUMA())
1566*8975f5c5SAndroid Build Coastguard Worker     {
1567*8975f5c5SAndroid Build Coastguard Worker         pixelWriteFunction = dstVkFormat.getIntendedFormat().pixelWriteFunction;
1568*8975f5c5SAndroid Build Coastguard Worker     }
1569*8975f5c5SAndroid Build Coastguard Worker 
1570*8975f5c5SAndroid Build Coastguard Worker     CopyImageCHROMIUM(sourceData, srcDataRowPitch, srcTextureFormat.pixelBytes, srcDataDepthPitch,
1571*8975f5c5SAndroid Build Coastguard Worker                       pixelReadFunction, destData, dstDataRowPitch, dstTextureFormat.pixelBytes,
1572*8975f5c5SAndroid Build Coastguard Worker                       dstDataDepthPitch, pixelWriteFunction, dstFormat.format,
1573*8975f5c5SAndroid Build Coastguard Worker                       dstFormat.componentType, sourceBox.width, sourceBox.height, sourceBox.depth,
1574*8975f5c5SAndroid Build Coastguard Worker                       unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
1575*8975f5c5SAndroid Build Coastguard Worker 
1576*8975f5c5SAndroid Build Coastguard Worker     if (shouldUpdateBeFlushed(gl::LevelIndex(index.getLevelIndex()), dstFormatID))
1577*8975f5c5SAndroid Build Coastguard Worker     {
1578*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(flushImageStagedUpdates(contextVk));
1579*8975f5c5SAndroid Build Coastguard Worker     }
1580*8975f5c5SAndroid Build Coastguard Worker 
1581*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1582*8975f5c5SAndroid Build Coastguard Worker }
1583*8975f5c5SAndroid Build Coastguard Worker 
copySubImageImplWithTransfer(ContextVk * contextVk,const gl::ImageIndex & index,const gl::Offset & dstOffset,const vk::Format & dstFormat,gl::LevelIndex sourceLevelGL,size_t sourceLayer,const gl::Box & sourceBox,vk::ImageHelper * srcImage)1584*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk,
1585*8975f5c5SAndroid Build Coastguard Worker                                                       const gl::ImageIndex &index,
1586*8975f5c5SAndroid Build Coastguard Worker                                                       const gl::Offset &dstOffset,
1587*8975f5c5SAndroid Build Coastguard Worker                                                       const vk::Format &dstFormat,
1588*8975f5c5SAndroid Build Coastguard Worker                                                       gl::LevelIndex sourceLevelGL,
1589*8975f5c5SAndroid Build Coastguard Worker                                                       size_t sourceLayer,
1590*8975f5c5SAndroid Build Coastguard Worker                                                       const gl::Box &sourceBox,
1591*8975f5c5SAndroid Build Coastguard Worker                                                       vk::ImageHelper *srcImage)
1592*8975f5c5SAndroid Build Coastguard Worker {
1593*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
1594*8975f5c5SAndroid Build Coastguard Worker 
1595*8975f5c5SAndroid Build Coastguard Worker     gl::LevelIndex level(index.getLevelIndex());
1596*8975f5c5SAndroid Build Coastguard Worker     uint32_t baseLayer  = index.hasLayer() ? index.getLayerIndex() : dstOffset.z;
1597*8975f5c5SAndroid Build Coastguard Worker     uint32_t layerCount = sourceBox.depth;
1598*8975f5c5SAndroid Build Coastguard Worker 
1599*8975f5c5SAndroid Build Coastguard Worker     gl::Offset srcOffset = {sourceBox.x, sourceBox.y, sourceBox.z};
1600*8975f5c5SAndroid Build Coastguard Worker     gl::Extents extents  = {sourceBox.width, sourceBox.height, sourceBox.depth};
1601*8975f5c5SAndroid Build Coastguard Worker 
1602*8975f5c5SAndroid Build Coastguard Worker     // Change source layout if necessary
1603*8975f5c5SAndroid Build Coastguard Worker     vk::CommandBufferAccess access;
1604*8975f5c5SAndroid Build Coastguard Worker     access.onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, srcImage);
1605*8975f5c5SAndroid Build Coastguard Worker 
1606*8975f5c5SAndroid Build Coastguard Worker     VkImageSubresourceLayers srcSubresource = {};
1607*8975f5c5SAndroid Build Coastguard Worker     srcSubresource.aspectMask               = VK_IMAGE_ASPECT_COLOR_BIT;
1608*8975f5c5SAndroid Build Coastguard Worker     srcSubresource.mipLevel                 = srcImage->toVkLevel(sourceLevelGL).get();
1609*8975f5c5SAndroid Build Coastguard Worker     srcSubresource.baseArrayLayer           = static_cast<uint32_t>(sourceLayer);
1610*8975f5c5SAndroid Build Coastguard Worker     srcSubresource.layerCount               = layerCount;
1611*8975f5c5SAndroid Build Coastguard Worker 
1612*8975f5c5SAndroid Build Coastguard Worker     bool isSrc3D  = srcImage->getExtents().depth > 1;
1613*8975f5c5SAndroid Build Coastguard Worker     bool isDest3D = gl_vk::GetImageType(mState.getType()) == VK_IMAGE_TYPE_3D;
1614*8975f5c5SAndroid Build Coastguard Worker 
1615*8975f5c5SAndroid Build Coastguard Worker     if (isSrc3D)
1616*8975f5c5SAndroid Build Coastguard Worker     {
1617*8975f5c5SAndroid Build Coastguard Worker         Set3DBaseArrayLayerAndLayerCount(&srcSubresource);
1618*8975f5c5SAndroid Build Coastguard Worker     }
1619*8975f5c5SAndroid Build Coastguard Worker     else
1620*8975f5c5SAndroid Build Coastguard Worker     {
1621*8975f5c5SAndroid Build Coastguard Worker         ASSERT(srcSubresource.baseArrayLayer == static_cast<uint32_t>(srcOffset.z));
1622*8975f5c5SAndroid Build Coastguard Worker         srcOffset.z = 0;
1623*8975f5c5SAndroid Build Coastguard Worker     }
1624*8975f5c5SAndroid Build Coastguard Worker 
1625*8975f5c5SAndroid Build Coastguard Worker     gl::Offset dstOffsetModified = dstOffset;
1626*8975f5c5SAndroid Build Coastguard Worker     if (!isDest3D)
1627*8975f5c5SAndroid Build Coastguard Worker     {
1628*8975f5c5SAndroid Build Coastguard Worker         // If destination is not 3D, destination offset must be 0.
1629*8975f5c5SAndroid Build Coastguard Worker         dstOffsetModified.z = 0;
1630*8975f5c5SAndroid Build Coastguard Worker     }
1631*8975f5c5SAndroid Build Coastguard Worker 
1632*8975f5c5SAndroid Build Coastguard Worker     // Perform self-copies through a staging buffer.
1633*8975f5c5SAndroid Build Coastguard Worker     // TODO: optimize to copy directly if possible.  http://anglebug.com/42263319
1634*8975f5c5SAndroid Build Coastguard Worker     bool isSelfCopy = mImage == srcImage;
1635*8975f5c5SAndroid Build Coastguard Worker 
1636*8975f5c5SAndroid Build Coastguard Worker     // If destination is valid, copy the source directly into it.
1637*8975f5c5SAndroid Build Coastguard Worker     if (shouldUpdateBeFlushed(level, dstFormat.getActualImageFormatID(getRequiredImageAccess())) &&
1638*8975f5c5SAndroid Build Coastguard Worker         !isSelfCopy)
1639*8975f5c5SAndroid Build Coastguard Worker     {
1640*8975f5c5SAndroid Build Coastguard Worker         // Make sure any updates to the image are already flushed.
1641*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
1642*8975f5c5SAndroid Build Coastguard Worker 
1643*8975f5c5SAndroid Build Coastguard Worker         access.onImageTransferWrite(level, 1, baseLayer, layerCount, VK_IMAGE_ASPECT_COLOR_BIT,
1644*8975f5c5SAndroid Build Coastguard Worker                                     mImage);
1645*8975f5c5SAndroid Build Coastguard Worker 
1646*8975f5c5SAndroid Build Coastguard Worker         vk::OutsideRenderPassCommandBuffer *commandBuffer;
1647*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
1648*8975f5c5SAndroid Build Coastguard Worker 
1649*8975f5c5SAndroid Build Coastguard Worker         VkImageSubresourceLayers destSubresource = srcSubresource;
1650*8975f5c5SAndroid Build Coastguard Worker         destSubresource.mipLevel                 = mImage->toVkLevel(level).get();
1651*8975f5c5SAndroid Build Coastguard Worker         destSubresource.baseArrayLayer           = baseLayer;
1652*8975f5c5SAndroid Build Coastguard Worker         destSubresource.layerCount               = layerCount;
1653*8975f5c5SAndroid Build Coastguard Worker 
1654*8975f5c5SAndroid Build Coastguard Worker         if (isDest3D)
1655*8975f5c5SAndroid Build Coastguard Worker         {
1656*8975f5c5SAndroid Build Coastguard Worker             Set3DBaseArrayLayerAndLayerCount(&destSubresource);
1657*8975f5c5SAndroid Build Coastguard Worker         }
1658*8975f5c5SAndroid Build Coastguard Worker         else if (!isSrc3D)
1659*8975f5c5SAndroid Build Coastguard Worker         {
1660*8975f5c5SAndroid Build Coastguard Worker             // extents.depth should be set to layer count if any of the source or destination is a
1661*8975f5c5SAndroid Build Coastguard Worker             // 2D Array.  If both are 2D Array, it should be set to 1.
1662*8975f5c5SAndroid Build Coastguard Worker             extents.depth = 1;
1663*8975f5c5SAndroid Build Coastguard Worker         }
1664*8975f5c5SAndroid Build Coastguard Worker 
1665*8975f5c5SAndroid Build Coastguard Worker         vk::ImageHelper::Copy(renderer, srcImage, mImage, srcOffset, dstOffsetModified, extents,
1666*8975f5c5SAndroid Build Coastguard Worker                               srcSubresource, destSubresource, commandBuffer);
1667*8975f5c5SAndroid Build Coastguard Worker     }
1668*8975f5c5SAndroid Build Coastguard Worker     else
1669*8975f5c5SAndroid Build Coastguard Worker     {
1670*8975f5c5SAndroid Build Coastguard Worker         // Create a temporary image to stage the copy
1671*8975f5c5SAndroid Build Coastguard Worker         std::unique_ptr<vk::RefCounted<vk::ImageHelper>> stagingImage;
1672*8975f5c5SAndroid Build Coastguard Worker         stagingImage = std::make_unique<vk::RefCounted<vk::ImageHelper>>();
1673*8975f5c5SAndroid Build Coastguard Worker 
1674*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(stagingImage->get().init2DStaging(
1675*8975f5c5SAndroid Build Coastguard Worker             contextVk, mState.hasProtectedContent(), renderer->getMemoryProperties(),
1676*8975f5c5SAndroid Build Coastguard Worker             gl::Extents(sourceBox.width, sourceBox.height, 1), dstFormat.getIntendedFormatID(),
1677*8975f5c5SAndroid Build Coastguard Worker             dstFormat.getActualImageFormatID(getRequiredImageAccess()), kTransferImageFlags,
1678*8975f5c5SAndroid Build Coastguard Worker             layerCount));
1679*8975f5c5SAndroid Build Coastguard Worker 
1680*8975f5c5SAndroid Build Coastguard Worker         access.onImageTransferWrite(gl::LevelIndex(0), 1, 0, layerCount, VK_IMAGE_ASPECT_COLOR_BIT,
1681*8975f5c5SAndroid Build Coastguard Worker                                     &stagingImage->get());
1682*8975f5c5SAndroid Build Coastguard Worker 
1683*8975f5c5SAndroid Build Coastguard Worker         vk::OutsideRenderPassCommandBuffer *commandBuffer;
1684*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
1685*8975f5c5SAndroid Build Coastguard Worker 
1686*8975f5c5SAndroid Build Coastguard Worker         VkImageSubresourceLayers destSubresource = srcSubresource;
1687*8975f5c5SAndroid Build Coastguard Worker         destSubresource.mipLevel                 = 0;
1688*8975f5c5SAndroid Build Coastguard Worker         destSubresource.baseArrayLayer           = 0;
1689*8975f5c5SAndroid Build Coastguard Worker         destSubresource.layerCount               = layerCount;
1690*8975f5c5SAndroid Build Coastguard Worker 
1691*8975f5c5SAndroid Build Coastguard Worker         if (!isSrc3D)
1692*8975f5c5SAndroid Build Coastguard Worker         {
1693*8975f5c5SAndroid Build Coastguard Worker             // extents.depth should be set to layer count if any of the source or destination is a
1694*8975f5c5SAndroid Build Coastguard Worker             // 2D Array.  If both are 2D Array, it should be set to 1.
1695*8975f5c5SAndroid Build Coastguard Worker             extents.depth = 1;
1696*8975f5c5SAndroid Build Coastguard Worker         }
1697*8975f5c5SAndroid Build Coastguard Worker 
1698*8975f5c5SAndroid Build Coastguard Worker         vk::ImageHelper::Copy(renderer, srcImage, &stagingImage->get(), srcOffset, gl::kOffsetZero,
1699*8975f5c5SAndroid Build Coastguard Worker                               extents, srcSubresource, destSubresource, commandBuffer);
1700*8975f5c5SAndroid Build Coastguard Worker 
1701*8975f5c5SAndroid Build Coastguard Worker         // Stage the copy for when the image storage is actually created.
1702*8975f5c5SAndroid Build Coastguard Worker         VkImageType imageType = gl_vk::GetImageType(mState.getType());
1703*8975f5c5SAndroid Build Coastguard Worker         const gl::ImageIndex stagingIndex =
1704*8975f5c5SAndroid Build Coastguard Worker             gl::ImageIndex::Make2DArrayRange(level.get(), baseLayer, layerCount);
1705*8975f5c5SAndroid Build Coastguard Worker         mImage->stageSubresourceUpdateFromImage(stagingImage.release(), stagingIndex,
1706*8975f5c5SAndroid Build Coastguard Worker                                                 vk::LevelIndex(0), dstOffsetModified, extents,
1707*8975f5c5SAndroid Build Coastguard Worker                                                 imageType);
1708*8975f5c5SAndroid Build Coastguard Worker     }
1709*8975f5c5SAndroid Build Coastguard Worker 
1710*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1711*8975f5c5SAndroid Build Coastguard Worker }
1712*8975f5c5SAndroid Build Coastguard Worker 
copySubImageImplWithDraw(ContextVk * contextVk,const gl::ImageIndex & index,const gl::Offset & dstOffset,const vk::Format & dstFormat,gl::LevelIndex sourceLevelGL,const gl::Box & sourceBox,bool isSrcFlipY,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,vk::ImageHelper * srcImage,const vk::ImageView * srcView,SurfaceRotation srcFramebufferRotation)1713*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk,
1714*8975f5c5SAndroid Build Coastguard Worker                                                   const gl::ImageIndex &index,
1715*8975f5c5SAndroid Build Coastguard Worker                                                   const gl::Offset &dstOffset,
1716*8975f5c5SAndroid Build Coastguard Worker                                                   const vk::Format &dstFormat,
1717*8975f5c5SAndroid Build Coastguard Worker                                                   gl::LevelIndex sourceLevelGL,
1718*8975f5c5SAndroid Build Coastguard Worker                                                   const gl::Box &sourceBox,
1719*8975f5c5SAndroid Build Coastguard Worker                                                   bool isSrcFlipY,
1720*8975f5c5SAndroid Build Coastguard Worker                                                   bool unpackFlipY,
1721*8975f5c5SAndroid Build Coastguard Worker                                                   bool unpackPremultiplyAlpha,
1722*8975f5c5SAndroid Build Coastguard Worker                                                   bool unpackUnmultiplyAlpha,
1723*8975f5c5SAndroid Build Coastguard Worker                                                   vk::ImageHelper *srcImage,
1724*8975f5c5SAndroid Build Coastguard Worker                                                   const vk::ImageView *srcView,
1725*8975f5c5SAndroid Build Coastguard Worker                                                   SurfaceRotation srcFramebufferRotation)
1726*8975f5c5SAndroid Build Coastguard Worker {
1727*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
1728*8975f5c5SAndroid Build Coastguard Worker     UtilsVk &utilsVk       = contextVk->getUtils();
1729*8975f5c5SAndroid Build Coastguard Worker 
1730*8975f5c5SAndroid Build Coastguard Worker     // Potentially make adjustments for pre-rotation.
1731*8975f5c5SAndroid Build Coastguard Worker     gl::Box rotatedSourceBox = sourceBox;
1732*8975f5c5SAndroid Build Coastguard Worker     gl::Extents srcExtents   = srcImage->getLevelExtents2D(vk::LevelIndex(0));
1733*8975f5c5SAndroid Build Coastguard Worker     switch (srcFramebufferRotation)
1734*8975f5c5SAndroid Build Coastguard Worker     {
1735*8975f5c5SAndroid Build Coastguard Worker         case SurfaceRotation::Identity:
1736*8975f5c5SAndroid Build Coastguard Worker             // No adjustments needed
1737*8975f5c5SAndroid Build Coastguard Worker             break;
1738*8975f5c5SAndroid Build Coastguard Worker         case SurfaceRotation::Rotated90Degrees:
1739*8975f5c5SAndroid Build Coastguard Worker             // Turn off y-flip for 90 degrees, as we don't want it affecting the
1740*8975f5c5SAndroid Build Coastguard Worker             // shaderParams.srcOffset calculation done in UtilsVk::copyImage().
1741*8975f5c5SAndroid Build Coastguard Worker             ASSERT(isSrcFlipY);
1742*8975f5c5SAndroid Build Coastguard Worker             isSrcFlipY = false;
1743*8975f5c5SAndroid Build Coastguard Worker             std::swap(rotatedSourceBox.x, rotatedSourceBox.y);
1744*8975f5c5SAndroid Build Coastguard Worker             std::swap(rotatedSourceBox.width, rotatedSourceBox.height);
1745*8975f5c5SAndroid Build Coastguard Worker             std::swap(srcExtents.width, srcExtents.height);
1746*8975f5c5SAndroid Build Coastguard Worker             break;
1747*8975f5c5SAndroid Build Coastguard Worker         case SurfaceRotation::Rotated180Degrees:
1748*8975f5c5SAndroid Build Coastguard Worker             ASSERT(isSrcFlipY);
1749*8975f5c5SAndroid Build Coastguard Worker             rotatedSourceBox.x = srcExtents.width - sourceBox.x - sourceBox.width - 1;
1750*8975f5c5SAndroid Build Coastguard Worker             rotatedSourceBox.y = srcExtents.height - sourceBox.y - sourceBox.height - 1;
1751*8975f5c5SAndroid Build Coastguard Worker             break;
1752*8975f5c5SAndroid Build Coastguard Worker         case SurfaceRotation::Rotated270Degrees:
1753*8975f5c5SAndroid Build Coastguard Worker             // Turn off y-flip for 270 degrees, as we don't want it affecting the
1754*8975f5c5SAndroid Build Coastguard Worker             // shaderParams.srcOffset calculation done in UtilsVk::copyImage().  It is needed
1755*8975f5c5SAndroid Build Coastguard Worker             // within the shader (when it will affect how the shader looks-up the source pixel),
1756*8975f5c5SAndroid Build Coastguard Worker             // and so shaderParams.flipY is turned on at the right time within
1757*8975f5c5SAndroid Build Coastguard Worker             // UtilsVk::copyImage().
1758*8975f5c5SAndroid Build Coastguard Worker             ASSERT(isSrcFlipY);
1759*8975f5c5SAndroid Build Coastguard Worker             isSrcFlipY         = false;
1760*8975f5c5SAndroid Build Coastguard Worker             rotatedSourceBox.x = srcExtents.height - sourceBox.y - sourceBox.height - 1;
1761*8975f5c5SAndroid Build Coastguard Worker             rotatedSourceBox.y = srcExtents.width - sourceBox.x - sourceBox.width - 1;
1762*8975f5c5SAndroid Build Coastguard Worker             std::swap(rotatedSourceBox.width, rotatedSourceBox.height);
1763*8975f5c5SAndroid Build Coastguard Worker             std::swap(srcExtents.width, srcExtents.height);
1764*8975f5c5SAndroid Build Coastguard Worker             break;
1765*8975f5c5SAndroid Build Coastguard Worker         default:
1766*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
1767*8975f5c5SAndroid Build Coastguard Worker             break;
1768*8975f5c5SAndroid Build Coastguard Worker     }
1769*8975f5c5SAndroid Build Coastguard Worker 
1770*8975f5c5SAndroid Build Coastguard Worker     gl::LevelIndex level(index.getLevelIndex());
1771*8975f5c5SAndroid Build Coastguard Worker 
1772*8975f5c5SAndroid Build Coastguard Worker     UtilsVk::CopyImageParameters params;
1773*8975f5c5SAndroid Build Coastguard Worker     params.srcOffset[0]        = rotatedSourceBox.x;
1774*8975f5c5SAndroid Build Coastguard Worker     params.srcOffset[1]        = rotatedSourceBox.y;
1775*8975f5c5SAndroid Build Coastguard Worker     params.srcExtents[0]       = rotatedSourceBox.width;
1776*8975f5c5SAndroid Build Coastguard Worker     params.srcExtents[1]       = rotatedSourceBox.height;
1777*8975f5c5SAndroid Build Coastguard Worker     params.dstOffset[0]        = dstOffset.x;
1778*8975f5c5SAndroid Build Coastguard Worker     params.dstOffset[1]        = dstOffset.y;
1779*8975f5c5SAndroid Build Coastguard Worker     params.srcMip              = srcImage->toVkLevel(sourceLevelGL).get();
1780*8975f5c5SAndroid Build Coastguard Worker     params.srcSampleCount      = srcImage->getSamples();
1781*8975f5c5SAndroid Build Coastguard Worker     params.srcHeight           = srcExtents.height;
1782*8975f5c5SAndroid Build Coastguard Worker     params.dstMip              = level;
1783*8975f5c5SAndroid Build Coastguard Worker     params.srcPremultiplyAlpha = unpackPremultiplyAlpha && !unpackUnmultiplyAlpha;
1784*8975f5c5SAndroid Build Coastguard Worker     params.srcUnmultiplyAlpha  = unpackUnmultiplyAlpha && !unpackPremultiplyAlpha;
1785*8975f5c5SAndroid Build Coastguard Worker     params.srcFlipY            = isSrcFlipY;
1786*8975f5c5SAndroid Build Coastguard Worker     params.dstFlipY            = unpackFlipY;
1787*8975f5c5SAndroid Build Coastguard Worker     params.srcRotation         = srcFramebufferRotation;
1788*8975f5c5SAndroid Build Coastguard Worker 
1789*8975f5c5SAndroid Build Coastguard Worker     uint32_t baseLayer  = index.hasLayer() ? index.getLayerIndex() : dstOffset.z;
1790*8975f5c5SAndroid Build Coastguard Worker     uint32_t layerCount = sourceBox.depth;
1791*8975f5c5SAndroid Build Coastguard Worker 
1792*8975f5c5SAndroid Build Coastguard Worker     gl::Extents extents = {sourceBox.width, sourceBox.height, sourceBox.depth};
1793*8975f5c5SAndroid Build Coastguard Worker 
1794*8975f5c5SAndroid Build Coastguard Worker     bool isSrc3D  = srcImage->getExtents().depth > 1;
1795*8975f5c5SAndroid Build Coastguard Worker     bool isDest3D = gl_vk::GetImageType(mState.getType()) == VK_IMAGE_TYPE_3D;
1796*8975f5c5SAndroid Build Coastguard Worker 
1797*8975f5c5SAndroid Build Coastguard Worker     // Perform self-copies through a staging buffer.
1798*8975f5c5SAndroid Build Coastguard Worker     // TODO: optimize to copy directly if possible.  http://anglebug.com/42263319
1799*8975f5c5SAndroid Build Coastguard Worker     bool isSelfCopy = mImage == srcImage;
1800*8975f5c5SAndroid Build Coastguard Worker     params.srcColorEncoding =
1801*8975f5c5SAndroid Build Coastguard Worker         gl::GetSizedInternalFormatInfo(srcImage->getIntendedFormat().glInternalFormat)
1802*8975f5c5SAndroid Build Coastguard Worker             .colorEncoding;
1803*8975f5c5SAndroid Build Coastguard Worker     params.dstColorEncoding =
1804*8975f5c5SAndroid Build Coastguard Worker         gl::GetSizedInternalFormatInfo(dstFormat.getIntendedFormat().glInternalFormat)
1805*8975f5c5SAndroid Build Coastguard Worker             .colorEncoding;
1806*8975f5c5SAndroid Build Coastguard Worker 
1807*8975f5c5SAndroid Build Coastguard Worker     // If destination is valid, copy the source directly into it.
1808*8975f5c5SAndroid Build Coastguard Worker     if (shouldUpdateBeFlushed(level, dstFormat.getActualImageFormatID(getRequiredImageAccess())) &&
1809*8975f5c5SAndroid Build Coastguard Worker         !isSelfCopy)
1810*8975f5c5SAndroid Build Coastguard Worker     {
1811*8975f5c5SAndroid Build Coastguard Worker         // Make sure any updates to the image are already flushed.
1812*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(flushImageStagedUpdates(contextVk));
1813*8975f5c5SAndroid Build Coastguard Worker 
1814*8975f5c5SAndroid Build Coastguard Worker         for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex)
1815*8975f5c5SAndroid Build Coastguard Worker         {
1816*8975f5c5SAndroid Build Coastguard Worker             params.srcLayer = layerIndex + sourceBox.z;
1817*8975f5c5SAndroid Build Coastguard Worker             params.dstLayer = baseLayer + layerIndex;
1818*8975f5c5SAndroid Build Coastguard Worker 
1819*8975f5c5SAndroid Build Coastguard Worker             const vk::ImageView *destView;
1820*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(getLevelLayerImageView(contextVk, level, baseLayer + layerIndex, &destView));
1821*8975f5c5SAndroid Build Coastguard Worker 
1822*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(utilsVk.copyImage(contextVk, mImage, destView, srcImage, srcView, params));
1823*8975f5c5SAndroid Build Coastguard Worker         }
1824*8975f5c5SAndroid Build Coastguard Worker     }
1825*8975f5c5SAndroid Build Coastguard Worker     else
1826*8975f5c5SAndroid Build Coastguard Worker     {
1827*8975f5c5SAndroid Build Coastguard Worker         GLint samples                      = srcImage->getSamples();
1828*8975f5c5SAndroid Build Coastguard Worker         gl::TextureType stagingTextureType = vk::Get2DTextureType(layerCount, samples);
1829*8975f5c5SAndroid Build Coastguard Worker 
1830*8975f5c5SAndroid Build Coastguard Worker         // Create a temporary image to stage the copy
1831*8975f5c5SAndroid Build Coastguard Worker         std::unique_ptr<vk::RefCounted<vk::ImageHelper>> stagingImage;
1832*8975f5c5SAndroid Build Coastguard Worker         stagingImage = std::make_unique<vk::RefCounted<vk::ImageHelper>>();
1833*8975f5c5SAndroid Build Coastguard Worker 
1834*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(stagingImage->get().init2DStaging(
1835*8975f5c5SAndroid Build Coastguard Worker             contextVk, mState.hasProtectedContent(), renderer->getMemoryProperties(),
1836*8975f5c5SAndroid Build Coastguard Worker             gl::Extents(sourceBox.width, sourceBox.height, 1), dstFormat.getIntendedFormatID(),
1837*8975f5c5SAndroid Build Coastguard Worker             dstFormat.getActualImageFormatID(getRequiredImageAccess()), kDrawStagingImageFlags,
1838*8975f5c5SAndroid Build Coastguard Worker             layerCount));
1839*8975f5c5SAndroid Build Coastguard Worker 
1840*8975f5c5SAndroid Build Coastguard Worker         params.dstOffset[0] = 0;
1841*8975f5c5SAndroid Build Coastguard Worker         params.dstOffset[1] = 0;
1842*8975f5c5SAndroid Build Coastguard Worker 
1843*8975f5c5SAndroid Build Coastguard Worker         for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex)
1844*8975f5c5SAndroid Build Coastguard Worker         {
1845*8975f5c5SAndroid Build Coastguard Worker             params.srcLayer = layerIndex + sourceBox.z;
1846*8975f5c5SAndroid Build Coastguard Worker             params.dstLayer = layerIndex;
1847*8975f5c5SAndroid Build Coastguard Worker 
1848*8975f5c5SAndroid Build Coastguard Worker             // Create a temporary view for this layer.
1849*8975f5c5SAndroid Build Coastguard Worker             vk::ImageView stagingView;
1850*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(stagingImage->get().initLayerImageView(
1851*8975f5c5SAndroid Build Coastguard Worker                 contextVk, stagingTextureType, VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(),
1852*8975f5c5SAndroid Build Coastguard Worker                 &stagingView, vk::LevelIndex(0), 1, layerIndex, 1));
1853*8975f5c5SAndroid Build Coastguard Worker 
1854*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(utilsVk.copyImage(contextVk, &stagingImage->get(), &stagingView, srcImage,
1855*8975f5c5SAndroid Build Coastguard Worker                                         srcView, params));
1856*8975f5c5SAndroid Build Coastguard Worker 
1857*8975f5c5SAndroid Build Coastguard Worker             // Queue the resource for cleanup as soon as the copy above is finished.  There's no
1858*8975f5c5SAndroid Build Coastguard Worker             // need to keep it around.
1859*8975f5c5SAndroid Build Coastguard Worker             contextVk->addGarbage(&stagingView);
1860*8975f5c5SAndroid Build Coastguard Worker         }
1861*8975f5c5SAndroid Build Coastguard Worker 
1862*8975f5c5SAndroid Build Coastguard Worker         if (!isSrc3D)
1863*8975f5c5SAndroid Build Coastguard Worker         {
1864*8975f5c5SAndroid Build Coastguard Worker             // extents.depth should be set to layer count if any of the source or destination is a
1865*8975f5c5SAndroid Build Coastguard Worker             // 2D Array.  If both are 2D Array, it should be set to 1.
1866*8975f5c5SAndroid Build Coastguard Worker             extents.depth = 1;
1867*8975f5c5SAndroid Build Coastguard Worker         }
1868*8975f5c5SAndroid Build Coastguard Worker 
1869*8975f5c5SAndroid Build Coastguard Worker         gl::Offset dstOffsetModified = dstOffset;
1870*8975f5c5SAndroid Build Coastguard Worker         if (!isDest3D)
1871*8975f5c5SAndroid Build Coastguard Worker         {
1872*8975f5c5SAndroid Build Coastguard Worker             // If destination is not 3D, destination offset must be 0.
1873*8975f5c5SAndroid Build Coastguard Worker             dstOffsetModified.z = 0;
1874*8975f5c5SAndroid Build Coastguard Worker         }
1875*8975f5c5SAndroid Build Coastguard Worker 
1876*8975f5c5SAndroid Build Coastguard Worker         // Stage the copy for when the image storage is actually created.
1877*8975f5c5SAndroid Build Coastguard Worker         VkImageType imageType = gl_vk::GetImageType(mState.getType());
1878*8975f5c5SAndroid Build Coastguard Worker         const gl::ImageIndex stagingIndex =
1879*8975f5c5SAndroid Build Coastguard Worker             gl::ImageIndex::Make2DArrayRange(level.get(), baseLayer, layerCount);
1880*8975f5c5SAndroid Build Coastguard Worker         mImage->stageSubresourceUpdateFromImage(stagingImage.release(), stagingIndex,
1881*8975f5c5SAndroid Build Coastguard Worker                                                 vk::LevelIndex(0), dstOffsetModified, extents,
1882*8975f5c5SAndroid Build Coastguard Worker                                                 imageType);
1883*8975f5c5SAndroid Build Coastguard Worker     }
1884*8975f5c5SAndroid Build Coastguard Worker 
1885*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1886*8975f5c5SAndroid Build Coastguard Worker }
1887*8975f5c5SAndroid Build Coastguard Worker 
setStorageImpl(ContextVk * contextVk,gl::TextureType type,const vk::Format & format)1888*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setStorageImpl(ContextVk *contextVk,
1889*8975f5c5SAndroid Build Coastguard Worker                                         gl::TextureType type,
1890*8975f5c5SAndroid Build Coastguard Worker                                         const vk::Format &format)
1891*8975f5c5SAndroid Build Coastguard Worker {
1892*8975f5c5SAndroid Build Coastguard Worker     if (!mOwnsImage)
1893*8975f5c5SAndroid Build Coastguard Worker     {
1894*8975f5c5SAndroid Build Coastguard Worker         releaseAndDeleteImageAndViews(contextVk);
1895*8975f5c5SAndroid Build Coastguard Worker     }
1896*8975f5c5SAndroid Build Coastguard Worker     else if (mImage)
1897*8975f5c5SAndroid Build Coastguard Worker     {
1898*8975f5c5SAndroid Build Coastguard Worker         if (!contextVk->hasDisplayTextureShareGroup())
1899*8975f5c5SAndroid Build Coastguard Worker         {
1900*8975f5c5SAndroid Build Coastguard Worker             contextVk->getShareGroup()->onTextureRelease(this);
1901*8975f5c5SAndroid Build Coastguard Worker         }
1902*8975f5c5SAndroid Build Coastguard Worker         mImage->releaseStagedUpdates(contextVk->getRenderer());
1903*8975f5c5SAndroid Build Coastguard Worker     }
1904*8975f5c5SAndroid Build Coastguard Worker 
1905*8975f5c5SAndroid Build Coastguard Worker     // Assume all multisample texture types must be renderable.
1906*8975f5c5SAndroid Build Coastguard Worker     if (type == gl::TextureType::_2DMultisample || type == gl::TextureType::_2DMultisampleArray)
1907*8975f5c5SAndroid Build Coastguard Worker     {
1908*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(ensureRenderableWithFormat(contextVk, format, nullptr));
1909*8975f5c5SAndroid Build Coastguard Worker     }
1910*8975f5c5SAndroid Build Coastguard Worker 
1911*8975f5c5SAndroid Build Coastguard Worker     // Fixed rate compression
1912*8975f5c5SAndroid Build Coastguard Worker     if (mState.getSurfaceCompressionFixedRate() != GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT)
1913*8975f5c5SAndroid Build Coastguard Worker     {
1914*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(ensureRenderableWithFormat(contextVk, format, nullptr));
1915*8975f5c5SAndroid Build Coastguard Worker     }
1916*8975f5c5SAndroid Build Coastguard Worker 
1917*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureImageAllocated(contextVk, format));
1918*8975f5c5SAndroid Build Coastguard Worker 
1919*8975f5c5SAndroid Build Coastguard Worker     if (mImage->valid())
1920*8975f5c5SAndroid Build Coastguard Worker     {
1921*8975f5c5SAndroid Build Coastguard Worker         releaseImage(contextVk);
1922*8975f5c5SAndroid Build Coastguard Worker     }
1923*8975f5c5SAndroid Build Coastguard Worker 
1924*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mState.getImmutableFormat());
1925*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!TextureHasAnyRedefinedLevels(mRedefinedLevels));
1926*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(initImage(contextVk, format.getIntendedFormatID(),
1927*8975f5c5SAndroid Build Coastguard Worker                         format.getActualImageFormatID(getRequiredImageAccess()),
1928*8975f5c5SAndroid Build Coastguard Worker                         ImageMipLevels::FullMipChainForGenerateMipmap));
1929*8975f5c5SAndroid Build Coastguard Worker 
1930*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1931*8975f5c5SAndroid Build Coastguard Worker }
1932*8975f5c5SAndroid Build Coastguard Worker 
setStorage(const gl::Context * context,gl::TextureType type,size_t levels,GLenum internalFormat,const gl::Extents & size)1933*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setStorage(const gl::Context *context,
1934*8975f5c5SAndroid Build Coastguard Worker                                     gl::TextureType type,
1935*8975f5c5SAndroid Build Coastguard Worker                                     size_t levels,
1936*8975f5c5SAndroid Build Coastguard Worker                                     GLenum internalFormat,
1937*8975f5c5SAndroid Build Coastguard Worker                                     const gl::Extents &size)
1938*8975f5c5SAndroid Build Coastguard Worker {
1939*8975f5c5SAndroid Build Coastguard Worker     return setStorageMultisample(context, type, 1, internalFormat, size, true);
1940*8975f5c5SAndroid Build Coastguard Worker }
1941*8975f5c5SAndroid Build Coastguard Worker 
setStorageMultisample(const gl::Context * context,gl::TextureType type,GLsizei samples,GLint internalformat,const gl::Extents & size,bool fixedSampleLocations)1942*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setStorageMultisample(const gl::Context *context,
1943*8975f5c5SAndroid Build Coastguard Worker                                                gl::TextureType type,
1944*8975f5c5SAndroid Build Coastguard Worker                                                GLsizei samples,
1945*8975f5c5SAndroid Build Coastguard Worker                                                GLint internalformat,
1946*8975f5c5SAndroid Build Coastguard Worker                                                const gl::Extents &size,
1947*8975f5c5SAndroid Build Coastguard Worker                                                bool fixedSampleLocations)
1948*8975f5c5SAndroid Build Coastguard Worker {
1949*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk     = GetAs<ContextVk>(context->getImplementation());
1950*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer   = contextVk->getRenderer();
1951*8975f5c5SAndroid Build Coastguard Worker     const vk::Format &format = renderer->getFormat(internalformat);
1952*8975f5c5SAndroid Build Coastguard Worker 
1953*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(setStorageImpl(contextVk, type, format));
1954*8975f5c5SAndroid Build Coastguard Worker 
1955*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1956*8975f5c5SAndroid Build Coastguard Worker }
1957*8975f5c5SAndroid Build Coastguard Worker 
setStorageExternalMemory(const gl::Context * context,gl::TextureType type,size_t levels,GLenum internalFormat,const gl::Extents & size,gl::MemoryObject * memoryObject,GLuint64 offset,GLbitfield createFlags,GLbitfield usageFlags,const void * imageCreateInfoPNext)1958*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setStorageExternalMemory(const gl::Context *context,
1959*8975f5c5SAndroid Build Coastguard Worker                                                   gl::TextureType type,
1960*8975f5c5SAndroid Build Coastguard Worker                                                   size_t levels,
1961*8975f5c5SAndroid Build Coastguard Worker                                                   GLenum internalFormat,
1962*8975f5c5SAndroid Build Coastguard Worker                                                   const gl::Extents &size,
1963*8975f5c5SAndroid Build Coastguard Worker                                                   gl::MemoryObject *memoryObject,
1964*8975f5c5SAndroid Build Coastguard Worker                                                   GLuint64 offset,
1965*8975f5c5SAndroid Build Coastguard Worker                                                   GLbitfield createFlags,
1966*8975f5c5SAndroid Build Coastguard Worker                                                   GLbitfield usageFlags,
1967*8975f5c5SAndroid Build Coastguard Worker                                                   const void *imageCreateInfoPNext)
1968*8975f5c5SAndroid Build Coastguard Worker {
1969*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk           = vk::GetImpl(context);
1970*8975f5c5SAndroid Build Coastguard Worker     MemoryObjectVk *memoryObjectVk = vk::GetImpl(memoryObject);
1971*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer         = contextVk->getRenderer();
1972*8975f5c5SAndroid Build Coastguard Worker 
1973*8975f5c5SAndroid Build Coastguard Worker     const vk::Format &vkFormat     = renderer->getFormat(internalFormat);
1974*8975f5c5SAndroid Build Coastguard Worker     angle::FormatID actualFormatID = vkFormat.getActualRenderableImageFormatID();
1975*8975f5c5SAndroid Build Coastguard Worker 
1976*8975f5c5SAndroid Build Coastguard Worker     releaseAndDeleteImageAndViews(contextVk);
1977*8975f5c5SAndroid Build Coastguard Worker 
1978*8975f5c5SAndroid Build Coastguard Worker     setImageHelper(contextVk, new vk::ImageHelper(), gl::TextureType::InvalidEnum, 0, 0, true, {});
1979*8975f5c5SAndroid Build Coastguard Worker 
1980*8975f5c5SAndroid Build Coastguard Worker     mImage->setTilingMode(gl_vk::GetTilingMode(mState.getTilingMode()));
1981*8975f5c5SAndroid Build Coastguard Worker 
1982*8975f5c5SAndroid Build Coastguard Worker     // EXT_external_objects issue 13 says that all supported usage flags must be specified.
1983*8975f5c5SAndroid Build Coastguard Worker     // However, ANGLE_external_objects_flags allows these flags to be masked.  Note that the GL enum
1984*8975f5c5SAndroid Build Coastguard Worker     // values constituting the bits of |usageFlags| are identical to their corresponding Vulkan
1985*8975f5c5SAndroid Build Coastguard Worker     // value.
1986*8975f5c5SAndroid Build Coastguard Worker     usageFlags &= vk::GetMaximalImageUsageFlags(renderer, actualFormatID);
1987*8975f5c5SAndroid Build Coastguard Worker 
1988*8975f5c5SAndroid Build Coastguard Worker     // Similarly, createFlags is restricted to what is valid.
1989*8975f5c5SAndroid Build Coastguard Worker     createFlags &= vk::GetMinimalImageCreateFlags(renderer, type, usageFlags) |
1990*8975f5c5SAndroid Build Coastguard Worker                    VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
1991*8975f5c5SAndroid Build Coastguard Worker 
1992*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(memoryObjectVk->createImage(contextVk, type, levels, internalFormat, size, offset,
1993*8975f5c5SAndroid Build Coastguard Worker                                           mImage, createFlags, usageFlags, imageCreateInfoPNext));
1994*8975f5c5SAndroid Build Coastguard Worker     mImageUsageFlags  = usageFlags;
1995*8975f5c5SAndroid Build Coastguard Worker     mImageCreateFlags = createFlags;
1996*8975f5c5SAndroid Build Coastguard Worker 
1997*8975f5c5SAndroid Build Coastguard Worker     constexpr VkImageUsageFlags kRenderableUsageFlags =
1998*8975f5c5SAndroid Build Coastguard Worker         kColorAttachmentImageFlags | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1999*8975f5c5SAndroid Build Coastguard Worker     if ((usageFlags & kRenderableUsageFlags) != 0)
2000*8975f5c5SAndroid Build Coastguard Worker     {
2001*8975f5c5SAndroid Build Coastguard Worker         mRequiredImageAccess = vk::ImageAccess::Renderable;
2002*8975f5c5SAndroid Build Coastguard Worker     }
2003*8975f5c5SAndroid Build Coastguard Worker 
2004*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(initImageViews(contextVk, getImageViewLevelCount()));
2005*8975f5c5SAndroid Build Coastguard Worker 
2006*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2007*8975f5c5SAndroid Build Coastguard Worker }
2008*8975f5c5SAndroid Build Coastguard Worker 
setStorageAttribs(const gl::Context * context,gl::TextureType type,size_t levels,GLint internalformat,const gl::Extents & size,const GLint * attribList)2009*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setStorageAttribs(const gl::Context *context,
2010*8975f5c5SAndroid Build Coastguard Worker                                            gl::TextureType type,
2011*8975f5c5SAndroid Build Coastguard Worker                                            size_t levels,
2012*8975f5c5SAndroid Build Coastguard Worker                                            GLint internalformat,
2013*8975f5c5SAndroid Build Coastguard Worker                                            const gl::Extents &size,
2014*8975f5c5SAndroid Build Coastguard Worker                                            const GLint *attribList)
2015*8975f5c5SAndroid Build Coastguard Worker {
2016*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk     = GetAs<ContextVk>(context->getImplementation());
2017*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer   = contextVk->getRenderer();
2018*8975f5c5SAndroid Build Coastguard Worker     const vk::Format &format = renderer->getFormat(internalformat);
2019*8975f5c5SAndroid Build Coastguard Worker 
2020*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(setStorageImpl(contextVk, type, format));
2021*8975f5c5SAndroid Build Coastguard Worker 
2022*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2023*8975f5c5SAndroid Build Coastguard Worker }
2024*8975f5c5SAndroid Build Coastguard Worker 
getImageCompressionRate(const gl::Context * context)2025*8975f5c5SAndroid Build Coastguard Worker GLint TextureVk::getImageCompressionRate(const gl::Context *context)
2026*8975f5c5SAndroid Build Coastguard Worker {
2027*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk   = vk::GetImpl(context);
2028*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
2029*8975f5c5SAndroid Build Coastguard Worker 
2030*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImage != nullptr && mImage->valid());
2031*8975f5c5SAndroid Build Coastguard Worker     ASSERT(renderer->getFeatures().supportsImageCompressionControl.enabled);
2032*8975f5c5SAndroid Build Coastguard Worker 
2033*8975f5c5SAndroid Build Coastguard Worker     if (!mOwnsImage)
2034*8975f5c5SAndroid Build Coastguard Worker     {
2035*8975f5c5SAndroid Build Coastguard Worker         return 0;
2036*8975f5c5SAndroid Build Coastguard Worker     }
2037*8975f5c5SAndroid Build Coastguard Worker 
2038*8975f5c5SAndroid Build Coastguard Worker     VkImageSubresource2EXT imageSubresource2      = {};
2039*8975f5c5SAndroid Build Coastguard Worker     imageSubresource2.sType                       = VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_EXT;
2040*8975f5c5SAndroid Build Coastguard Worker     imageSubresource2.imageSubresource.aspectMask = mImage->getAspectFlags();
2041*8975f5c5SAndroid Build Coastguard Worker 
2042*8975f5c5SAndroid Build Coastguard Worker     VkImageCompressionPropertiesEXT compressionProperties = {};
2043*8975f5c5SAndroid Build Coastguard Worker     compressionProperties.sType               = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT;
2044*8975f5c5SAndroid Build Coastguard Worker     VkSubresourceLayout2EXT subresourceLayout = {};
2045*8975f5c5SAndroid Build Coastguard Worker     subresourceLayout.sType                   = VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_EXT;
2046*8975f5c5SAndroid Build Coastguard Worker     subresourceLayout.pNext                   = &compressionProperties;
2047*8975f5c5SAndroid Build Coastguard Worker 
2048*8975f5c5SAndroid Build Coastguard Worker     vkGetImageSubresourceLayout2EXT(renderer->getDevice(), mImage->getImage().getHandle(),
2049*8975f5c5SAndroid Build Coastguard Worker                                     &imageSubresource2, &subresourceLayout);
2050*8975f5c5SAndroid Build Coastguard Worker 
2051*8975f5c5SAndroid Build Coastguard Worker     GLint compressionRate;
2052*8975f5c5SAndroid Build Coastguard Worker     // For an existing image, should only report one compression rate
2053*8975f5c5SAndroid Build Coastguard Worker     vk_gl::convertCompressionFlagsToGLFixedRates(
2054*8975f5c5SAndroid Build Coastguard Worker         compressionProperties.imageCompressionFixedRateFlags, 1, &compressionRate);
2055*8975f5c5SAndroid Build Coastguard Worker     return compressionRate;
2056*8975f5c5SAndroid Build Coastguard Worker }
2057*8975f5c5SAndroid Build Coastguard Worker 
getFormatSupportedCompressionRatesImpl(vk::Renderer * renderer,const vk::Format & format,GLsizei bufSize,GLint * rates)2058*8975f5c5SAndroid Build Coastguard Worker GLint TextureVk::getFormatSupportedCompressionRatesImpl(vk::Renderer *renderer,
2059*8975f5c5SAndroid Build Coastguard Worker                                                         const vk::Format &format,
2060*8975f5c5SAndroid Build Coastguard Worker                                                         GLsizei bufSize,
2061*8975f5c5SAndroid Build Coastguard Worker                                                         GLint *rates)
2062*8975f5c5SAndroid Build Coastguard Worker {
2063*8975f5c5SAndroid Build Coastguard Worker     if (renderer->getFeatures().supportsImageCompressionControl.enabled)
2064*8975f5c5SAndroid Build Coastguard Worker     {
2065*8975f5c5SAndroid Build Coastguard Worker         VkImageCompressionControlEXT compressionInfo = {};
2066*8975f5c5SAndroid Build Coastguard Worker         compressionInfo.sType = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT;
2067*8975f5c5SAndroid Build Coastguard Worker         // Use default compression control flag for query
2068*8975f5c5SAndroid Build Coastguard Worker         compressionInfo.flags = VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT;
2069*8975f5c5SAndroid Build Coastguard Worker 
2070*8975f5c5SAndroid Build Coastguard Worker         VkImageCompressionPropertiesEXT compressionProp = {};
2071*8975f5c5SAndroid Build Coastguard Worker         compressionProp.sType = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT;
2072*8975f5c5SAndroid Build Coastguard Worker 
2073*8975f5c5SAndroid Build Coastguard Worker         if (vk::ImageHelper::FormatSupportsUsage(
2074*8975f5c5SAndroid Build Coastguard Worker                 renderer,
2075*8975f5c5SAndroid Build Coastguard Worker                 vk::GetVkFormatFromFormatID(renderer, format.getActualRenderableImageFormatID()),
2076*8975f5c5SAndroid Build Coastguard Worker                 VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
2077*8975f5c5SAndroid Build Coastguard Worker                 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
2078*8975f5c5SAndroid Build Coastguard Worker                     VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
2079*8975f5c5SAndroid Build Coastguard Worker                 0, &compressionInfo, &compressionProp,
2080*8975f5c5SAndroid Build Coastguard Worker                 vk::ImageHelper::FormatSupportCheck::OnlyQuerySuccess))
2081*8975f5c5SAndroid Build Coastguard Worker         {
2082*8975f5c5SAndroid Build Coastguard Worker             if ((compressionProp.imageCompressionFlags &
2083*8975f5c5SAndroid Build Coastguard Worker                  VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT) != 0)
2084*8975f5c5SAndroid Build Coastguard Worker             {
2085*8975f5c5SAndroid Build Coastguard Worker                 return vk_gl::convertCompressionFlagsToGLFixedRates(
2086*8975f5c5SAndroid Build Coastguard Worker                     compressionProp.imageCompressionFixedRateFlags, bufSize, rates);
2087*8975f5c5SAndroid Build Coastguard Worker             }
2088*8975f5c5SAndroid Build Coastguard Worker         }
2089*8975f5c5SAndroid Build Coastguard Worker     }
2090*8975f5c5SAndroid Build Coastguard Worker 
2091*8975f5c5SAndroid Build Coastguard Worker     return 0;
2092*8975f5c5SAndroid Build Coastguard Worker }
2093*8975f5c5SAndroid Build Coastguard Worker 
getFormatSupportedCompressionRates(const gl::Context * context,GLenum internalformat,GLsizei bufSize,GLint * rates)2094*8975f5c5SAndroid Build Coastguard Worker GLint TextureVk::getFormatSupportedCompressionRates(const gl::Context *context,
2095*8975f5c5SAndroid Build Coastguard Worker                                                     GLenum internalformat,
2096*8975f5c5SAndroid Build Coastguard Worker                                                     GLsizei bufSize,
2097*8975f5c5SAndroid Build Coastguard Worker                                                     GLint *rates)
2098*8975f5c5SAndroid Build Coastguard Worker {
2099*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk     = vk::GetImpl(context);
2100*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer   = contextVk->getRenderer();
2101*8975f5c5SAndroid Build Coastguard Worker     const vk::Format &format = renderer->getFormat(internalformat);
2102*8975f5c5SAndroid Build Coastguard Worker 
2103*8975f5c5SAndroid Build Coastguard Worker     return getFormatSupportedCompressionRatesImpl(renderer, format, bufSize, rates);
2104*8975f5c5SAndroid Build Coastguard Worker }
2105*8975f5c5SAndroid Build Coastguard Worker 
handleImmutableSamplerTransition(const vk::ImageHelper * previousImage,const vk::ImageHelper * nextImage)2106*8975f5c5SAndroid Build Coastguard Worker void TextureVk::handleImmutableSamplerTransition(const vk::ImageHelper *previousImage,
2107*8975f5c5SAndroid Build Coastguard Worker                                                  const vk::ImageHelper *nextImage)
2108*8975f5c5SAndroid Build Coastguard Worker {
2109*8975f5c5SAndroid Build Coastguard Worker     // Did the previous image have an immutable sampler
2110*8975f5c5SAndroid Build Coastguard Worker     bool previousImageHadImmutableSampler =
2111*8975f5c5SAndroid Build Coastguard Worker         previousImage && previousImage->valid() && previousImage->hasImmutableSampler();
2112*8975f5c5SAndroid Build Coastguard Worker 
2113*8975f5c5SAndroid Build Coastguard Worker     // Does the next image require an immutable sampler?
2114*8975f5c5SAndroid Build Coastguard Worker     bool nextImageRequiresImmutableSampler =
2115*8975f5c5SAndroid Build Coastguard Worker         nextImage && nextImage->valid() && nextImage->hasImmutableSampler();
2116*8975f5c5SAndroid Build Coastguard Worker 
2117*8975f5c5SAndroid Build Coastguard Worker     // Has the external format changed?
2118*8975f5c5SAndroid Build Coastguard Worker     bool externalFormatChanged = false;
2119*8975f5c5SAndroid Build Coastguard Worker     if (previousImageHadImmutableSampler && nextImageRequiresImmutableSampler)
2120*8975f5c5SAndroid Build Coastguard Worker     {
2121*8975f5c5SAndroid Build Coastguard Worker         externalFormatChanged =
2122*8975f5c5SAndroid Build Coastguard Worker             previousImage->getExternalFormat() != nextImage->getExternalFormat();
2123*8975f5c5SAndroid Build Coastguard Worker     }
2124*8975f5c5SAndroid Build Coastguard Worker 
2125*8975f5c5SAndroid Build Coastguard Worker     // Handle transition of immutable sampler state
2126*8975f5c5SAndroid Build Coastguard Worker     if ((previousImageHadImmutableSampler != nextImageRequiresImmutableSampler) ||
2127*8975f5c5SAndroid Build Coastguard Worker         externalFormatChanged)
2128*8975f5c5SAndroid Build Coastguard Worker     {
2129*8975f5c5SAndroid Build Coastguard Worker         // The immutable sampler state is dirty.
2130*8975f5c5SAndroid Build Coastguard Worker         resetSampler();
2131*8975f5c5SAndroid Build Coastguard Worker         mImmutableSamplerDirty = true;
2132*8975f5c5SAndroid Build Coastguard Worker     }
2133*8975f5c5SAndroid Build Coastguard Worker }
2134*8975f5c5SAndroid Build Coastguard Worker 
setEGLImageTarget(const gl::Context * context,gl::TextureType type,egl::Image * image)2135*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setEGLImageTarget(const gl::Context *context,
2136*8975f5c5SAndroid Build Coastguard Worker                                            gl::TextureType type,
2137*8975f5c5SAndroid Build Coastguard Worker                                            egl::Image *image)
2138*8975f5c5SAndroid Build Coastguard Worker {
2139*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
2140*8975f5c5SAndroid Build Coastguard Worker     ImageVk *imageVk     = vk::GetImpl(image);
2141*8975f5c5SAndroid Build Coastguard Worker 
2142*8975f5c5SAndroid Build Coastguard Worker     // Early out if we are creating TextureVk with the exact same eglImage and target/face/level to
2143*8975f5c5SAndroid Build Coastguard Worker     // avoid unnecessarily dirty the state and allocating new ImageViews etc.
2144*8975f5c5SAndroid Build Coastguard Worker     if (mImage == imageVk->getImage() && mEGLImageNativeType == imageVk->getImageTextureType() &&
2145*8975f5c5SAndroid Build Coastguard Worker         static_cast<GLint>(mEGLImageLevelOffset) == imageVk->getImageLevel().get() &&
2146*8975f5c5SAndroid Build Coastguard Worker         mEGLImageLayerOffset == imageVk->getImageLayer())
2147*8975f5c5SAndroid Build Coastguard Worker     {
2148*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
2149*8975f5c5SAndroid Build Coastguard Worker     }
2150*8975f5c5SAndroid Build Coastguard Worker 
2151*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(contextVk->getShareGroup()->lockDefaultContextsPriority(contextVk));
2152*8975f5c5SAndroid Build Coastguard Worker 
2153*8975f5c5SAndroid Build Coastguard Worker     // TODO: Textures other than EGLImage targets can have immutable samplers.
2154*8975f5c5SAndroid Build Coastguard Worker     // http://anglebug.com/42264309
2155*8975f5c5SAndroid Build Coastguard Worker     handleImmutableSamplerTransition(mImage, imageVk ? imageVk->getImage() : nullptr);
2156*8975f5c5SAndroid Build Coastguard Worker 
2157*8975f5c5SAndroid Build Coastguard Worker     releaseAndDeleteImageAndViews(contextVk);
2158*8975f5c5SAndroid Build Coastguard Worker 
2159*8975f5c5SAndroid Build Coastguard Worker     UniqueSerial siblingSerial = imageVk->generateSiblingSerial();
2160*8975f5c5SAndroid Build Coastguard Worker     setImageHelper(contextVk, imageVk->getImage(), imageVk->getImageTextureType(),
2161*8975f5c5SAndroid Build Coastguard Worker                    imageVk->getImageLevel().get(), imageVk->getImageLayer(), false, siblingSerial);
2162*8975f5c5SAndroid Build Coastguard Worker 
2163*8975f5c5SAndroid Build Coastguard Worker     // Update ImageViewHelper's colorspace related state
2164*8975f5c5SAndroid Build Coastguard Worker     EGLenum imageColorspaceAttribute = image->getColorspaceAttribute();
2165*8975f5c5SAndroid Build Coastguard Worker     if (imageColorspaceAttribute != EGL_GL_COLORSPACE_DEFAULT_EXT)
2166*8975f5c5SAndroid Build Coastguard Worker     {
2167*8975f5c5SAndroid Build Coastguard Worker         egl::ImageColorspace imageColorspace =
2168*8975f5c5SAndroid Build Coastguard Worker             (imageColorspaceAttribute == EGL_GL_COLORSPACE_SRGB_KHR) ? egl::ImageColorspace::SRGB
2169*8975f5c5SAndroid Build Coastguard Worker                                                                      : egl::ImageColorspace::Linear;
2170*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mImage != nullptr);
2171*8975f5c5SAndroid Build Coastguard Worker         mImageView.updateEglImageColorspace(*mImage, imageColorspace);
2172*8975f5c5SAndroid Build Coastguard Worker     }
2173*8975f5c5SAndroid Build Coastguard Worker 
2174*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(initImageViews(contextVk, getImageViewLevelCount()));
2175*8975f5c5SAndroid Build Coastguard Worker 
2176*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2177*8975f5c5SAndroid Build Coastguard Worker }
2178*8975f5c5SAndroid Build Coastguard Worker 
setImageExternal(const gl::Context * context,gl::TextureType type,egl::Stream * stream,const egl::Stream::GLTextureDescription & desc)2179*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setImageExternal(const gl::Context *context,
2180*8975f5c5SAndroid Build Coastguard Worker                                           gl::TextureType type,
2181*8975f5c5SAndroid Build Coastguard Worker                                           egl::Stream *stream,
2182*8975f5c5SAndroid Build Coastguard Worker                                           const egl::Stream::GLTextureDescription &desc)
2183*8975f5c5SAndroid Build Coastguard Worker {
2184*8975f5c5SAndroid Build Coastguard Worker     ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
2185*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Stop;
2186*8975f5c5SAndroid Build Coastguard Worker }
2187*8975f5c5SAndroid Build Coastguard Worker 
setBuffer(const gl::Context * context,GLenum internalFormat)2188*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setBuffer(const gl::Context *context, GLenum internalFormat)
2189*8975f5c5SAndroid Build Coastguard Worker {
2190*8975f5c5SAndroid Build Coastguard Worker     // No longer an image
2191*8975f5c5SAndroid Build Coastguard Worker     releaseAndDeleteImageAndViews(vk::GetImpl(context));
2192*8975f5c5SAndroid Build Coastguard Worker     resetSampler();
2193*8975f5c5SAndroid Build Coastguard Worker 
2194*8975f5c5SAndroid Build Coastguard Worker     // There's nothing else to do here.
2195*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2196*8975f5c5SAndroid Build Coastguard Worker }
2197*8975f5c5SAndroid Build Coastguard Worker 
getNativeImageIndex(const gl::ImageIndex & inputImageIndex) const2198*8975f5c5SAndroid Build Coastguard Worker gl::ImageIndex TextureVk::getNativeImageIndex(const gl::ImageIndex &inputImageIndex) const
2199*8975f5c5SAndroid Build Coastguard Worker {
2200*8975f5c5SAndroid Build Coastguard Worker     if (mEGLImageNativeType == gl::TextureType::InvalidEnum)
2201*8975f5c5SAndroid Build Coastguard Worker     {
2202*8975f5c5SAndroid Build Coastguard Worker         return inputImageIndex;
2203*8975f5c5SAndroid Build Coastguard Worker     }
2204*8975f5c5SAndroid Build Coastguard Worker 
2205*8975f5c5SAndroid Build Coastguard Worker     // inputImageIndex can point to a specific layer, but only for non-2D textures.
2206*8975f5c5SAndroid Build Coastguard Worker     // mEGLImageNativeType can be a valid type, but only for 2D textures.
2207*8975f5c5SAndroid Build Coastguard Worker     // As such, both of these cannot be true at the same time.
2208*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!inputImageIndex.hasLayer() && inputImageIndex.getLevelIndex() == 0);
2209*8975f5c5SAndroid Build Coastguard Worker 
2210*8975f5c5SAndroid Build Coastguard Worker     return gl::ImageIndex::MakeFromType(mEGLImageNativeType, mEGLImageLevelOffset,
2211*8975f5c5SAndroid Build Coastguard Worker                                         mEGLImageLayerOffset);
2212*8975f5c5SAndroid Build Coastguard Worker }
2213*8975f5c5SAndroid Build Coastguard Worker 
getNativeImageLevel(gl::LevelIndex frontendLevel) const2214*8975f5c5SAndroid Build Coastguard Worker gl::LevelIndex TextureVk::getNativeImageLevel(gl::LevelIndex frontendLevel) const
2215*8975f5c5SAndroid Build Coastguard Worker {
2216*8975f5c5SAndroid Build Coastguard Worker     ASSERT(frontendLevel.get() == 0 || mEGLImageLevelOffset == 0);
2217*8975f5c5SAndroid Build Coastguard Worker     return frontendLevel + mEGLImageLevelOffset;
2218*8975f5c5SAndroid Build Coastguard Worker }
2219*8975f5c5SAndroid Build Coastguard Worker 
getNativeImageLayer(uint32_t frontendLayer) const2220*8975f5c5SAndroid Build Coastguard Worker uint32_t TextureVk::getNativeImageLayer(uint32_t frontendLayer) const
2221*8975f5c5SAndroid Build Coastguard Worker {
2222*8975f5c5SAndroid Build Coastguard Worker     ASSERT(frontendLayer == 0 || mEGLImageLayerOffset == 0);
2223*8975f5c5SAndroid Build Coastguard Worker     return frontendLayer + mEGLImageLayerOffset;
2224*8975f5c5SAndroid Build Coastguard Worker }
2225*8975f5c5SAndroid Build Coastguard Worker 
releaseAndDeleteImageAndViews(ContextVk * contextVk)2226*8975f5c5SAndroid Build Coastguard Worker void TextureVk::releaseAndDeleteImageAndViews(ContextVk *contextVk)
2227*8975f5c5SAndroid Build Coastguard Worker {
2228*8975f5c5SAndroid Build Coastguard Worker     if (mImage)
2229*8975f5c5SAndroid Build Coastguard Worker     {
2230*8975f5c5SAndroid Build Coastguard Worker         if (mOwnsImage)
2231*8975f5c5SAndroid Build Coastguard Worker         {
2232*8975f5c5SAndroid Build Coastguard Worker             releaseStagedUpdates(contextVk);
2233*8975f5c5SAndroid Build Coastguard Worker         }
2234*8975f5c5SAndroid Build Coastguard Worker         releaseImage(contextVk);
2235*8975f5c5SAndroid Build Coastguard Worker         mImageObserverBinding.bind(nullptr);
2236*8975f5c5SAndroid Build Coastguard Worker         mRequiresMutableStorage = false;
2237*8975f5c5SAndroid Build Coastguard Worker         mRequiredImageAccess    = vk::ImageAccess::SampleOnly;
2238*8975f5c5SAndroid Build Coastguard Worker         mImageCreateFlags       = 0;
2239*8975f5c5SAndroid Build Coastguard Worker         SafeDelete(mImage);
2240*8975f5c5SAndroid Build Coastguard Worker     }
2241*8975f5c5SAndroid Build Coastguard Worker 
2242*8975f5c5SAndroid Build Coastguard Worker     if (!contextVk->hasDisplayTextureShareGroup())
2243*8975f5c5SAndroid Build Coastguard Worker     {
2244*8975f5c5SAndroid Build Coastguard Worker         contextVk->getShareGroup()->onTextureRelease(this);
2245*8975f5c5SAndroid Build Coastguard Worker     }
2246*8975f5c5SAndroid Build Coastguard Worker 
2247*8975f5c5SAndroid Build Coastguard Worker     if (getBuffer().get() != nullptr)
2248*8975f5c5SAndroid Build Coastguard Worker     {
2249*8975f5c5SAndroid Build Coastguard Worker         mBufferContentsObservers->disableForBuffer(getBuffer().get());
2250*8975f5c5SAndroid Build Coastguard Worker     }
2251*8975f5c5SAndroid Build Coastguard Worker 
2252*8975f5c5SAndroid Build Coastguard Worker     if (mBufferViews.isInitialized())
2253*8975f5c5SAndroid Build Coastguard Worker     {
2254*8975f5c5SAndroid Build Coastguard Worker         mBufferViews.release(contextVk);
2255*8975f5c5SAndroid Build Coastguard Worker         onStateChange(angle::SubjectMessage::SubjectChanged);
2256*8975f5c5SAndroid Build Coastguard Worker     }
2257*8975f5c5SAndroid Build Coastguard Worker     mRedefinedLevels = {};
2258*8975f5c5SAndroid Build Coastguard Worker     mDescriptorSetCacheManager.releaseKeys(contextVk->getRenderer());
2259*8975f5c5SAndroid Build Coastguard Worker }
2260*8975f5c5SAndroid Build Coastguard Worker 
initImageUsageFlags(ContextVk * contextVk,angle::FormatID actualFormatID)2261*8975f5c5SAndroid Build Coastguard Worker void TextureVk::initImageUsageFlags(ContextVk *contextVk, angle::FormatID actualFormatID)
2262*8975f5c5SAndroid Build Coastguard Worker {
2263*8975f5c5SAndroid Build Coastguard Worker     ASSERT(actualFormatID != angle::FormatID::NONE);
2264*8975f5c5SAndroid Build Coastguard Worker 
2265*8975f5c5SAndroid Build Coastguard Worker     mImageUsageFlags = kTransferImageFlags | VK_IMAGE_USAGE_SAMPLED_BIT;
2266*8975f5c5SAndroid Build Coastguard Worker 
2267*8975f5c5SAndroid Build Coastguard Worker     // If the image has depth/stencil support, add those as possible usage.
2268*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
2269*8975f5c5SAndroid Build Coastguard Worker     if (angle::Format::Get(actualFormatID).hasDepthOrStencilBits())
2270*8975f5c5SAndroid Build Coastguard Worker     {
2271*8975f5c5SAndroid Build Coastguard Worker         // Work around a bug in the Mock ICD:
2272*8975f5c5SAndroid Build Coastguard Worker         // https://github.com/KhronosGroup/Vulkan-Tools/issues/445
2273*8975f5c5SAndroid Build Coastguard Worker         if (renderer->hasImageFormatFeatureBits(actualFormatID,
2274*8975f5c5SAndroid Build Coastguard Worker                                                 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))
2275*8975f5c5SAndroid Build Coastguard Worker         {
2276*8975f5c5SAndroid Build Coastguard Worker             mImageUsageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
2277*8975f5c5SAndroid Build Coastguard Worker 
2278*8975f5c5SAndroid Build Coastguard Worker             if (renderer->getFeatures().supportsShaderFramebufferFetchDepthStencil.enabled)
2279*8975f5c5SAndroid Build Coastguard Worker             {
2280*8975f5c5SAndroid Build Coastguard Worker                 mImageUsageFlags |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
2281*8975f5c5SAndroid Build Coastguard Worker             }
2282*8975f5c5SAndroid Build Coastguard Worker         }
2283*8975f5c5SAndroid Build Coastguard Worker     }
2284*8975f5c5SAndroid Build Coastguard Worker     else if (renderer->hasImageFormatFeatureBits(actualFormatID,
2285*8975f5c5SAndroid Build Coastguard Worker                                                  VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
2286*8975f5c5SAndroid Build Coastguard Worker     {
2287*8975f5c5SAndroid Build Coastguard Worker         mImageUsageFlags |= kColorAttachmentImageFlags;
2288*8975f5c5SAndroid Build Coastguard Worker     }
2289*8975f5c5SAndroid Build Coastguard Worker }
2290*8975f5c5SAndroid Build Coastguard Worker 
ensureImageAllocated(ContextVk * contextVk,const vk::Format & format)2291*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::ensureImageAllocated(ContextVk *contextVk, const vk::Format &format)
2292*8975f5c5SAndroid Build Coastguard Worker {
2293*8975f5c5SAndroid Build Coastguard Worker     if (mImage == nullptr)
2294*8975f5c5SAndroid Build Coastguard Worker     {
2295*8975f5c5SAndroid Build Coastguard Worker         setImageHelper(contextVk, new vk::ImageHelper(), gl::TextureType::InvalidEnum, 0, 0, true,
2296*8975f5c5SAndroid Build Coastguard Worker                        {});
2297*8975f5c5SAndroid Build Coastguard Worker     }
2298*8975f5c5SAndroid Build Coastguard Worker 
2299*8975f5c5SAndroid Build Coastguard Worker     initImageUsageFlags(contextVk, format.getActualImageFormatID(getRequiredImageAccess()));
2300*8975f5c5SAndroid Build Coastguard Worker 
2301*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2302*8975f5c5SAndroid Build Coastguard Worker }
2303*8975f5c5SAndroid Build Coastguard Worker 
setImageHelper(ContextVk * contextVk,vk::ImageHelper * imageHelper,gl::TextureType eglImageNativeType,uint32_t imageLevelOffset,uint32_t imageLayerOffset,bool selfOwned,UniqueSerial siblingSerial)2304*8975f5c5SAndroid Build Coastguard Worker void TextureVk::setImageHelper(ContextVk *contextVk,
2305*8975f5c5SAndroid Build Coastguard Worker                                vk::ImageHelper *imageHelper,
2306*8975f5c5SAndroid Build Coastguard Worker                                gl::TextureType eglImageNativeType,
2307*8975f5c5SAndroid Build Coastguard Worker                                uint32_t imageLevelOffset,
2308*8975f5c5SAndroid Build Coastguard Worker                                uint32_t imageLayerOffset,
2309*8975f5c5SAndroid Build Coastguard Worker                                bool selfOwned,
2310*8975f5c5SAndroid Build Coastguard Worker                                UniqueSerial siblingSerial)
2311*8975f5c5SAndroid Build Coastguard Worker {
2312*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImage == nullptr);
2313*8975f5c5SAndroid Build Coastguard Worker 
2314*8975f5c5SAndroid Build Coastguard Worker     mImageObserverBinding.bind(imageHelper);
2315*8975f5c5SAndroid Build Coastguard Worker 
2316*8975f5c5SAndroid Build Coastguard Worker     ASSERT(selfOwned == !siblingSerial.valid());
2317*8975f5c5SAndroid Build Coastguard Worker     mOwnsImage          = selfOwned;
2318*8975f5c5SAndroid Build Coastguard Worker     mImageSiblingSerial = siblingSerial;
2319*8975f5c5SAndroid Build Coastguard Worker     // If image is shared between other container objects, force it to renderable format since we
2320*8975f5c5SAndroid Build Coastguard Worker     // don't know if other container object will render or not.
2321*8975f5c5SAndroid Build Coastguard Worker     if (!mOwnsImage && !imageHelper->isBackedByExternalMemory())
2322*8975f5c5SAndroid Build Coastguard Worker     {
2323*8975f5c5SAndroid Build Coastguard Worker         mRequiredImageAccess = vk::ImageAccess::Renderable;
2324*8975f5c5SAndroid Build Coastguard Worker     }
2325*8975f5c5SAndroid Build Coastguard Worker     mEGLImageNativeType  = eglImageNativeType;
2326*8975f5c5SAndroid Build Coastguard Worker     mEGLImageLevelOffset = imageLevelOffset;
2327*8975f5c5SAndroid Build Coastguard Worker     mEGLImageLayerOffset = imageLayerOffset;
2328*8975f5c5SAndroid Build Coastguard Worker     mImage               = imageHelper;
2329*8975f5c5SAndroid Build Coastguard Worker 
2330*8975f5c5SAndroid Build Coastguard Worker     // All render targets must be already destroyed prior to this call.
2331*8975f5c5SAndroid Build Coastguard Worker     for (auto &renderTargets : mSingleLayerRenderTargets)
2332*8975f5c5SAndroid Build Coastguard Worker     {
2333*8975f5c5SAndroid Build Coastguard Worker         ASSERT(renderTargets.empty());
2334*8975f5c5SAndroid Build Coastguard Worker     }
2335*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mMultiLayerRenderTargets.empty());
2336*8975f5c5SAndroid Build Coastguard Worker 
2337*8975f5c5SAndroid Build Coastguard Worker     if (!selfOwned)
2338*8975f5c5SAndroid Build Coastguard Worker     {
2339*8975f5c5SAndroid Build Coastguard Worker         // (!selfOwned) implies that the texture is a target sibling.
2340*8975f5c5SAndroid Build Coastguard Worker         // Inherit a few VkImage's create attributes from ImageHelper.
2341*8975f5c5SAndroid Build Coastguard Worker         mImageCreateFlags       = mImage->getCreateFlags();
2342*8975f5c5SAndroid Build Coastguard Worker         mImageUsageFlags        = mImage->getUsage();
2343*8975f5c5SAndroid Build Coastguard Worker         mRequiresMutableStorage = (mImageCreateFlags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) != 0;
2344*8975f5c5SAndroid Build Coastguard Worker     }
2345*8975f5c5SAndroid Build Coastguard Worker 
2346*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
2347*8975f5c5SAndroid Build Coastguard Worker 
2348*8975f5c5SAndroid Build Coastguard Worker     getImageViews().init(renderer);
2349*8975f5c5SAndroid Build Coastguard Worker }
2350*8975f5c5SAndroid Build Coastguard Worker 
redefineLevel(const gl::Context * context,const gl::ImageIndex & index,const vk::Format & format,const gl::Extents & size)2351*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::redefineLevel(const gl::Context *context,
2352*8975f5c5SAndroid Build Coastguard Worker                                        const gl::ImageIndex &index,
2353*8975f5c5SAndroid Build Coastguard Worker                                        const vk::Format &format,
2354*8975f5c5SAndroid Build Coastguard Worker                                        const gl::Extents &size)
2355*8975f5c5SAndroid Build Coastguard Worker {
2356*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
2357*8975f5c5SAndroid Build Coastguard Worker 
2358*8975f5c5SAndroid Build Coastguard Worker     if (!mOwnsImage)
2359*8975f5c5SAndroid Build Coastguard Worker     {
2360*8975f5c5SAndroid Build Coastguard Worker         releaseAndDeleteImageAndViews(contextVk);
2361*8975f5c5SAndroid Build Coastguard Worker     }
2362*8975f5c5SAndroid Build Coastguard Worker 
2363*8975f5c5SAndroid Build Coastguard Worker     if (mImage != nullptr)
2364*8975f5c5SAndroid Build Coastguard Worker     {
2365*8975f5c5SAndroid Build Coastguard Worker         // If there are any staged changes for this index, we can remove them since we're going to
2366*8975f5c5SAndroid Build Coastguard Worker         // override them with this call.
2367*8975f5c5SAndroid Build Coastguard Worker         gl::LevelIndex levelIndexGL(index.getLevelIndex());
2368*8975f5c5SAndroid Build Coastguard Worker         const uint32_t layerIndex = index.hasLayer() ? index.getLayerIndex() : 0;
2369*8975f5c5SAndroid Build Coastguard Worker         if (gl::IsArrayTextureType(index.getType()))
2370*8975f5c5SAndroid Build Coastguard Worker         {
2371*8975f5c5SAndroid Build Coastguard Worker             // A multi-layer texture is being redefined, remove all updates to this level; the
2372*8975f5c5SAndroid Build Coastguard Worker             // number of layers may have changed.
2373*8975f5c5SAndroid Build Coastguard Worker             mImage->removeStagedUpdates(contextVk, levelIndexGL, levelIndexGL);
2374*8975f5c5SAndroid Build Coastguard Worker         }
2375*8975f5c5SAndroid Build Coastguard Worker         else
2376*8975f5c5SAndroid Build Coastguard Worker         {
2377*8975f5c5SAndroid Build Coastguard Worker             // Otherwise remove only updates to this layer.  For example, cube map updates can be
2378*8975f5c5SAndroid Build Coastguard Worker             // done through glTexImage2D, one per cube face (i.e. layer) and so should not remove
2379*8975f5c5SAndroid Build Coastguard Worker             // updates to the other layers.
2380*8975f5c5SAndroid Build Coastguard Worker             ASSERT(index.getLayerCount() == 1);
2381*8975f5c5SAndroid Build Coastguard Worker             mImage->removeSingleSubresourceStagedUpdates(contextVk, levelIndexGL, layerIndex,
2382*8975f5c5SAndroid Build Coastguard Worker                                                          index.getLayerCount());
2383*8975f5c5SAndroid Build Coastguard Worker         }
2384*8975f5c5SAndroid Build Coastguard Worker 
2385*8975f5c5SAndroid Build Coastguard Worker         if (mImage->valid())
2386*8975f5c5SAndroid Build Coastguard Worker         {
2387*8975f5c5SAndroid Build Coastguard Worker             TextureLevelAllocation levelAllocation =
2388*8975f5c5SAndroid Build Coastguard Worker                 IsTextureLevelInAllocatedImage(*mImage, levelIndexGL)
2389*8975f5c5SAndroid Build Coastguard Worker                     ? TextureLevelAllocation::WithinAllocatedImage
2390*8975f5c5SAndroid Build Coastguard Worker                     : TextureLevelAllocation::OutsideAllocatedImage;
2391*8975f5c5SAndroid Build Coastguard Worker             TextureLevelDefinition levelDefinition =
2392*8975f5c5SAndroid Build Coastguard Worker                 IsTextureLevelDefinitionCompatibleWithImage(
2393*8975f5c5SAndroid Build Coastguard Worker                     *mImage, levelIndexGL, size, format.getIntendedFormatID(),
2394*8975f5c5SAndroid Build Coastguard Worker                     format.getActualImageFormatID(getRequiredImageAccess()))
2395*8975f5c5SAndroid Build Coastguard Worker                     ? TextureLevelDefinition::Compatible
2396*8975f5c5SAndroid Build Coastguard Worker                     : TextureLevelDefinition::Incompatible;
2397*8975f5c5SAndroid Build Coastguard Worker             if (TextureRedefineLevel(levelAllocation, levelDefinition, mState.getImmutableFormat(),
2398*8975f5c5SAndroid Build Coastguard Worker                                      mImage->getLevelCount(), layerIndex, index,
2399*8975f5c5SAndroid Build Coastguard Worker                                      mImage->getFirstAllocatedLevel(), &mRedefinedLevels))
2400*8975f5c5SAndroid Build Coastguard Worker             {
2401*8975f5c5SAndroid Build Coastguard Worker                 releaseImage(contextVk);
2402*8975f5c5SAndroid Build Coastguard Worker             }
2403*8975f5c5SAndroid Build Coastguard Worker         }
2404*8975f5c5SAndroid Build Coastguard Worker     }
2405*8975f5c5SAndroid Build Coastguard Worker 
2406*8975f5c5SAndroid Build Coastguard Worker     // If image is not released due to an out-of-range or incompatible level definition, the image
2407*8975f5c5SAndroid Build Coastguard Worker     // is still valid and we shouldn't redefine it to use the new format.  In that case,
2408*8975f5c5SAndroid Build Coastguard Worker     // ensureImageAllocated will only use the format to update the staging buffer's alignment to
2409*8975f5c5SAndroid Build Coastguard Worker     // support both the previous and the new formats.
2410*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureImageAllocated(contextVk, format));
2411*8975f5c5SAndroid Build Coastguard Worker 
2412*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2413*8975f5c5SAndroid Build Coastguard Worker }
2414*8975f5c5SAndroid Build Coastguard Worker 
copyImageDataToBufferAndGetData(ContextVk * contextVk,gl::LevelIndex sourceLevelGL,uint32_t layerCount,const gl::Box & sourceArea,RenderPassClosureReason reason,vk::BufferHelper * copyBuffer,uint8_t ** outDataPtr)2415*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copyImageDataToBufferAndGetData(ContextVk *contextVk,
2416*8975f5c5SAndroid Build Coastguard Worker                                                          gl::LevelIndex sourceLevelGL,
2417*8975f5c5SAndroid Build Coastguard Worker                                                          uint32_t layerCount,
2418*8975f5c5SAndroid Build Coastguard Worker                                                          const gl::Box &sourceArea,
2419*8975f5c5SAndroid Build Coastguard Worker                                                          RenderPassClosureReason reason,
2420*8975f5c5SAndroid Build Coastguard Worker                                                          vk::BufferHelper *copyBuffer,
2421*8975f5c5SAndroid Build Coastguard Worker                                                          uint8_t **outDataPtr)
2422*8975f5c5SAndroid Build Coastguard Worker {
2423*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRACE_EVENT0("gpu.angle", "TextureVk::copyImageDataToBufferAndGetData");
2424*8975f5c5SAndroid Build Coastguard Worker 
2425*8975f5c5SAndroid Build Coastguard Worker     // Make sure the source is initialized and it's images are flushed.
2426*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
2427*8975f5c5SAndroid Build Coastguard Worker 
2428*8975f5c5SAndroid Build Coastguard Worker     gl::Box modifiedSourceArea = sourceArea;
2429*8975f5c5SAndroid Build Coastguard Worker 
2430*8975f5c5SAndroid Build Coastguard Worker     bool is3D = mImage->getExtents().depth > 1;
2431*8975f5c5SAndroid Build Coastguard Worker     if (is3D)
2432*8975f5c5SAndroid Build Coastguard Worker     {
2433*8975f5c5SAndroid Build Coastguard Worker         layerCount = 1;
2434*8975f5c5SAndroid Build Coastguard Worker     }
2435*8975f5c5SAndroid Build Coastguard Worker     else
2436*8975f5c5SAndroid Build Coastguard Worker     {
2437*8975f5c5SAndroid Build Coastguard Worker         modifiedSourceArea.depth = 1;
2438*8975f5c5SAndroid Build Coastguard Worker     }
2439*8975f5c5SAndroid Build Coastguard Worker 
2440*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mImage->copyImageDataToBuffer(contextVk, sourceLevelGL, layerCount, 0,
2441*8975f5c5SAndroid Build Coastguard Worker                                             modifiedSourceArea, copyBuffer, outDataPtr));
2442*8975f5c5SAndroid Build Coastguard Worker 
2443*8975f5c5SAndroid Build Coastguard Worker     // Explicitly finish. If new use cases arise where we don't want to block we can change this.
2444*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(contextVk->finishImpl(reason));
2445*8975f5c5SAndroid Build Coastguard Worker     // invalidate must be called after wait for finish.
2446*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(copyBuffer->invalidate(contextVk->getRenderer()));
2447*8975f5c5SAndroid Build Coastguard Worker 
2448*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2449*8975f5c5SAndroid Build Coastguard Worker }
2450*8975f5c5SAndroid Build Coastguard Worker 
copyBufferDataToImage(ContextVk * contextVk,vk::BufferHelper * srcBuffer,const gl::ImageIndex index,uint32_t rowLength,uint32_t imageHeight,const gl::Box & sourceArea,size_t offset,VkImageAspectFlags aspectFlags)2451*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copyBufferDataToImage(ContextVk *contextVk,
2452*8975f5c5SAndroid Build Coastguard Worker                                                vk::BufferHelper *srcBuffer,
2453*8975f5c5SAndroid Build Coastguard Worker                                                const gl::ImageIndex index,
2454*8975f5c5SAndroid Build Coastguard Worker                                                uint32_t rowLength,
2455*8975f5c5SAndroid Build Coastguard Worker                                                uint32_t imageHeight,
2456*8975f5c5SAndroid Build Coastguard Worker                                                const gl::Box &sourceArea,
2457*8975f5c5SAndroid Build Coastguard Worker                                                size_t offset,
2458*8975f5c5SAndroid Build Coastguard Worker                                                VkImageAspectFlags aspectFlags)
2459*8975f5c5SAndroid Build Coastguard Worker {
2460*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRACE_EVENT0("gpu.angle", "TextureVk::copyBufferDataToImage");
2461*8975f5c5SAndroid Build Coastguard Worker 
2462*8975f5c5SAndroid Build Coastguard Worker     // Vulkan Spec requires the bufferOffset to be a multiple of pixel size for
2463*8975f5c5SAndroid Build Coastguard Worker     // vkCmdCopyBufferToImage.
2464*8975f5c5SAndroid Build Coastguard Worker     ASSERT((offset % vk::GetImageCopyBufferAlignment(mImage->getActualFormatID())) == 0);
2465*8975f5c5SAndroid Build Coastguard Worker 
2466*8975f5c5SAndroid Build Coastguard Worker     gl::LevelIndex level = gl::LevelIndex(index.getLevelIndex());
2467*8975f5c5SAndroid Build Coastguard Worker     GLuint layerCount    = index.getLayerCount();
2468*8975f5c5SAndroid Build Coastguard Worker     GLuint layerIndex    = 0;
2469*8975f5c5SAndroid Build Coastguard Worker 
2470*8975f5c5SAndroid Build Coastguard Worker     ASSERT((aspectFlags & kDepthStencilAspects) != kDepthStencilAspects);
2471*8975f5c5SAndroid Build Coastguard Worker 
2472*8975f5c5SAndroid Build Coastguard Worker     VkBufferImageCopy region           = {};
2473*8975f5c5SAndroid Build Coastguard Worker     region.bufferOffset                = offset;
2474*8975f5c5SAndroid Build Coastguard Worker     region.bufferRowLength             = rowLength;
2475*8975f5c5SAndroid Build Coastguard Worker     region.bufferImageHeight           = imageHeight;
2476*8975f5c5SAndroid Build Coastguard Worker     region.imageExtent.width           = sourceArea.width;
2477*8975f5c5SAndroid Build Coastguard Worker     region.imageExtent.height          = sourceArea.height;
2478*8975f5c5SAndroid Build Coastguard Worker     region.imageExtent.depth           = sourceArea.depth;
2479*8975f5c5SAndroid Build Coastguard Worker     region.imageOffset.x               = sourceArea.x;
2480*8975f5c5SAndroid Build Coastguard Worker     region.imageOffset.y               = sourceArea.y;
2481*8975f5c5SAndroid Build Coastguard Worker     region.imageOffset.z               = sourceArea.z;
2482*8975f5c5SAndroid Build Coastguard Worker     region.imageSubresource.aspectMask = aspectFlags;
2483*8975f5c5SAndroid Build Coastguard Worker     region.imageSubresource.layerCount = layerCount;
2484*8975f5c5SAndroid Build Coastguard Worker     region.imageSubresource.mipLevel   = mImage->toVkLevel(level).get();
2485*8975f5c5SAndroid Build Coastguard Worker 
2486*8975f5c5SAndroid Build Coastguard Worker     if (gl::IsArrayTextureType(index.getType()))
2487*8975f5c5SAndroid Build Coastguard Worker     {
2488*8975f5c5SAndroid Build Coastguard Worker         layerIndex               = sourceArea.z;
2489*8975f5c5SAndroid Build Coastguard Worker         region.imageOffset.z     = 0;
2490*8975f5c5SAndroid Build Coastguard Worker         region.imageExtent.depth = 1;
2491*8975f5c5SAndroid Build Coastguard Worker     }
2492*8975f5c5SAndroid Build Coastguard Worker     else if (index.getType() == gl::TextureType::CubeMap)
2493*8975f5c5SAndroid Build Coastguard Worker     {
2494*8975f5c5SAndroid Build Coastguard Worker         // Copy to the correct cube map face.
2495*8975f5c5SAndroid Build Coastguard Worker         layerIndex = index.getLayerIndex();
2496*8975f5c5SAndroid Build Coastguard Worker     }
2497*8975f5c5SAndroid Build Coastguard Worker     region.imageSubresource.baseArrayLayer = layerIndex;
2498*8975f5c5SAndroid Build Coastguard Worker 
2499*8975f5c5SAndroid Build Coastguard Worker     // Make sure the source is initialized and its images are flushed.
2500*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
2501*8975f5c5SAndroid Build Coastguard Worker 
2502*8975f5c5SAndroid Build Coastguard Worker     vk::CommandBufferAccess access;
2503*8975f5c5SAndroid Build Coastguard Worker     access.onBufferTransferRead(srcBuffer);
2504*8975f5c5SAndroid Build Coastguard Worker     access.onImageTransferWrite(level, 1, layerIndex, layerCount, mImage->getAspectFlags(), mImage);
2505*8975f5c5SAndroid Build Coastguard Worker 
2506*8975f5c5SAndroid Build Coastguard Worker     vk::OutsideRenderPassCommandBuffer *commandBuffer;
2507*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
2508*8975f5c5SAndroid Build Coastguard Worker 
2509*8975f5c5SAndroid Build Coastguard Worker     commandBuffer->copyBufferToImage(srcBuffer->getBuffer().getHandle(), mImage->getImage(),
2510*8975f5c5SAndroid Build Coastguard Worker                                      mImage->getCurrentLayout(contextVk->getRenderer()), 1,
2511*8975f5c5SAndroid Build Coastguard Worker                                      &region);
2512*8975f5c5SAndroid Build Coastguard Worker 
2513*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2514*8975f5c5SAndroid Build Coastguard Worker }
2515*8975f5c5SAndroid Build Coastguard Worker 
generateMipmapsWithCompute(ContextVk * contextVk)2516*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::generateMipmapsWithCompute(ContextVk *contextVk)
2517*8975f5c5SAndroid Build Coastguard Worker {
2518*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
2519*8975f5c5SAndroid Build Coastguard Worker 
2520*8975f5c5SAndroid Build Coastguard Worker     // Requires that the image:
2521*8975f5c5SAndroid Build Coastguard Worker     //
2522*8975f5c5SAndroid Build Coastguard Worker     // - is not sRGB
2523*8975f5c5SAndroid Build Coastguard Worker     // - is not integer
2524*8975f5c5SAndroid Build Coastguard Worker     // - is 2D or 2D array
2525*8975f5c5SAndroid Build Coastguard Worker     // - is single sample
2526*8975f5c5SAndroid Build Coastguard Worker     // - is color image
2527*8975f5c5SAndroid Build Coastguard Worker     //
2528*8975f5c5SAndroid Build Coastguard Worker     // Support for the first two can be added easily.  Supporting 3D textures, MSAA and
2529*8975f5c5SAndroid Build Coastguard Worker     // depth/stencil would be more involved.
2530*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mImage->getActualFormat().isSRGB);
2531*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mImage->getActualFormat().isInt());
2532*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImage->getType() == VK_IMAGE_TYPE_2D);
2533*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImage->getSamples() == 1);
2534*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImage->getAspectFlags() == VK_IMAGE_ASPECT_COLOR_BIT);
2535*8975f5c5SAndroid Build Coastguard Worker 
2536*8975f5c5SAndroid Build Coastguard Worker     // Create the appropriate sampler.
2537*8975f5c5SAndroid Build Coastguard Worker     GLenum filter = CalculateGenerateMipmapFilter(contextVk, mImage->getActualFormatID());
2538*8975f5c5SAndroid Build Coastguard Worker 
2539*8975f5c5SAndroid Build Coastguard Worker     gl::SamplerState samplerState;
2540*8975f5c5SAndroid Build Coastguard Worker     samplerState.setMinFilter(filter);
2541*8975f5c5SAndroid Build Coastguard Worker     samplerState.setMagFilter(filter);
2542*8975f5c5SAndroid Build Coastguard Worker     samplerState.setWrapS(GL_CLAMP_TO_EDGE);
2543*8975f5c5SAndroid Build Coastguard Worker     samplerState.setWrapT(GL_CLAMP_TO_EDGE);
2544*8975f5c5SAndroid Build Coastguard Worker     samplerState.setWrapR(GL_CLAMP_TO_EDGE);
2545*8975f5c5SAndroid Build Coastguard Worker 
2546*8975f5c5SAndroid Build Coastguard Worker     vk::SharedSamplerPtr sampler;
2547*8975f5c5SAndroid Build Coastguard Worker     vk::SamplerDesc samplerDesc(contextVk, samplerState, false, nullptr,
2548*8975f5c5SAndroid Build Coastguard Worker                                 static_cast<angle::FormatID>(0));
2549*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, samplerDesc, &sampler));
2550*8975f5c5SAndroid Build Coastguard Worker 
2551*8975f5c5SAndroid Build Coastguard Worker     // If the image has more levels than supported, generate as many mips as possible at a time.
2552*8975f5c5SAndroid Build Coastguard Worker     const vk::LevelIndex maxGenerateLevels(UtilsVk::GetGenerateMipmapMaxLevels(contextVk));
2553*8975f5c5SAndroid Build Coastguard Worker     vk::LevelIndex dstMaxLevelVk = mImage->toVkLevel(gl::LevelIndex(mState.getMipmapMaxLevel()));
2554*8975f5c5SAndroid Build Coastguard Worker     for (vk::LevelIndex dstBaseLevelVk =
2555*8975f5c5SAndroid Build Coastguard Worker              mImage->toVkLevel(gl::LevelIndex(mState.getEffectiveBaseLevel() + 1));
2556*8975f5c5SAndroid Build Coastguard Worker          dstBaseLevelVk <= dstMaxLevelVk; dstBaseLevelVk = dstBaseLevelVk + maxGenerateLevels.get())
2557*8975f5c5SAndroid Build Coastguard Worker     {
2558*8975f5c5SAndroid Build Coastguard Worker         vk::CommandBufferAccess access;
2559*8975f5c5SAndroid Build Coastguard Worker 
2560*8975f5c5SAndroid Build Coastguard Worker         // For mipmap generation, we should make sure that there is no pending write for the source
2561*8975f5c5SAndroid Build Coastguard Worker         // mip level. If there is, a barrier should be inserted before the source mip being used.
2562*8975f5c5SAndroid Build Coastguard Worker         const vk::LevelIndex srcLevelVk = dstBaseLevelVk - 1;
2563*8975f5c5SAndroid Build Coastguard Worker         uint32_t writeLevelCount =
2564*8975f5c5SAndroid Build Coastguard Worker             std::min(maxGenerateLevels.get(), dstMaxLevelVk.get() + 1 - dstBaseLevelVk.get());
2565*8975f5c5SAndroid Build Coastguard Worker 
2566*8975f5c5SAndroid Build Coastguard Worker         access.onImageComputeMipmapGenerationRead(mImage->toGLLevel(srcLevelVk), 1, 0,
2567*8975f5c5SAndroid Build Coastguard Worker                                                   mImage->getLayerCount(),
2568*8975f5c5SAndroid Build Coastguard Worker                                                   VK_IMAGE_ASPECT_COLOR_BIT, mImage);
2569*8975f5c5SAndroid Build Coastguard Worker         access.onImageComputeShaderWrite(mImage->toGLLevel(dstBaseLevelVk), writeLevelCount, 0,
2570*8975f5c5SAndroid Build Coastguard Worker                                          mImage->getLayerCount(), VK_IMAGE_ASPECT_COLOR_BIT,
2571*8975f5c5SAndroid Build Coastguard Worker                                          mImage);
2572*8975f5c5SAndroid Build Coastguard Worker 
2573*8975f5c5SAndroid Build Coastguard Worker         vk::OutsideRenderPassCommandBuffer *commandBuffer;
2574*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
2575*8975f5c5SAndroid Build Coastguard Worker 
2576*8975f5c5SAndroid Build Coastguard Worker         // Generate mipmaps for every layer separately.
2577*8975f5c5SAndroid Build Coastguard Worker         for (uint32_t layer = 0; layer < mImage->getLayerCount(); ++layer)
2578*8975f5c5SAndroid Build Coastguard Worker         {
2579*8975f5c5SAndroid Build Coastguard Worker             // Create the necessary views.
2580*8975f5c5SAndroid Build Coastguard Worker             const vk::ImageView *srcView                         = nullptr;
2581*8975f5c5SAndroid Build Coastguard Worker             UtilsVk::GenerateMipmapDestLevelViews destLevelViews = {};
2582*8975f5c5SAndroid Build Coastguard Worker 
2583*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(getImageViews().getLevelLayerDrawImageView(contextVk, *mImage, srcLevelVk,
2584*8975f5c5SAndroid Build Coastguard Worker                                                                  layer, &srcView));
2585*8975f5c5SAndroid Build Coastguard Worker 
2586*8975f5c5SAndroid Build Coastguard Worker             vk::LevelIndex dstLevelCount = maxGenerateLevels;
2587*8975f5c5SAndroid Build Coastguard Worker             for (vk::LevelIndex levelVk(0); levelVk < maxGenerateLevels; ++levelVk)
2588*8975f5c5SAndroid Build Coastguard Worker             {
2589*8975f5c5SAndroid Build Coastguard Worker                 vk::LevelIndex dstLevelVk = dstBaseLevelVk + levelVk.get();
2590*8975f5c5SAndroid Build Coastguard Worker 
2591*8975f5c5SAndroid Build Coastguard Worker                 // If fewer levels left than maxGenerateLevels, cut the loop short.
2592*8975f5c5SAndroid Build Coastguard Worker                 if (dstLevelVk > dstMaxLevelVk)
2593*8975f5c5SAndroid Build Coastguard Worker                 {
2594*8975f5c5SAndroid Build Coastguard Worker                     dstLevelCount = levelVk;
2595*8975f5c5SAndroid Build Coastguard Worker                     break;
2596*8975f5c5SAndroid Build Coastguard Worker                 }
2597*8975f5c5SAndroid Build Coastguard Worker 
2598*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(getImageViews().getLevelLayerDrawImageView(
2599*8975f5c5SAndroid Build Coastguard Worker                     contextVk, *mImage, dstLevelVk, layer, &destLevelViews[levelVk.get()]));
2600*8975f5c5SAndroid Build Coastguard Worker             }
2601*8975f5c5SAndroid Build Coastguard Worker 
2602*8975f5c5SAndroid Build Coastguard Worker             // If the image has fewer than maximum levels, fill the last views with a unused view.
2603*8975f5c5SAndroid Build Coastguard Worker             ASSERT(dstLevelCount > vk::LevelIndex(0));
2604*8975f5c5SAndroid Build Coastguard Worker             for (vk::LevelIndex levelVk = dstLevelCount;
2605*8975f5c5SAndroid Build Coastguard Worker                  levelVk < vk::LevelIndex(UtilsVk::kGenerateMipmapMaxLevels); ++levelVk)
2606*8975f5c5SAndroid Build Coastguard Worker             {
2607*8975f5c5SAndroid Build Coastguard Worker                 destLevelViews[levelVk.get()] = destLevelViews[levelVk.get() - 1];
2608*8975f5c5SAndroid Build Coastguard Worker             }
2609*8975f5c5SAndroid Build Coastguard Worker 
2610*8975f5c5SAndroid Build Coastguard Worker             // Generate mipmaps.
2611*8975f5c5SAndroid Build Coastguard Worker             UtilsVk::GenerateMipmapParameters params = {};
2612*8975f5c5SAndroid Build Coastguard Worker             params.srcLevel                          = srcLevelVk.get();
2613*8975f5c5SAndroid Build Coastguard Worker             params.dstLevelCount                     = dstLevelCount.get();
2614*8975f5c5SAndroid Build Coastguard Worker 
2615*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(contextVk->getUtils().generateMipmap(contextVk, mImage, srcView, mImage,
2616*8975f5c5SAndroid Build Coastguard Worker                                                            destLevelViews, sampler->get(), params));
2617*8975f5c5SAndroid Build Coastguard Worker         }
2618*8975f5c5SAndroid Build Coastguard Worker     }
2619*8975f5c5SAndroid Build Coastguard Worker 
2620*8975f5c5SAndroid Build Coastguard Worker     contextVk->trackImageWithOutsideRenderPassEvent(mImage);
2621*8975f5c5SAndroid Build Coastguard Worker 
2622*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2623*8975f5c5SAndroid Build Coastguard Worker }
2624*8975f5c5SAndroid Build Coastguard Worker 
generateMipmapsWithCPU(const gl::Context * context)2625*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::generateMipmapsWithCPU(const gl::Context *context)
2626*8975f5c5SAndroid Build Coastguard Worker {
2627*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
2628*8975f5c5SAndroid Build Coastguard Worker 
2629*8975f5c5SAndroid Build Coastguard Worker     gl::LevelIndex baseLevelGL(mState.getEffectiveBaseLevel());
2630*8975f5c5SAndroid Build Coastguard Worker     vk::LevelIndex baseLevelVk         = mImage->toVkLevel(baseLevelGL);
2631*8975f5c5SAndroid Build Coastguard Worker     const gl::Extents baseLevelExtents = mImage->getLevelExtents(baseLevelVk);
2632*8975f5c5SAndroid Build Coastguard Worker     uint32_t imageLayerCount           = mImage->getLayerCount();
2633*8975f5c5SAndroid Build Coastguard Worker 
2634*8975f5c5SAndroid Build Coastguard Worker     uint8_t *imageData = nullptr;
2635*8975f5c5SAndroid Build Coastguard Worker     gl::Box imageArea(0, 0, 0, baseLevelExtents.width, baseLevelExtents.height,
2636*8975f5c5SAndroid Build Coastguard Worker                       baseLevelExtents.depth);
2637*8975f5c5SAndroid Build Coastguard Worker 
2638*8975f5c5SAndroid Build Coastguard Worker     vk::RendererScoped<vk::BufferHelper> bufferHelper(contextVk->getRenderer());
2639*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(copyImageDataToBufferAndGetData(contextVk, baseLevelGL, imageLayerCount, imageArea,
2640*8975f5c5SAndroid Build Coastguard Worker                                               RenderPassClosureReason::GenerateMipmapOnCPU,
2641*8975f5c5SAndroid Build Coastguard Worker                                               &bufferHelper.get(), &imageData));
2642*8975f5c5SAndroid Build Coastguard Worker 
2643*8975f5c5SAndroid Build Coastguard Worker     const angle::Format &angleFormat = mImage->getActualFormat();
2644*8975f5c5SAndroid Build Coastguard Worker     GLuint sourceRowPitch            = baseLevelExtents.width * angleFormat.pixelBytes;
2645*8975f5c5SAndroid Build Coastguard Worker     GLuint sourceDepthPitch          = sourceRowPitch * baseLevelExtents.height;
2646*8975f5c5SAndroid Build Coastguard Worker     size_t baseLevelAllocationSize   = sourceDepthPitch * baseLevelExtents.depth;
2647*8975f5c5SAndroid Build Coastguard Worker 
2648*8975f5c5SAndroid Build Coastguard Worker     // We now have the base level available to be manipulated in the imageData pointer. Generate all
2649*8975f5c5SAndroid Build Coastguard Worker     // the missing mipmaps with the slow path. For each layer, use the copied data to generate all
2650*8975f5c5SAndroid Build Coastguard Worker     // the mips.
2651*8975f5c5SAndroid Build Coastguard Worker     for (GLuint layer = 0; layer < imageLayerCount; layer++)
2652*8975f5c5SAndroid Build Coastguard Worker     {
2653*8975f5c5SAndroid Build Coastguard Worker         size_t bufferOffset = layer * baseLevelAllocationSize;
2654*8975f5c5SAndroid Build Coastguard Worker 
2655*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(generateMipmapLevelsWithCPU(contextVk, angleFormat, layer, baseLevelGL + 1,
2656*8975f5c5SAndroid Build Coastguard Worker                                               gl::LevelIndex(mState.getMipmapMaxLevel()),
2657*8975f5c5SAndroid Build Coastguard Worker                                               baseLevelExtents.width, baseLevelExtents.height,
2658*8975f5c5SAndroid Build Coastguard Worker                                               baseLevelExtents.depth, sourceRowPitch,
2659*8975f5c5SAndroid Build Coastguard Worker                                               sourceDepthPitch, imageData + bufferOffset));
2660*8975f5c5SAndroid Build Coastguard Worker     }
2661*8975f5c5SAndroid Build Coastguard Worker 
2662*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!TextureHasAnyRedefinedLevels(mRedefinedLevels));
2663*8975f5c5SAndroid Build Coastguard Worker     return flushImageStagedUpdates(contextVk);
2664*8975f5c5SAndroid Build Coastguard Worker }
2665*8975f5c5SAndroid Build Coastguard Worker 
generateMipmap(const gl::Context * context)2666*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::generateMipmap(const gl::Context *context)
2667*8975f5c5SAndroid Build Coastguard Worker {
2668*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk   = vk::GetImpl(context);
2669*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
2670*8975f5c5SAndroid Build Coastguard Worker 
2671*8975f5c5SAndroid Build Coastguard Worker     // The image should already be allocated by a prior syncState.
2672*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImage->valid());
2673*8975f5c5SAndroid Build Coastguard Worker 
2674*8975f5c5SAndroid Build Coastguard Worker     // If base level has changed, the front-end should have called syncState already.
2675*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mState.getImmutableFormat() ||
2676*8975f5c5SAndroid Build Coastguard Worker            mImage->getFirstAllocatedLevel() == gl::LevelIndex(mState.getEffectiveBaseLevel()));
2677*8975f5c5SAndroid Build Coastguard Worker 
2678*8975f5c5SAndroid Build Coastguard Worker     // Only staged update here is the robust resource init if any.
2679*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::FullMipChainForGenerateMipmap));
2680*8975f5c5SAndroid Build Coastguard Worker 
2681*8975f5c5SAndroid Build Coastguard Worker     vk::LevelIndex baseLevel = mImage->toVkLevel(gl::LevelIndex(mState.getEffectiveBaseLevel()));
2682*8975f5c5SAndroid Build Coastguard Worker     vk::LevelIndex maxLevel  = mImage->toVkLevel(gl::LevelIndex(mState.getMipmapMaxLevel()));
2683*8975f5c5SAndroid Build Coastguard Worker     ASSERT(maxLevel != vk::LevelIndex(0));
2684*8975f5c5SAndroid Build Coastguard Worker 
2685*8975f5c5SAndroid Build Coastguard Worker     if (getImageViews().hasColorspaceOverrideForWrite(*mImage))
2686*8975f5c5SAndroid Build Coastguard Worker     {
2687*8975f5c5SAndroid Build Coastguard Worker         angle::FormatID actualFormatID =
2688*8975f5c5SAndroid Build Coastguard Worker             getImageViews().getColorspaceOverrideFormatForWrite(mImage->getActualFormatID());
2689*8975f5c5SAndroid Build Coastguard Worker         return contextVk->getUtils().generateMipmapWithDraw(
2690*8975f5c5SAndroid Build Coastguard Worker             contextVk, mImage, actualFormatID,
2691*8975f5c5SAndroid Build Coastguard Worker             gl::IsMipmapFiltered(mState.getSamplerState().getMinFilter()));
2692*8975f5c5SAndroid Build Coastguard Worker     }
2693*8975f5c5SAndroid Build Coastguard Worker 
2694*8975f5c5SAndroid Build Coastguard Worker     // If it's possible to generate mipmap in compute, that would give the best possible
2695*8975f5c5SAndroid Build Coastguard Worker     // performance on some hardware.
2696*8975f5c5SAndroid Build Coastguard Worker     if (CanGenerateMipmapWithCompute(renderer, mImage->getType(), mImage->getActualFormatID(),
2697*8975f5c5SAndroid Build Coastguard Worker                                      mImage->getSamples(), mOwnsImage))
2698*8975f5c5SAndroid Build Coastguard Worker     {
2699*8975f5c5SAndroid Build Coastguard Worker         ASSERT((mImageUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT) != 0);
2700*8975f5c5SAndroid Build Coastguard Worker         return generateMipmapsWithCompute(contextVk);
2701*8975f5c5SAndroid Build Coastguard Worker     }
2702*8975f5c5SAndroid Build Coastguard Worker     else if (renderer->hasImageFormatFeatureBits(mImage->getActualFormatID(), kBlitFeatureFlags))
2703*8975f5c5SAndroid Build Coastguard Worker     {
2704*8975f5c5SAndroid Build Coastguard Worker         // Otherwise, use blit if possible.
2705*8975f5c5SAndroid Build Coastguard Worker         return mImage->generateMipmapsWithBlit(contextVk, baseLevel, maxLevel);
2706*8975f5c5SAndroid Build Coastguard Worker     }
2707*8975f5c5SAndroid Build Coastguard Worker 
2708*8975f5c5SAndroid Build Coastguard Worker     ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_HIGH,
2709*8975f5c5SAndroid Build Coastguard Worker                           "Mipmap generated on CPU due to format restrictions");
2710*8975f5c5SAndroid Build Coastguard Worker 
2711*8975f5c5SAndroid Build Coastguard Worker     // If not possible to generate mipmaps on the GPU, do it on the CPU for conformance.
2712*8975f5c5SAndroid Build Coastguard Worker     return generateMipmapsWithCPU(context);
2713*8975f5c5SAndroid Build Coastguard Worker }
2714*8975f5c5SAndroid Build Coastguard Worker 
setBaseLevel(const gl::Context * context,GLuint baseLevel)2715*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::setBaseLevel(const gl::Context *context, GLuint baseLevel)
2716*8975f5c5SAndroid Build Coastguard Worker {
2717*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2718*8975f5c5SAndroid Build Coastguard Worker }
2719*8975f5c5SAndroid Build Coastguard Worker 
maybeUpdateBaseMaxLevels(ContextVk * contextVk,TextureUpdateResult * updateResultOut)2720*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::maybeUpdateBaseMaxLevels(ContextVk *contextVk,
2721*8975f5c5SAndroid Build Coastguard Worker                                                   TextureUpdateResult *updateResultOut)
2722*8975f5c5SAndroid Build Coastguard Worker {
2723*8975f5c5SAndroid Build Coastguard Worker     if (!mImage)
2724*8975f5c5SAndroid Build Coastguard Worker     {
2725*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
2726*8975f5c5SAndroid Build Coastguard Worker     }
2727*8975f5c5SAndroid Build Coastguard Worker 
2728*8975f5c5SAndroid Build Coastguard Worker     bool baseLevelChanged = mCurrentBaseLevel.get() != static_cast<GLint>(mState.getBaseLevel());
2729*8975f5c5SAndroid Build Coastguard Worker     bool maxLevelChanged  = mCurrentMaxLevel.get() != static_cast<GLint>(mState.getMaxLevel());
2730*8975f5c5SAndroid Build Coastguard Worker 
2731*8975f5c5SAndroid Build Coastguard Worker     if (!maxLevelChanged && !baseLevelChanged)
2732*8975f5c5SAndroid Build Coastguard Worker     {
2733*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
2734*8975f5c5SAndroid Build Coastguard Worker     }
2735*8975f5c5SAndroid Build Coastguard Worker 
2736*8975f5c5SAndroid Build Coastguard Worker     gl::LevelIndex newBaseLevel = gl::LevelIndex(mState.getEffectiveBaseLevel());
2737*8975f5c5SAndroid Build Coastguard Worker     gl::LevelIndex newMaxLevel  = gl::LevelIndex(mState.getEffectiveMaxLevel());
2738*8975f5c5SAndroid Build Coastguard Worker     ASSERT(newBaseLevel <= newMaxLevel);
2739*8975f5c5SAndroid Build Coastguard Worker 
2740*8975f5c5SAndroid Build Coastguard Worker     if (!mImage->valid())
2741*8975f5c5SAndroid Build Coastguard Worker     {
2742*8975f5c5SAndroid Build Coastguard Worker         // No further work to do, let staged updates handle the new levels
2743*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
2744*8975f5c5SAndroid Build Coastguard Worker     }
2745*8975f5c5SAndroid Build Coastguard Worker 
2746*8975f5c5SAndroid Build Coastguard Worker     if (mState.getImmutableFormat())
2747*8975f5c5SAndroid Build Coastguard Worker     {
2748*8975f5c5SAndroid Build Coastguard Worker         // For immutable texture, baseLevel/maxLevel should be a subset of the texture's actual
2749*8975f5c5SAndroid Build Coastguard Worker         // number of mip levels. We don't need to respecify an image.
2750*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!baseLevelChanged || newBaseLevel >= mImage->getFirstAllocatedLevel());
2751*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!maxLevelChanged || newMaxLevel < gl::LevelIndex(mImage->getLevelCount()));
2752*8975f5c5SAndroid Build Coastguard Worker     }
2753*8975f5c5SAndroid Build Coastguard Worker     else if (!baseLevelChanged && (newMaxLevel <= mImage->getLastAllocatedLevel()))
2754*8975f5c5SAndroid Build Coastguard Worker     {
2755*8975f5c5SAndroid Build Coastguard Worker         // With a valid image, check if only changing the maxLevel to a subset of the texture's
2756*8975f5c5SAndroid Build Coastguard Worker         // actual number of mip levels
2757*8975f5c5SAndroid Build Coastguard Worker         ASSERT(maxLevelChanged);
2758*8975f5c5SAndroid Build Coastguard Worker     }
2759*8975f5c5SAndroid Build Coastguard Worker     else
2760*8975f5c5SAndroid Build Coastguard Worker     {
2761*8975f5c5SAndroid Build Coastguard Worker         *updateResultOut = TextureUpdateResult::ImageRespecified;
2762*8975f5c5SAndroid Build Coastguard Worker         return respecifyImageStorage(contextVk);
2763*8975f5c5SAndroid Build Coastguard Worker     }
2764*8975f5c5SAndroid Build Coastguard Worker 
2765*8975f5c5SAndroid Build Coastguard Worker     // Don't need to respecify the texture; but do need to update which vkImageView's are served up
2766*8975f5c5SAndroid Build Coastguard Worker     // by ImageViewHelper
2767*8975f5c5SAndroid Build Coastguard Worker 
2768*8975f5c5SAndroid Build Coastguard Worker     // Update the current max level in ImageViewHelper
2769*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(initImageViews(contextVk, newMaxLevel - newBaseLevel + 1));
2770*8975f5c5SAndroid Build Coastguard Worker 
2771*8975f5c5SAndroid Build Coastguard Worker     mCurrentBaseLevel = newBaseLevel;
2772*8975f5c5SAndroid Build Coastguard Worker     mCurrentMaxLevel  = newMaxLevel;
2773*8975f5c5SAndroid Build Coastguard Worker 
2774*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2775*8975f5c5SAndroid Build Coastguard Worker }
2776*8975f5c5SAndroid Build Coastguard Worker 
copyAndStageImageData(ContextVk * contextVk,gl::LevelIndex previousFirstAllocateLevel,vk::ImageHelper * srcImage,vk::ImageHelper * dstImage)2777*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::copyAndStageImageData(ContextVk *contextVk,
2778*8975f5c5SAndroid Build Coastguard Worker                                                gl::LevelIndex previousFirstAllocateLevel,
2779*8975f5c5SAndroid Build Coastguard Worker                                                vk::ImageHelper *srcImage,
2780*8975f5c5SAndroid Build Coastguard Worker                                                vk::ImageHelper *dstImage)
2781*8975f5c5SAndroid Build Coastguard Worker {
2782*8975f5c5SAndroid Build Coastguard Worker     // Preserve the data in the Vulkan image.  GL texture's staged updates that correspond to
2783*8975f5c5SAndroid Build Coastguard Worker     // levels outside the range of the Vulkan image will remain intact.
2784*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
2785*8975f5c5SAndroid Build Coastguard Worker 
2786*8975f5c5SAndroid Build Coastguard Worker     // This path is only called when switching from !owned to owned, in which case if any level was
2787*8975f5c5SAndroid Build Coastguard Worker     // redefined it's already released and deleted by TextureVk::redefineLevel().
2788*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!TextureHasAnyRedefinedLevels(mRedefinedLevels));
2789*8975f5c5SAndroid Build Coastguard Worker 
2790*8975f5c5SAndroid Build Coastguard Worker     // Create a temp copy of srcImage for staging.
2791*8975f5c5SAndroid Build Coastguard Worker     std::unique_ptr<vk::RefCounted<vk::ImageHelper>> stagingImage;
2792*8975f5c5SAndroid Build Coastguard Worker     stagingImage = std::make_unique<vk::RefCounted<vk::ImageHelper>>();
2793*8975f5c5SAndroid Build Coastguard Worker 
2794*8975f5c5SAndroid Build Coastguard Worker     const uint32_t levelCount = srcImage->getLevelCount();
2795*8975f5c5SAndroid Build Coastguard Worker     const uint32_t layerCount = srcImage->getLayerCount();
2796*8975f5c5SAndroid Build Coastguard Worker 
2797*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(stagingImage->get().initStaging(
2798*8975f5c5SAndroid Build Coastguard Worker         contextVk, mState.hasProtectedContent(), renderer->getMemoryProperties(),
2799*8975f5c5SAndroid Build Coastguard Worker         srcImage->getType(), srcImage->getExtents(), srcImage->getIntendedFormatID(),
2800*8975f5c5SAndroid Build Coastguard Worker         srcImage->getActualFormatID(), srcImage->getSamples(), kTransferImageFlags, levelCount,
2801*8975f5c5SAndroid Build Coastguard Worker         layerCount));
2802*8975f5c5SAndroid Build Coastguard Worker 
2803*8975f5c5SAndroid Build Coastguard Worker     // Copy the src image wholly into the staging image
2804*8975f5c5SAndroid Build Coastguard Worker     const VkImageAspectFlags aspectFlags = srcImage->getAspectFlags();
2805*8975f5c5SAndroid Build Coastguard Worker 
2806*8975f5c5SAndroid Build Coastguard Worker     vk::CommandBufferAccess access;
2807*8975f5c5SAndroid Build Coastguard Worker     access.onImageTransferWrite(gl::LevelIndex(0), levelCount, 0, layerCount, aspectFlags,
2808*8975f5c5SAndroid Build Coastguard Worker                                 &stagingImage->get());
2809*8975f5c5SAndroid Build Coastguard Worker     access.onImageTransferRead(aspectFlags, srcImage);
2810*8975f5c5SAndroid Build Coastguard Worker 
2811*8975f5c5SAndroid Build Coastguard Worker     vk::OutsideRenderPassCommandBuffer *commandBuffer;
2812*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
2813*8975f5c5SAndroid Build Coastguard Worker 
2814*8975f5c5SAndroid Build Coastguard Worker     VkImageCopy copyRegion               = {};
2815*8975f5c5SAndroid Build Coastguard Worker     copyRegion.srcSubresource.aspectMask = aspectFlags;
2816*8975f5c5SAndroid Build Coastguard Worker     copyRegion.srcSubresource.layerCount = layerCount;
2817*8975f5c5SAndroid Build Coastguard Worker     copyRegion.dstSubresource            = copyRegion.srcSubresource;
2818*8975f5c5SAndroid Build Coastguard Worker 
2819*8975f5c5SAndroid Build Coastguard Worker     for (vk::LevelIndex levelVk(0); levelVk < vk::LevelIndex(levelCount); ++levelVk)
2820*8975f5c5SAndroid Build Coastguard Worker     {
2821*8975f5c5SAndroid Build Coastguard Worker         gl::Extents levelExtents = srcImage->getLevelExtents(levelVk);
2822*8975f5c5SAndroid Build Coastguard Worker 
2823*8975f5c5SAndroid Build Coastguard Worker         copyRegion.srcSubresource.mipLevel = levelVk.get();
2824*8975f5c5SAndroid Build Coastguard Worker         copyRegion.dstSubresource.mipLevel = levelVk.get();
2825*8975f5c5SAndroid Build Coastguard Worker         gl_vk::GetExtent(levelExtents, &copyRegion.extent);
2826*8975f5c5SAndroid Build Coastguard Worker 
2827*8975f5c5SAndroid Build Coastguard Worker         commandBuffer->copyImage(srcImage->getImage(), srcImage->getCurrentLayout(renderer),
2828*8975f5c5SAndroid Build Coastguard Worker                                  stagingImage->get().getImage(),
2829*8975f5c5SAndroid Build Coastguard Worker                                  stagingImage->get().getCurrentLayout(renderer), 1, &copyRegion);
2830*8975f5c5SAndroid Build Coastguard Worker     }
2831*8975f5c5SAndroid Build Coastguard Worker 
2832*8975f5c5SAndroid Build Coastguard Worker     // Stage the staging image in the destination
2833*8975f5c5SAndroid Build Coastguard Worker     dstImage->stageSubresourceUpdatesFromAllImageLevels(stagingImage.release(),
2834*8975f5c5SAndroid Build Coastguard Worker                                                         previousFirstAllocateLevel);
2835*8975f5c5SAndroid Build Coastguard Worker 
2836*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2837*8975f5c5SAndroid Build Coastguard Worker }
2838*8975f5c5SAndroid Build Coastguard Worker 
reinitImageAsRenderable(ContextVk * contextVk,const vk::Format & format)2839*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::reinitImageAsRenderable(ContextVk *contextVk, const vk::Format &format)
2840*8975f5c5SAndroid Build Coastguard Worker {
2841*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImage->valid());
2842*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
2843*8975f5c5SAndroid Build Coastguard Worker 
2844*8975f5c5SAndroid Build Coastguard Worker     const uint32_t levelCount = mImage->getLevelCount();
2845*8975f5c5SAndroid Build Coastguard Worker     const uint32_t layerCount = mImage->getLayerCount();
2846*8975f5c5SAndroid Build Coastguard Worker 
2847*8975f5c5SAndroid Build Coastguard Worker     // Make sure the source is initialized and its staged updates are flushed.
2848*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(flushImageStagedUpdates(contextVk));
2849*8975f5c5SAndroid Build Coastguard Worker 
2850*8975f5c5SAndroid Build Coastguard Worker     const angle::Format &srcFormat = mImage->getActualFormat();
2851*8975f5c5SAndroid Build Coastguard Worker     const angle::Format &dstFormat = format.getActualImageFormat(getRequiredImageAccess());
2852*8975f5c5SAndroid Build Coastguard Worker 
2853*8975f5c5SAndroid Build Coastguard Worker     // If layerCount or levelCount is bigger than 1, we go for the slow path for now. The problem
2854*8975f5c5SAndroid Build Coastguard Worker     // with draw path is that in the multiple level/layer case, we have to do copy in a loop.
2855*8975f5c5SAndroid Build Coastguard Worker     // Currently copySubImageImplWithDraw() calls ensureImageInitalized which forces flush out
2856*8975f5c5SAndroid Build Coastguard Worker     // staged updates that we just staged inside the loop which is wrong.
2857*8975f5c5SAndroid Build Coastguard Worker     if (levelCount == 1 && layerCount == 1 &&
2858*8975f5c5SAndroid Build Coastguard Worker         !IsTextureLevelRedefined(mRedefinedLevels, mState.getType(),
2859*8975f5c5SAndroid Build Coastguard Worker                                  mImage->getFirstAllocatedLevel()))
2860*8975f5c5SAndroid Build Coastguard Worker     {
2861*8975f5c5SAndroid Build Coastguard Worker         ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_LOW,
2862*8975f5c5SAndroid Build Coastguard Worker                               "Copying image data due to texture format fallback");
2863*8975f5c5SAndroid Build Coastguard Worker 
2864*8975f5c5SAndroid Build Coastguard Worker         ASSERT(CanCopyWithDraw(renderer, mImage->getActualFormatID(), mImage->getTilingMode(),
2865*8975f5c5SAndroid Build Coastguard Worker                                format.getActualImageFormatID(getRequiredImageAccess()),
2866*8975f5c5SAndroid Build Coastguard Worker                                getTilingMode()));
2867*8975f5c5SAndroid Build Coastguard Worker         vk::LevelIndex levelVk(0);
2868*8975f5c5SAndroid Build Coastguard Worker         gl::LevelIndex sourceLevelGL = mImage->toGLLevel(levelVk);
2869*8975f5c5SAndroid Build Coastguard Worker         gl::Box sourceBox(gl::kOffsetZero, mImage->getLevelExtents(levelVk));
2870*8975f5c5SAndroid Build Coastguard Worker         const gl::ImageIndex index =
2871*8975f5c5SAndroid Build Coastguard Worker             gl::ImageIndex::MakeFromType(mState.getType(), sourceLevelGL.get());
2872*8975f5c5SAndroid Build Coastguard Worker 
2873*8975f5c5SAndroid Build Coastguard Worker         // Flush the render pass, which may incur a vkQueueSubmit, before taking any views.
2874*8975f5c5SAndroid Build Coastguard Worker         // Otherwise the view serials would not reflect the render pass they are really used in.
2875*8975f5c5SAndroid Build Coastguard Worker         // http://crbug.com/1272266#c22
2876*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(
2877*8975f5c5SAndroid Build Coastguard Worker             contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::PrepareForImageCopy));
2878*8975f5c5SAndroid Build Coastguard Worker 
2879*8975f5c5SAndroid Build Coastguard Worker         return copySubImageImplWithDraw(contextVk, index, gl::kOffsetZero, format, sourceLevelGL,
2880*8975f5c5SAndroid Build Coastguard Worker                                         sourceBox, false, false, false, false, mImage,
2881*8975f5c5SAndroid Build Coastguard Worker                                         &getCopyImageView(), SurfaceRotation::Identity);
2882*8975f5c5SAndroid Build Coastguard Worker     }
2883*8975f5c5SAndroid Build Coastguard Worker 
2884*8975f5c5SAndroid Build Coastguard Worker     for (vk::LevelIndex levelVk(0); levelVk < vk::LevelIndex(levelCount); ++levelVk)
2885*8975f5c5SAndroid Build Coastguard Worker     {
2886*8975f5c5SAndroid Build Coastguard Worker         gl::LevelIndex levelGL = mImage->toGLLevel(levelVk);
2887*8975f5c5SAndroid Build Coastguard Worker         if (IsTextureLevelRedefined(mRedefinedLevels, mState.getType(), levelGL))
2888*8975f5c5SAndroid Build Coastguard Worker         {
2889*8975f5c5SAndroid Build Coastguard Worker             continue;
2890*8975f5c5SAndroid Build Coastguard Worker         }
2891*8975f5c5SAndroid Build Coastguard Worker 
2892*8975f5c5SAndroid Build Coastguard Worker         ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_HIGH,
2893*8975f5c5SAndroid Build Coastguard Worker                               "GPU stall due to texture format fallback");
2894*8975f5c5SAndroid Build Coastguard Worker 
2895*8975f5c5SAndroid Build Coastguard Worker         gl::Box sourceBox(gl::kOffsetZero, mImage->getLevelExtents(levelVk));
2896*8975f5c5SAndroid Build Coastguard Worker         // copy and stage entire layer
2897*8975f5c5SAndroid Build Coastguard Worker         const gl::ImageIndex index =
2898*8975f5c5SAndroid Build Coastguard Worker             gl::ImageIndex::MakeFromType(mState.getType(), levelGL.get(), 0, layerCount);
2899*8975f5c5SAndroid Build Coastguard Worker 
2900*8975f5c5SAndroid Build Coastguard Worker         // Read back the requested region of the source texture
2901*8975f5c5SAndroid Build Coastguard Worker         vk::RendererScoped<vk::BufferHelper> bufferHelper(renderer);
2902*8975f5c5SAndroid Build Coastguard Worker         vk::BufferHelper *srcBuffer = &bufferHelper.get();
2903*8975f5c5SAndroid Build Coastguard Worker         uint8_t *srcData            = nullptr;
2904*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mImage->copyImageDataToBuffer(contextVk, levelGL, layerCount, 0, sourceBox,
2905*8975f5c5SAndroid Build Coastguard Worker                                                 srcBuffer, &srcData));
2906*8975f5c5SAndroid Build Coastguard Worker 
2907*8975f5c5SAndroid Build Coastguard Worker         // Explicitly finish. If new use cases arise where we don't want to block we can change
2908*8975f5c5SAndroid Build Coastguard Worker         // this.
2909*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(contextVk->finishImpl(RenderPassClosureReason::TextureReformatToRenderable));
2910*8975f5c5SAndroid Build Coastguard Worker         // invalidate must be called after wait for finish.
2911*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(srcBuffer->invalidate(renderer));
2912*8975f5c5SAndroid Build Coastguard Worker 
2913*8975f5c5SAndroid Build Coastguard Worker         size_t dstBufferSize = sourceBox.width * sourceBox.height * sourceBox.depth *
2914*8975f5c5SAndroid Build Coastguard Worker                                dstFormat.pixelBytes * layerCount;
2915*8975f5c5SAndroid Build Coastguard Worker 
2916*8975f5c5SAndroid Build Coastguard Worker         // Allocate memory in the destination texture for the copy/conversion.
2917*8975f5c5SAndroid Build Coastguard Worker         uint8_t *dstData = nullptr;
2918*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mImage->stageSubresourceUpdateAndGetData(
2919*8975f5c5SAndroid Build Coastguard Worker             contextVk, dstBufferSize, index, mImage->getLevelExtents(levelVk), gl::kOffsetZero,
2920*8975f5c5SAndroid Build Coastguard Worker             &dstData, dstFormat.id));
2921*8975f5c5SAndroid Build Coastguard Worker 
2922*8975f5c5SAndroid Build Coastguard Worker         // Source and destination data is tightly packed
2923*8975f5c5SAndroid Build Coastguard Worker         GLuint srcDataRowPitch = sourceBox.width * srcFormat.pixelBytes;
2924*8975f5c5SAndroid Build Coastguard Worker         GLuint dstDataRowPitch = sourceBox.width * dstFormat.pixelBytes;
2925*8975f5c5SAndroid Build Coastguard Worker 
2926*8975f5c5SAndroid Build Coastguard Worker         GLuint srcDataDepthPitch = srcDataRowPitch * sourceBox.height;
2927*8975f5c5SAndroid Build Coastguard Worker         GLuint dstDataDepthPitch = dstDataRowPitch * sourceBox.height;
2928*8975f5c5SAndroid Build Coastguard Worker 
2929*8975f5c5SAndroid Build Coastguard Worker         GLuint srcDataLayerPitch = srcDataDepthPitch * sourceBox.depth;
2930*8975f5c5SAndroid Build Coastguard Worker         GLuint dstDataLayerPitch = dstDataDepthPitch * sourceBox.depth;
2931*8975f5c5SAndroid Build Coastguard Worker 
2932*8975f5c5SAndroid Build Coastguard Worker         rx::PixelReadFunction pixelReadFunction   = srcFormat.pixelReadFunction;
2933*8975f5c5SAndroid Build Coastguard Worker         rx::PixelWriteFunction pixelWriteFunction = dstFormat.pixelWriteFunction;
2934*8975f5c5SAndroid Build Coastguard Worker 
2935*8975f5c5SAndroid Build Coastguard Worker         const gl::InternalFormat &dstFormatInfo = *mState.getImageDesc(index).format.info;
2936*8975f5c5SAndroid Build Coastguard Worker         for (uint32_t layer = 0; layer < layerCount; layer++)
2937*8975f5c5SAndroid Build Coastguard Worker         {
2938*8975f5c5SAndroid Build Coastguard Worker             CopyImageCHROMIUM(srcData + layer * srcDataLayerPitch, srcDataRowPitch,
2939*8975f5c5SAndroid Build Coastguard Worker                               srcFormat.pixelBytes, srcDataDepthPitch, pixelReadFunction,
2940*8975f5c5SAndroid Build Coastguard Worker                               dstData + layer * dstDataLayerPitch, dstDataRowPitch,
2941*8975f5c5SAndroid Build Coastguard Worker                               dstFormat.pixelBytes, dstDataDepthPitch, pixelWriteFunction,
2942*8975f5c5SAndroid Build Coastguard Worker                               dstFormatInfo.format, dstFormatInfo.componentType, sourceBox.width,
2943*8975f5c5SAndroid Build Coastguard Worker                               sourceBox.height, sourceBox.depth, false, false, false);
2944*8975f5c5SAndroid Build Coastguard Worker         }
2945*8975f5c5SAndroid Build Coastguard Worker     }
2946*8975f5c5SAndroid Build Coastguard Worker 
2947*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2948*8975f5c5SAndroid Build Coastguard Worker }
2949*8975f5c5SAndroid Build Coastguard Worker 
respecifyImageStorage(ContextVk * contextVk)2950*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::respecifyImageStorage(ContextVk *contextVk)
2951*8975f5c5SAndroid Build Coastguard Worker {
2952*8975f5c5SAndroid Build Coastguard Worker     if (!mImage->valid())
2953*8975f5c5SAndroid Build Coastguard Worker     {
2954*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!TextureHasAnyRedefinedLevels(mRedefinedLevels));
2955*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
2956*8975f5c5SAndroid Build Coastguard Worker     }
2957*8975f5c5SAndroid Build Coastguard Worker 
2958*8975f5c5SAndroid Build Coastguard Worker     // Recreate the image to reflect new base or max levels.
2959*8975f5c5SAndroid Build Coastguard Worker     // First, flush any pending updates so we have good data in the current mImage
2960*8975f5c5SAndroid Build Coastguard Worker     if (mImage->hasStagedUpdatesInAllocatedLevels())
2961*8975f5c5SAndroid Build Coastguard Worker     {
2962*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(flushImageStagedUpdates(contextVk));
2963*8975f5c5SAndroid Build Coastguard Worker     }
2964*8975f5c5SAndroid Build Coastguard Worker 
2965*8975f5c5SAndroid Build Coastguard Worker     if (!mOwnsImage)
2966*8975f5c5SAndroid Build Coastguard Worker     {
2967*8975f5c5SAndroid Build Coastguard Worker         // Cache values needed for copy and stage operations
2968*8975f5c5SAndroid Build Coastguard Worker         vk::ImageHelper *srcImage = mImage;
2969*8975f5c5SAndroid Build Coastguard Worker         const vk::Format &format  = getBaseLevelFormat(contextVk->getRenderer());
2970*8975f5c5SAndroid Build Coastguard Worker 
2971*8975f5c5SAndroid Build Coastguard Worker         // If any level was redefined but the image was not owned by the Texture, it's already
2972*8975f5c5SAndroid Build Coastguard Worker         // released and deleted by TextureVk::redefineLevel().
2973*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!TextureHasAnyRedefinedLevels(mRedefinedLevels));
2974*8975f5c5SAndroid Build Coastguard Worker 
2975*8975f5c5SAndroid Build Coastguard Worker         // Save previousFirstAllocateLevel before mImage becomes invalid
2976*8975f5c5SAndroid Build Coastguard Worker         gl::LevelIndex previousFirstAllocateLevel = mImage->getFirstAllocatedLevel();
2977*8975f5c5SAndroid Build Coastguard Worker 
2978*8975f5c5SAndroid Build Coastguard Worker         // If we didn't own the image, release the current and create a new one
2979*8975f5c5SAndroid Build Coastguard Worker         releaseImage(contextVk);
2980*8975f5c5SAndroid Build Coastguard Worker 
2981*8975f5c5SAndroid Build Coastguard Worker         // Create the image helper
2982*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(ensureImageAllocated(contextVk, format));
2983*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(initImage(contextVk, format.getIntendedFormatID(),
2984*8975f5c5SAndroid Build Coastguard Worker                             format.getActualImageFormatID(getRequiredImageAccess()),
2985*8975f5c5SAndroid Build Coastguard Worker                             mState.getImmutableFormat()
2986*8975f5c5SAndroid Build Coastguard Worker                                 ? ImageMipLevels::FullMipChainForGenerateMipmap
2987*8975f5c5SAndroid Build Coastguard Worker                                 : ImageMipLevels::EnabledLevels));
2988*8975f5c5SAndroid Build Coastguard Worker 
2989*8975f5c5SAndroid Build Coastguard Worker         // Make a copy of the old image (that's being released) and stage that as an update to the
2990*8975f5c5SAndroid Build Coastguard Worker         // new image.
2991*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(copyAndStageImageData(contextVk, previousFirstAllocateLevel, srcImage, mImage));
2992*8975f5c5SAndroid Build Coastguard Worker     }
2993*8975f5c5SAndroid Build Coastguard Worker     else
2994*8975f5c5SAndroid Build Coastguard Worker     {
2995*8975f5c5SAndroid Build Coastguard Worker         const vk::Format &format = getBaseLevelFormat(contextVk->getRenderer());
2996*8975f5c5SAndroid Build Coastguard Worker         if (mImage->getActualFormatID() != format.getActualImageFormatID(getRequiredImageAccess()))
2997*8975f5c5SAndroid Build Coastguard Worker         {
2998*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(reinitImageAsRenderable(contextVk, format));
2999*8975f5c5SAndroid Build Coastguard Worker         }
3000*8975f5c5SAndroid Build Coastguard Worker         else
3001*8975f5c5SAndroid Build Coastguard Worker         {
3002*8975f5c5SAndroid Build Coastguard Worker             stageSelfAsSubresourceUpdates(contextVk);
3003*8975f5c5SAndroid Build Coastguard Worker         }
3004*8975f5c5SAndroid Build Coastguard Worker         // Release the current image so that it will be recreated with the correct number of mip
3005*8975f5c5SAndroid Build Coastguard Worker         // levels, base level, and max level.
3006*8975f5c5SAndroid Build Coastguard Worker         releaseImage(contextVk);
3007*8975f5c5SAndroid Build Coastguard Worker     }
3008*8975f5c5SAndroid Build Coastguard Worker 
3009*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3010*8975f5c5SAndroid Build Coastguard Worker }
3011*8975f5c5SAndroid Build Coastguard Worker 
bindTexImage(const gl::Context * context,egl::Surface * surface)3012*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::bindTexImage(const gl::Context *context, egl::Surface *surface)
3013*8975f5c5SAndroid Build Coastguard Worker {
3014*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
3015*8975f5c5SAndroid Build Coastguard Worker 
3016*8975f5c5SAndroid Build Coastguard Worker     releaseAndDeleteImageAndViews(contextVk);
3017*8975f5c5SAndroid Build Coastguard Worker 
3018*8975f5c5SAndroid Build Coastguard Worker     // eglBindTexImage can only be called with pbuffer (offscreen) surfaces
3019*8975f5c5SAndroid Build Coastguard Worker     OffscreenSurfaceVk *offscreenSurface = GetImplAs<OffscreenSurfaceVk>(surface);
3020*8975f5c5SAndroid Build Coastguard Worker     // Surface can only have single target. Just generate valid serial with throw-away generator.
3021*8975f5c5SAndroid Build Coastguard Worker     UniqueSerial siblingSerial = UniqueSerialFactory().generate();
3022*8975f5c5SAndroid Build Coastguard Worker     setImageHelper(contextVk, offscreenSurface->getColorAttachmentImage(),
3023*8975f5c5SAndroid Build Coastguard Worker                    gl::TextureType::InvalidEnum, 0, 0, false, siblingSerial);
3024*8975f5c5SAndroid Build Coastguard Worker 
3025*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImage->getLayerCount() == 1);
3026*8975f5c5SAndroid Build Coastguard Worker     return initImageViews(contextVk, getImageViewLevelCount());
3027*8975f5c5SAndroid Build Coastguard Worker }
3028*8975f5c5SAndroid Build Coastguard Worker 
releaseTexImage(const gl::Context * context)3029*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::releaseTexImage(const gl::Context *context)
3030*8975f5c5SAndroid Build Coastguard Worker {
3031*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
3032*8975f5c5SAndroid Build Coastguard Worker 
3033*8975f5c5SAndroid Build Coastguard Worker     releaseImage(contextVk);
3034*8975f5c5SAndroid Build Coastguard Worker 
3035*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3036*8975f5c5SAndroid Build Coastguard Worker }
3037*8975f5c5SAndroid Build Coastguard Worker 
getAttachmentRenderTarget(const gl::Context * context,GLenum binding,const gl::ImageIndex & imageIndex,GLsizei samples,FramebufferAttachmentRenderTarget ** rtOut)3038*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context,
3039*8975f5c5SAndroid Build Coastguard Worker                                                    GLenum binding,
3040*8975f5c5SAndroid Build Coastguard Worker                                                    const gl::ImageIndex &imageIndex,
3041*8975f5c5SAndroid Build Coastguard Worker                                                    GLsizei samples,
3042*8975f5c5SAndroid Build Coastguard Worker                                                    FramebufferAttachmentRenderTarget **rtOut)
3043*8975f5c5SAndroid Build Coastguard Worker {
3044*8975f5c5SAndroid Build Coastguard Worker     GLint requestedLevel = imageIndex.getLevelIndex();
3045*8975f5c5SAndroid Build Coastguard Worker     ASSERT(requestedLevel >= 0);
3046*8975f5c5SAndroid Build Coastguard Worker 
3047*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
3048*8975f5c5SAndroid Build Coastguard Worker 
3049*8975f5c5SAndroid Build Coastguard Worker     // Sync the texture's image.  See comment on this function in the header.
3050*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(respecifyImageStorageIfNecessary(contextVk, gl::Command::Draw));
3051*8975f5c5SAndroid Build Coastguard Worker 
3052*8975f5c5SAndroid Build Coastguard Worker     // Don't flush staged updates here. We'll handle that in FramebufferVk so we can defer clears.
3053*8975f5c5SAndroid Build Coastguard Worker 
3054*8975f5c5SAndroid Build Coastguard Worker     if (!mImage->valid())
3055*8975f5c5SAndroid Build Coastguard Worker     {
3056*8975f5c5SAndroid Build Coastguard Worker         const vk::Format &format = getBaseLevelFormat(contextVk->getRenderer());
3057*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(initImage(contextVk, format.getIntendedFormatID(),
3058*8975f5c5SAndroid Build Coastguard Worker                             format.getActualImageFormatID(getRequiredImageAccess()),
3059*8975f5c5SAndroid Build Coastguard Worker                             ImageMipLevels::EnabledLevels));
3060*8975f5c5SAndroid Build Coastguard Worker     }
3061*8975f5c5SAndroid Build Coastguard Worker 
3062*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(performImageQueueTransferIfNecessary(contextVk));
3063*8975f5c5SAndroid Build Coastguard Worker 
3064*8975f5c5SAndroid Build Coastguard Worker     const bool hasRenderToTextureEXT =
3065*8975f5c5SAndroid Build Coastguard Worker         contextVk->getFeatures().supportsMultisampledRenderToSingleSampled.enabled;
3066*8975f5c5SAndroid Build Coastguard Worker 
3067*8975f5c5SAndroid Build Coastguard Worker     // If samples > 1 here, we have a singlesampled texture that's being multisampled rendered to.
3068*8975f5c5SAndroid Build Coastguard Worker     // In this case, create a multisampled image that is otherwise identical to the single sampled
3069*8975f5c5SAndroid Build Coastguard Worker     // image.  That multisampled image is used as color or depth/stencil attachment, while the
3070*8975f5c5SAndroid Build Coastguard Worker     // original image is used as the resolve attachment.
3071*8975f5c5SAndroid Build Coastguard Worker     const gl::RenderToTextureImageIndex renderToTextureIndex =
3072*8975f5c5SAndroid Build Coastguard Worker         hasRenderToTextureEXT
3073*8975f5c5SAndroid Build Coastguard Worker             ? gl::RenderToTextureImageIndex::Default
3074*8975f5c5SAndroid Build Coastguard Worker             : static_cast<gl::RenderToTextureImageIndex>(PackSampleCount(samples));
3075*8975f5c5SAndroid Build Coastguard Worker 
3076*8975f5c5SAndroid Build Coastguard Worker     if (samples > 1 && !hasRenderToTextureEXT)
3077*8975f5c5SAndroid Build Coastguard Worker     {
3078*8975f5c5SAndroid Build Coastguard Worker         // Initialize mMultisampledImages and mMultisampledImageViews if necessary
3079*8975f5c5SAndroid Build Coastguard Worker         if (mMultisampledImages == nullptr)
3080*8975f5c5SAndroid Build Coastguard Worker         {
3081*8975f5c5SAndroid Build Coastguard Worker             mMultisampledImages     = std::make_unique<MultiSampleImages>();
3082*8975f5c5SAndroid Build Coastguard Worker             mMultisampledImageViews = std::make_unique<MultiSampleImageViews>();
3083*8975f5c5SAndroid Build Coastguard Worker         }
3084*8975f5c5SAndroid Build Coastguard Worker 
3085*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mState.getBaseLevelDesc().samples <= 1);
3086*8975f5c5SAndroid Build Coastguard Worker 
3087*8975f5c5SAndroid Build Coastguard Worker         vk::ImageHelper &multisampledImage =
3088*8975f5c5SAndroid Build Coastguard Worker             mMultisampledImages->at(renderToTextureIndex)[requestedLevel];
3089*8975f5c5SAndroid Build Coastguard Worker         if (!multisampledImage.valid())
3090*8975f5c5SAndroid Build Coastguard Worker         {
3091*8975f5c5SAndroid Build Coastguard Worker             // Ensure the view serial is valid.
3092*8975f5c5SAndroid Build Coastguard Worker             vk::Renderer *renderer = contextVk->getRenderer();
3093*8975f5c5SAndroid Build Coastguard Worker             mMultisampledImageViews->at(renderToTextureIndex)[requestedLevel].init(renderer);
3094*8975f5c5SAndroid Build Coastguard Worker 
3095*8975f5c5SAndroid Build Coastguard Worker             // The MSAA image always comes from the single sampled one, so disable robust init.
3096*8975f5c5SAndroid Build Coastguard Worker             bool useRobustInit = false;
3097*8975f5c5SAndroid Build Coastguard Worker 
3098*8975f5c5SAndroid Build Coastguard Worker             // Calculate extents for multisample image
3099*8975f5c5SAndroid Build Coastguard Worker             VkExtent3D extents = {};
3100*8975f5c5SAndroid Build Coastguard Worker             gl_vk::GetExtent(
3101*8975f5c5SAndroid Build Coastguard Worker                 mImage->getLevelExtents(mImage->toVkLevel(gl::LevelIndex(requestedLevel))),
3102*8975f5c5SAndroid Build Coastguard Worker                 &extents);
3103*8975f5c5SAndroid Build Coastguard Worker 
3104*8975f5c5SAndroid Build Coastguard Worker             // Create the implicit multisampled image.
3105*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(multisampledImage.initImplicitMultisampledRenderToTexture(
3106*8975f5c5SAndroid Build Coastguard Worker                 contextVk, mState.hasProtectedContent(), renderer->getMemoryProperties(),
3107*8975f5c5SAndroid Build Coastguard Worker                 mState.getType(), samples, *mImage, extents, useRobustInit));
3108*8975f5c5SAndroid Build Coastguard Worker         }
3109*8975f5c5SAndroid Build Coastguard Worker     }
3110*8975f5c5SAndroid Build Coastguard Worker 
3111*8975f5c5SAndroid Build Coastguard Worker     GLuint layerIndex = 0, layerCount = 0, imageLayerCount = 0;
3112*8975f5c5SAndroid Build Coastguard Worker     GetRenderTargetLayerCountAndIndex(mImage, imageIndex, &layerIndex, &layerCount,
3113*8975f5c5SAndroid Build Coastguard Worker                                       &imageLayerCount);
3114*8975f5c5SAndroid Build Coastguard Worker 
3115*8975f5c5SAndroid Build Coastguard Worker     if (layerCount == 1)
3116*8975f5c5SAndroid Build Coastguard Worker     {
3117*8975f5c5SAndroid Build Coastguard Worker         initSingleLayerRenderTargets(contextVk, imageLayerCount, gl::LevelIndex(requestedLevel),
3118*8975f5c5SAndroid Build Coastguard Worker                                      renderToTextureIndex);
3119*8975f5c5SAndroid Build Coastguard Worker 
3120*8975f5c5SAndroid Build Coastguard Worker         std::vector<RenderTargetVector> &levelRenderTargets =
3121*8975f5c5SAndroid Build Coastguard Worker             mSingleLayerRenderTargets[renderToTextureIndex];
3122*8975f5c5SAndroid Build Coastguard Worker         ASSERT(requestedLevel < static_cast<int32_t>(levelRenderTargets.size()));
3123*8975f5c5SAndroid Build Coastguard Worker 
3124*8975f5c5SAndroid Build Coastguard Worker         RenderTargetVector &layerRenderTargets = levelRenderTargets[requestedLevel];
3125*8975f5c5SAndroid Build Coastguard Worker         ASSERT(imageIndex.getLayerIndex() < static_cast<int32_t>(layerRenderTargets.size()));
3126*8975f5c5SAndroid Build Coastguard Worker 
3127*8975f5c5SAndroid Build Coastguard Worker         *rtOut = &layerRenderTargets[layerIndex];
3128*8975f5c5SAndroid Build Coastguard Worker     }
3129*8975f5c5SAndroid Build Coastguard Worker     else
3130*8975f5c5SAndroid Build Coastguard Worker     {
3131*8975f5c5SAndroid Build Coastguard Worker         ASSERT(layerCount > 0);
3132*8975f5c5SAndroid Build Coastguard Worker         *rtOut = getMultiLayerRenderTarget(contextVk, gl::LevelIndex(imageIndex.getLevelIndex()),
3133*8975f5c5SAndroid Build Coastguard Worker                                            layerIndex, layerCount);
3134*8975f5c5SAndroid Build Coastguard Worker     }
3135*8975f5c5SAndroid Build Coastguard Worker 
3136*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3137*8975f5c5SAndroid Build Coastguard Worker }
3138*8975f5c5SAndroid Build Coastguard Worker 
ensureImageInitialized(ContextVk * contextVk,ImageMipLevels mipLevels)3139*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::ensureImageInitialized(ContextVk *contextVk, ImageMipLevels mipLevels)
3140*8975f5c5SAndroid Build Coastguard Worker {
3141*8975f5c5SAndroid Build Coastguard Worker     if (mImage->valid() && !mImage->hasStagedUpdatesInAllocatedLevels())
3142*8975f5c5SAndroid Build Coastguard Worker     {
3143*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
3144*8975f5c5SAndroid Build Coastguard Worker     }
3145*8975f5c5SAndroid Build Coastguard Worker 
3146*8975f5c5SAndroid Build Coastguard Worker     if (!mImage->valid())
3147*8975f5c5SAndroid Build Coastguard Worker     {
3148*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!TextureHasAnyRedefinedLevels(mRedefinedLevels));
3149*8975f5c5SAndroid Build Coastguard Worker 
3150*8975f5c5SAndroid Build Coastguard Worker         const vk::Format &format = getBaseLevelFormat(contextVk->getRenderer());
3151*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(initImage(contextVk, format.getIntendedFormatID(),
3152*8975f5c5SAndroid Build Coastguard Worker                             format.getActualImageFormatID(getRequiredImageAccess()), mipLevels));
3153*8975f5c5SAndroid Build Coastguard Worker         if (mipLevels == ImageMipLevels::FullMipChainForGenerateMipmap)
3154*8975f5c5SAndroid Build Coastguard Worker         {
3155*8975f5c5SAndroid Build Coastguard Worker             // Remove staged updates to non-base mips when generating mipmaps.  These can only be
3156*8975f5c5SAndroid Build Coastguard Worker             // emulated format init clears that are staged in initImage.
3157*8975f5c5SAndroid Build Coastguard Worker             mImage->removeStagedUpdates(contextVk,
3158*8975f5c5SAndroid Build Coastguard Worker                                         gl::LevelIndex(mState.getEffectiveBaseLevel() + 1),
3159*8975f5c5SAndroid Build Coastguard Worker                                         gl::LevelIndex(mState.getMipmapMaxLevel()));
3160*8975f5c5SAndroid Build Coastguard Worker         }
3161*8975f5c5SAndroid Build Coastguard Worker     }
3162*8975f5c5SAndroid Build Coastguard Worker 
3163*8975f5c5SAndroid Build Coastguard Worker     return flushImageStagedUpdates(contextVk);
3164*8975f5c5SAndroid Build Coastguard Worker }
3165*8975f5c5SAndroid Build Coastguard Worker 
flushImageStagedUpdates(ContextVk * contextVk)3166*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::flushImageStagedUpdates(ContextVk *contextVk)
3167*8975f5c5SAndroid Build Coastguard Worker {
3168*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImage->valid());
3169*8975f5c5SAndroid Build Coastguard Worker 
3170*8975f5c5SAndroid Build Coastguard Worker     gl::LevelIndex firstLevelGL = getNativeImageLevel(mImage->getFirstAllocatedLevel());
3171*8975f5c5SAndroid Build Coastguard Worker     uint32_t firstLayer         = getNativeImageLayer(0);
3172*8975f5c5SAndroid Build Coastguard Worker 
3173*8975f5c5SAndroid Build Coastguard Worker     return mImage->flushStagedUpdates(contextVk, firstLevelGL,
3174*8975f5c5SAndroid Build Coastguard Worker                                       firstLevelGL + getImageViewLevelCount(), firstLayer,
3175*8975f5c5SAndroid Build Coastguard Worker                                       firstLayer + getImageViewLayerCount(), mRedefinedLevels);
3176*8975f5c5SAndroid Build Coastguard Worker }
3177*8975f5c5SAndroid Build Coastguard Worker 
performImageQueueTransferIfNecessary(ContextVk * contextVk)3178*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::performImageQueueTransferIfNecessary(ContextVk *contextVk)
3179*8975f5c5SAndroid Build Coastguard Worker {
3180*8975f5c5SAndroid Build Coastguard Worker     if (mImage->valid() && mImage->isQueueFamilyChangeNeccesary(contextVk->getDeviceQueueIndex()))
3181*8975f5c5SAndroid Build Coastguard Worker     {
3182*8975f5c5SAndroid Build Coastguard Worker         vk::ImageLayout newLayout = vk::ImageLayout::AllGraphicsShadersWrite;
3183*8975f5c5SAndroid Build Coastguard Worker         if (mImage->getUsage() & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
3184*8975f5c5SAndroid Build Coastguard Worker         {
3185*8975f5c5SAndroid Build Coastguard Worker             newLayout = vk::ImageLayout::ColorWrite;
3186*8975f5c5SAndroid Build Coastguard Worker         }
3187*8975f5c5SAndroid Build Coastguard Worker         else if (mImage->getUsage() & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
3188*8975f5c5SAndroid Build Coastguard Worker         {
3189*8975f5c5SAndroid Build Coastguard Worker             newLayout = vk::ImageLayout::DepthWriteStencilWrite;
3190*8975f5c5SAndroid Build Coastguard Worker         }
3191*8975f5c5SAndroid Build Coastguard Worker         else if (mImage->getUsage() &
3192*8975f5c5SAndroid Build Coastguard Worker                  (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))
3193*8975f5c5SAndroid Build Coastguard Worker         {
3194*8975f5c5SAndroid Build Coastguard Worker             newLayout = vk::ImageLayout::AllGraphicsShadersReadOnly;
3195*8975f5c5SAndroid Build Coastguard Worker         }
3196*8975f5c5SAndroid Build Coastguard Worker 
3197*8975f5c5SAndroid Build Coastguard Worker         vk::OutsideRenderPassCommandBuffer *commandBuffer;
3198*8975f5c5SAndroid Build Coastguard Worker         vk::CommandBufferAccess access;
3199*8975f5c5SAndroid Build Coastguard Worker         access.onExternalAcquireRelease(mImage);
3200*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
3201*8975f5c5SAndroid Build Coastguard Worker         mImage->changeLayoutAndQueue(contextVk, mImage->getAspectFlags(), newLayout,
3202*8975f5c5SAndroid Build Coastguard Worker                                      contextVk->getDeviceQueueIndex(), commandBuffer);
3203*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(contextVk->onEGLImageQueueChange());
3204*8975f5c5SAndroid Build Coastguard Worker     }
3205*8975f5c5SAndroid Build Coastguard Worker 
3206*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3207*8975f5c5SAndroid Build Coastguard Worker }
3208*8975f5c5SAndroid Build Coastguard Worker 
initSingleLayerRenderTargets(ContextVk * contextVk,GLuint layerCount,gl::LevelIndex levelIndex,gl::RenderToTextureImageIndex renderToTextureIndex)3209*8975f5c5SAndroid Build Coastguard Worker void TextureVk::initSingleLayerRenderTargets(ContextVk *contextVk,
3210*8975f5c5SAndroid Build Coastguard Worker                                              GLuint layerCount,
3211*8975f5c5SAndroid Build Coastguard Worker                                              gl::LevelIndex levelIndex,
3212*8975f5c5SAndroid Build Coastguard Worker                                              gl::RenderToTextureImageIndex renderToTextureIndex)
3213*8975f5c5SAndroid Build Coastguard Worker {
3214*8975f5c5SAndroid Build Coastguard Worker     GLint requestedLevel = levelIndex.get();
3215*8975f5c5SAndroid Build Coastguard Worker     std::vector<RenderTargetVector> &allLevelsRenderTargets =
3216*8975f5c5SAndroid Build Coastguard Worker         mSingleLayerRenderTargets[renderToTextureIndex];
3217*8975f5c5SAndroid Build Coastguard Worker 
3218*8975f5c5SAndroid Build Coastguard Worker     if (allLevelsRenderTargets.size() <= static_cast<uint32_t>(requestedLevel))
3219*8975f5c5SAndroid Build Coastguard Worker     {
3220*8975f5c5SAndroid Build Coastguard Worker         allLevelsRenderTargets.resize(requestedLevel + 1);
3221*8975f5c5SAndroid Build Coastguard Worker     }
3222*8975f5c5SAndroid Build Coastguard Worker 
3223*8975f5c5SAndroid Build Coastguard Worker     RenderTargetVector &renderTargets = allLevelsRenderTargets[requestedLevel];
3224*8975f5c5SAndroid Build Coastguard Worker 
3225*8975f5c5SAndroid Build Coastguard Worker     // Lazy init. Check if already initialized.
3226*8975f5c5SAndroid Build Coastguard Worker     if (!renderTargets.empty())
3227*8975f5c5SAndroid Build Coastguard Worker     {
3228*8975f5c5SAndroid Build Coastguard Worker         return;
3229*8975f5c5SAndroid Build Coastguard Worker     }
3230*8975f5c5SAndroid Build Coastguard Worker 
3231*8975f5c5SAndroid Build Coastguard Worker     // There are |layerCount| render targets, one for each layer
3232*8975f5c5SAndroid Build Coastguard Worker     renderTargets.resize(layerCount);
3233*8975f5c5SAndroid Build Coastguard Worker 
3234*8975f5c5SAndroid Build Coastguard Worker     const bool isMultisampledRenderToTexture =
3235*8975f5c5SAndroid Build Coastguard Worker         renderToTextureIndex != gl::RenderToTextureImageIndex::Default;
3236*8975f5c5SAndroid Build Coastguard Worker 
3237*8975f5c5SAndroid Build Coastguard Worker     vk::ImageHelper *drawImage             = mImage;
3238*8975f5c5SAndroid Build Coastguard Worker     vk::ImageViewHelper *drawImageViews    = &getImageViews();
3239*8975f5c5SAndroid Build Coastguard Worker     vk::ImageHelper *resolveImage          = nullptr;
3240*8975f5c5SAndroid Build Coastguard Worker     vk::ImageViewHelper *resolveImageViews = nullptr;
3241*8975f5c5SAndroid Build Coastguard Worker 
3242*8975f5c5SAndroid Build Coastguard Worker     RenderTargetTransience transience = RenderTargetTransience::Default;
3243*8975f5c5SAndroid Build Coastguard Worker 
3244*8975f5c5SAndroid Build Coastguard Worker     // If multisampled render to texture, use the multisampled image as draw image instead, and
3245*8975f5c5SAndroid Build Coastguard Worker     // resolve into the texture's image automatically.
3246*8975f5c5SAndroid Build Coastguard Worker     if (isMultisampledRenderToTexture)
3247*8975f5c5SAndroid Build Coastguard Worker     {
3248*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mMultisampledImages->at(renderToTextureIndex)[requestedLevel].valid());
3249*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!mImage->isYuvResolve());
3250*8975f5c5SAndroid Build Coastguard Worker 
3251*8975f5c5SAndroid Build Coastguard Worker         resolveImage      = drawImage;
3252*8975f5c5SAndroid Build Coastguard Worker         resolveImageViews = drawImageViews;
3253*8975f5c5SAndroid Build Coastguard Worker         drawImage         = &mMultisampledImages->at(renderToTextureIndex)[requestedLevel];
3254*8975f5c5SAndroid Build Coastguard Worker         drawImageViews    = &mMultisampledImageViews->at(renderToTextureIndex)[requestedLevel];
3255*8975f5c5SAndroid Build Coastguard Worker 
3256*8975f5c5SAndroid Build Coastguard Worker         // If the texture is depth/stencil, GL_EXT_multisampled_render_to_texture2 explicitly
3257*8975f5c5SAndroid Build Coastguard Worker         // indicates that there is no need for the image to be resolved.  In that case, mark the
3258*8975f5c5SAndroid Build Coastguard Worker         // render target as entirely transient.
3259*8975f5c5SAndroid Build Coastguard Worker         if (mImage->getAspectFlags() != VK_IMAGE_ASPECT_COLOR_BIT)
3260*8975f5c5SAndroid Build Coastguard Worker         {
3261*8975f5c5SAndroid Build Coastguard Worker             transience = RenderTargetTransience::EntirelyTransient;
3262*8975f5c5SAndroid Build Coastguard Worker         }
3263*8975f5c5SAndroid Build Coastguard Worker         else
3264*8975f5c5SAndroid Build Coastguard Worker         {
3265*8975f5c5SAndroid Build Coastguard Worker             transience = RenderTargetTransience::MultisampledTransient;
3266*8975f5c5SAndroid Build Coastguard Worker         }
3267*8975f5c5SAndroid Build Coastguard Worker     }
3268*8975f5c5SAndroid Build Coastguard Worker     else if (mImage->isYuvResolve())
3269*8975f5c5SAndroid Build Coastguard Worker     {
3270*8975f5c5SAndroid Build Coastguard Worker         // If rendering to YUV, similar to multisampled render to texture
3271*8975f5c5SAndroid Build Coastguard Worker         resolveImage      = drawImage;
3272*8975f5c5SAndroid Build Coastguard Worker         resolveImageViews = drawImageViews;
3273*8975f5c5SAndroid Build Coastguard Worker 
3274*8975f5c5SAndroid Build Coastguard Worker         if (contextVk->getRenderer()->nullColorAttachmentWithExternalFormatResolve())
3275*8975f5c5SAndroid Build Coastguard Worker         {
3276*8975f5c5SAndroid Build Coastguard Worker             // If null color attachment, we still keep drawImage as is (the same as
3277*8975f5c5SAndroid Build Coastguard Worker             // resolveImage) to avoid special treatment in many places where they assume there must
3278*8975f5c5SAndroid Build Coastguard Worker             // be a color attachment if there is a resolve attachment. But when renderPass is
3279*8975f5c5SAndroid Build Coastguard Worker             // created, color attachment will be ignored.
3280*8975f5c5SAndroid Build Coastguard Worker         }
3281*8975f5c5SAndroid Build Coastguard Worker         else
3282*8975f5c5SAndroid Build Coastguard Worker         {
3283*8975f5c5SAndroid Build Coastguard Worker             transience = RenderTargetTransience::YuvResolveTransient;
3284*8975f5c5SAndroid Build Coastguard Worker             // Need to populate drawImage here; either abuse mMultisampledImages etc
3285*8975f5c5SAndroid Build Coastguard Worker             // or build something parallel to it. we don't have a vulkan implementation which
3286*8975f5c5SAndroid Build Coastguard Worker             // wants this path yet, though.
3287*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
3288*8975f5c5SAndroid Build Coastguard Worker         }
3289*8975f5c5SAndroid Build Coastguard Worker     }
3290*8975f5c5SAndroid Build Coastguard Worker 
3291*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex)
3292*8975f5c5SAndroid Build Coastguard Worker     {
3293*8975f5c5SAndroid Build Coastguard Worker         renderTargets[layerIndex].init(drawImage, drawImageViews, resolveImage, resolveImageViews,
3294*8975f5c5SAndroid Build Coastguard Worker                                        mImageSiblingSerial, getNativeImageLevel(levelIndex),
3295*8975f5c5SAndroid Build Coastguard Worker                                        getNativeImageLayer(layerIndex), 1, transience);
3296*8975f5c5SAndroid Build Coastguard Worker     }
3297*8975f5c5SAndroid Build Coastguard Worker }
3298*8975f5c5SAndroid Build Coastguard Worker 
getMultiLayerRenderTarget(ContextVk * contextVk,gl::LevelIndex level,GLuint layerIndex,GLuint layerCount)3299*8975f5c5SAndroid Build Coastguard Worker RenderTargetVk *TextureVk::getMultiLayerRenderTarget(ContextVk *contextVk,
3300*8975f5c5SAndroid Build Coastguard Worker                                                      gl::LevelIndex level,
3301*8975f5c5SAndroid Build Coastguard Worker                                                      GLuint layerIndex,
3302*8975f5c5SAndroid Build Coastguard Worker                                                      GLuint layerCount)
3303*8975f5c5SAndroid Build Coastguard Worker {
3304*8975f5c5SAndroid Build Coastguard Worker     vk::ImageViewHelper *imageViews = &getImageViews();
3305*8975f5c5SAndroid Build Coastguard Worker     vk::ImageSubresourceRange range = imageViews->getSubresourceDrawRange(
3306*8975f5c5SAndroid Build Coastguard Worker         level, layerIndex, vk::GetLayerMode(*mImage, layerCount));
3307*8975f5c5SAndroid Build Coastguard Worker 
3308*8975f5c5SAndroid Build Coastguard Worker     auto iter = mMultiLayerRenderTargets.find(range);
3309*8975f5c5SAndroid Build Coastguard Worker     if (iter != mMultiLayerRenderTargets.end())
3310*8975f5c5SAndroid Build Coastguard Worker     {
3311*8975f5c5SAndroid Build Coastguard Worker         return iter->second.get();
3312*8975f5c5SAndroid Build Coastguard Worker     }
3313*8975f5c5SAndroid Build Coastguard Worker 
3314*8975f5c5SAndroid Build Coastguard Worker     // Create the layered render target.  Note that multisampled render to texture is not
3315*8975f5c5SAndroid Build Coastguard Worker     // allowed with layered render targets; nor is YUV rendering.
3316*8975f5c5SAndroid Build Coastguard Worker     std::unique_ptr<RenderTargetVk> &rt = mMultiLayerRenderTargets[range];
3317*8975f5c5SAndroid Build Coastguard Worker     if (!rt)
3318*8975f5c5SAndroid Build Coastguard Worker     {
3319*8975f5c5SAndroid Build Coastguard Worker         rt = std::make_unique<RenderTargetVk>();
3320*8975f5c5SAndroid Build Coastguard Worker     }
3321*8975f5c5SAndroid Build Coastguard Worker 
3322*8975f5c5SAndroid Build Coastguard Worker     rt->init(mImage, imageViews, nullptr, nullptr, mImageSiblingSerial, getNativeImageLevel(level),
3323*8975f5c5SAndroid Build Coastguard Worker              getNativeImageLayer(layerIndex), layerCount, RenderTargetTransience::Default);
3324*8975f5c5SAndroid Build Coastguard Worker 
3325*8975f5c5SAndroid Build Coastguard Worker     return rt.get();
3326*8975f5c5SAndroid Build Coastguard Worker }
3327*8975f5c5SAndroid Build Coastguard Worker 
prepareForGenerateMipmap(ContextVk * contextVk)3328*8975f5c5SAndroid Build Coastguard Worker void TextureVk::prepareForGenerateMipmap(ContextVk *contextVk)
3329*8975f5c5SAndroid Build Coastguard Worker {
3330*8975f5c5SAndroid Build Coastguard Worker     gl::LevelIndex baseLevel(mState.getEffectiveBaseLevel());
3331*8975f5c5SAndroid Build Coastguard Worker     gl::LevelIndex maxLevel(mState.getMipmapMaxLevel());
3332*8975f5c5SAndroid Build Coastguard Worker 
3333*8975f5c5SAndroid Build Coastguard Worker     // Remove staged updates to the range that's being respecified (which is all the mips except
3334*8975f5c5SAndroid Build Coastguard Worker     // baseLevel).
3335*8975f5c5SAndroid Build Coastguard Worker     gl::LevelIndex firstGeneratedLevel = baseLevel + 1;
3336*8975f5c5SAndroid Build Coastguard Worker     mImage->removeStagedUpdates(contextVk, firstGeneratedLevel, maxLevel);
3337*8975f5c5SAndroid Build Coastguard Worker 
3338*8975f5c5SAndroid Build Coastguard Worker     TextureRedefineGenerateMipmapLevels(baseLevel, maxLevel, firstGeneratedLevel,
3339*8975f5c5SAndroid Build Coastguard Worker                                         &mRedefinedLevels);
3340*8975f5c5SAndroid Build Coastguard Worker 
3341*8975f5c5SAndroid Build Coastguard Worker     // If generating mipmap and base level is incompatibly redefined, the image is going to be
3342*8975f5c5SAndroid Build Coastguard Worker     // recreated.  Don't try to preserve the other mips.
3343*8975f5c5SAndroid Build Coastguard Worker     if (IsTextureLevelRedefined(mRedefinedLevels, mState.getType(), baseLevel))
3344*8975f5c5SAndroid Build Coastguard Worker     {
3345*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!mState.getImmutableFormat());
3346*8975f5c5SAndroid Build Coastguard Worker         releaseImage(contextVk);
3347*8975f5c5SAndroid Build Coastguard Worker     }
3348*8975f5c5SAndroid Build Coastguard Worker 
3349*8975f5c5SAndroid Build Coastguard Worker     const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc();
3350*8975f5c5SAndroid Build Coastguard Worker     VkImageType imageType              = gl_vk::GetImageType(mState.getType());
3351*8975f5c5SAndroid Build Coastguard Worker     const vk::Format &format           = getBaseLevelFormat(contextVk->getRenderer());
3352*8975f5c5SAndroid Build Coastguard Worker     const GLint samples                = baseLevelDesc.samples ? baseLevelDesc.samples : 1;
3353*8975f5c5SAndroid Build Coastguard Worker 
3354*8975f5c5SAndroid Build Coastguard Worker     // If the compute path is to be used to generate mipmaps, add the STORAGE usage.
3355*8975f5c5SAndroid Build Coastguard Worker     if (CanGenerateMipmapWithCompute(contextVk->getRenderer(), imageType,
3356*8975f5c5SAndroid Build Coastguard Worker                                      format.getActualImageFormatID(getRequiredImageAccess()),
3357*8975f5c5SAndroid Build Coastguard Worker                                      samples, mOwnsImage))
3358*8975f5c5SAndroid Build Coastguard Worker     {
3359*8975f5c5SAndroid Build Coastguard Worker         mImageUsageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
3360*8975f5c5SAndroid Build Coastguard Worker     }
3361*8975f5c5SAndroid Build Coastguard Worker }
3362*8975f5c5SAndroid Build Coastguard Worker 
respecifyImageStorageIfNecessary(ContextVk * contextVk,gl::Command source)3363*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::respecifyImageStorageIfNecessary(ContextVk *contextVk, gl::Command source)
3364*8975f5c5SAndroid Build Coastguard Worker {
3365*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mState.getBuffer().get() == nullptr);
3366*8975f5c5SAndroid Build Coastguard Worker 
3367*8975f5c5SAndroid Build Coastguard Worker     VkImageUsageFlags oldUsageFlags   = mImageUsageFlags;
3368*8975f5c5SAndroid Build Coastguard Worker     VkImageCreateFlags oldCreateFlags = mImageCreateFlags;
3369*8975f5c5SAndroid Build Coastguard Worker 
3370*8975f5c5SAndroid Build Coastguard Worker     // Create a new image if the storage state is enabled for the first time.
3371*8975f5c5SAndroid Build Coastguard Worker     if (mState.hasBeenBoundAsImage())
3372*8975f5c5SAndroid Build Coastguard Worker     {
3373*8975f5c5SAndroid Build Coastguard Worker         mImageUsageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
3374*8975f5c5SAndroid Build Coastguard Worker         mRequiresMutableStorage = true;
3375*8975f5c5SAndroid Build Coastguard Worker     }
3376*8975f5c5SAndroid Build Coastguard Worker 
3377*8975f5c5SAndroid Build Coastguard Worker     // If we're handling dirty srgb decode/override state, we may have to reallocate the image with
3378*8975f5c5SAndroid Build Coastguard Worker     // VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT. Vulkan requires this bit to be set in order to use
3379*8975f5c5SAndroid Build Coastguard Worker     // imageviews with a format that does not match the texture's internal format.
3380*8975f5c5SAndroid Build Coastguard Worker     if (isSRGBOverrideEnabled())
3381*8975f5c5SAndroid Build Coastguard Worker     {
3382*8975f5c5SAndroid Build Coastguard Worker         mRequiresMutableStorage = true;
3383*8975f5c5SAndroid Build Coastguard Worker     }
3384*8975f5c5SAndroid Build Coastguard Worker 
3385*8975f5c5SAndroid Build Coastguard Worker     if (mRequiresMutableStorage)
3386*8975f5c5SAndroid Build Coastguard Worker     {
3387*8975f5c5SAndroid Build Coastguard Worker         mImageCreateFlags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
3388*8975f5c5SAndroid Build Coastguard Worker     }
3389*8975f5c5SAndroid Build Coastguard Worker 
3390*8975f5c5SAndroid Build Coastguard Worker     // Create a new image if used as attachment for the first time. This must be called before
3391*8975f5c5SAndroid Build Coastguard Worker     // prepareForGenerateMipmap since this changes the format which prepareForGenerateMipmap relies
3392*8975f5c5SAndroid Build Coastguard Worker     // on.
3393*8975f5c5SAndroid Build Coastguard Worker     if (mState.hasBeenBoundAsAttachment())
3394*8975f5c5SAndroid Build Coastguard Worker     {
3395*8975f5c5SAndroid Build Coastguard Worker         TextureUpdateResult updateResult = TextureUpdateResult::ImageUnaffected;
3396*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(ensureRenderable(contextVk, &updateResult));
3397*8975f5c5SAndroid Build Coastguard Worker         if (updateResult == TextureUpdateResult::ImageRespecified)
3398*8975f5c5SAndroid Build Coastguard Worker         {
3399*8975f5c5SAndroid Build Coastguard Worker             oldUsageFlags  = mImageUsageFlags;
3400*8975f5c5SAndroid Build Coastguard Worker             oldCreateFlags = mImageCreateFlags;
3401*8975f5c5SAndroid Build Coastguard Worker         }
3402*8975f5c5SAndroid Build Coastguard Worker     }
3403*8975f5c5SAndroid Build Coastguard Worker 
3404*8975f5c5SAndroid Build Coastguard Worker     // Before redefining the image for any reason, check to see if it's about to go through mipmap
3405*8975f5c5SAndroid Build Coastguard Worker     // generation.  In that case, drop every staged change for the subsequent mips after base, and
3406*8975f5c5SAndroid Build Coastguard Worker     // make sure the image is created with the complete mip chain.
3407*8975f5c5SAndroid Build Coastguard Worker     const bool isGenerateMipmap = source == gl::Command::GenerateMipmap;
3408*8975f5c5SAndroid Build Coastguard Worker     if (isGenerateMipmap)
3409*8975f5c5SAndroid Build Coastguard Worker     {
3410*8975f5c5SAndroid Build Coastguard Worker         prepareForGenerateMipmap(contextVk);
3411*8975f5c5SAndroid Build Coastguard Worker     }
3412*8975f5c5SAndroid Build Coastguard Worker 
3413*8975f5c5SAndroid Build Coastguard Worker     // If texture was not originally created using the MSRTSS flag, it should be recreated when it
3414*8975f5c5SAndroid Build Coastguard Worker     // is bound to an MSRTT framebuffer.
3415*8975f5c5SAndroid Build Coastguard Worker     if (contextVk->getFeatures().supportsMultisampledRenderToSingleSampled.enabled &&
3416*8975f5c5SAndroid Build Coastguard Worker         !contextVk->getFeatures().preferMSRTSSFlagByDefault.enabled &&
3417*8975f5c5SAndroid Build Coastguard Worker         mState.hasBeenBoundToMSRTTFramebuffer() &&
3418*8975f5c5SAndroid Build Coastguard Worker         ((mImageCreateFlags & VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT) == 0))
3419*8975f5c5SAndroid Build Coastguard Worker     {
3420*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(respecifyImageStorage(contextVk));
3421*8975f5c5SAndroid Build Coastguard Worker         oldUsageFlags  = mImageUsageFlags;
3422*8975f5c5SAndroid Build Coastguard Worker         oldCreateFlags = mImageCreateFlags;
3423*8975f5c5SAndroid Build Coastguard Worker     }
3424*8975f5c5SAndroid Build Coastguard Worker 
3425*8975f5c5SAndroid Build Coastguard Worker     // For immutable texture, base level does not affect allocation. Only usage flags are. If usage
3426*8975f5c5SAndroid Build Coastguard Worker     // flag changed, we respecify image storage early on. This makes the code more reliable and also
3427*8975f5c5SAndroid Build Coastguard Worker     // better performance wise. Otherwise, we will try to preserve base level by calling
3428*8975f5c5SAndroid Build Coastguard Worker     // stageSelfAsSubresourceUpdates and then later on find out the mImageUsageFlags changed and the
3429*8975f5c5SAndroid Build Coastguard Worker     // whole thing has to be respecified.
3430*8975f5c5SAndroid Build Coastguard Worker     if (mState.getImmutableFormat() &&
3431*8975f5c5SAndroid Build Coastguard Worker         (oldUsageFlags != mImageUsageFlags || oldCreateFlags != mImageCreateFlags))
3432*8975f5c5SAndroid Build Coastguard Worker     {
3433*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(respecifyImageStorage(contextVk));
3434*8975f5c5SAndroid Build Coastguard Worker         oldUsageFlags  = mImageUsageFlags;
3435*8975f5c5SAndroid Build Coastguard Worker         oldCreateFlags = mImageCreateFlags;
3436*8975f5c5SAndroid Build Coastguard Worker     }
3437*8975f5c5SAndroid Build Coastguard Worker 
3438*8975f5c5SAndroid Build Coastguard Worker     // Set base and max level before initializing the image
3439*8975f5c5SAndroid Build Coastguard Worker     TextureUpdateResult updateResult = TextureUpdateResult::ImageUnaffected;
3440*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(maybeUpdateBaseMaxLevels(contextVk, &updateResult));
3441*8975f5c5SAndroid Build Coastguard Worker 
3442*8975f5c5SAndroid Build Coastguard Worker     // Updating levels could have respecified the storage, recapture mImageCreateFlags
3443*8975f5c5SAndroid Build Coastguard Worker     if (updateResult == TextureUpdateResult::ImageRespecified)
3444*8975f5c5SAndroid Build Coastguard Worker     {
3445*8975f5c5SAndroid Build Coastguard Worker         oldUsageFlags  = mImageUsageFlags;
3446*8975f5c5SAndroid Build Coastguard Worker         oldCreateFlags = mImageCreateFlags;
3447*8975f5c5SAndroid Build Coastguard Worker     }
3448*8975f5c5SAndroid Build Coastguard Worker 
3449*8975f5c5SAndroid Build Coastguard Worker     // It is possible for the image to have a single level (because it doesn't use mipmapping),
3450*8975f5c5SAndroid Build Coastguard Worker     // then have more levels defined in it and mipmapping enabled.  In that case, the image needs
3451*8975f5c5SAndroid Build Coastguard Worker     // to be recreated.
3452*8975f5c5SAndroid Build Coastguard Worker     bool isMipmapEnabledByMinFilter = false;
3453*8975f5c5SAndroid Build Coastguard Worker     if (!isGenerateMipmap && mImage && mImage->valid())
3454*8975f5c5SAndroid Build Coastguard Worker     {
3455*8975f5c5SAndroid Build Coastguard Worker         isMipmapEnabledByMinFilter =
3456*8975f5c5SAndroid Build Coastguard Worker             mImage->getLevelCount() < getMipLevelCount(ImageMipLevels::EnabledLevels);
3457*8975f5c5SAndroid Build Coastguard Worker     }
3458*8975f5c5SAndroid Build Coastguard Worker 
3459*8975f5c5SAndroid Build Coastguard Worker     // If generating mipmaps and the image needs to be recreated (not full-mip already, or changed
3460*8975f5c5SAndroid Build Coastguard Worker     // usage flags), make sure it's recreated.
3461*8975f5c5SAndroid Build Coastguard Worker     if (isGenerateMipmap && mImage && mImage->valid() &&
3462*8975f5c5SAndroid Build Coastguard Worker         (oldUsageFlags != mImageUsageFlags ||
3463*8975f5c5SAndroid Build Coastguard Worker          (!mState.getImmutableFormat() &&
3464*8975f5c5SAndroid Build Coastguard Worker           mImage->getLevelCount() !=
3465*8975f5c5SAndroid Build Coastguard Worker               getMipLevelCount(ImageMipLevels::FullMipChainForGenerateMipmap))))
3466*8975f5c5SAndroid Build Coastguard Worker     {
3467*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mOwnsImage);
3468*8975f5c5SAndroid Build Coastguard Worker         // Immutable texture is not expected to reach here. The usage flag change should have
3469*8975f5c5SAndroid Build Coastguard Worker         // been handled earlier and level count change should not need to reallocate
3470*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!mState.getImmutableFormat());
3471*8975f5c5SAndroid Build Coastguard Worker 
3472*8975f5c5SAndroid Build Coastguard Worker         // Flush staged updates to the base level of the image.  Note that updates to the rest of
3473*8975f5c5SAndroid Build Coastguard Worker         // the levels have already been discarded through the |removeStagedUpdates| call above.
3474*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(flushImageStagedUpdates(contextVk));
3475*8975f5c5SAndroid Build Coastguard Worker 
3476*8975f5c5SAndroid Build Coastguard Worker         stageSelfAsSubresourceUpdates(contextVk);
3477*8975f5c5SAndroid Build Coastguard Worker 
3478*8975f5c5SAndroid Build Coastguard Worker         // Release the mImage without collecting garbage from image views.
3479*8975f5c5SAndroid Build Coastguard Worker         releaseImage(contextVk);
3480*8975f5c5SAndroid Build Coastguard Worker     }
3481*8975f5c5SAndroid Build Coastguard Worker 
3482*8975f5c5SAndroid Build Coastguard Worker     // Respecify the image if it's changed in usage, or if any of its levels are redefined and no
3483*8975f5c5SAndroid Build Coastguard Worker     // update to base/max levels were done (otherwise the above call would have already taken care
3484*8975f5c5SAndroid Build Coastguard Worker     // of this).  Note that if both base/max and image usage are changed, the image is recreated
3485*8975f5c5SAndroid Build Coastguard Worker     // twice, which incurs unnecessary copies.  This is not expected to be happening in real
3486*8975f5c5SAndroid Build Coastguard Worker     // applications.
3487*8975f5c5SAndroid Build Coastguard Worker     if (oldUsageFlags != mImageUsageFlags || oldCreateFlags != mImageCreateFlags ||
3488*8975f5c5SAndroid Build Coastguard Worker         TextureHasAnyRedefinedLevels(mRedefinedLevels) || isMipmapEnabledByMinFilter)
3489*8975f5c5SAndroid Build Coastguard Worker     {
3490*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(respecifyImageStorage(contextVk));
3491*8975f5c5SAndroid Build Coastguard Worker     }
3492*8975f5c5SAndroid Build Coastguard Worker 
3493*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3494*8975f5c5SAndroid Build Coastguard Worker }
3495*8975f5c5SAndroid Build Coastguard Worker 
onLabelUpdate(const gl::Context * context)3496*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::onLabelUpdate(const gl::Context *context)
3497*8975f5c5SAndroid Build Coastguard Worker {
3498*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
3499*8975f5c5SAndroid Build Coastguard Worker     return updateTextureLabel(contextVk);
3500*8975f5c5SAndroid Build Coastguard Worker }
3501*8975f5c5SAndroid Build Coastguard Worker 
updateTextureLabel(ContextVk * contextVk)3502*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::updateTextureLabel(ContextVk *contextVk)
3503*8975f5c5SAndroid Build Coastguard Worker {
3504*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
3505*8975f5c5SAndroid Build Coastguard Worker     std::string label      = mState.getLabel();
3506*8975f5c5SAndroid Build Coastguard Worker     if (!label.empty() && renderer->enableDebugUtils() && imageValid())
3507*8975f5c5SAndroid Build Coastguard Worker     {
3508*8975f5c5SAndroid Build Coastguard Worker         return vk::SetDebugUtilsObjectName(contextVk, VK_OBJECT_TYPE_IMAGE,
3509*8975f5c5SAndroid Build Coastguard Worker                                            (uint64_t)(getImage().getImage().getHandle()),
3510*8975f5c5SAndroid Build Coastguard Worker                                            mState.getLabel());
3511*8975f5c5SAndroid Build Coastguard Worker     }
3512*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3513*8975f5c5SAndroid Build Coastguard Worker }
3514*8975f5c5SAndroid Build Coastguard Worker 
getRGBAConversionBufferHelper(vk::Renderer * renderer,angle::FormatID formatID) const3515*8975f5c5SAndroid Build Coastguard Worker vk::BufferHelper *TextureVk::getRGBAConversionBufferHelper(vk::Renderer *renderer,
3516*8975f5c5SAndroid Build Coastguard Worker                                                            angle::FormatID formatID) const
3517*8975f5c5SAndroid Build Coastguard Worker {
3518*8975f5c5SAndroid Build Coastguard Worker     BufferVk *bufferVk                                        = vk::GetImpl(getBuffer().get());
3519*8975f5c5SAndroid Build Coastguard Worker     const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding = mState.getBuffer();
3520*8975f5c5SAndroid Build Coastguard Worker     const VertexConversionBuffer::CacheKey cacheKey{
3521*8975f5c5SAndroid Build Coastguard Worker         formatID, 16, static_cast<size_t>(bufferBinding.getOffset()), false, true};
3522*8975f5c5SAndroid Build Coastguard Worker     ConversionBuffer *conversion = bufferVk->getVertexConversionBuffer(renderer, cacheKey);
3523*8975f5c5SAndroid Build Coastguard Worker     return conversion->getBuffer();
3524*8975f5c5SAndroid Build Coastguard Worker }
3525*8975f5c5SAndroid Build Coastguard Worker 
convertBufferToRGBA(ContextVk * contextVk,size_t & conversionBufferSize)3526*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::convertBufferToRGBA(ContextVk *contextVk, size_t &conversionBufferSize)
3527*8975f5c5SAndroid Build Coastguard Worker {
3528*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer             = contextVk->getRenderer();
3529*8975f5c5SAndroid Build Coastguard Worker     const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc();
3530*8975f5c5SAndroid Build Coastguard Worker     const vk::Format *imageUniformFormat =
3531*8975f5c5SAndroid Build Coastguard Worker         &renderer->getFormat(baseLevelDesc.format.info->sizedInternalFormat);
3532*8975f5c5SAndroid Build Coastguard Worker     const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding = mState.getBuffer();
3533*8975f5c5SAndroid Build Coastguard Worker     BufferVk *bufferVk                                        = vk::GetImpl(getBuffer().get());
3534*8975f5c5SAndroid Build Coastguard Worker     const size_t bindingOffset                                = bufferBinding.getOffset();
3535*8975f5c5SAndroid Build Coastguard Worker     const VkDeviceSize bufferSize                             = bufferVk->getSize();
3536*8975f5c5SAndroid Build Coastguard Worker     const VkDeviceSize bufferSizeFromOffset                   = bufferSize - bindingOffset;
3537*8975f5c5SAndroid Build Coastguard Worker     conversionBufferSize = roundUpPow2<size_t>(static_cast<size_t>((bufferSizeFromOffset / 3) * 4),
3538*8975f5c5SAndroid Build Coastguard Worker                                                4 * sizeof(uint32_t));
3539*8975f5c5SAndroid Build Coastguard Worker 
3540*8975f5c5SAndroid Build Coastguard Worker     const VertexConversionBuffer::CacheKey cacheKey{imageUniformFormat->getIntendedFormatID(), 16,
3541*8975f5c5SAndroid Build Coastguard Worker                                                     bindingOffset, false, true};
3542*8975f5c5SAndroid Build Coastguard Worker     ConversionBuffer *conversion = bufferVk->getVertexConversionBuffer(renderer, cacheKey);
3543*8975f5c5SAndroid Build Coastguard Worker     mBufferContentsObservers->enableForBuffer(getBuffer().get());
3544*8975f5c5SAndroid Build Coastguard Worker     if (!conversion->valid())
3545*8975f5c5SAndroid Build Coastguard Worker     {
3546*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(contextVk->initBufferForVertexConversion(conversion, conversionBufferSize,
3547*8975f5c5SAndroid Build Coastguard Worker                                                            vk::MemoryHostVisibility::NonVisible));
3548*8975f5c5SAndroid Build Coastguard Worker     }
3549*8975f5c5SAndroid Build Coastguard Worker     vk::BufferHelper *conversionBufferHelper = conversion->getBuffer();
3550*8975f5c5SAndroid Build Coastguard Worker 
3551*8975f5c5SAndroid Build Coastguard Worker     if (conversion->dirty())
3552*8975f5c5SAndroid Build Coastguard Worker     {
3553*8975f5c5SAndroid Build Coastguard Worker         vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
3554*8975f5c5SAndroid Build Coastguard Worker         UtilsVk &utilsVk               = contextVk->getUtils();
3555*8975f5c5SAndroid Build Coastguard Worker         const VkDeviceSize pixelSize   = 3 * sizeof(uint32_t);
3556*8975f5c5SAndroid Build Coastguard Worker         const VkDeviceSize pixelCount  = bufferSizeFromOffset / pixelSize;
3557*8975f5c5SAndroid Build Coastguard Worker 
3558*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(utilsVk.copyRgbToRgba(contextVk, imageUniformFormat->getIntendedFormat(),
3559*8975f5c5SAndroid Build Coastguard Worker                                         &bufferHelper, static_cast<uint32_t>(bindingOffset),
3560*8975f5c5SAndroid Build Coastguard Worker                                         static_cast<uint32_t>(pixelCount), conversionBufferHelper));
3561*8975f5c5SAndroid Build Coastguard Worker         conversion->clearDirty();
3562*8975f5c5SAndroid Build Coastguard Worker     }
3563*8975f5c5SAndroid Build Coastguard Worker 
3564*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3565*8975f5c5SAndroid Build Coastguard Worker }
3566*8975f5c5SAndroid Build Coastguard Worker 
syncState(const gl::Context * context,const gl::Texture::DirtyBits & dirtyBits,gl::Command source)3567*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::syncState(const gl::Context *context,
3568*8975f5c5SAndroid Build Coastguard Worker                                    const gl::Texture::DirtyBits &dirtyBits,
3569*8975f5c5SAndroid Build Coastguard Worker                                    gl::Command source)
3570*8975f5c5SAndroid Build Coastguard Worker {
3571*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk   = vk::GetImpl(context);
3572*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
3573*8975f5c5SAndroid Build Coastguard Worker 
3574*8975f5c5SAndroid Build Coastguard Worker     // If this is a texture buffer, release buffer views.  There's nothing else to sync.  The
3575*8975f5c5SAndroid Build Coastguard Worker     // image must already be deleted, and the sampler reset.
3576*8975f5c5SAndroid Build Coastguard Worker     if (mState.getBuffer().get() != nullptr)
3577*8975f5c5SAndroid Build Coastguard Worker     {
3578*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mImage == nullptr);
3579*8975f5c5SAndroid Build Coastguard Worker 
3580*8975f5c5SAndroid Build Coastguard Worker         const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding = mState.getBuffer();
3581*8975f5c5SAndroid Build Coastguard Worker 
3582*8975f5c5SAndroid Build Coastguard Worker         VkDeviceSize offset = bufferBinding.getOffset();
3583*8975f5c5SAndroid Build Coastguard Worker         VkDeviceSize size   = gl::GetBoundBufferAvailableSize(bufferBinding);
3584*8975f5c5SAndroid Build Coastguard Worker 
3585*8975f5c5SAndroid Build Coastguard Worker         if (NeedsRGBAEmulation(renderer, getBaseLevelFormat(renderer).getIntendedFormatID()))
3586*8975f5c5SAndroid Build Coastguard Worker         {
3587*8975f5c5SAndroid Build Coastguard Worker             size_t conversionBufferSize;
3588*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(convertBufferToRGBA(contextVk, conversionBufferSize));
3589*8975f5c5SAndroid Build Coastguard Worker             offset = 0;
3590*8975f5c5SAndroid Build Coastguard Worker             size   = conversionBufferSize;
3591*8975f5c5SAndroid Build Coastguard Worker         }
3592*8975f5c5SAndroid Build Coastguard Worker 
3593*8975f5c5SAndroid Build Coastguard Worker         mBufferViews.release(contextVk);
3594*8975f5c5SAndroid Build Coastguard Worker         mBufferViews.init(renderer, offset, size);
3595*8975f5c5SAndroid Build Coastguard Worker         mDescriptorSetCacheManager.releaseKeys(renderer);
3596*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
3597*8975f5c5SAndroid Build Coastguard Worker     }
3598*8975f5c5SAndroid Build Coastguard Worker 
3599*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(respecifyImageStorageIfNecessary(contextVk, source));
3600*8975f5c5SAndroid Build Coastguard Worker 
3601*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(performImageQueueTransferIfNecessary(contextVk));
3602*8975f5c5SAndroid Build Coastguard Worker 
3603*8975f5c5SAndroid Build Coastguard Worker     // Initialize the image storage and flush the pixel buffer.
3604*8975f5c5SAndroid Build Coastguard Worker     const bool isGenerateMipmap = source == gl::Command::GenerateMipmap;
3605*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureImageInitialized(contextVk, isGenerateMipmap
3606*8975f5c5SAndroid Build Coastguard Worker                                                     ? ImageMipLevels::FullMipChainForGenerateMipmap
3607*8975f5c5SAndroid Build Coastguard Worker                                                     : ImageMipLevels::EnabledLevels));
3608*8975f5c5SAndroid Build Coastguard Worker 
3609*8975f5c5SAndroid Build Coastguard Worker     // Mask out the IMPLEMENTATION dirty bit to avoid unnecessary syncs.
3610*8975f5c5SAndroid Build Coastguard Worker     // Keep it set when the border color is used and needs to be resynced.
3611*8975f5c5SAndroid Build Coastguard Worker     gl::Texture::DirtyBits localBits = dirtyBits;
3612*8975f5c5SAndroid Build Coastguard Worker     if (!mState.getSamplerState().usesBorderColor())
3613*8975f5c5SAndroid Build Coastguard Worker     {
3614*8975f5c5SAndroid Build Coastguard Worker         localBits.reset(gl::Texture::DIRTY_BIT_IMPLEMENTATION);
3615*8975f5c5SAndroid Build Coastguard Worker     }
3616*8975f5c5SAndroid Build Coastguard Worker     localBits.reset(gl::Texture::DIRTY_BIT_BASE_LEVEL);
3617*8975f5c5SAndroid Build Coastguard Worker     localBits.reset(gl::Texture::DIRTY_BIT_MAX_LEVEL);
3618*8975f5c5SAndroid Build Coastguard Worker 
3619*8975f5c5SAndroid Build Coastguard Worker     // For AHBs, the ImageViews are created with VkSamplerYcbcrConversionInfo's chromaFilter
3620*8975f5c5SAndroid Build Coastguard Worker     // matching min/magFilters as part of the eglEGLImageTargetTexture2DOES() call. However, the
3621*8975f5c5SAndroid Build Coastguard Worker     // min/mag filters can change later, requiring the ImageViews to be refreshed.
3622*8975f5c5SAndroid Build Coastguard Worker     if (mImage->valid() && mImage->hasImmutableSampler() &&
3623*8975f5c5SAndroid Build Coastguard Worker         (dirtyBits.test(gl::Texture::DIRTY_BIT_MIN_FILTER) ||
3624*8975f5c5SAndroid Build Coastguard Worker          dirtyBits.test(gl::Texture::DIRTY_BIT_MAG_FILTER)))
3625*8975f5c5SAndroid Build Coastguard Worker     {
3626*8975f5c5SAndroid Build Coastguard Worker         const gl::SamplerState &samplerState = mState.getSamplerState();
3627*8975f5c5SAndroid Build Coastguard Worker         VkFilter chromaFilter = samplerState.getMinFilter() == samplerState.getMagFilter()
3628*8975f5c5SAndroid Build Coastguard Worker                                     ? gl_vk::GetFilter(samplerState.getMinFilter())
3629*8975f5c5SAndroid Build Coastguard Worker                                     : vk::kDefaultYCbCrChromaFilter;
3630*8975f5c5SAndroid Build Coastguard Worker         if (mImage->updateChromaFilter(renderer, chromaFilter))
3631*8975f5c5SAndroid Build Coastguard Worker         {
3632*8975f5c5SAndroid Build Coastguard Worker             resetSampler();
3633*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(refreshImageViews(contextVk));
3634*8975f5c5SAndroid Build Coastguard Worker         }
3635*8975f5c5SAndroid Build Coastguard Worker     }
3636*8975f5c5SAndroid Build Coastguard Worker 
3637*8975f5c5SAndroid Build Coastguard Worker     if (localBits.none() && mSampler)
3638*8975f5c5SAndroid Build Coastguard Worker     {
3639*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
3640*8975f5c5SAndroid Build Coastguard Worker     }
3641*8975f5c5SAndroid Build Coastguard Worker 
3642*8975f5c5SAndroid Build Coastguard Worker     if (mSampler)
3643*8975f5c5SAndroid Build Coastguard Worker     {
3644*8975f5c5SAndroid Build Coastguard Worker         resetSampler();
3645*8975f5c5SAndroid Build Coastguard Worker     }
3646*8975f5c5SAndroid Build Coastguard Worker 
3647*8975f5c5SAndroid Build Coastguard Worker     if (localBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_RED) ||
3648*8975f5c5SAndroid Build Coastguard Worker         localBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_GREEN) ||
3649*8975f5c5SAndroid Build Coastguard Worker         localBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_BLUE) ||
3650*8975f5c5SAndroid Build Coastguard Worker         localBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA))
3651*8975f5c5SAndroid Build Coastguard Worker     {
3652*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(refreshImageViews(contextVk));
3653*8975f5c5SAndroid Build Coastguard Worker     }
3654*8975f5c5SAndroid Build Coastguard Worker 
3655*8975f5c5SAndroid Build Coastguard Worker     if (localBits.test(gl::Texture::DIRTY_BIT_SRGB_OVERRIDE) ||
3656*8975f5c5SAndroid Build Coastguard Worker         localBits.test(gl::Texture::DIRTY_BIT_SRGB_DECODE))
3657*8975f5c5SAndroid Build Coastguard Worker     {
3658*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mImage != nullptr);
3659*8975f5c5SAndroid Build Coastguard Worker         gl::SrgbDecode srgbDecode = (mState.getSamplerState().getSRGBDecode() == GL_SKIP_DECODE_EXT)
3660*8975f5c5SAndroid Build Coastguard Worker                                         ? gl::SrgbDecode::Skip
3661*8975f5c5SAndroid Build Coastguard Worker                                         : gl::SrgbDecode::Default;
3662*8975f5c5SAndroid Build Coastguard Worker         mImageView.updateSrgbDecode(*mImage, srgbDecode);
3663*8975f5c5SAndroid Build Coastguard Worker         mImageView.updateSrgbOverride(*mImage, mState.getSRGBOverride());
3664*8975f5c5SAndroid Build Coastguard Worker 
3665*8975f5c5SAndroid Build Coastguard Worker         if (!renderer->getFeatures().supportsImageFormatList.enabled)
3666*8975f5c5SAndroid Build Coastguard Worker         {
3667*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(refreshImageViews(contextVk));
3668*8975f5c5SAndroid Build Coastguard Worker         }
3669*8975f5c5SAndroid Build Coastguard Worker     }
3670*8975f5c5SAndroid Build Coastguard Worker 
3671*8975f5c5SAndroid Build Coastguard Worker     vk::SamplerDesc samplerDesc(contextVk, mState.getSamplerState(), mState.isStencilMode(),
3672*8975f5c5SAndroid Build Coastguard Worker                                 &mImage->getYcbcrConversionDesc(), mImage->getIntendedFormatID());
3673*8975f5c5SAndroid Build Coastguard Worker     auto y2yConversionDesc = mImage->getY2YConversionDesc();
3674*8975f5c5SAndroid Build Coastguard Worker     vk::SamplerDesc samplerDescSamplerExternal2DY2YEXT(contextVk, mState.getSamplerState(),
3675*8975f5c5SAndroid Build Coastguard Worker                                                        mState.isStencilMode(), &y2yConversionDesc,
3676*8975f5c5SAndroid Build Coastguard Worker                                                        mImage->getIntendedFormatID());
3677*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, samplerDesc, &mSampler));
3678*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, samplerDescSamplerExternal2DY2YEXT,
3679*8975f5c5SAndroid Build Coastguard Worker                                                      &mY2YSampler));
3680*8975f5c5SAndroid Build Coastguard Worker 
3681*8975f5c5SAndroid Build Coastguard Worker     updateCachedImageViewSerials();
3682*8975f5c5SAndroid Build Coastguard Worker 
3683*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3684*8975f5c5SAndroid Build Coastguard Worker }
3685*8975f5c5SAndroid Build Coastguard Worker 
initializeContents(const gl::Context * context,GLenum binding,const gl::ImageIndex & imageIndex)3686*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::initializeContents(const gl::Context *context,
3687*8975f5c5SAndroid Build Coastguard Worker                                             GLenum binding,
3688*8975f5c5SAndroid Build Coastguard Worker                                             const gl::ImageIndex &imageIndex)
3689*8975f5c5SAndroid Build Coastguard Worker {
3690*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk      = vk::GetImpl(context);
3691*8975f5c5SAndroid Build Coastguard Worker     const gl::ImageDesc &desc = mState.getImageDesc(imageIndex);
3692*8975f5c5SAndroid Build Coastguard Worker     const vk::Format &format =
3693*8975f5c5SAndroid Build Coastguard Worker         contextVk->getRenderer()->getFormat(desc.format.info->sizedInternalFormat);
3694*8975f5c5SAndroid Build Coastguard Worker 
3695*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImage);
3696*8975f5c5SAndroid Build Coastguard Worker     // Note that we cannot ensure the image is initialized because we might be calling subImage
3697*8975f5c5SAndroid Build Coastguard Worker     // on a non-complete cube map.
3698*8975f5c5SAndroid Build Coastguard Worker     return mImage->stageRobustResourceClearWithFormat(
3699*8975f5c5SAndroid Build Coastguard Worker         contextVk, imageIndex, desc.size, format.getIntendedFormat(),
3700*8975f5c5SAndroid Build Coastguard Worker         format.getActualImageFormat(getRequiredImageAccess()));
3701*8975f5c5SAndroid Build Coastguard Worker }
3702*8975f5c5SAndroid Build Coastguard Worker 
initializeContentsWithBlack(const gl::Context * context,GLenum binding,const gl::ImageIndex & imageIndex)3703*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::initializeContentsWithBlack(const gl::Context *context,
3704*8975f5c5SAndroid Build Coastguard Worker                                                      GLenum binding,
3705*8975f5c5SAndroid Build Coastguard Worker                                                      const gl::ImageIndex &imageIndex)
3706*8975f5c5SAndroid Build Coastguard Worker {
3707*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk      = vk::GetImpl(context);
3708*8975f5c5SAndroid Build Coastguard Worker     const gl::ImageDesc &desc = mState.getImageDesc(imageIndex);
3709*8975f5c5SAndroid Build Coastguard Worker     const vk::Format &format =
3710*8975f5c5SAndroid Build Coastguard Worker         contextVk->getRenderer()->getFormat(desc.format.info->sizedInternalFormat);
3711*8975f5c5SAndroid Build Coastguard Worker 
3712*8975f5c5SAndroid Build Coastguard Worker     VkClearValue clearValue = {};
3713*8975f5c5SAndroid Build Coastguard Worker     clearValue.color        = {{0, 0, 0, 1.0f}};
3714*8975f5c5SAndroid Build Coastguard Worker 
3715*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImage);
3716*8975f5c5SAndroid Build Coastguard Worker     // Note that we cannot ensure the image is initialized because we might be calling subImage
3717*8975f5c5SAndroid Build Coastguard Worker     // on a non-complete cube map.
3718*8975f5c5SAndroid Build Coastguard Worker     return mImage->stageResourceClearWithFormat(
3719*8975f5c5SAndroid Build Coastguard Worker         contextVk, imageIndex, desc.size, format.getIntendedFormat(),
3720*8975f5c5SAndroid Build Coastguard Worker         format.getActualImageFormat(getRequiredImageAccess()), clearValue);
3721*8975f5c5SAndroid Build Coastguard Worker }
3722*8975f5c5SAndroid Build Coastguard Worker 
releaseOwnershipOfImage(const gl::Context * context)3723*8975f5c5SAndroid Build Coastguard Worker void TextureVk::releaseOwnershipOfImage(const gl::Context *context)
3724*8975f5c5SAndroid Build Coastguard Worker {
3725*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
3726*8975f5c5SAndroid Build Coastguard Worker 
3727*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mImageSiblingSerial.valid());
3728*8975f5c5SAndroid Build Coastguard Worker 
3729*8975f5c5SAndroid Build Coastguard Worker     mOwnsImage = false;
3730*8975f5c5SAndroid Build Coastguard Worker     releaseAndDeleteImageAndViews(contextVk);
3731*8975f5c5SAndroid Build Coastguard Worker }
3732*8975f5c5SAndroid Build Coastguard Worker 
getReadImageView(GLenum srgbDecode,bool texelFetchStaticUse,bool samplerExternal2DY2YEXT) const3733*8975f5c5SAndroid Build Coastguard Worker const vk::ImageView &TextureVk::getReadImageView(GLenum srgbDecode,
3734*8975f5c5SAndroid Build Coastguard Worker                                                  bool texelFetchStaticUse,
3735*8975f5c5SAndroid Build Coastguard Worker                                                  bool samplerExternal2DY2YEXT) const
3736*8975f5c5SAndroid Build Coastguard Worker {
3737*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImage->valid());
3738*8975f5c5SAndroid Build Coastguard Worker 
3739*8975f5c5SAndroid Build Coastguard Worker     const vk::ImageViewHelper &imageViews = getImageViews();
3740*8975f5c5SAndroid Build Coastguard Worker 
3741*8975f5c5SAndroid Build Coastguard Worker     if (mState.isStencilMode() && imageViews.hasStencilReadImageView())
3742*8975f5c5SAndroid Build Coastguard Worker     {
3743*8975f5c5SAndroid Build Coastguard Worker         return imageViews.getStencilReadImageView();
3744*8975f5c5SAndroid Build Coastguard Worker     }
3745*8975f5c5SAndroid Build Coastguard Worker 
3746*8975f5c5SAndroid Build Coastguard Worker     if (samplerExternal2DY2YEXT)
3747*8975f5c5SAndroid Build Coastguard Worker     {
3748*8975f5c5SAndroid Build Coastguard Worker         ASSERT(imageViews.getSamplerExternal2DY2YEXTImageView().valid());
3749*8975f5c5SAndroid Build Coastguard Worker         return imageViews.getSamplerExternal2DY2YEXTImageView();
3750*8975f5c5SAndroid Build Coastguard Worker     }
3751*8975f5c5SAndroid Build Coastguard Worker 
3752*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImage != nullptr && mImage->valid());
3753*8975f5c5SAndroid Build Coastguard Worker     gl::SrgbDecode decode =
3754*8975f5c5SAndroid Build Coastguard Worker         (srgbDecode == GL_DECODE_EXT) ? gl::SrgbDecode::Default : gl::SrgbDecode::Skip;
3755*8975f5c5SAndroid Build Coastguard Worker     imageViews.updateSrgbDecode(*mImage, decode);
3756*8975f5c5SAndroid Build Coastguard Worker     imageViews.updateStaticTexelFetch(*mImage, texelFetchStaticUse);
3757*8975f5c5SAndroid Build Coastguard Worker 
3758*8975f5c5SAndroid Build Coastguard Worker     ASSERT(imageViews.getReadImageView().valid());
3759*8975f5c5SAndroid Build Coastguard Worker     return imageViews.getReadImageView();
3760*8975f5c5SAndroid Build Coastguard Worker }
3761*8975f5c5SAndroid Build Coastguard Worker 
getCopyImageView() const3762*8975f5c5SAndroid Build Coastguard Worker const vk::ImageView &TextureVk::getCopyImageView() const
3763*8975f5c5SAndroid Build Coastguard Worker {
3764*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImage->valid());
3765*8975f5c5SAndroid Build Coastguard Worker 
3766*8975f5c5SAndroid Build Coastguard Worker     const vk::ImageViewHelper &imageViews = getImageViews();
3767*8975f5c5SAndroid Build Coastguard Worker 
3768*8975f5c5SAndroid Build Coastguard Worker     const angle::Format &angleFormat = mImage->getActualFormat();
3769*8975f5c5SAndroid Build Coastguard Worker     ASSERT(angleFormat.isSRGB ==
3770*8975f5c5SAndroid Build Coastguard Worker            (ConvertToLinear(mImage->getActualFormatID()) != angle::FormatID::NONE));
3771*8975f5c5SAndroid Build Coastguard Worker     if (angleFormat.isSRGB)
3772*8975f5c5SAndroid Build Coastguard Worker     {
3773*8975f5c5SAndroid Build Coastguard Worker         return imageViews.getSRGBCopyImageView();
3774*8975f5c5SAndroid Build Coastguard Worker     }
3775*8975f5c5SAndroid Build Coastguard Worker     return imageViews.getLinearCopyImageView();
3776*8975f5c5SAndroid Build Coastguard Worker }
3777*8975f5c5SAndroid Build Coastguard Worker 
getLevelLayerImageView(vk::Context * context,gl::LevelIndex level,size_t layer,const vk::ImageView ** imageViewOut)3778*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::getLevelLayerImageView(vk::Context *context,
3779*8975f5c5SAndroid Build Coastguard Worker                                                 gl::LevelIndex level,
3780*8975f5c5SAndroid Build Coastguard Worker                                                 size_t layer,
3781*8975f5c5SAndroid Build Coastguard Worker                                                 const vk::ImageView **imageViewOut)
3782*8975f5c5SAndroid Build Coastguard Worker {
3783*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImage && mImage->valid());
3784*8975f5c5SAndroid Build Coastguard Worker 
3785*8975f5c5SAndroid Build Coastguard Worker     gl::LevelIndex levelGL = getNativeImageLevel(level);
3786*8975f5c5SAndroid Build Coastguard Worker     vk::LevelIndex levelVk = mImage->toVkLevel(levelGL);
3787*8975f5c5SAndroid Build Coastguard Worker     uint32_t nativeLayer   = getNativeImageLayer(static_cast<uint32_t>(layer));
3788*8975f5c5SAndroid Build Coastguard Worker 
3789*8975f5c5SAndroid Build Coastguard Worker     return getImageViews().getLevelLayerDrawImageView(context, *mImage, levelVk, nativeLayer,
3790*8975f5c5SAndroid Build Coastguard Worker                                                       imageViewOut);
3791*8975f5c5SAndroid Build Coastguard Worker }
3792*8975f5c5SAndroid Build Coastguard Worker 
getStorageImageView(vk::Context * context,const gl::ImageUnit & binding,const vk::ImageView ** imageViewOut)3793*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::getStorageImageView(vk::Context *context,
3794*8975f5c5SAndroid Build Coastguard Worker                                              const gl::ImageUnit &binding,
3795*8975f5c5SAndroid Build Coastguard Worker                                              const vk::ImageView **imageViewOut)
3796*8975f5c5SAndroid Build Coastguard Worker {
3797*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = context->getRenderer();
3798*8975f5c5SAndroid Build Coastguard Worker 
3799*8975f5c5SAndroid Build Coastguard Worker     angle::FormatID formatID = angle::Format::InternalFormatToID(binding.format);
3800*8975f5c5SAndroid Build Coastguard Worker     const vk::Format *format = &renderer->getFormat(formatID);
3801*8975f5c5SAndroid Build Coastguard Worker 
3802*8975f5c5SAndroid Build Coastguard Worker     format = AdjustStorageViewFormatPerWorkarounds(renderer, format, getRequiredImageAccess());
3803*8975f5c5SAndroid Build Coastguard Worker 
3804*8975f5c5SAndroid Build Coastguard Worker     gl::LevelIndex nativeLevelGL =
3805*8975f5c5SAndroid Build Coastguard Worker         getNativeImageLevel(gl::LevelIndex(static_cast<uint32_t>(binding.level)));
3806*8975f5c5SAndroid Build Coastguard Worker     vk::LevelIndex nativeLevelVk = mImage->toVkLevel(nativeLevelGL);
3807*8975f5c5SAndroid Build Coastguard Worker 
3808*8975f5c5SAndroid Build Coastguard Worker     if (binding.layered != GL_TRUE)
3809*8975f5c5SAndroid Build Coastguard Worker     {
3810*8975f5c5SAndroid Build Coastguard Worker         uint32_t nativeLayer = getNativeImageLayer(static_cast<uint32_t>(binding.layer));
3811*8975f5c5SAndroid Build Coastguard Worker 
3812*8975f5c5SAndroid Build Coastguard Worker         return getImageViews().getLevelLayerStorageImageView(
3813*8975f5c5SAndroid Build Coastguard Worker             context, *mImage, nativeLevelVk, nativeLayer,
3814*8975f5c5SAndroid Build Coastguard Worker             VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
3815*8975f5c5SAndroid Build Coastguard Worker             format->getActualImageFormatID(getRequiredImageAccess()), imageViewOut);
3816*8975f5c5SAndroid Build Coastguard Worker     }
3817*8975f5c5SAndroid Build Coastguard Worker 
3818*8975f5c5SAndroid Build Coastguard Worker     uint32_t nativeLayer = getNativeImageLayer(0);
3819*8975f5c5SAndroid Build Coastguard Worker 
3820*8975f5c5SAndroid Build Coastguard Worker     return getImageViews().getLevelStorageImageView(
3821*8975f5c5SAndroid Build Coastguard Worker         context, mState.getType(), *mImage, nativeLevelVk, nativeLayer,
3822*8975f5c5SAndroid Build Coastguard Worker         VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
3823*8975f5c5SAndroid Build Coastguard Worker         format->getActualImageFormatID(getRequiredImageAccess()), imageViewOut);
3824*8975f5c5SAndroid Build Coastguard Worker }
3825*8975f5c5SAndroid Build Coastguard Worker 
getPossiblyEmulatedTextureBuffer(vk::Context * context) const3826*8975f5c5SAndroid Build Coastguard Worker vk::BufferHelper *TextureVk::getPossiblyEmulatedTextureBuffer(vk::Context *context) const
3827*8975f5c5SAndroid Build Coastguard Worker {
3828*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = context->getRenderer();
3829*8975f5c5SAndroid Build Coastguard Worker 
3830*8975f5c5SAndroid Build Coastguard Worker     angle::FormatID format = getBaseLevelFormat(renderer).getIntendedFormatID();
3831*8975f5c5SAndroid Build Coastguard Worker     if (NeedsRGBAEmulation(renderer, format))
3832*8975f5c5SAndroid Build Coastguard Worker     {
3833*8975f5c5SAndroid Build Coastguard Worker         return getRGBAConversionBufferHelper(renderer, format);
3834*8975f5c5SAndroid Build Coastguard Worker     }
3835*8975f5c5SAndroid Build Coastguard Worker 
3836*8975f5c5SAndroid Build Coastguard Worker     BufferVk *bufferVk = vk::GetImpl(getBuffer().get());
3837*8975f5c5SAndroid Build Coastguard Worker     return &bufferVk->getBuffer();
3838*8975f5c5SAndroid Build Coastguard Worker }
3839*8975f5c5SAndroid Build Coastguard Worker 
getBufferView(vk::Context * context,const vk::Format * imageUniformFormat,const gl::SamplerBinding * samplerBinding,bool isImage,const vk::BufferView ** viewOut)3840*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::getBufferView(vk::Context *context,
3841*8975f5c5SAndroid Build Coastguard Worker                                        const vk::Format *imageUniformFormat,
3842*8975f5c5SAndroid Build Coastguard Worker                                        const gl::SamplerBinding *samplerBinding,
3843*8975f5c5SAndroid Build Coastguard Worker                                        bool isImage,
3844*8975f5c5SAndroid Build Coastguard Worker                                        const vk::BufferView **viewOut)
3845*8975f5c5SAndroid Build Coastguard Worker {
3846*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = context->getRenderer();
3847*8975f5c5SAndroid Build Coastguard Worker 
3848*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mState.getBuffer().get() != nullptr);
3849*8975f5c5SAndroid Build Coastguard Worker 
3850*8975f5c5SAndroid Build Coastguard Worker     // Use the format specified by glTexBuffer if no format specified by the shader.
3851*8975f5c5SAndroid Build Coastguard Worker     if (imageUniformFormat == nullptr)
3852*8975f5c5SAndroid Build Coastguard Worker     {
3853*8975f5c5SAndroid Build Coastguard Worker         imageUniformFormat = &getBaseLevelFormat(renderer);
3854*8975f5c5SAndroid Build Coastguard Worker     }
3855*8975f5c5SAndroid Build Coastguard Worker 
3856*8975f5c5SAndroid Build Coastguard Worker     if (isImage)
3857*8975f5c5SAndroid Build Coastguard Worker     {
3858*8975f5c5SAndroid Build Coastguard Worker         imageUniformFormat = AdjustStorageViewFormatPerWorkarounds(renderer, imageUniformFormat,
3859*8975f5c5SAndroid Build Coastguard Worker                                                                    getRequiredImageAccess());
3860*8975f5c5SAndroid Build Coastguard Worker     }
3861*8975f5c5SAndroid Build Coastguard Worker 
3862*8975f5c5SAndroid Build Coastguard Worker     const vk::BufferHelper *buffer = &vk::GetImpl(mState.getBuffer().get())->getBuffer();
3863*8975f5c5SAndroid Build Coastguard Worker 
3864*8975f5c5SAndroid Build Coastguard Worker     if (NeedsRGBAEmulation(renderer, imageUniformFormat->getIntendedFormatID()))
3865*8975f5c5SAndroid Build Coastguard Worker     {
3866*8975f5c5SAndroid Build Coastguard Worker         buffer = getRGBAConversionBufferHelper(renderer, imageUniformFormat->getIntendedFormatID());
3867*8975f5c5SAndroid Build Coastguard Worker         imageUniformFormat = &renderer->getFormat(
3868*8975f5c5SAndroid Build Coastguard Worker             GetRGBAEmulationDstFormat(imageUniformFormat->getIntendedFormatID()));
3869*8975f5c5SAndroid Build Coastguard Worker     }
3870*8975f5c5SAndroid Build Coastguard Worker 
3871*8975f5c5SAndroid Build Coastguard Worker     if (samplerBinding)
3872*8975f5c5SAndroid Build Coastguard Worker     {
3873*8975f5c5SAndroid Build Coastguard Worker         imageUniformFormat =
3874*8975f5c5SAndroid Build Coastguard Worker             AdjustViewFormatForSampler(renderer, imageUniformFormat, samplerBinding->format);
3875*8975f5c5SAndroid Build Coastguard Worker     }
3876*8975f5c5SAndroid Build Coastguard Worker 
3877*8975f5c5SAndroid Build Coastguard Worker     // Create a view for the required format.
3878*8975f5c5SAndroid Build Coastguard Worker     return mBufferViews.getView(context, *buffer, buffer->getOffset(), *imageUniformFormat,
3879*8975f5c5SAndroid Build Coastguard Worker                                 viewOut);
3880*8975f5c5SAndroid Build Coastguard Worker }
3881*8975f5c5SAndroid Build Coastguard Worker 
initImage(ContextVk * contextVk,angle::FormatID intendedImageFormatID,angle::FormatID actualImageFormatID,ImageMipLevels mipLevels)3882*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::initImage(ContextVk *contextVk,
3883*8975f5c5SAndroid Build Coastguard Worker                                    angle::FormatID intendedImageFormatID,
3884*8975f5c5SAndroid Build Coastguard Worker                                    angle::FormatID actualImageFormatID,
3885*8975f5c5SAndroid Build Coastguard Worker                                    ImageMipLevels mipLevels)
3886*8975f5c5SAndroid Build Coastguard Worker {
3887*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
3888*8975f5c5SAndroid Build Coastguard Worker 
3889*8975f5c5SAndroid Build Coastguard Worker     // Create the image. For immutable texture, we always allocate the full immutable levels
3890*8975f5c5SAndroid Build Coastguard Worker     // specified by texStorage call. Otherwise we only try to allocate from base to max levels.
3891*8975f5c5SAndroid Build Coastguard Worker     const gl::ImageDesc *firstLevelDesc;
3892*8975f5c5SAndroid Build Coastguard Worker     uint32_t firstLevel, levelCount;
3893*8975f5c5SAndroid Build Coastguard Worker     if (mState.getImmutableFormat())
3894*8975f5c5SAndroid Build Coastguard Worker     {
3895*8975f5c5SAndroid Build Coastguard Worker         firstLevelDesc = &mState.getLevelZeroDesc();
3896*8975f5c5SAndroid Build Coastguard Worker         firstLevel     = 0;
3897*8975f5c5SAndroid Build Coastguard Worker         levelCount     = mState.getImmutableLevels();
3898*8975f5c5SAndroid Build Coastguard Worker     }
3899*8975f5c5SAndroid Build Coastguard Worker     else
3900*8975f5c5SAndroid Build Coastguard Worker     {
3901*8975f5c5SAndroid Build Coastguard Worker         firstLevelDesc = &mState.getBaseLevelDesc();
3902*8975f5c5SAndroid Build Coastguard Worker         firstLevel     = mState.getEffectiveBaseLevel();
3903*8975f5c5SAndroid Build Coastguard Worker         levelCount     = getMipLevelCount(mipLevels);
3904*8975f5c5SAndroid Build Coastguard Worker     }
3905*8975f5c5SAndroid Build Coastguard Worker     const gl::Extents &firstLevelExtents = firstLevelDesc->size;
3906*8975f5c5SAndroid Build Coastguard Worker 
3907*8975f5c5SAndroid Build Coastguard Worker     VkExtent3D vkExtent;
3908*8975f5c5SAndroid Build Coastguard Worker     uint32_t layerCount;
3909*8975f5c5SAndroid Build Coastguard Worker     gl_vk::GetExtentsAndLayerCount(mState.getType(), firstLevelExtents, &vkExtent, &layerCount);
3910*8975f5c5SAndroid Build Coastguard Worker     GLint samples = mState.getBaseLevelDesc().samples ? mState.getBaseLevelDesc().samples : 1;
3911*8975f5c5SAndroid Build Coastguard Worker 
3912*8975f5c5SAndroid Build Coastguard Worker     if (contextVk->getFeatures().limitSampleCountTo2.enabled)
3913*8975f5c5SAndroid Build Coastguard Worker     {
3914*8975f5c5SAndroid Build Coastguard Worker         samples = std::min(samples, 2);
3915*8975f5c5SAndroid Build Coastguard Worker     }
3916*8975f5c5SAndroid Build Coastguard Worker 
3917*8975f5c5SAndroid Build Coastguard Worker     if (mState.hasProtectedContent())
3918*8975f5c5SAndroid Build Coastguard Worker     {
3919*8975f5c5SAndroid Build Coastguard Worker         mImageCreateFlags |= VK_IMAGE_CREATE_PROTECTED_BIT;
3920*8975f5c5SAndroid Build Coastguard Worker     }
3921*8975f5c5SAndroid Build Coastguard Worker 
3922*8975f5c5SAndroid Build Coastguard Worker     if (renderer->getFeatures().supportsComputeTranscodeEtcToBc.enabled &&
3923*8975f5c5SAndroid Build Coastguard Worker         IsETCFormat(intendedImageFormatID) && IsBCFormat(actualImageFormatID))
3924*8975f5c5SAndroid Build Coastguard Worker     {
3925*8975f5c5SAndroid Build Coastguard Worker         mImageCreateFlags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT |
3926*8975f5c5SAndroid Build Coastguard Worker                              VK_IMAGE_CREATE_EXTENDED_USAGE_BIT |
3927*8975f5c5SAndroid Build Coastguard Worker                              VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT;
3928*8975f5c5SAndroid Build Coastguard Worker         mImageUsageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
3929*8975f5c5SAndroid Build Coastguard Worker     }
3930*8975f5c5SAndroid Build Coastguard Worker 
3931*8975f5c5SAndroid Build Coastguard Worker     mImageCreateFlags |=
3932*8975f5c5SAndroid Build Coastguard Worker         vk::GetMinimalImageCreateFlags(renderer, mState.getType(), mImageUsageFlags);
3933*8975f5c5SAndroid Build Coastguard Worker 
3934*8975f5c5SAndroid Build Coastguard Worker     const VkFormat actualImageFormat =
3935*8975f5c5SAndroid Build Coastguard Worker         rx::vk::GetVkFormatFromFormatID(renderer, actualImageFormatID);
3936*8975f5c5SAndroid Build Coastguard Worker     const VkImageType imageType     = gl_vk::GetImageType(mState.getType());
3937*8975f5c5SAndroid Build Coastguard Worker     const VkImageTiling imageTiling = mImage->getTilingMode();
3938*8975f5c5SAndroid Build Coastguard Worker 
3939*8975f5c5SAndroid Build Coastguard Worker     // The MSRTSS bit is included in the create flag for all textures if the feature flag
3940*8975f5c5SAndroid Build Coastguard Worker     // corresponding to its preference is enabled. Otherwise, it is enabled for a texture if it is
3941*8975f5c5SAndroid Build Coastguard Worker     // bound to an MSRTT framebuffer.
3942*8975f5c5SAndroid Build Coastguard Worker     const bool shouldIncludeMSRTSSBit =
3943*8975f5c5SAndroid Build Coastguard Worker         contextVk->getFeatures().supportsMultisampledRenderToSingleSampled.enabled &&
3944*8975f5c5SAndroid Build Coastguard Worker         (contextVk->getFeatures().preferMSRTSSFlagByDefault.enabled ||
3945*8975f5c5SAndroid Build Coastguard Worker          mState.hasBeenBoundToMSRTTFramebuffer());
3946*8975f5c5SAndroid Build Coastguard Worker 
3947*8975f5c5SAndroid Build Coastguard Worker     if ((mImageUsageFlags & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
3948*8975f5c5SAndroid Build Coastguard Worker                              VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) != 0 &&
3949*8975f5c5SAndroid Build Coastguard Worker         mOwnsImage && samples == 1 && shouldIncludeMSRTSSBit)
3950*8975f5c5SAndroid Build Coastguard Worker     {
3951*8975f5c5SAndroid Build Coastguard Worker         VkImageCreateFlags createFlagsMultisampled =
3952*8975f5c5SAndroid Build Coastguard Worker             mImageCreateFlags | VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT;
3953*8975f5c5SAndroid Build Coastguard Worker         bool isActualFormatSRGB             = angle::Format::Get(actualImageFormatID).isSRGB;
3954*8975f5c5SAndroid Build Coastguard Worker         const VkFormat additionalViewFormat = rx::vk::GetVkFormatFromFormatID(
3955*8975f5c5SAndroid Build Coastguard Worker             renderer, isActualFormatSRGB ? ConvertToLinear(actualImageFormatID)
3956*8975f5c5SAndroid Build Coastguard Worker                                          : ConvertToSRGB(actualImageFormatID));
3957*8975f5c5SAndroid Build Coastguard Worker         const bool isAdditionalFormatValid = additionalViewFormat != VK_FORMAT_UNDEFINED;
3958*8975f5c5SAndroid Build Coastguard Worker 
3959*8975f5c5SAndroid Build Coastguard Worker         // If the texture has already been bound to an MSRTT framebuffer, lack of support should
3960*8975f5c5SAndroid Build Coastguard Worker         // result in failure.
3961*8975f5c5SAndroid Build Coastguard Worker         bool supportsMSRTTUsageActualFormat = vk::ImageHelper::FormatSupportsUsage(
3962*8975f5c5SAndroid Build Coastguard Worker             renderer, actualImageFormat, imageType, imageTiling, mImageUsageFlags,
3963*8975f5c5SAndroid Build Coastguard Worker             createFlagsMultisampled, nullptr, nullptr,
3964*8975f5c5SAndroid Build Coastguard Worker             vk::ImageHelper::FormatSupportCheck::RequireMultisampling);
3965*8975f5c5SAndroid Build Coastguard Worker         bool supportsMSRTTUsageAdditionalFormat =
3966*8975f5c5SAndroid Build Coastguard Worker             !isAdditionalFormatValid ||
3967*8975f5c5SAndroid Build Coastguard Worker             vk::ImageHelper::FormatSupportsUsage(
3968*8975f5c5SAndroid Build Coastguard Worker                 renderer, additionalViewFormat, imageType, imageTiling, mImageUsageFlags,
3969*8975f5c5SAndroid Build Coastguard Worker                 createFlagsMultisampled, nullptr, nullptr,
3970*8975f5c5SAndroid Build Coastguard Worker                 vk::ImageHelper::FormatSupportCheck::RequireMultisampling);
3971*8975f5c5SAndroid Build Coastguard Worker 
3972*8975f5c5SAndroid Build Coastguard Worker         bool supportsMSRTTUsage =
3973*8975f5c5SAndroid Build Coastguard Worker             supportsMSRTTUsageActualFormat && supportsMSRTTUsageAdditionalFormat;
3974*8975f5c5SAndroid Build Coastguard Worker         if (ANGLE_UNLIKELY(mState.hasBeenBoundToMSRTTFramebuffer() && !supportsMSRTTUsage))
3975*8975f5c5SAndroid Build Coastguard Worker         {
3976*8975f5c5SAndroid Build Coastguard Worker             ERR() << "Texture bound to EXT_multisampled_render_to_texture framebuffer, "
3977*8975f5c5SAndroid Build Coastguard Worker                   << "but this device does not support this format.";
3978*8975f5c5SAndroid Build Coastguard Worker             ANGLE_VK_TRY(contextVk, VK_ERROR_FORMAT_NOT_SUPPORTED);
3979*8975f5c5SAndroid Build Coastguard Worker         }
3980*8975f5c5SAndroid Build Coastguard Worker 
3981*8975f5c5SAndroid Build Coastguard Worker         // Note: If we ever fail the following check, we should use the emulation path for this
3982*8975f5c5SAndroid Build Coastguard Worker         // texture instead of ignoring MSRTT.
3983*8975f5c5SAndroid Build Coastguard Worker         if (supportsMSRTTUsage)
3984*8975f5c5SAndroid Build Coastguard Worker         {
3985*8975f5c5SAndroid Build Coastguard Worker             // If supported by format add the MSRTSS flag because any texture might end up as an
3986*8975f5c5SAndroid Build Coastguard Worker             // MSRTT attachment.
3987*8975f5c5SAndroid Build Coastguard Worker             mImageCreateFlags |= VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT;
3988*8975f5c5SAndroid Build Coastguard Worker         }
3989*8975f5c5SAndroid Build Coastguard Worker     }
3990*8975f5c5SAndroid Build Coastguard Worker 
3991*8975f5c5SAndroid Build Coastguard Worker     // Any format with VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT support is required to also support
3992*8975f5c5SAndroid Build Coastguard Worker     // VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT.  So no format feature query is needed.
3993*8975f5c5SAndroid Build Coastguard Worker     // However, it's still necessary to use vkGetPhysicalDeviceImageFormatProperties2 to ensure host
3994*8975f5c5SAndroid Build Coastguard Worker     // image copy is supported for the specific usage and flags.
3995*8975f5c5SAndroid Build Coastguard Worker     //
3996*8975f5c5SAndroid Build Coastguard Worker     // All TextureVk images are expected to have VK_IMAGE_USAGE_SAMPLED_BIT, so that is not checked
3997*8975f5c5SAndroid Build Coastguard Worker     // either.
3998*8975f5c5SAndroid Build Coastguard Worker     ASSERT((mImageUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) != 0);
3999*8975f5c5SAndroid Build Coastguard Worker     if (mOwnsImage && samples == 1 && renderer->getFeatures().supportsHostImageCopy.enabled)
4000*8975f5c5SAndroid Build Coastguard Worker     {
4001*8975f5c5SAndroid Build Coastguard Worker         VkHostImageCopyDevicePerformanceQueryEXT perfQuery = {};
4002*8975f5c5SAndroid Build Coastguard Worker         perfQuery.sType = VK_STRUCTURE_TYPE_HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY_EXT;
4003*8975f5c5SAndroid Build Coastguard Worker 
4004*8975f5c5SAndroid Build Coastguard Worker         // If host image copy is supported at all ...
4005*8975f5c5SAndroid Build Coastguard Worker         if (vk::ImageHelper::FormatSupportsUsage(
4006*8975f5c5SAndroid Build Coastguard Worker                 renderer, actualImageFormat, imageType, imageTiling,
4007*8975f5c5SAndroid Build Coastguard Worker                 mImageUsageFlags | VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT, mImageCreateFlags, nullptr,
4008*8975f5c5SAndroid Build Coastguard Worker                 &perfQuery, vk::ImageHelper::FormatSupportCheck::OnlyQuerySuccess))
4009*8975f5c5SAndroid Build Coastguard Worker         {
4010*8975f5c5SAndroid Build Coastguard Worker             // Only enable it if it has no performance impact whatsoever (or impact is tiny, given
4011*8975f5c5SAndroid Build Coastguard Worker             // feature).
4012*8975f5c5SAndroid Build Coastguard Worker             if (perfQuery.identicalMemoryLayout ||
4013*8975f5c5SAndroid Build Coastguard Worker                 (perfQuery.optimalDeviceAccess &&
4014*8975f5c5SAndroid Build Coastguard Worker                  renderer->getFeatures().allowHostImageCopyDespiteNonIdenticalLayout.enabled))
4015*8975f5c5SAndroid Build Coastguard Worker             {
4016*8975f5c5SAndroid Build Coastguard Worker                 mImageUsageFlags |= VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
4017*8975f5c5SAndroid Build Coastguard Worker             }
4018*8975f5c5SAndroid Build Coastguard Worker         }
4019*8975f5c5SAndroid Build Coastguard Worker     }
4020*8975f5c5SAndroid Build Coastguard Worker 
4021*8975f5c5SAndroid Build Coastguard Worker     // Fixed rate compression
4022*8975f5c5SAndroid Build Coastguard Worker     VkImageCompressionControlEXT *compressionInfo   = nullptr;
4023*8975f5c5SAndroid Build Coastguard Worker     VkImageCompressionControlEXT compressionInfoVar = {};
4024*8975f5c5SAndroid Build Coastguard Worker     compressionInfoVar.sType = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT;
4025*8975f5c5SAndroid Build Coastguard Worker     VkImageCompressionFixedRateFlagsEXT compressionRates = VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT;
4026*8975f5c5SAndroid Build Coastguard Worker     if (mOwnsImage && renderer->getFeatures().supportsImageCompressionControl.enabled)
4027*8975f5c5SAndroid Build Coastguard Worker     {
4028*8975f5c5SAndroid Build Coastguard Worker         // Use default compression control flag for query
4029*8975f5c5SAndroid Build Coastguard Worker         compressionInfoVar.flags = VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT;
4030*8975f5c5SAndroid Build Coastguard Worker 
4031*8975f5c5SAndroid Build Coastguard Worker         VkImageCompressionPropertiesEXT compressionProp = {};
4032*8975f5c5SAndroid Build Coastguard Worker         compressionProp.sType = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT;
4033*8975f5c5SAndroid Build Coastguard Worker 
4034*8975f5c5SAndroid Build Coastguard Worker         // If fixed rate compression is supported by this type, not support YUV now.
4035*8975f5c5SAndroid Build Coastguard Worker         const vk::Format &format = renderer->getFormat(intendedImageFormatID);
4036*8975f5c5SAndroid Build Coastguard Worker         if (!mImage->isYuvResolve() &&
4037*8975f5c5SAndroid Build Coastguard Worker             (getFormatSupportedCompressionRatesImpl(renderer, format, 0, nullptr) != 0))
4038*8975f5c5SAndroid Build Coastguard Worker         {
4039*8975f5c5SAndroid Build Coastguard Worker             mImage->getCompressionFixedRate(&compressionInfoVar, &compressionRates,
4040*8975f5c5SAndroid Build Coastguard Worker                                             mState.getSurfaceCompressionFixedRate());
4041*8975f5c5SAndroid Build Coastguard Worker             compressionInfo = &compressionInfoVar;
4042*8975f5c5SAndroid Build Coastguard Worker         }
4043*8975f5c5SAndroid Build Coastguard Worker     }
4044*8975f5c5SAndroid Build Coastguard Worker 
4045*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mImage->initExternal(
4046*8975f5c5SAndroid Build Coastguard Worker         contextVk, mState.getType(), vkExtent, intendedImageFormatID, actualImageFormatID, samples,
4047*8975f5c5SAndroid Build Coastguard Worker         mImageUsageFlags, mImageCreateFlags, vk::ImageLayout::Undefined, nullptr,
4048*8975f5c5SAndroid Build Coastguard Worker         gl::LevelIndex(firstLevel), levelCount, layerCount,
4049*8975f5c5SAndroid Build Coastguard Worker         contextVk->isRobustResourceInitEnabled(), mState.hasProtectedContent(),
4050*8975f5c5SAndroid Build Coastguard Worker         vk::ImageHelper::deriveConversionDesc(contextVk, actualImageFormatID,
4051*8975f5c5SAndroid Build Coastguard Worker                                               intendedImageFormatID),
4052*8975f5c5SAndroid Build Coastguard Worker         compressionInfo));
4053*8975f5c5SAndroid Build Coastguard Worker 
4054*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(updateTextureLabel(contextVk));
4055*8975f5c5SAndroid Build Coastguard Worker 
4056*8975f5c5SAndroid Build Coastguard Worker     // Update create flags with mImage's create flags
4057*8975f5c5SAndroid Build Coastguard Worker     mImageCreateFlags |= mImage->getCreateFlags();
4058*8975f5c5SAndroid Build Coastguard Worker     mRequiresMutableStorage = (mImageCreateFlags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) != 0;
4059*8975f5c5SAndroid Build Coastguard Worker 
4060*8975f5c5SAndroid Build Coastguard Worker     VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
4061*8975f5c5SAndroid Build Coastguard Worker     if (mState.hasProtectedContent())
4062*8975f5c5SAndroid Build Coastguard Worker     {
4063*8975f5c5SAndroid Build Coastguard Worker         flags |= VK_MEMORY_PROPERTY_PROTECTED_BIT;
4064*8975f5c5SAndroid Build Coastguard Worker     }
4065*8975f5c5SAndroid Build Coastguard Worker 
4066*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(contextVk->initImageAllocation(mImage, mState.hasProtectedContent(),
4067*8975f5c5SAndroid Build Coastguard Worker                                              renderer->getMemoryProperties(), flags,
4068*8975f5c5SAndroid Build Coastguard Worker                                              vk::MemoryAllocationType::TextureImage));
4069*8975f5c5SAndroid Build Coastguard Worker 
4070*8975f5c5SAndroid Build Coastguard Worker     const uint32_t viewLevelCount =
4071*8975f5c5SAndroid Build Coastguard Worker         mState.getImmutableFormat() ? getMipLevelCount(ImageMipLevels::EnabledLevels) : levelCount;
4072*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(initImageViews(contextVk, viewLevelCount));
4073*8975f5c5SAndroid Build Coastguard Worker 
4074*8975f5c5SAndroid Build Coastguard Worker     mCurrentBaseLevel = gl::LevelIndex(mState.getBaseLevel());
4075*8975f5c5SAndroid Build Coastguard Worker     mCurrentMaxLevel  = gl::LevelIndex(mState.getMaxLevel());
4076*8975f5c5SAndroid Build Coastguard Worker 
4077*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4078*8975f5c5SAndroid Build Coastguard Worker }
4079*8975f5c5SAndroid Build Coastguard Worker 
initImageViews(ContextVk * contextVk,uint32_t levelCount)4080*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::initImageViews(ContextVk *contextVk, uint32_t levelCount)
4081*8975f5c5SAndroid Build Coastguard Worker {
4082*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImage != nullptr && mImage->valid());
4083*8975f5c5SAndroid Build Coastguard Worker 
4084*8975f5c5SAndroid Build Coastguard Worker     gl::LevelIndex baseLevelGL =
4085*8975f5c5SAndroid Build Coastguard Worker         getNativeImageLevel(gl::LevelIndex(mState.getEffectiveBaseLevel()));
4086*8975f5c5SAndroid Build Coastguard Worker     vk::LevelIndex baseLevelVk = mImage->toVkLevel(baseLevelGL);
4087*8975f5c5SAndroid Build Coastguard Worker     uint32_t baseLayer         = getNativeImageLayer(0);
4088*8975f5c5SAndroid Build Coastguard Worker 
4089*8975f5c5SAndroid Build Coastguard Worker     const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc();
4090*8975f5c5SAndroid Build Coastguard Worker     const bool sized                   = baseLevelDesc.format.info->sized;
4091*8975f5c5SAndroid Build Coastguard Worker 
4092*8975f5c5SAndroid Build Coastguard Worker     const angle::Format &intendedFormat = mImage->getIntendedFormat();
4093*8975f5c5SAndroid Build Coastguard Worker     gl::SwizzleState formatSwizzle      = GetFormatSwizzle(intendedFormat, sized);
4094*8975f5c5SAndroid Build Coastguard Worker     gl::SwizzleState readSwizzle        = ApplySwizzle(formatSwizzle, mState.getSwizzleState());
4095*8975f5c5SAndroid Build Coastguard Worker 
4096*8975f5c5SAndroid Build Coastguard Worker     // Use this as a proxy for the SRGB override & skip decode settings.
4097*8975f5c5SAndroid Build Coastguard Worker     bool createExtraSRGBViews = mRequiresMutableStorage;
4098*8975f5c5SAndroid Build Coastguard Worker 
4099*8975f5c5SAndroid Build Coastguard Worker     const VkImageUsageFlags kDisallowedSwizzledUsage =
4100*8975f5c5SAndroid Build Coastguard Worker         VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
4101*8975f5c5SAndroid Build Coastguard Worker         VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
4102*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(getImageViews().initReadViews(contextVk, mState.getType(), *mImage, formatSwizzle,
4103*8975f5c5SAndroid Build Coastguard Worker                                             readSwizzle, baseLevelVk, levelCount, baseLayer,
4104*8975f5c5SAndroid Build Coastguard Worker                                             getImageViewLayerCount(), createExtraSRGBViews,
4105*8975f5c5SAndroid Build Coastguard Worker                                             getImage().getUsage() & ~kDisallowedSwizzledUsage));
4106*8975f5c5SAndroid Build Coastguard Worker 
4107*8975f5c5SAndroid Build Coastguard Worker     updateCachedImageViewSerials();
4108*8975f5c5SAndroid Build Coastguard Worker 
4109*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4110*8975f5c5SAndroid Build Coastguard Worker }
4111*8975f5c5SAndroid Build Coastguard Worker 
releaseImage(ContextVk * contextVk)4112*8975f5c5SAndroid Build Coastguard Worker void TextureVk::releaseImage(ContextVk *contextVk)
4113*8975f5c5SAndroid Build Coastguard Worker {
4114*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
4115*8975f5c5SAndroid Build Coastguard Worker 
4116*8975f5c5SAndroid Build Coastguard Worker     releaseImageViews(contextVk);
4117*8975f5c5SAndroid Build Coastguard Worker 
4118*8975f5c5SAndroid Build Coastguard Worker     if (mImage)
4119*8975f5c5SAndroid Build Coastguard Worker     {
4120*8975f5c5SAndroid Build Coastguard Worker         if (mOwnsImage)
4121*8975f5c5SAndroid Build Coastguard Worker         {
4122*8975f5c5SAndroid Build Coastguard Worker             mImage->releaseImageFromShareContexts(renderer, contextVk, mImageSiblingSerial);
4123*8975f5c5SAndroid Build Coastguard Worker         }
4124*8975f5c5SAndroid Build Coastguard Worker         else
4125*8975f5c5SAndroid Build Coastguard Worker         {
4126*8975f5c5SAndroid Build Coastguard Worker             mImage->finalizeImageLayoutInShareContexts(renderer, contextVk, mImageSiblingSerial);
4127*8975f5c5SAndroid Build Coastguard Worker             mImageObserverBinding.bind(nullptr);
4128*8975f5c5SAndroid Build Coastguard Worker             mImage = nullptr;
4129*8975f5c5SAndroid Build Coastguard Worker         }
4130*8975f5c5SAndroid Build Coastguard Worker     }
4131*8975f5c5SAndroid Build Coastguard Worker 
4132*8975f5c5SAndroid Build Coastguard Worker     if (mMultisampledImages)
4133*8975f5c5SAndroid Build Coastguard Worker     {
4134*8975f5c5SAndroid Build Coastguard Worker         for (gl::TexLevelArray<vk::ImageHelper> &images : *mMultisampledImages)
4135*8975f5c5SAndroid Build Coastguard Worker         {
4136*8975f5c5SAndroid Build Coastguard Worker             for (vk::ImageHelper &image : images)
4137*8975f5c5SAndroid Build Coastguard Worker             {
4138*8975f5c5SAndroid Build Coastguard Worker                 if (image.valid())
4139*8975f5c5SAndroid Build Coastguard Worker                 {
4140*8975f5c5SAndroid Build Coastguard Worker                     image.releaseImageFromShareContexts(renderer, contextVk, mImageSiblingSerial);
4141*8975f5c5SAndroid Build Coastguard Worker                 }
4142*8975f5c5SAndroid Build Coastguard Worker             }
4143*8975f5c5SAndroid Build Coastguard Worker         }
4144*8975f5c5SAndroid Build Coastguard Worker         mMultisampledImages.reset();
4145*8975f5c5SAndroid Build Coastguard Worker     }
4146*8975f5c5SAndroid Build Coastguard Worker 
4147*8975f5c5SAndroid Build Coastguard Worker     onStateChange(angle::SubjectMessage::SubjectChanged);
4148*8975f5c5SAndroid Build Coastguard Worker     mRedefinedLevels = {};
4149*8975f5c5SAndroid Build Coastguard Worker }
4150*8975f5c5SAndroid Build Coastguard Worker 
releaseImageViews(ContextVk * contextVk)4151*8975f5c5SAndroid Build Coastguard Worker void TextureVk::releaseImageViews(ContextVk *contextVk)
4152*8975f5c5SAndroid Build Coastguard Worker {
4153*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
4154*8975f5c5SAndroid Build Coastguard Worker 
4155*8975f5c5SAndroid Build Coastguard Worker     mDescriptorSetCacheManager.releaseKeys(renderer);
4156*8975f5c5SAndroid Build Coastguard Worker 
4157*8975f5c5SAndroid Build Coastguard Worker     if (mImage == nullptr)
4158*8975f5c5SAndroid Build Coastguard Worker     {
4159*8975f5c5SAndroid Build Coastguard Worker         if (mMultisampledImageViews)
4160*8975f5c5SAndroid Build Coastguard Worker         {
4161*8975f5c5SAndroid Build Coastguard Worker             for (gl::TexLevelArray<vk::ImageViewHelper> &imageViewHelpers :
4162*8975f5c5SAndroid Build Coastguard Worker                  *mMultisampledImageViews)
4163*8975f5c5SAndroid Build Coastguard Worker             {
4164*8975f5c5SAndroid Build Coastguard Worker                 for (vk::ImageViewHelper &imageViewHelper : imageViewHelpers)
4165*8975f5c5SAndroid Build Coastguard Worker                 {
4166*8975f5c5SAndroid Build Coastguard Worker                     ASSERT(imageViewHelper.isImageViewGarbageEmpty());
4167*8975f5c5SAndroid Build Coastguard Worker                 }
4168*8975f5c5SAndroid Build Coastguard Worker             }
4169*8975f5c5SAndroid Build Coastguard Worker             mMultisampledImageViews.reset();
4170*8975f5c5SAndroid Build Coastguard Worker         }
4171*8975f5c5SAndroid Build Coastguard Worker         for (auto &renderTargets : mSingleLayerRenderTargets)
4172*8975f5c5SAndroid Build Coastguard Worker         {
4173*8975f5c5SAndroid Build Coastguard Worker             ASSERT(renderTargets.empty());
4174*8975f5c5SAndroid Build Coastguard Worker         }
4175*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mMultiLayerRenderTargets.empty());
4176*8975f5c5SAndroid Build Coastguard Worker         return;
4177*8975f5c5SAndroid Build Coastguard Worker     }
4178*8975f5c5SAndroid Build Coastguard Worker 
4179*8975f5c5SAndroid Build Coastguard Worker     mImageView.release(renderer, mImage->getResourceUse());
4180*8975f5c5SAndroid Build Coastguard Worker 
4181*8975f5c5SAndroid Build Coastguard Worker     if (mMultisampledImageViews)
4182*8975f5c5SAndroid Build Coastguard Worker     {
4183*8975f5c5SAndroid Build Coastguard Worker         for (gl::TexLevelArray<vk::ImageViewHelper> &imageViewHelpers : *mMultisampledImageViews)
4184*8975f5c5SAndroid Build Coastguard Worker         {
4185*8975f5c5SAndroid Build Coastguard Worker             for (vk::ImageViewHelper &imageViewHelper : imageViewHelpers)
4186*8975f5c5SAndroid Build Coastguard Worker             {
4187*8975f5c5SAndroid Build Coastguard Worker                 imageViewHelper.release(renderer, mImage->getResourceUse());
4188*8975f5c5SAndroid Build Coastguard Worker             }
4189*8975f5c5SAndroid Build Coastguard Worker         }
4190*8975f5c5SAndroid Build Coastguard Worker         mMultisampledImageViews.reset();
4191*8975f5c5SAndroid Build Coastguard Worker     }
4192*8975f5c5SAndroid Build Coastguard Worker 
4193*8975f5c5SAndroid Build Coastguard Worker     for (auto &renderTargets : mSingleLayerRenderTargets)
4194*8975f5c5SAndroid Build Coastguard Worker     {
4195*8975f5c5SAndroid Build Coastguard Worker         for (RenderTargetVector &renderTargetLevels : renderTargets)
4196*8975f5c5SAndroid Build Coastguard Worker         {
4197*8975f5c5SAndroid Build Coastguard Worker             for (RenderTargetVk &renderTargetVk : renderTargetLevels)
4198*8975f5c5SAndroid Build Coastguard Worker             {
4199*8975f5c5SAndroid Build Coastguard Worker                 renderTargetVk.releaseFramebuffers(contextVk);
4200*8975f5c5SAndroid Build Coastguard Worker             }
4201*8975f5c5SAndroid Build Coastguard Worker             // Clear the layers tracked for each level
4202*8975f5c5SAndroid Build Coastguard Worker             renderTargetLevels.clear();
4203*8975f5c5SAndroid Build Coastguard Worker         }
4204*8975f5c5SAndroid Build Coastguard Worker         // Then clear the levels
4205*8975f5c5SAndroid Build Coastguard Worker         renderTargets.clear();
4206*8975f5c5SAndroid Build Coastguard Worker     }
4207*8975f5c5SAndroid Build Coastguard Worker 
4208*8975f5c5SAndroid Build Coastguard Worker     for (auto &renderTargetPair : mMultiLayerRenderTargets)
4209*8975f5c5SAndroid Build Coastguard Worker     {
4210*8975f5c5SAndroid Build Coastguard Worker         renderTargetPair.second->releaseFramebuffers(contextVk);
4211*8975f5c5SAndroid Build Coastguard Worker     }
4212*8975f5c5SAndroid Build Coastguard Worker     mMultiLayerRenderTargets.clear();
4213*8975f5c5SAndroid Build Coastguard Worker }
4214*8975f5c5SAndroid Build Coastguard Worker 
releaseStagedUpdates(ContextVk * contextVk)4215*8975f5c5SAndroid Build Coastguard Worker void TextureVk::releaseStagedUpdates(ContextVk *contextVk)
4216*8975f5c5SAndroid Build Coastguard Worker {
4217*8975f5c5SAndroid Build Coastguard Worker     if (mImage)
4218*8975f5c5SAndroid Build Coastguard Worker     {
4219*8975f5c5SAndroid Build Coastguard Worker         mImage->releaseStagedUpdates(contextVk->getRenderer());
4220*8975f5c5SAndroid Build Coastguard Worker     }
4221*8975f5c5SAndroid Build Coastguard Worker }
4222*8975f5c5SAndroid Build Coastguard Worker 
getMipLevelCount(ImageMipLevels mipLevels) const4223*8975f5c5SAndroid Build Coastguard Worker uint32_t TextureVk::getMipLevelCount(ImageMipLevels mipLevels) const
4224*8975f5c5SAndroid Build Coastguard Worker {
4225*8975f5c5SAndroid Build Coastguard Worker     switch (mipLevels)
4226*8975f5c5SAndroid Build Coastguard Worker     {
4227*8975f5c5SAndroid Build Coastguard Worker         // Returns level count from base to max that has been specified, i.e, enabled.
4228*8975f5c5SAndroid Build Coastguard Worker         case ImageMipLevels::EnabledLevels:
4229*8975f5c5SAndroid Build Coastguard Worker             return mState.getEnabledLevelCount();
4230*8975f5c5SAndroid Build Coastguard Worker         // Returns all mipmap levels from base to max regardless if an image has been specified or
4231*8975f5c5SAndroid Build Coastguard Worker         // not.
4232*8975f5c5SAndroid Build Coastguard Worker         case ImageMipLevels::FullMipChainForGenerateMipmap:
4233*8975f5c5SAndroid Build Coastguard Worker             return getMaxLevelCount() - mState.getEffectiveBaseLevel();
4234*8975f5c5SAndroid Build Coastguard Worker 
4235*8975f5c5SAndroid Build Coastguard Worker         default:
4236*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
4237*8975f5c5SAndroid Build Coastguard Worker             return 0;
4238*8975f5c5SAndroid Build Coastguard Worker     }
4239*8975f5c5SAndroid Build Coastguard Worker }
4240*8975f5c5SAndroid Build Coastguard Worker 
getMaxLevelCount() const4241*8975f5c5SAndroid Build Coastguard Worker uint32_t TextureVk::getMaxLevelCount() const
4242*8975f5c5SAndroid Build Coastguard Worker {
4243*8975f5c5SAndroid Build Coastguard Worker     // getMipmapMaxLevel will be 0 here if mipmaps are not used, so the levelCount is always +1.
4244*8975f5c5SAndroid Build Coastguard Worker     return mState.getMipmapMaxLevel() + 1;
4245*8975f5c5SAndroid Build Coastguard Worker }
4246*8975f5c5SAndroid Build Coastguard Worker 
generateMipmapLevelsWithCPU(ContextVk * contextVk,const angle::Format & sourceFormat,GLuint layer,gl::LevelIndex firstMipLevel,gl::LevelIndex maxMipLevel,const size_t sourceWidth,const size_t sourceHeight,const size_t sourceDepth,const size_t sourceRowPitch,const size_t sourceDepthPitch,uint8_t * sourceData)4247*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::generateMipmapLevelsWithCPU(ContextVk *contextVk,
4248*8975f5c5SAndroid Build Coastguard Worker                                                      const angle::Format &sourceFormat,
4249*8975f5c5SAndroid Build Coastguard Worker                                                      GLuint layer,
4250*8975f5c5SAndroid Build Coastguard Worker                                                      gl::LevelIndex firstMipLevel,
4251*8975f5c5SAndroid Build Coastguard Worker                                                      gl::LevelIndex maxMipLevel,
4252*8975f5c5SAndroid Build Coastguard Worker                                                      const size_t sourceWidth,
4253*8975f5c5SAndroid Build Coastguard Worker                                                      const size_t sourceHeight,
4254*8975f5c5SAndroid Build Coastguard Worker                                                      const size_t sourceDepth,
4255*8975f5c5SAndroid Build Coastguard Worker                                                      const size_t sourceRowPitch,
4256*8975f5c5SAndroid Build Coastguard Worker                                                      const size_t sourceDepthPitch,
4257*8975f5c5SAndroid Build Coastguard Worker                                                      uint8_t *sourceData)
4258*8975f5c5SAndroid Build Coastguard Worker {
4259*8975f5c5SAndroid Build Coastguard Worker     size_t previousLevelWidth      = sourceWidth;
4260*8975f5c5SAndroid Build Coastguard Worker     size_t previousLevelHeight     = sourceHeight;
4261*8975f5c5SAndroid Build Coastguard Worker     size_t previousLevelDepth      = sourceDepth;
4262*8975f5c5SAndroid Build Coastguard Worker     uint8_t *previousLevelData     = sourceData;
4263*8975f5c5SAndroid Build Coastguard Worker     size_t previousLevelRowPitch   = sourceRowPitch;
4264*8975f5c5SAndroid Build Coastguard Worker     size_t previousLevelDepthPitch = sourceDepthPitch;
4265*8975f5c5SAndroid Build Coastguard Worker 
4266*8975f5c5SAndroid Build Coastguard Worker     for (gl::LevelIndex currentMipLevel = firstMipLevel; currentMipLevel <= maxMipLevel;
4267*8975f5c5SAndroid Build Coastguard Worker          ++currentMipLevel)
4268*8975f5c5SAndroid Build Coastguard Worker     {
4269*8975f5c5SAndroid Build Coastguard Worker         // Compute next level width and height.
4270*8975f5c5SAndroid Build Coastguard Worker         size_t mipWidth  = std::max<size_t>(1, previousLevelWidth >> 1);
4271*8975f5c5SAndroid Build Coastguard Worker         size_t mipHeight = std::max<size_t>(1, previousLevelHeight >> 1);
4272*8975f5c5SAndroid Build Coastguard Worker         size_t mipDepth  = std::max<size_t>(1, previousLevelDepth >> 1);
4273*8975f5c5SAndroid Build Coastguard Worker 
4274*8975f5c5SAndroid Build Coastguard Worker         // With the width and height of the next mip, we can allocate the next buffer we need.
4275*8975f5c5SAndroid Build Coastguard Worker         uint8_t *destData     = nullptr;
4276*8975f5c5SAndroid Build Coastguard Worker         size_t destRowPitch   = mipWidth * sourceFormat.pixelBytes;
4277*8975f5c5SAndroid Build Coastguard Worker         size_t destDepthPitch = destRowPitch * mipHeight;
4278*8975f5c5SAndroid Build Coastguard Worker 
4279*8975f5c5SAndroid Build Coastguard Worker         size_t mipAllocationSize = destDepthPitch * mipDepth;
4280*8975f5c5SAndroid Build Coastguard Worker         gl::Extents mipLevelExtents(static_cast<int>(mipWidth), static_cast<int>(mipHeight),
4281*8975f5c5SAndroid Build Coastguard Worker                                     static_cast<int>(mipDepth));
4282*8975f5c5SAndroid Build Coastguard Worker 
4283*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mImage->stageSubresourceUpdateAndGetData(
4284*8975f5c5SAndroid Build Coastguard Worker             contextVk, mipAllocationSize,
4285*8975f5c5SAndroid Build Coastguard Worker             gl::ImageIndex::MakeFromType(mState.getType(), currentMipLevel.get(), layer),
4286*8975f5c5SAndroid Build Coastguard Worker             mipLevelExtents, gl::Offset(), &destData, sourceFormat.id));
4287*8975f5c5SAndroid Build Coastguard Worker 
4288*8975f5c5SAndroid Build Coastguard Worker         // Generate the mipmap into that new buffer
4289*8975f5c5SAndroid Build Coastguard Worker         sourceFormat.mipGenerationFunction(
4290*8975f5c5SAndroid Build Coastguard Worker             previousLevelWidth, previousLevelHeight, previousLevelDepth, previousLevelData,
4291*8975f5c5SAndroid Build Coastguard Worker             previousLevelRowPitch, previousLevelDepthPitch, destData, destRowPitch, destDepthPitch);
4292*8975f5c5SAndroid Build Coastguard Worker 
4293*8975f5c5SAndroid Build Coastguard Worker         // Swap for the next iteration
4294*8975f5c5SAndroid Build Coastguard Worker         previousLevelWidth      = mipWidth;
4295*8975f5c5SAndroid Build Coastguard Worker         previousLevelHeight     = mipHeight;
4296*8975f5c5SAndroid Build Coastguard Worker         previousLevelDepth      = mipDepth;
4297*8975f5c5SAndroid Build Coastguard Worker         previousLevelData       = destData;
4298*8975f5c5SAndroid Build Coastguard Worker         previousLevelRowPitch   = destRowPitch;
4299*8975f5c5SAndroid Build Coastguard Worker         previousLevelDepthPitch = destDepthPitch;
4300*8975f5c5SAndroid Build Coastguard Worker     }
4301*8975f5c5SAndroid Build Coastguard Worker 
4302*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4303*8975f5c5SAndroid Build Coastguard Worker }
4304*8975f5c5SAndroid Build Coastguard Worker 
getImplementationSizedFormat(const gl::Context * context) const4305*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &TextureVk::getImplementationSizedFormat(const gl::Context *context) const
4306*8975f5c5SAndroid Build Coastguard Worker {
4307*8975f5c5SAndroid Build Coastguard Worker     GLenum sizedFormat = GL_NONE;
4308*8975f5c5SAndroid Build Coastguard Worker 
4309*8975f5c5SAndroid Build Coastguard Worker     if (mImage && mImage->valid())
4310*8975f5c5SAndroid Build Coastguard Worker     {
4311*8975f5c5SAndroid Build Coastguard Worker         sizedFormat = mImage->getActualFormat().glInternalFormat;
4312*8975f5c5SAndroid Build Coastguard Worker     }
4313*8975f5c5SAndroid Build Coastguard Worker     else
4314*8975f5c5SAndroid Build Coastguard Worker     {
4315*8975f5c5SAndroid Build Coastguard Worker         ContextVk *contextVk     = vk::GetImpl(context);
4316*8975f5c5SAndroid Build Coastguard Worker         const vk::Format &format = getBaseLevelFormat(contextVk->getRenderer());
4317*8975f5c5SAndroid Build Coastguard Worker         sizedFormat = format.getActualImageFormat(getRequiredImageAccess()).glInternalFormat;
4318*8975f5c5SAndroid Build Coastguard Worker     }
4319*8975f5c5SAndroid Build Coastguard Worker 
4320*8975f5c5SAndroid Build Coastguard Worker     return gl::GetSizedInternalFormatInfo(sizedFormat);
4321*8975f5c5SAndroid Build Coastguard Worker }
4322*8975f5c5SAndroid Build Coastguard Worker 
getColorReadFormat(const gl::Context * context)4323*8975f5c5SAndroid Build Coastguard Worker GLenum TextureVk::getColorReadFormat(const gl::Context *context)
4324*8975f5c5SAndroid Build Coastguard Worker {
4325*8975f5c5SAndroid Build Coastguard Worker     const gl::InternalFormat &sizedFormat = getImplementationSizedFormat(context);
4326*8975f5c5SAndroid Build Coastguard Worker     return sizedFormat.format;
4327*8975f5c5SAndroid Build Coastguard Worker }
4328*8975f5c5SAndroid Build Coastguard Worker 
getColorReadType(const gl::Context * context)4329*8975f5c5SAndroid Build Coastguard Worker GLenum TextureVk::getColorReadType(const gl::Context *context)
4330*8975f5c5SAndroid Build Coastguard Worker {
4331*8975f5c5SAndroid Build Coastguard Worker     const gl::InternalFormat &sizedFormat = getImplementationSizedFormat(context);
4332*8975f5c5SAndroid Build Coastguard Worker     return sizedFormat.type;
4333*8975f5c5SAndroid Build Coastguard Worker }
4334*8975f5c5SAndroid Build Coastguard Worker 
getTexImage(const gl::Context * context,const gl::PixelPackState & packState,gl::Buffer * packBuffer,gl::TextureTarget target,GLint level,GLenum format,GLenum type,void * pixels)4335*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::getTexImage(const gl::Context *context,
4336*8975f5c5SAndroid Build Coastguard Worker                                      const gl::PixelPackState &packState,
4337*8975f5c5SAndroid Build Coastguard Worker                                      gl::Buffer *packBuffer,
4338*8975f5c5SAndroid Build Coastguard Worker                                      gl::TextureTarget target,
4339*8975f5c5SAndroid Build Coastguard Worker                                      GLint level,
4340*8975f5c5SAndroid Build Coastguard Worker                                      GLenum format,
4341*8975f5c5SAndroid Build Coastguard Worker                                      GLenum type,
4342*8975f5c5SAndroid Build Coastguard Worker                                      void *pixels)
4343*8975f5c5SAndroid Build Coastguard Worker {
4344*8975f5c5SAndroid Build Coastguard Worker     if (packBuffer && this->isCompressedFormatEmulated(context, target, level))
4345*8975f5c5SAndroid Build Coastguard Worker     {
4346*8975f5c5SAndroid Build Coastguard Worker         // TODO (anglebug.com/42265933): Can't populate from a buffer using emulated format
4347*8975f5c5SAndroid Build Coastguard Worker         UNIMPLEMENTED();
4348*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Stop;
4349*8975f5c5SAndroid Build Coastguard Worker     }
4350*8975f5c5SAndroid Build Coastguard Worker 
4351*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
4352*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
4353*8975f5c5SAndroid Build Coastguard Worker 
4354*8975f5c5SAndroid Build Coastguard Worker     GLint baseLevel = static_cast<int>(mState.getBaseLevel());
4355*8975f5c5SAndroid Build Coastguard Worker     if (level < baseLevel || level >= baseLevel + static_cast<int>(mState.getEnabledLevelCount()))
4356*8975f5c5SAndroid Build Coastguard Worker     {
4357*8975f5c5SAndroid Build Coastguard Worker         // TODO(http://anglebug.com/42264855): Handle inconsistent textures.
4358*8975f5c5SAndroid Build Coastguard Worker         WARN() << "GetTexImage for inconsistent texture levels is not implemented.";
4359*8975f5c5SAndroid Build Coastguard Worker         UNIMPLEMENTED();
4360*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
4361*8975f5c5SAndroid Build Coastguard Worker     }
4362*8975f5c5SAndroid Build Coastguard Worker 
4363*8975f5c5SAndroid Build Coastguard Worker     gl::MaybeOverrideLuminance(format, type, getColorReadFormat(context),
4364*8975f5c5SAndroid Build Coastguard Worker                                getColorReadType(context));
4365*8975f5c5SAndroid Build Coastguard Worker 
4366*8975f5c5SAndroid Build Coastguard Worker     uint32_t layer      = 0;
4367*8975f5c5SAndroid Build Coastguard Worker     uint32_t layerCount = 1;
4368*8975f5c5SAndroid Build Coastguard Worker 
4369*8975f5c5SAndroid Build Coastguard Worker     switch (target)
4370*8975f5c5SAndroid Build Coastguard Worker     {
4371*8975f5c5SAndroid Build Coastguard Worker         case gl::TextureTarget::CubeMapArray:
4372*8975f5c5SAndroid Build Coastguard Worker         case gl::TextureTarget::_2DArray:
4373*8975f5c5SAndroid Build Coastguard Worker             layerCount = mImage->getLayerCount();
4374*8975f5c5SAndroid Build Coastguard Worker             break;
4375*8975f5c5SAndroid Build Coastguard Worker         default:
4376*8975f5c5SAndroid Build Coastguard Worker             if (gl::IsCubeMapFaceTarget(target))
4377*8975f5c5SAndroid Build Coastguard Worker             {
4378*8975f5c5SAndroid Build Coastguard Worker                 layer = static_cast<uint32_t>(gl::CubeMapTextureTargetToFaceIndex(target));
4379*8975f5c5SAndroid Build Coastguard Worker             }
4380*8975f5c5SAndroid Build Coastguard Worker             break;
4381*8975f5c5SAndroid Build Coastguard Worker     }
4382*8975f5c5SAndroid Build Coastguard Worker 
4383*8975f5c5SAndroid Build Coastguard Worker     return mImage->readPixelsForGetImage(contextVk, packState, packBuffer, gl::LevelIndex(level),
4384*8975f5c5SAndroid Build Coastguard Worker                                          layer, layerCount, format, type, pixels);
4385*8975f5c5SAndroid Build Coastguard Worker }
4386*8975f5c5SAndroid Build Coastguard Worker 
getCompressedTexImage(const gl::Context * context,const gl::PixelPackState & packState,gl::Buffer * packBuffer,gl::TextureTarget target,GLint level,void * pixels)4387*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::getCompressedTexImage(const gl::Context *context,
4388*8975f5c5SAndroid Build Coastguard Worker                                                const gl::PixelPackState &packState,
4389*8975f5c5SAndroid Build Coastguard Worker                                                gl::Buffer *packBuffer,
4390*8975f5c5SAndroid Build Coastguard Worker                                                gl::TextureTarget target,
4391*8975f5c5SAndroid Build Coastguard Worker                                                GLint level,
4392*8975f5c5SAndroid Build Coastguard Worker                                                void *pixels)
4393*8975f5c5SAndroid Build Coastguard Worker {
4394*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
4395*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
4396*8975f5c5SAndroid Build Coastguard Worker 
4397*8975f5c5SAndroid Build Coastguard Worker     GLint baseLevel = static_cast<int>(mState.getBaseLevel());
4398*8975f5c5SAndroid Build Coastguard Worker     if (level < baseLevel || level >= baseLevel + static_cast<int>(mState.getEnabledLevelCount()))
4399*8975f5c5SAndroid Build Coastguard Worker     {
4400*8975f5c5SAndroid Build Coastguard Worker         // TODO(http://anglebug.com/42264855): Handle inconsistent textures.
4401*8975f5c5SAndroid Build Coastguard Worker         WARN() << "GetCompressedTexImage for inconsistent texture levels is not implemented.";
4402*8975f5c5SAndroid Build Coastguard Worker         UNIMPLEMENTED();
4403*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
4404*8975f5c5SAndroid Build Coastguard Worker     }
4405*8975f5c5SAndroid Build Coastguard Worker 
4406*8975f5c5SAndroid Build Coastguard Worker     uint32_t layer      = 0;
4407*8975f5c5SAndroid Build Coastguard Worker     uint32_t layerCount = 1;
4408*8975f5c5SAndroid Build Coastguard Worker 
4409*8975f5c5SAndroid Build Coastguard Worker     switch (target)
4410*8975f5c5SAndroid Build Coastguard Worker     {
4411*8975f5c5SAndroid Build Coastguard Worker         case gl::TextureTarget::CubeMapArray:
4412*8975f5c5SAndroid Build Coastguard Worker         case gl::TextureTarget::_2DArray:
4413*8975f5c5SAndroid Build Coastguard Worker             layerCount = mImage->getLayerCount();
4414*8975f5c5SAndroid Build Coastguard Worker             break;
4415*8975f5c5SAndroid Build Coastguard Worker         default:
4416*8975f5c5SAndroid Build Coastguard Worker             if (gl::IsCubeMapFaceTarget(target))
4417*8975f5c5SAndroid Build Coastguard Worker             {
4418*8975f5c5SAndroid Build Coastguard Worker                 layer = static_cast<uint32_t>(gl::CubeMapTextureTargetToFaceIndex(target));
4419*8975f5c5SAndroid Build Coastguard Worker             }
4420*8975f5c5SAndroid Build Coastguard Worker             break;
4421*8975f5c5SAndroid Build Coastguard Worker     }
4422*8975f5c5SAndroid Build Coastguard Worker 
4423*8975f5c5SAndroid Build Coastguard Worker     return mImage->readPixelsForCompressedGetImage(
4424*8975f5c5SAndroid Build Coastguard Worker         contextVk, packState, packBuffer, gl::LevelIndex(level), layer, layerCount, pixels);
4425*8975f5c5SAndroid Build Coastguard Worker }
4426*8975f5c5SAndroid Build Coastguard Worker 
getBaseLevelFormat(vk::Renderer * renderer) const4427*8975f5c5SAndroid Build Coastguard Worker const vk::Format &TextureVk::getBaseLevelFormat(vk::Renderer *renderer) const
4428*8975f5c5SAndroid Build Coastguard Worker {
4429*8975f5c5SAndroid Build Coastguard Worker     const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc();
4430*8975f5c5SAndroid Build Coastguard Worker     return renderer->getFormat(baseLevelDesc.format.info->sizedInternalFormat);
4431*8975f5c5SAndroid Build Coastguard Worker }
4432*8975f5c5SAndroid Build Coastguard Worker 
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)4433*8975f5c5SAndroid Build Coastguard Worker void TextureVk::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
4434*8975f5c5SAndroid Build Coastguard Worker {
4435*8975f5c5SAndroid Build Coastguard Worker     ASSERT(index == kTextureImageSubjectIndex &&
4436*8975f5c5SAndroid Build Coastguard Worker            (message == angle::SubjectMessage::SubjectChanged ||
4437*8975f5c5SAndroid Build Coastguard Worker             message == angle::SubjectMessage::InitializationComplete));
4438*8975f5c5SAndroid Build Coastguard Worker 
4439*8975f5c5SAndroid Build Coastguard Worker     // Forward the notification to the parent that the staging buffer changed.
4440*8975f5c5SAndroid Build Coastguard Worker     onStateChange(message);
4441*8975f5c5SAndroid Build Coastguard Worker }
4442*8975f5c5SAndroid Build Coastguard Worker 
getImageViewSubresourceSerialImpl(vk::ImageViewColorspace colorspace) const4443*8975f5c5SAndroid Build Coastguard Worker vk::ImageOrBufferViewSubresourceSerial TextureVk::getImageViewSubresourceSerialImpl(
4444*8975f5c5SAndroid Build Coastguard Worker     vk::ImageViewColorspace colorspace) const
4445*8975f5c5SAndroid Build Coastguard Worker {
4446*8975f5c5SAndroid Build Coastguard Worker     gl::LevelIndex baseLevel(mState.getEffectiveBaseLevel());
4447*8975f5c5SAndroid Build Coastguard Worker     // getMipmapMaxLevel will clamp to the max level if it is smaller than the number of mips.
4448*8975f5c5SAndroid Build Coastguard Worker     uint32_t levelCount = gl::LevelIndex(mState.getMipmapMaxLevel()) - baseLevel + 1;
4449*8975f5c5SAndroid Build Coastguard Worker 
4450*8975f5c5SAndroid Build Coastguard Worker     return getImageViews().getSubresourceSerialForColorspace(baseLevel, levelCount, 0,
4451*8975f5c5SAndroid Build Coastguard Worker                                                              vk::LayerMode::All, colorspace);
4452*8975f5c5SAndroid Build Coastguard Worker }
4453*8975f5c5SAndroid Build Coastguard Worker 
getBufferViewSerial() const4454*8975f5c5SAndroid Build Coastguard Worker vk::ImageOrBufferViewSubresourceSerial TextureVk::getBufferViewSerial() const
4455*8975f5c5SAndroid Build Coastguard Worker {
4456*8975f5c5SAndroid Build Coastguard Worker     return mBufferViews.getSerial();
4457*8975f5c5SAndroid Build Coastguard Worker }
4458*8975f5c5SAndroid Build Coastguard Worker 
getStorageImageViewSerial(const gl::ImageUnit & binding) const4459*8975f5c5SAndroid Build Coastguard Worker vk::ImageOrBufferViewSubresourceSerial TextureVk::getStorageImageViewSerial(
4460*8975f5c5SAndroid Build Coastguard Worker     const gl::ImageUnit &binding) const
4461*8975f5c5SAndroid Build Coastguard Worker {
4462*8975f5c5SAndroid Build Coastguard Worker     vk::LayerMode layerMode = binding.layered == GL_TRUE ? vk::LayerMode::All : vk::LayerMode::_1;
4463*8975f5c5SAndroid Build Coastguard Worker     uint32_t frontendLayer  = binding.layered == GL_TRUE ? 0 : static_cast<uint32_t>(binding.layer);
4464*8975f5c5SAndroid Build Coastguard Worker     uint32_t nativeLayer    = getNativeImageLayer(frontendLayer);
4465*8975f5c5SAndroid Build Coastguard Worker 
4466*8975f5c5SAndroid Build Coastguard Worker     gl::LevelIndex baseLevel(
4467*8975f5c5SAndroid Build Coastguard Worker         getNativeImageLevel(gl::LevelIndex(static_cast<uint32_t>(binding.level))));
4468*8975f5c5SAndroid Build Coastguard Worker 
4469*8975f5c5SAndroid Build Coastguard Worker     return getImageViews().getSubresourceSerial(baseLevel, 1, nativeLayer, layerMode);
4470*8975f5c5SAndroid Build Coastguard Worker }
4471*8975f5c5SAndroid Build Coastguard Worker 
getImageViewLayerCount() const4472*8975f5c5SAndroid Build Coastguard Worker uint32_t TextureVk::getImageViewLayerCount() const
4473*8975f5c5SAndroid Build Coastguard Worker {
4474*8975f5c5SAndroid Build Coastguard Worker     // We use a special layer count here to handle EGLImages. They might only be
4475*8975f5c5SAndroid Build Coastguard Worker     // looking at one layer of a cube or 2D array texture.
4476*8975f5c5SAndroid Build Coastguard Worker     return mEGLImageNativeType == gl::TextureType::InvalidEnum ? mImage->getLayerCount() : 1;
4477*8975f5c5SAndroid Build Coastguard Worker }
4478*8975f5c5SAndroid Build Coastguard Worker 
getImageViewLevelCount() const4479*8975f5c5SAndroid Build Coastguard Worker uint32_t TextureVk::getImageViewLevelCount() const
4480*8975f5c5SAndroid Build Coastguard Worker {
4481*8975f5c5SAndroid Build Coastguard Worker     // We use a special level count here to handle EGLImages. They might only be
4482*8975f5c5SAndroid Build Coastguard Worker     // looking at one level of the texture's mipmap chain.
4483*8975f5c5SAndroid Build Coastguard Worker     return mEGLImageNativeType == gl::TextureType::InvalidEnum ? mImage->getLevelCount() : 1;
4484*8975f5c5SAndroid Build Coastguard Worker }
4485*8975f5c5SAndroid Build Coastguard Worker 
refreshImageViews(ContextVk * contextVk)4486*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::refreshImageViews(ContextVk *contextVk)
4487*8975f5c5SAndroid Build Coastguard Worker {
4488*8975f5c5SAndroid Build Coastguard Worker     vk::ImageViewHelper &imageView = getImageViews();
4489*8975f5c5SAndroid Build Coastguard Worker     if (mImage == nullptr)
4490*8975f5c5SAndroid Build Coastguard Worker     {
4491*8975f5c5SAndroid Build Coastguard Worker         ASSERT(imageView.isImageViewGarbageEmpty());
4492*8975f5c5SAndroid Build Coastguard Worker     }
4493*8975f5c5SAndroid Build Coastguard Worker     else
4494*8975f5c5SAndroid Build Coastguard Worker     {
4495*8975f5c5SAndroid Build Coastguard Worker         vk::Renderer *renderer = contextVk->getRenderer();
4496*8975f5c5SAndroid Build Coastguard Worker         imageView.release(renderer, mImage->getResourceUse());
4497*8975f5c5SAndroid Build Coastguard Worker 
4498*8975f5c5SAndroid Build Coastguard Worker         // Since view has changed, some descriptorSet cache maybe obsolete. SO proactively release
4499*8975f5c5SAndroid Build Coastguard Worker         // cache.
4500*8975f5c5SAndroid Build Coastguard Worker         mDescriptorSetCacheManager.releaseKeys(renderer);
4501*8975f5c5SAndroid Build Coastguard Worker 
4502*8975f5c5SAndroid Build Coastguard Worker         for (auto &renderTargets : mSingleLayerRenderTargets)
4503*8975f5c5SAndroid Build Coastguard Worker         {
4504*8975f5c5SAndroid Build Coastguard Worker             for (RenderTargetVector &renderTargetLevels : renderTargets)
4505*8975f5c5SAndroid Build Coastguard Worker             {
4506*8975f5c5SAndroid Build Coastguard Worker                 for (RenderTargetVk &renderTargetVk : renderTargetLevels)
4507*8975f5c5SAndroid Build Coastguard Worker                 {
4508*8975f5c5SAndroid Build Coastguard Worker                     renderTargetVk.releaseFramebuffers(contextVk);
4509*8975f5c5SAndroid Build Coastguard Worker                 }
4510*8975f5c5SAndroid Build Coastguard Worker             }
4511*8975f5c5SAndroid Build Coastguard Worker         }
4512*8975f5c5SAndroid Build Coastguard Worker         for (auto &renderTargetPair : mMultiLayerRenderTargets)
4513*8975f5c5SAndroid Build Coastguard Worker         {
4514*8975f5c5SAndroid Build Coastguard Worker             renderTargetPair.second->releaseFramebuffers(contextVk);
4515*8975f5c5SAndroid Build Coastguard Worker         }
4516*8975f5c5SAndroid Build Coastguard Worker     }
4517*8975f5c5SAndroid Build Coastguard Worker 
4518*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(initImageViews(contextVk, getImageViewLevelCount()));
4519*8975f5c5SAndroid Build Coastguard Worker 
4520*8975f5c5SAndroid Build Coastguard Worker     // Let any Framebuffers know we need to refresh the RenderTarget cache.
4521*8975f5c5SAndroid Build Coastguard Worker     onStateChange(angle::SubjectMessage::SubjectChanged);
4522*8975f5c5SAndroid Build Coastguard Worker 
4523*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4524*8975f5c5SAndroid Build Coastguard Worker }
4525*8975f5c5SAndroid Build Coastguard Worker 
ensureMutable(ContextVk * contextVk)4526*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::ensureMutable(ContextVk *contextVk)
4527*8975f5c5SAndroid Build Coastguard Worker {
4528*8975f5c5SAndroid Build Coastguard Worker     if (mRequiresMutableStorage)
4529*8975f5c5SAndroid Build Coastguard Worker     {
4530*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
4531*8975f5c5SAndroid Build Coastguard Worker     }
4532*8975f5c5SAndroid Build Coastguard Worker 
4533*8975f5c5SAndroid Build Coastguard Worker     mRequiresMutableStorage = true;
4534*8975f5c5SAndroid Build Coastguard Worker     mImageCreateFlags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
4535*8975f5c5SAndroid Build Coastguard Worker 
4536*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(respecifyImageStorage(contextVk));
4537*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
4538*8975f5c5SAndroid Build Coastguard Worker 
4539*8975f5c5SAndroid Build Coastguard Worker     return refreshImageViews(contextVk);
4540*8975f5c5SAndroid Build Coastguard Worker }
4541*8975f5c5SAndroid Build Coastguard Worker 
ensureRenderable(ContextVk * contextVk,TextureUpdateResult * updateResultOut)4542*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::ensureRenderable(ContextVk *contextVk,
4543*8975f5c5SAndroid Build Coastguard Worker                                           TextureUpdateResult *updateResultOut)
4544*8975f5c5SAndroid Build Coastguard Worker {
4545*8975f5c5SAndroid Build Coastguard Worker     return ensureRenderableWithFormat(contextVk, getBaseLevelFormat(contextVk->getRenderer()),
4546*8975f5c5SAndroid Build Coastguard Worker                                       updateResultOut);
4547*8975f5c5SAndroid Build Coastguard Worker }
4548*8975f5c5SAndroid Build Coastguard Worker 
ensureRenderableWithFormat(ContextVk * contextVk,const vk::Format & format,TextureUpdateResult * updateResultOut)4549*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::ensureRenderableWithFormat(ContextVk *contextVk,
4550*8975f5c5SAndroid Build Coastguard Worker                                                     const vk::Format &format,
4551*8975f5c5SAndroid Build Coastguard Worker                                                     TextureUpdateResult *updateResultOut)
4552*8975f5c5SAndroid Build Coastguard Worker {
4553*8975f5c5SAndroid Build Coastguard Worker     if (mRequiredImageAccess == vk::ImageAccess::Renderable)
4554*8975f5c5SAndroid Build Coastguard Worker     {
4555*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
4556*8975f5c5SAndroid Build Coastguard Worker     }
4557*8975f5c5SAndroid Build Coastguard Worker 
4558*8975f5c5SAndroid Build Coastguard Worker     mRequiredImageAccess = vk::ImageAccess::Renderable;
4559*8975f5c5SAndroid Build Coastguard Worker     if (!mImage)
4560*8975f5c5SAndroid Build Coastguard Worker     {
4561*8975f5c5SAndroid Build Coastguard Worker         // Later on when ensureImageAllocated() is called, it will ensure a renderable format is
4562*8975f5c5SAndroid Build Coastguard Worker         // used.
4563*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
4564*8975f5c5SAndroid Build Coastguard Worker     }
4565*8975f5c5SAndroid Build Coastguard Worker 
4566*8975f5c5SAndroid Build Coastguard Worker     if (!format.hasRenderableImageFallbackFormat())
4567*8975f5c5SAndroid Build Coastguard Worker     {
4568*8975f5c5SAndroid Build Coastguard Worker         // If there is no fallback format for renderable, then nothing to do.
4569*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
4570*8975f5c5SAndroid Build Coastguard Worker     }
4571*8975f5c5SAndroid Build Coastguard Worker 
4572*8975f5c5SAndroid Build Coastguard Worker     // luminance/alpha format never fallback for rendering and if we ever do fallback, the
4573*8975f5c5SAndroid Build Coastguard Worker     // following code may not handle it properly.
4574*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!format.getIntendedFormat().isLUMA());
4575*8975f5c5SAndroid Build Coastguard Worker 
4576*8975f5c5SAndroid Build Coastguard Worker     angle::FormatID previousActualFormatID =
4577*8975f5c5SAndroid Build Coastguard Worker         format.getActualImageFormatID(vk::ImageAccess::SampleOnly);
4578*8975f5c5SAndroid Build Coastguard Worker     angle::FormatID actualFormatID = format.getActualImageFormatID(vk::ImageAccess::Renderable);
4579*8975f5c5SAndroid Build Coastguard Worker 
4580*8975f5c5SAndroid Build Coastguard Worker     if (!mImage->valid())
4581*8975f5c5SAndroid Build Coastguard Worker     {
4582*8975f5c5SAndroid Build Coastguard Worker         // Immutable texture must already have a valid image
4583*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!mState.getImmutableFormat());
4584*8975f5c5SAndroid Build Coastguard Worker         // If we have staged updates and they were encoded with different format, we need to flush
4585*8975f5c5SAndroid Build Coastguard Worker         // out these staged updates. The respecifyImageStorage should handle reading back the
4586*8975f5c5SAndroid Build Coastguard Worker         // flushed data and re-stage it with the new format.
4587*8975f5c5SAndroid Build Coastguard Worker         angle::FormatID intendedFormatID = format.getIntendedFormatID();
4588*8975f5c5SAndroid Build Coastguard Worker 
4589*8975f5c5SAndroid Build Coastguard Worker         gl::LevelIndex levelGLStart, levelGLEnd;
4590*8975f5c5SAndroid Build Coastguard Worker         ImageMipLevels mipLevels;
4591*8975f5c5SAndroid Build Coastguard Worker         if (mState.getImmutableFormat())
4592*8975f5c5SAndroid Build Coastguard Worker         {
4593*8975f5c5SAndroid Build Coastguard Worker             levelGLStart = gl::LevelIndex(0);
4594*8975f5c5SAndroid Build Coastguard Worker             levelGLEnd   = gl::LevelIndex(mState.getImmutableLevels());
4595*8975f5c5SAndroid Build Coastguard Worker             mipLevels    = ImageMipLevels::FullMipChainForGenerateMipmap;
4596*8975f5c5SAndroid Build Coastguard Worker         }
4597*8975f5c5SAndroid Build Coastguard Worker         else
4598*8975f5c5SAndroid Build Coastguard Worker         {
4599*8975f5c5SAndroid Build Coastguard Worker             levelGLStart = gl::LevelIndex(mState.getEffectiveBaseLevel());
4600*8975f5c5SAndroid Build Coastguard Worker             levelGLEnd =
4601*8975f5c5SAndroid Build Coastguard Worker                 gl::LevelIndex(levelGLStart + getMipLevelCount(ImageMipLevels::EnabledLevels));
4602*8975f5c5SAndroid Build Coastguard Worker             mipLevels = ImageMipLevels::EnabledLevels;
4603*8975f5c5SAndroid Build Coastguard Worker         }
4604*8975f5c5SAndroid Build Coastguard Worker 
4605*8975f5c5SAndroid Build Coastguard Worker         if (mImage->hasStagedImageUpdatesWithMismatchedFormat(levelGLStart, levelGLEnd,
4606*8975f5c5SAndroid Build Coastguard Worker                                                               actualFormatID))
4607*8975f5c5SAndroid Build Coastguard Worker         {
4608*8975f5c5SAndroid Build Coastguard Worker             angle::FormatID sampleOnlyFormatID =
4609*8975f5c5SAndroid Build Coastguard Worker                 format.getActualImageFormatID(vk::ImageAccess::SampleOnly);
4610*8975f5c5SAndroid Build Coastguard Worker 
4611*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(initImage(contextVk, intendedFormatID, sampleOnlyFormatID, mipLevels));
4612*8975f5c5SAndroid Build Coastguard Worker         }
4613*8975f5c5SAndroid Build Coastguard Worker         else
4614*8975f5c5SAndroid Build Coastguard Worker         {
4615*8975f5c5SAndroid Build Coastguard Worker             // First try to convert any staged buffer updates from old format to new format using
4616*8975f5c5SAndroid Build Coastguard Worker             // CPU.
4617*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(mImage->reformatStagedBufferUpdates(contextVk, previousActualFormatID,
4618*8975f5c5SAndroid Build Coastguard Worker                                                           actualFormatID));
4619*8975f5c5SAndroid Build Coastguard Worker         }
4620*8975f5c5SAndroid Build Coastguard Worker     }
4621*8975f5c5SAndroid Build Coastguard Worker 
4622*8975f5c5SAndroid Build Coastguard Worker     // Make sure we update mImageUsage bits
4623*8975f5c5SAndroid Build Coastguard Worker     const bool imageWasInitialized = mImage->valid();
4624*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensureImageAllocated(contextVk, format));
4625*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(respecifyImageStorage(contextVk));
4626*8975f5c5SAndroid Build Coastguard Worker     if (imageWasInitialized)
4627*8975f5c5SAndroid Build Coastguard Worker     {
4628*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
4629*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(refreshImageViews(contextVk));
4630*8975f5c5SAndroid Build Coastguard Worker     }
4631*8975f5c5SAndroid Build Coastguard Worker 
4632*8975f5c5SAndroid Build Coastguard Worker     if (updateResultOut != nullptr)
4633*8975f5c5SAndroid Build Coastguard Worker     {
4634*8975f5c5SAndroid Build Coastguard Worker         *updateResultOut = TextureUpdateResult::ImageRespecified;
4635*8975f5c5SAndroid Build Coastguard Worker     }
4636*8975f5c5SAndroid Build Coastguard Worker 
4637*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4638*8975f5c5SAndroid Build Coastguard Worker }
4639*8975f5c5SAndroid Build Coastguard Worker 
ensureRenderableIfCopyTextureCannotTransfer(ContextVk * contextVk,const gl::InternalFormat & dstFormat,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,TextureVk * source)4640*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::ensureRenderableIfCopyTextureCannotTransfer(
4641*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk,
4642*8975f5c5SAndroid Build Coastguard Worker     const gl::InternalFormat &dstFormat,
4643*8975f5c5SAndroid Build Coastguard Worker     bool unpackFlipY,
4644*8975f5c5SAndroid Build Coastguard Worker     bool unpackPremultiplyAlpha,
4645*8975f5c5SAndroid Build Coastguard Worker     bool unpackUnmultiplyAlpha,
4646*8975f5c5SAndroid Build Coastguard Worker     TextureVk *source)
4647*8975f5c5SAndroid Build Coastguard Worker {
4648*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
4649*8975f5c5SAndroid Build Coastguard Worker 
4650*8975f5c5SAndroid Build Coastguard Worker     VkImageTiling srcTilingMode   = source->getImage().getTilingMode();
4651*8975f5c5SAndroid Build Coastguard Worker     const vk::Format &dstVkFormat = renderer->getFormat(dstFormat.sizedInternalFormat);
4652*8975f5c5SAndroid Build Coastguard Worker     angle::FormatID dstFormatID   = dstVkFormat.getActualImageFormatID(getRequiredImageAccess());
4653*8975f5c5SAndroid Build Coastguard Worker     VkImageTiling dstTilingMode   = getTilingMode();
4654*8975f5c5SAndroid Build Coastguard Worker 
4655*8975f5c5SAndroid Build Coastguard Worker     if (!CanCopyWithTransferForCopyTexture(
4656*8975f5c5SAndroid Build Coastguard Worker             renderer, source->getImage(), srcTilingMode, dstVkFormat.getIntendedFormatID(),
4657*8975f5c5SAndroid Build Coastguard Worker             dstFormatID, dstTilingMode, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha))
4658*8975f5c5SAndroid Build Coastguard Worker     {
4659*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(ensureRenderableWithFormat(contextVk, dstVkFormat, nullptr));
4660*8975f5c5SAndroid Build Coastguard Worker     }
4661*8975f5c5SAndroid Build Coastguard Worker 
4662*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4663*8975f5c5SAndroid Build Coastguard Worker }
4664*8975f5c5SAndroid Build Coastguard Worker 
ensureRenderableIfCopyTexImageCannotTransfer(ContextVk * contextVk,const gl::InternalFormat & dstFormat,gl::Framebuffer * source)4665*8975f5c5SAndroid Build Coastguard Worker angle::Result TextureVk::ensureRenderableIfCopyTexImageCannotTransfer(
4666*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk,
4667*8975f5c5SAndroid Build Coastguard Worker     const gl::InternalFormat &dstFormat,
4668*8975f5c5SAndroid Build Coastguard Worker     gl::Framebuffer *source)
4669*8975f5c5SAndroid Build Coastguard Worker {
4670*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer       = contextVk->getRenderer();
4671*8975f5c5SAndroid Build Coastguard Worker     FramebufferVk *framebufferVk = vk::GetImpl(source);
4672*8975f5c5SAndroid Build Coastguard Worker 
4673*8975f5c5SAndroid Build Coastguard Worker     RenderTargetVk *colorReadRT = framebufferVk->getColorReadRenderTarget();
4674*8975f5c5SAndroid Build Coastguard Worker 
4675*8975f5c5SAndroid Build Coastguard Worker     angle::FormatID srcIntendedFormatID = colorReadRT->getImageIntendedFormatID();
4676*8975f5c5SAndroid Build Coastguard Worker     angle::FormatID srcActualFormatID   = colorReadRT->getImageActualFormatID();
4677*8975f5c5SAndroid Build Coastguard Worker     VkImageTiling srcTilingMode         = colorReadRT->getImageForCopy().getTilingMode();
4678*8975f5c5SAndroid Build Coastguard Worker     const vk::Format &dstVkFormat       = renderer->getFormat(dstFormat.sizedInternalFormat);
4679*8975f5c5SAndroid Build Coastguard Worker     angle::FormatID dstIntendedFormatID = dstVkFormat.getIntendedFormatID();
4680*8975f5c5SAndroid Build Coastguard Worker     angle::FormatID dstActualFormatID =
4681*8975f5c5SAndroid Build Coastguard Worker         dstVkFormat.getActualImageFormatID(getRequiredImageAccess());
4682*8975f5c5SAndroid Build Coastguard Worker     VkImageTiling destTilingMode = getTilingMode();
4683*8975f5c5SAndroid Build Coastguard Worker 
4684*8975f5c5SAndroid Build Coastguard Worker     bool isViewportFlipY = contextVk->isViewportFlipEnabledForReadFBO();
4685*8975f5c5SAndroid Build Coastguard Worker 
4686*8975f5c5SAndroid Build Coastguard Worker     if (!CanCopyWithTransferForTexImage(renderer, srcIntendedFormatID, srcActualFormatID,
4687*8975f5c5SAndroid Build Coastguard Worker                                         srcTilingMode, dstIntendedFormatID, dstActualFormatID,
4688*8975f5c5SAndroid Build Coastguard Worker                                         destTilingMode, isViewportFlipY))
4689*8975f5c5SAndroid Build Coastguard Worker     {
4690*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(ensureRenderableWithFormat(contextVk, dstVkFormat, nullptr));
4691*8975f5c5SAndroid Build Coastguard Worker     }
4692*8975f5c5SAndroid Build Coastguard Worker 
4693*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4694*8975f5c5SAndroid Build Coastguard Worker }
4695*8975f5c5SAndroid Build Coastguard Worker 
stageSelfAsSubresourceUpdates(ContextVk * contextVk)4696*8975f5c5SAndroid Build Coastguard Worker void TextureVk::stageSelfAsSubresourceUpdates(ContextVk *contextVk)
4697*8975f5c5SAndroid Build Coastguard Worker {
4698*8975f5c5SAndroid Build Coastguard Worker     // If we are calling stageSelfAsSubresourceUpdates(), the current image will be swapped
4699*8975f5c5SAndroid Build Coastguard Worker     // to prevImage in stageSelfAsSubresourceUpdates(), therefore we need to release the
4700*8975f5c5SAndroid Build Coastguard Worker     // imageViews first as we want to use current image.mUse to keep track of imageViews' resource
4701*8975f5c5SAndroid Build Coastguard Worker     // lifetime.
4702*8975f5c5SAndroid Build Coastguard Worker     releaseImageViews(contextVk);
4703*8975f5c5SAndroid Build Coastguard Worker     // Make the image stage itself as updates to its levels.
4704*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mImageSiblingSerial.valid());
4705*8975f5c5SAndroid Build Coastguard Worker     mImage->stageSelfAsSubresourceUpdates(contextVk, mImage->getLevelCount(), mState.getType(),
4706*8975f5c5SAndroid Build Coastguard Worker                                           mRedefinedLevels);
4707*8975f5c5SAndroid Build Coastguard Worker }
4708*8975f5c5SAndroid Build Coastguard Worker 
updateCachedImageViewSerials()4709*8975f5c5SAndroid Build Coastguard Worker void TextureVk::updateCachedImageViewSerials()
4710*8975f5c5SAndroid Build Coastguard Worker {
4711*8975f5c5SAndroid Build Coastguard Worker     mCachedImageViewSubresourceSerialSRGBDecode =
4712*8975f5c5SAndroid Build Coastguard Worker         getImageViewSubresourceSerialImpl(vk::ImageViewColorspace::SRGB);
4713*8975f5c5SAndroid Build Coastguard Worker     mCachedImageViewSubresourceSerialSkipDecode =
4714*8975f5c5SAndroid Build Coastguard Worker         getImageViewSubresourceSerialImpl(vk::ImageViewColorspace::Linear);
4715*8975f5c5SAndroid Build Coastguard Worker }
4716*8975f5c5SAndroid Build Coastguard Worker }  // namespace rx
4717