• 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.h:
7 //    Defines the class interface for TextureVk, implementing TextureImpl.
8 //
9 
10 #ifndef LIBANGLE_RENDERER_VULKAN_TEXTUREVK_H_
11 #define LIBANGLE_RENDERER_VULKAN_TEXTUREVK_H_
12 
13 #include "libANGLE/renderer/TextureImpl.h"
14 #include "libANGLE/renderer/vulkan/RenderTargetVk.h"
15 #include "libANGLE/renderer/vulkan/ResourceVk.h"
16 #include "libANGLE/renderer/vulkan/SamplerVk.h"
17 #include "libANGLE/renderer/vulkan/vk_helpers.h"
18 
19 namespace rx
20 {
21 
22 enum class ImageMipLevels
23 {
24     EnabledLevels = 0,
25     FullMipChain  = 1,
26 
27     InvalidEnum = 2,
28 };
29 
30 // vkCmdCopyBufferToImage buffer offset multiple
31 constexpr VkDeviceSize kBufferOffsetMultiple = 4;
32 
33 class TextureVk : public TextureImpl, public angle::ObserverInterface
34 {
35   public:
36     TextureVk(const gl::TextureState &state, RendererVk *renderer);
37     ~TextureVk() override;
38     void onDestroy(const gl::Context *context) override;
39 
40     angle::Result setImage(const gl::Context *context,
41                            const gl::ImageIndex &index,
42                            GLenum internalFormat,
43                            const gl::Extents &size,
44                            GLenum format,
45                            GLenum type,
46                            const gl::PixelUnpackState &unpack,
47                            gl::Buffer *unpackBuffer,
48                            const uint8_t *pixels) override;
49     angle::Result setSubImage(const gl::Context *context,
50                               const gl::ImageIndex &index,
51                               const gl::Box &area,
52                               GLenum format,
53                               GLenum type,
54                               const gl::PixelUnpackState &unpack,
55                               gl::Buffer *unpackBuffer,
56                               const uint8_t *pixels) override;
57 
58     angle::Result setCompressedImage(const gl::Context *context,
59                                      const gl::ImageIndex &index,
60                                      GLenum internalFormat,
61                                      const gl::Extents &size,
62                                      const gl::PixelUnpackState &unpack,
63                                      size_t imageSize,
64                                      const uint8_t *pixels) override;
65     angle::Result setCompressedSubImage(const gl::Context *context,
66                                         const gl::ImageIndex &index,
67                                         const gl::Box &area,
68                                         GLenum format,
69                                         const gl::PixelUnpackState &unpack,
70                                         size_t imageSize,
71                                         const uint8_t *pixels) override;
72 
73     angle::Result copyImage(const gl::Context *context,
74                             const gl::ImageIndex &index,
75                             const gl::Rectangle &sourceArea,
76                             GLenum internalFormat,
77                             gl::Framebuffer *source) override;
78     angle::Result copySubImage(const gl::Context *context,
79                                const gl::ImageIndex &index,
80                                const gl::Offset &destOffset,
81                                const gl::Rectangle &sourceArea,
82                                gl::Framebuffer *source) override;
83 
84     angle::Result copyTexture(const gl::Context *context,
85                               const gl::ImageIndex &index,
86                               GLenum internalFormat,
87                               GLenum type,
88                               GLint sourceLevelGL,
89                               bool unpackFlipY,
90                               bool unpackPremultiplyAlpha,
91                               bool unpackUnmultiplyAlpha,
92                               const gl::Texture *source) override;
93     angle::Result copySubTexture(const gl::Context *context,
94                                  const gl::ImageIndex &index,
95                                  const gl::Offset &destOffset,
96                                  GLint sourceLevelGL,
97                                  const gl::Box &sourceBox,
98                                  bool unpackFlipY,
99                                  bool unpackPremultiplyAlpha,
100                                  bool unpackUnmultiplyAlpha,
101                                  const gl::Texture *source) override;
102 
103     angle::Result copyRenderbufferSubData(const gl::Context *context,
104                                           const gl::Renderbuffer *srcBuffer,
105                                           GLint srcLevel,
106                                           GLint srcX,
107                                           GLint srcY,
108                                           GLint srcZ,
109                                           GLint dstLevel,
110                                           GLint dstX,
111                                           GLint dstY,
112                                           GLint dstZ,
113                                           GLsizei srcWidth,
114                                           GLsizei srcHeight,
115                                           GLsizei srcDepth) override;
116 
117     angle::Result copyTextureSubData(const gl::Context *context,
118                                      const gl::Texture *srcTexture,
119                                      GLint srcLevel,
120                                      GLint srcX,
121                                      GLint srcY,
122                                      GLint srcZ,
123                                      GLint dstLevel,
124                                      GLint dstX,
125                                      GLint dstY,
126                                      GLint dstZ,
127                                      GLsizei srcWidth,
128                                      GLsizei srcHeight,
129                                      GLsizei srcDepth) override;
130 
131     angle::Result copyCompressedTexture(const gl::Context *context,
132                                         const gl::Texture *source) override;
133 
134     angle::Result setStorage(const gl::Context *context,
135                              gl::TextureType type,
136                              size_t levels,
137                              GLenum internalFormat,
138                              const gl::Extents &size) override;
139 
140     angle::Result setStorageExternalMemory(const gl::Context *context,
141                                            gl::TextureType type,
142                                            size_t levels,
143                                            GLenum internalFormat,
144                                            const gl::Extents &size,
145                                            gl::MemoryObject *memoryObject,
146                                            GLuint64 offset,
147                                            GLbitfield createFlags,
148                                            GLbitfield usageFlags) override;
149 
150     angle::Result setEGLImageTarget(const gl::Context *context,
151                                     gl::TextureType type,
152                                     egl::Image *image) override;
153 
154     angle::Result setImageExternal(const gl::Context *context,
155                                    gl::TextureType type,
156                                    egl::Stream *stream,
157                                    const egl::Stream::GLTextureDescription &desc) override;
158 
159     angle::Result setBuffer(const gl::Context *context, GLenum internalFormat) override;
160 
161     angle::Result generateMipmap(const gl::Context *context) override;
162 
163     angle::Result setBaseLevel(const gl::Context *context, GLuint baseLevel) override;
164 
165     angle::Result bindTexImage(const gl::Context *context, egl::Surface *surface) override;
166     angle::Result releaseTexImage(const gl::Context *context) override;
167 
168     angle::Result getAttachmentRenderTarget(const gl::Context *context,
169                                             GLenum binding,
170                                             const gl::ImageIndex &imageIndex,
171                                             GLsizei samples,
172                                             FramebufferAttachmentRenderTarget **rtOut) override;
173 
174     angle::Result syncState(const gl::Context *context,
175                             const gl::Texture::DirtyBits &dirtyBits,
176                             gl::Command source) override;
177 
178     angle::Result setStorageMultisample(const gl::Context *context,
179                                         gl::TextureType type,
180                                         GLsizei samples,
181                                         GLint internalformat,
182                                         const gl::Extents &size,
183                                         bool fixedSampleLocations) override;
184 
185     angle::Result initializeContents(const gl::Context *context,
186                                      const gl::ImageIndex &imageIndex) override;
187 
getImage()188     const vk::ImageHelper &getImage() const
189     {
190         ASSERT(mImage && mImage->valid());
191         return *mImage;
192     }
193 
getImage()194     vk::ImageHelper &getImage()
195     {
196         ASSERT(mImage && mImage->valid());
197         return *mImage;
198     }
199 
retainImageViews(vk::ResourceUseList * resourceUseList)200     void retainImageViews(vk::ResourceUseList *resourceUseList)
201     {
202         getImageViews().retain(resourceUseList);
203     }
204 
retainBufferViews(vk::ResourceUseList * resourceUseList)205     void retainBufferViews(vk::ResourceUseList *resourceUseList)
206     {
207         mBufferViews.retain(resourceUseList);
208     }
209 
210     void releaseOwnershipOfImage(const gl::Context *context);
211 
212     const vk::ImageView &getReadImageViewAndRecordUse(ContextVk *contextVk,
213                                                       GLenum srgbDecode,
214                                                       bool texelFetchStaticUse) const;
215 
216     // A special view for cube maps as a 2D array, used with shaders that do texelFetch() and for
217     // seamful cube map emulation.
218     const vk::ImageView &getFetchImageViewAndRecordUse(ContextVk *contextVk,
219                                                        GLenum srgbDecode,
220                                                        bool texelFetchStaticUse) const;
221 
222     // A special view used for texture copies that shouldn't perform swizzle.
223     const vk::ImageView &getCopyImageViewAndRecordUse(ContextVk *contextVk) const;
224     angle::Result getStorageImageView(ContextVk *contextVk,
225                                       const gl::ImageUnit &binding,
226                                       const vk::ImageView **imageViewOut);
227 
getSampler()228     const vk::SamplerHelper &getSampler() const
229     {
230         ASSERT(mSampler.valid());
231         return mSampler.get();
232     }
233 
234     angle::Result getBufferViewAndRecordUse(ContextVk *contextVk,
235                                             const vk::Format *imageUniformFormat,
236                                             bool isImage,
237                                             const vk::BufferView **viewOut);
238 
239     // Normally, initialize the image with enabled mipmap level counts.
240     angle::Result ensureImageInitialized(ContextVk *contextVk, ImageMipLevels mipLevels);
241 
242     vk::ImageOrBufferViewSubresourceSerial getImageViewSubresourceSerial(
243         const gl::SamplerState &samplerState) const;
244     vk::ImageOrBufferViewSubresourceSerial getBufferViewSerial() const;
245 
overrideStagingBufferSizeForTesting(size_t initialSizeForTesting)246     void overrideStagingBufferSizeForTesting(size_t initialSizeForTesting)
247     {
248         mStagingBufferInitialSize = initialSizeForTesting;
249     }
250 
251     GLenum getColorReadFormat(const gl::Context *context) override;
252     GLenum getColorReadType(const gl::Context *context) override;
253 
254     angle::Result getTexImage(const gl::Context *context,
255                               const gl::PixelPackState &packState,
256                               gl::Buffer *packBuffer,
257                               gl::TextureTarget target,
258                               GLint level,
259                               GLenum format,
260                               GLenum type,
261                               void *pixels) override;
262 
hasBeenBoundAsImage()263     ANGLE_INLINE bool hasBeenBoundAsImage() const { return mState.hasBeenBoundAsImage(); }
getBuffer()264     ANGLE_INLINE const gl::OffsetBindingPointer<gl::Buffer> &getBuffer() const
265     {
266         return mState.getBuffer();
267     }
268 
isSRGBOverrideEnabled()269     bool isSRGBOverrideEnabled() const
270     {
271         return mState.getSRGBOverride() != gl::SrgbOverride::Default;
272     }
273 
274     angle::Result ensureMutable(ContextVk *contextVk);
275 
getAndResetImmutableSamplerDirtyState()276     bool getAndResetImmutableSamplerDirtyState()
277     {
278         bool isDirty           = mImmutableSamplerDirty;
279         mImmutableSamplerDirty = false;
280         return isDirty;
281     }
282 
283   private:
284     // Transform an image index from the frontend into one that can be used on the backing
285     // ImageHelper, taking into account mipmap or cube face offsets
286     gl::ImageIndex getNativeImageIndex(const gl::ImageIndex &inputImageIndex) const;
287     gl::LevelIndex getNativeImageLevel(gl::LevelIndex frontendLevel) const;
288     uint32_t getNativeImageLayer(uint32_t frontendLayer) const;
289 
290     void releaseAndDeleteImageAndViews(ContextVk *contextVk);
291     angle::Result ensureImageAllocated(ContextVk *contextVk, const vk::Format &format);
292     void setImageHelper(ContextVk *contextVk,
293                         vk::ImageHelper *imageHelper,
294                         gl::TextureType imageType,
295                         const vk::Format &format,
296                         uint32_t imageLevelOffset,
297                         uint32_t imageLayerOffset,
298                         gl::LevelIndex imageBaseLevel,
299                         bool selfOwned);
300     void updateImageHelper(ContextVk *contextVk, size_t imageCopyBufferAlignment);
getImageViews()301     vk::ImageViewHelper &getImageViews()
302     {
303         return mMultisampledImageViews[gl::RenderToTextureImageIndex::Default];
304     }
getImageViews()305     const vk::ImageViewHelper &getImageViews() const
306     {
307         return mMultisampledImageViews[gl::RenderToTextureImageIndex::Default];
308     }
309 
310     // Redefine a mip level of the texture.  If the new size and format don't match the allocated
311     // image, the image may be released.  When redefining a mip of a multi-level image, updates are
312     // forced to be staged, as another mip of the image may be bound to a framebuffer.  For example,
313     // assume texture has two mips, and framebuffer is bound to mip 0.  Redefining mip 1 to an
314     // incompatible size shouldn't affect the framebuffer, especially if the redefinition comes from
315     // something like glCopyTexSubImage2D() (which simultaneously is reading from said framebuffer,
316     // i.e. mip 0 of the texture).
317     angle::Result redefineLevel(const gl::Context *context,
318                                 const gl::ImageIndex &index,
319                                 const vk::Format &format,
320                                 const gl::Extents &size);
321 
322     angle::Result setImageImpl(const gl::Context *context,
323                                const gl::ImageIndex &index,
324                                const gl::InternalFormat &formatInfo,
325                                const gl::Extents &size,
326                                GLenum type,
327                                const gl::PixelUnpackState &unpack,
328                                gl::Buffer *unpackBuffer,
329                                const uint8_t *pixels);
330     angle::Result setSubImageImpl(const gl::Context *context,
331                                   const gl::ImageIndex &index,
332                                   const gl::Box &area,
333                                   const gl::InternalFormat &formatInfo,
334                                   GLenum type,
335                                   const gl::PixelUnpackState &unpack,
336                                   gl::Buffer *unpackBuffer,
337                                   const uint8_t *pixels,
338                                   const vk::Format &vkFormat);
339 
340     angle::Result copyImageDataToBufferAndGetData(ContextVk *contextVk,
341                                                   gl::LevelIndex sourceLevelGL,
342                                                   uint32_t layerCount,
343                                                   const gl::Box &sourceArea,
344                                                   uint8_t **outDataPtr);
345 
346     angle::Result copyBufferDataToImage(ContextVk *contextVk,
347                                         vk::BufferHelper *srcBuffer,
348                                         const gl::ImageIndex index,
349                                         uint32_t rowLength,
350                                         uint32_t imageHeight,
351                                         const gl::Box &sourceArea,
352                                         size_t offset,
353                                         VkImageAspectFlags aspectFlags);
354 
355     // Called from syncState to prepare the image for mipmap generation.
356     void prepareForGenerateMipmap(ContextVk *contextVk);
357 
358     // Generate mipmaps from level 0 into the rest of the mips.  This requires the image to have
359     // STORAGE usage.
360     angle::Result generateMipmapsWithCompute(ContextVk *contextVk);
361 
362     angle::Result generateMipmapsWithCPU(const gl::Context *context);
363 
364     angle::Result generateMipmapLevelsWithCPU(ContextVk *contextVk,
365                                               const angle::Format &sourceFormat,
366                                               GLuint layer,
367                                               gl::LevelIndex firstMipLevel,
368                                               gl::LevelIndex maxMipLevel,
369                                               const size_t sourceWidth,
370                                               const size_t sourceHeight,
371                                               const size_t sourceDepth,
372                                               const size_t sourceRowPitch,
373                                               const size_t sourceDepthPitch,
374                                               uint8_t *sourceData);
375 
376     angle::Result copySubImageImpl(const gl::Context *context,
377                                    const gl::ImageIndex &index,
378                                    const gl::Offset &destOffset,
379                                    const gl::Rectangle &sourceArea,
380                                    const gl::InternalFormat &internalFormat,
381                                    gl::Framebuffer *source);
382 
383     angle::Result copySubTextureImpl(ContextVk *contextVk,
384                                      const gl::ImageIndex &index,
385                                      const gl::Offset &destOffset,
386                                      const gl::InternalFormat &destFormat,
387                                      gl::LevelIndex sourceLevelGL,
388                                      const gl::Box &sourceBox,
389                                      bool unpackFlipY,
390                                      bool unpackPremultiplyAlpha,
391                                      bool unpackUnmultiplyAlpha,
392                                      TextureVk *source);
393 
394     angle::Result copySubImageImplWithTransfer(ContextVk *contextVk,
395                                                const gl::ImageIndex &index,
396                                                const gl::Offset &destOffset,
397                                                const vk::Format &destFormat,
398                                                gl::LevelIndex sourceLevelGL,
399                                                size_t sourceLayer,
400                                                const gl::Box &sourceBox,
401                                                vk::ImageHelper *srcImage);
402 
403     angle::Result copySubImageImplWithDraw(ContextVk *contextVk,
404                                            const gl::ImageIndex &index,
405                                            const gl::Offset &destOffset,
406                                            const vk::Format &destFormat,
407                                            gl::LevelIndex sourceLevelGL,
408                                            const gl::Box &sourceBox,
409                                            bool isSrcFlipY,
410                                            bool unpackFlipY,
411                                            bool unpackPremultiplyAlpha,
412                                            bool unpackUnmultiplyAlpha,
413                                            vk::ImageHelper *srcImage,
414                                            const vk::ImageView *srcView,
415                                            SurfaceRotation srcFramebufferRotation);
416 
417     angle::Result initImage(ContextVk *contextVk,
418                             const vk::Format &format,
419                             const bool sized,
420                             const gl::Extents &firstLevelExtents,
421                             const uint32_t firstLevel,
422                             const uint32_t levelCount);
423     void releaseImage(ContextVk *contextVk);
424     void releaseStagingBuffer(ContextVk *contextVk);
425     uint32_t getMipLevelCount(ImageMipLevels mipLevels) const;
426     uint32_t getMaxLevelCount() const;
427     angle::Result copyAndStageImageData(ContextVk *contextVk,
428                                         gl::LevelIndex previousFirstAllocateLevel,
429                                         vk::ImageHelper *srcImage,
430                                         vk::ImageHelper *dstImage);
431     angle::Result initImageViews(ContextVk *contextVk,
432                                  const vk::Format &format,
433                                  const bool sized,
434                                  uint32_t levelCount,
435                                  uint32_t layerCount);
436     void initSingleLayerRenderTargets(ContextVk *contextVk,
437                                       GLuint layerCount,
438                                       gl::LevelIndex levelIndexGL,
439                                       gl::RenderToTextureImageIndex renderToTextureIndex);
440     RenderTargetVk *getMultiLayerRenderTarget(ContextVk *contextVk,
441                                               gl::LevelIndex level,
442                                               GLuint layerIndex,
443                                               GLuint layerCount);
444     angle::Result getLevelLayerImageView(ContextVk *contextVk,
445                                          gl::LevelIndex levelGL,
446                                          size_t layer,
447                                          const vk::ImageView **imageViewOut);
448 
449     // Flush image's staged updates for all levels and layers.
450     angle::Result flushImageStagedUpdates(ContextVk *contextVk);
451 
452     const gl::InternalFormat &getImplementationSizedFormat(const gl::Context *context) const;
453     const vk::Format &getBaseLevelFormat(RendererVk *renderer) const;
454     // Queues a flush of any modified image attributes. The image will be reallocated with its new
455     // attributes at the next opportunity.
456     angle::Result respecifyImageStorage(ContextVk *contextVk);
457     angle::Result respecifyImageStorageAndLevels(ContextVk *contextVk,
458                                                  gl::LevelIndex previousFirstAllocateLevelGL,
459                                                  gl::LevelIndex baseLevelGL,
460                                                  gl::LevelIndex maxLevelGL);
461 
462     // Update base and max levels, and re-create image if needed.
463     angle::Result updateBaseMaxLevels(ContextVk *contextVk,
464                                       bool baseLevelChanged,
465                                       bool maxLevelChanged);
466 
467     bool isFastUnpackPossible(const vk::Format &vkFormat, size_t offset) const;
468 
469     bool shouldUpdateBeStaged(gl::LevelIndex textureLevelIndexGL) const;
470 
471     // We monitor the staging buffer and set dirty bits if the staging buffer changes. Note that we
472     // support changes in the staging buffer even outside the TextureVk class.
473     void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
474 
getTilingMode()475     ANGLE_INLINE VkImageTiling getTilingMode()
476     {
477         return (mImage->valid()) ? mImage->getTilingMode() : VK_IMAGE_TILING_OPTIMAL;
478     }
479 
480     angle::Result refreshImageViews(ContextVk *contextVk);
481     bool shouldDecodeSRGB(ContextVk *contextVk, GLenum srgbDecode, bool texelFetchStaticUse) const;
482     void initImageUsageFlags(ContextVk *contextVk, const vk::Format &format);
483     void handleImmutableSamplerTransition(const vk::ImageHelper *previousImage,
484                                           const vk::ImageHelper *nextImage);
485 
486     bool mOwnsImage;
487     bool mRequiresMutableStorage;
488     bool mImmutableSamplerDirty;
489 
490     gl::TextureType mImageNativeType;
491 
492     // The layer offset to apply when converting from a frontend texture layer to a texture layer in
493     // mImage. Used when this texture sources a cube map face or 3D texture layer from an EGL image.
494     uint32_t mImageLayerOffset;
495 
496     // The level offset to apply when converting from a frontend texture level to texture level in
497     // mImage.
498     uint32_t mImageLevelOffset;
499 
500     // If multisampled rendering to texture, an intermediate multisampled image is created for use
501     // as renderpass color attachment.  An array of images and image views are used based on the
502     // number of samples used with multisampled rendering to texture.  Index 0 corresponds to the
503     // non-multisampled-render-to-texture usage of the texture.
504 
505     // - index 0: Unused.  See description of |mImage|.
506     // - index N: intermediate multisampled image used for multisampled rendering to texture with
507     //   1 << N samples
508     gl::RenderToTextureImageMap<vk::ImageHelper> mMultisampledImages;
509 
510     // |ImageViewHelper| contains all the current views for the Texture. The views are always owned
511     // by the Texture and are not shared like |mImage|. They also have different lifetimes and can
512     // be reallocated independently of |mImage| on state changes.
513     //
514     // - index 0: views for the texture's image (regardless of |mOwnsImage|).
515     // - index N: views for mMultisampledImages[N]
516     gl::RenderToTextureImageMap<vk::ImageViewHelper> mMultisampledImageViews;
517 
518     // Texture buffers create texel buffer views instead.  |BufferViewHelper| contains the views
519     // corresponding to the attached buffer range.
520     vk::BufferViewHelper mBufferViews;
521 
522     // Render targets stored as array of vector of vectors
523     //
524     // - First dimension: index N contains render targets with views from mMultisampledImageViews[N]
525     // - Second dimension: level
526     // - Third dimension: layer
527     gl::RenderToTextureImageMap<std::vector<RenderTargetVector>> mSingleLayerRenderTargets;
528     // Multi-layer render targets stored as a hash map.  This is used for layered attachments
529     // which covers the entire layer (glFramebufferTextureLayer) or multiview attachments which
530     // cover a range of layers (glFramebufferTextureMultiviewOVR).
531     angle::HashMap<vk::ImageSubresourceRange, std::unique_ptr<RenderTargetVk>>
532         mMultiLayerRenderTargets;
533 
534     // |mImage| wraps a VkImage and VkDeviceMemory that represents the gl::Texture. |mOwnsImage|
535     // indicates that |TextureVk| owns the image. Otherwise it is a weak pointer shared with another
536     // class. Due to this sharing, for example through EGL images, the image must always be
537     // dynamically allocated as the texture can release ownership for example and it can be
538     // transferred to another |TextureVk|.
539     vk::ImageHelper *mImage;
540 
541     // |mSampler| contains the relevant Vulkan sampler states representing the OpenGL Texture
542     // sampling states for the Texture.
543     vk::SamplerBinding mSampler;
544 
545     // Overridden in some tests.
546     size_t mStagingBufferInitialSize;
547 
548     // The created vkImage usage flag.
549     VkImageUsageFlags mImageUsageFlags;
550 
551     // Additional image create flags
552     VkImageCreateFlags mImageCreateFlags;
553 
554     // If an image level is incompatibly redefined, the image lives through the call that did this
555     // (i.e. set and copy levels), because the image may be used by the framebuffer in the very same
556     // call.  As a result, updates to this redefined level are staged (in both the call that
557     // redefines it, and any future calls such as subimage updates).  This bitset flags redefined
558     // levels so that their updates will be force-staged until image is recreated.
559     //
560     // In common cases with mipmapped textures, the base/max level would need adjusting as the
561     // texture is no longer mip-complete.  However, if every level is redefined such that at the end
562     // the image becomes mip-complete again, no reinitialization of the image is done.  This bitset
563     // is additionally used to ensure the image is recreated in the next syncState, if not already.
564     gl::TexLevelMask mRedefinedLevels;
565 
566     angle::ObserverBinding mImageObserverBinding;
567 };
568 
569 }  // namespace rx
570 
571 #endif  // LIBANGLE_RENDERER_VULKAN_TEXTUREVK_H_
572