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