xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/vulkan/TextureVk.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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/SamplerVk.h"
16 #include "libANGLE/renderer/vulkan/vk_helpers.h"
17 #include "libANGLE/renderer/vulkan/vk_resource.h"
18 
19 namespace rx
20 {
21 
22 enum class TextureUpdateResult
23 {
24     ImageUnaffected,
25     ImageRespecified,
26 };
27 
28 class TextureVk : public TextureImpl, public angle::ObserverInterface
29 {
30   public:
31     TextureVk(const gl::TextureState &state, vk::Renderer *renderer);
32     ~TextureVk() override;
33     void onDestroy(const gl::Context *context) override;
34 
35     angle::Result setImage(const gl::Context *context,
36                            const gl::ImageIndex &index,
37                            GLenum internalFormat,
38                            const gl::Extents &size,
39                            GLenum format,
40                            GLenum type,
41                            const gl::PixelUnpackState &unpack,
42                            gl::Buffer *unpackBuffer,
43                            const uint8_t *pixels) override;
44     angle::Result setSubImage(const gl::Context *context,
45                               const gl::ImageIndex &index,
46                               const gl::Box &area,
47                               GLenum format,
48                               GLenum type,
49                               const gl::PixelUnpackState &unpack,
50                               gl::Buffer *unpackBuffer,
51                               const uint8_t *pixels) override;
52 
53     angle::Result setCompressedImage(const gl::Context *context,
54                                      const gl::ImageIndex &index,
55                                      GLenum internalFormat,
56                                      const gl::Extents &size,
57                                      const gl::PixelUnpackState &unpack,
58                                      size_t imageSize,
59                                      const uint8_t *pixels) override;
60     angle::Result setCompressedSubImage(const gl::Context *context,
61                                         const gl::ImageIndex &index,
62                                         const gl::Box &area,
63                                         GLenum format,
64                                         const gl::PixelUnpackState &unpack,
65                                         size_t imageSize,
66                                         const uint8_t *pixels) override;
67 
68     angle::Result copyImage(const gl::Context *context,
69                             const gl::ImageIndex &index,
70                             const gl::Rectangle &sourceArea,
71                             GLenum internalFormat,
72                             gl::Framebuffer *source) override;
73     angle::Result copySubImage(const gl::Context *context,
74                                const gl::ImageIndex &index,
75                                const gl::Offset &destOffset,
76                                const gl::Rectangle &sourceArea,
77                                gl::Framebuffer *source) override;
78 
79     angle::Result copyTexture(const gl::Context *context,
80                               const gl::ImageIndex &index,
81                               GLenum internalFormat,
82                               GLenum type,
83                               GLint sourceLevelGL,
84                               bool unpackFlipY,
85                               bool unpackPremultiplyAlpha,
86                               bool unpackUnmultiplyAlpha,
87                               const gl::Texture *source) override;
88     angle::Result copySubTexture(const gl::Context *context,
89                                  const gl::ImageIndex &index,
90                                  const gl::Offset &destOffset,
91                                  GLint sourceLevelGL,
92                                  const gl::Box &sourceBox,
93                                  bool unpackFlipY,
94                                  bool unpackPremultiplyAlpha,
95                                  bool unpackUnmultiplyAlpha,
96                                  const gl::Texture *source) override;
97 
98     angle::Result copyRenderbufferSubData(const gl::Context *context,
99                                           const gl::Renderbuffer *srcBuffer,
100                                           GLint srcLevel,
101                                           GLint srcX,
102                                           GLint srcY,
103                                           GLint srcZ,
104                                           GLint dstLevel,
105                                           GLint dstX,
106                                           GLint dstY,
107                                           GLint dstZ,
108                                           GLsizei srcWidth,
109                                           GLsizei srcHeight,
110                                           GLsizei srcDepth) override;
111 
112     angle::Result copyTextureSubData(const gl::Context *context,
113                                      const gl::Texture *srcTexture,
114                                      GLint srcLevel,
115                                      GLint srcX,
116                                      GLint srcY,
117                                      GLint srcZ,
118                                      GLint dstLevel,
119                                      GLint dstX,
120                                      GLint dstY,
121                                      GLint dstZ,
122                                      GLsizei srcWidth,
123                                      GLsizei srcHeight,
124                                      GLsizei srcDepth) override;
125 
126     angle::Result copyCompressedTexture(const gl::Context *context,
127                                         const gl::Texture *source) override;
128 
129     angle::Result clearImage(const gl::Context *context,
130                              GLint level,
131                              GLenum format,
132                              GLenum type,
133                              const uint8_t *data) override;
134 
135     angle::Result clearSubImage(const gl::Context *context,
136                                 GLint level,
137                                 const gl::Box &area,
138                                 GLenum format,
139                                 GLenum type,
140                                 const uint8_t *data) override;
141 
142     angle::Result setStorage(const gl::Context *context,
143                              gl::TextureType type,
144                              size_t levels,
145                              GLenum internalFormat,
146                              const gl::Extents &size) override;
147 
148     angle::Result setStorageExternalMemory(const gl::Context *context,
149                                            gl::TextureType type,
150                                            size_t levels,
151                                            GLenum internalFormat,
152                                            const gl::Extents &size,
153                                            gl::MemoryObject *memoryObject,
154                                            GLuint64 offset,
155                                            GLbitfield createFlags,
156                                            GLbitfield usageFlags,
157                                            const void *imageCreateInfoPNext) override;
158 
159     angle::Result setEGLImageTarget(const gl::Context *context,
160                                     gl::TextureType type,
161                                     egl::Image *image) override;
162 
163     angle::Result setImageExternal(const gl::Context *context,
164                                    gl::TextureType type,
165                                    egl::Stream *stream,
166                                    const egl::Stream::GLTextureDescription &desc) override;
167 
168     angle::Result setBuffer(const gl::Context *context, GLenum internalFormat) override;
169 
170     angle::Result generateMipmap(const gl::Context *context) override;
171 
172     angle::Result setBaseLevel(const gl::Context *context, GLuint baseLevel) override;
173 
174     angle::Result bindTexImage(const gl::Context *context, egl::Surface *surface) override;
175     angle::Result releaseTexImage(const gl::Context *context) override;
176 
177     angle::Result getAttachmentRenderTarget(const gl::Context *context,
178                                             GLenum binding,
179                                             const gl::ImageIndex &imageIndex,
180                                             GLsizei samples,
181                                             FramebufferAttachmentRenderTarget **rtOut) override;
182 
183     angle::Result syncState(const gl::Context *context,
184                             const gl::Texture::DirtyBits &dirtyBits,
185                             gl::Command source) override;
186 
187     angle::Result setStorageMultisample(const gl::Context *context,
188                                         gl::TextureType type,
189                                         GLsizei samples,
190                                         GLint internalformat,
191                                         const gl::Extents &size,
192                                         bool fixedSampleLocations) override;
193 
194     angle::Result setStorageAttribs(const gl::Context *context,
195                                     gl::TextureType type,
196                                     size_t levels,
197                                     GLint internalFormat,
198                                     const gl::Extents &size,
199                                     const GLint *attribList) override;
200 
201     angle::Result initializeContents(const gl::Context *context,
202                                      GLenum binding,
203                                      const gl::ImageIndex &imageIndex) override;
204 
205     angle::Result initializeContentsWithBlack(const gl::Context *context,
206                                               GLenum binding,
207                                               const gl::ImageIndex &imageIndex);
208 
getRequiredExternalTextureImageUnits(const gl::Context * context)209     GLint getRequiredExternalTextureImageUnits([[maybe_unused]] const gl::Context *context) override
210     {
211         // For now, we assume that only one image unit is needed to support
212         // external GL textures in the Vulkan backend.
213         return 1;
214     }
215 
getImage()216     const vk::ImageHelper &getImage() const
217     {
218         ASSERT(mImage && mImage->valid());
219         return *mImage;
220     }
221 
getImage()222     vk::ImageHelper &getImage()
223     {
224         ASSERT(mImage && mImage->valid());
225         return *mImage;
226     }
227 
retainBufferViews(vk::CommandBufferHelperCommon * commandBufferHelper)228     void retainBufferViews(vk::CommandBufferHelperCommon *commandBufferHelper)
229     {
230         commandBufferHelper->retainResource(&mBufferViews);
231     }
232 
isImmutable()233     bool isImmutable() { return mState.getImmutableFormat(); }
imageValid()234     bool imageValid() const { return (mImage && mImage->valid()); }
235 
236     void releaseOwnershipOfImage(const gl::Context *context);
237 
238     const vk::ImageView &getReadImageView(GLenum srgbDecode,
239                                           bool texelFetchStaticUse,
240                                           bool samplerExternal2DY2YEXT) const;
241 
242     angle::Result getBufferView(vk::Context *context,
243                                 const vk::Format *imageUniformFormat,
244                                 const gl::SamplerBinding *samplerBinding,
245                                 bool isImage,
246                                 const vk::BufferView **viewOut);
247 
248     // A special view used for texture copies that shouldn't perform swizzle.
249     const vk::ImageView &getCopyImageView() const;
250     angle::Result getStorageImageView(vk::Context *context,
251                                       const gl::ImageUnit &binding,
252                                       const vk::ImageView **imageViewOut);
253 
getSampler(bool isSamplerExternalY2Y)254     const vk::SamplerHelper &getSampler(bool isSamplerExternalY2Y) const
255     {
256         if (isSamplerExternalY2Y)
257         {
258             ASSERT(mY2YSampler->valid());
259             return *mY2YSampler.get();
260         }
261         ASSERT(mSampler->valid());
262         return *mSampler.get();
263     }
264 
resetSampler()265     void resetSampler()
266     {
267         mSampler.reset();
268         mY2YSampler.reset();
269     }
270 
271     // Normally, initialize the image with enabled mipmap level counts.
272     angle::Result ensureImageInitialized(ContextVk *contextVk, ImageMipLevels mipLevels);
273 
getImageViewSubresourceSerial(const gl::SamplerState & samplerState,bool staticTexelFetchAccess)274     vk::ImageOrBufferViewSubresourceSerial getImageViewSubresourceSerial(
275         const gl::SamplerState &samplerState,
276         bool staticTexelFetchAccess) const
277     {
278         ASSERT(mImage != nullptr);
279         gl::SrgbDecode srgbDecode = (samplerState.getSRGBDecode() == GL_SKIP_DECODE_EXT)
280                                         ? gl::SrgbDecode::Skip
281                                         : gl::SrgbDecode::Default;
282         mImageView.updateSrgbDecode(*mImage, srgbDecode);
283         mImageView.updateStaticTexelFetch(*mImage, staticTexelFetchAccess);
284 
285         if (mImageView.getColorspaceForRead() == vk::ImageViewColorspace::SRGB)
286         {
287             ASSERT(getImageViewSubresourceSerialImpl(vk::ImageViewColorspace::SRGB) ==
288                    mCachedImageViewSubresourceSerialSRGBDecode);
289             return mCachedImageViewSubresourceSerialSRGBDecode;
290         }
291         else
292         {
293             ASSERT(getImageViewSubresourceSerialImpl(vk::ImageViewColorspace::Linear) ==
294                    mCachedImageViewSubresourceSerialSkipDecode);
295             return mCachedImageViewSubresourceSerialSkipDecode;
296         }
297     }
298 
299     vk::ImageOrBufferViewSubresourceSerial getBufferViewSerial() const;
300     vk::ImageOrBufferViewSubresourceSerial getStorageImageViewSerial(
301         const gl::ImageUnit &binding) const;
302 
303     GLenum getColorReadFormat(const gl::Context *context) override;
304     GLenum getColorReadType(const gl::Context *context) override;
305 
306     angle::Result getTexImage(const gl::Context *context,
307                               const gl::PixelPackState &packState,
308                               gl::Buffer *packBuffer,
309                               gl::TextureTarget target,
310                               GLint level,
311                               GLenum format,
312                               GLenum type,
313                               void *pixels) override;
314 
315     angle::Result getCompressedTexImage(const gl::Context *context,
316                                         const gl::PixelPackState &packState,
317                                         gl::Buffer *packBuffer,
318                                         gl::TextureTarget target,
319                                         GLint level,
320                                         void *pixels) override;
321 
hasBeenBoundAsImage()322     ANGLE_INLINE bool hasBeenBoundAsImage() const { return mState.hasBeenBoundAsImage(); }
getBuffer()323     ANGLE_INLINE const gl::OffsetBindingPointer<gl::Buffer> &getBuffer() const
324     {
325         return mState.getBuffer();
326     }
327     vk::BufferHelper *getPossiblyEmulatedTextureBuffer(vk::Context *context) const;
328 
isSRGBOverrideEnabled()329     bool isSRGBOverrideEnabled() const
330     {
331         return mState.getSRGBOverride() != gl::SrgbOverride::Default;
332     }
333 
updateSrgbDecodeState(ContextVk * contextVk,const gl::SamplerState & samplerState)334     angle::Result updateSrgbDecodeState(ContextVk *contextVk, const gl::SamplerState &samplerState)
335     {
336         ASSERT(mImage != nullptr && mImage->valid());
337         gl::SrgbDecode srgbDecode = (samplerState.getSRGBDecode() == GL_SKIP_DECODE_EXT)
338                                         ? gl::SrgbDecode::Skip
339                                         : gl::SrgbDecode::Default;
340         mImageView.updateSrgbDecode(*mImage, srgbDecode);
341         if (mImageView.hasColorspaceOverrideForRead(*mImage))
342         {
343             ANGLE_TRY(ensureMutable(contextVk));
344         }
345         return angle::Result::Continue;
346     }
347 
348     angle::Result ensureRenderable(ContextVk *contextVk, TextureUpdateResult *updateResultOut);
349 
getAndResetImmutableSamplerDirtyState()350     bool getAndResetImmutableSamplerDirtyState()
351     {
352         bool isDirty           = mImmutableSamplerDirty;
353         mImmutableSamplerDirty = false;
354         return isDirty;
355     }
356 
357     angle::Result onLabelUpdate(const gl::Context *context) override;
358 
onNewDescriptorSet(const vk::SharedDescriptorSetCacheKey & sharedCacheKey)359     void onNewDescriptorSet(const vk::SharedDescriptorSetCacheKey &sharedCacheKey)
360     {
361         mDescriptorSetCacheManager.addKey(sharedCacheKey);
362     }
363 
364     // Check if the texture is consistently specified. Used for flushing mutable textures.
365     bool isMutableTextureConsistentlySpecifiedForFlush();
366     bool isMipImageDescDefined(gl::TextureTarget textureTarget, size_t level);
367 
368     GLint getImageCompressionRate(const gl::Context *context) override;
369     GLint getFormatSupportedCompressionRates(const gl::Context *context,
370                                              GLenum internalformat,
371                                              GLsizei bufSize,
372                                              GLint *rates) override;
373 
374   private:
375     // Transform an image index from the frontend into one that can be used on the backing
376     // ImageHelper, taking into account mipmap or cube face offsets
377     gl::ImageIndex getNativeImageIndex(const gl::ImageIndex &inputImageIndex) const;
378     gl::LevelIndex getNativeImageLevel(gl::LevelIndex frontendLevel) const;
379     uint32_t getNativeImageLayer(uint32_t frontendLayer) const;
380 
381     // Get the layer count for views.
382     uint32_t getImageViewLayerCount() const;
383     // Get the level count for views.
384     uint32_t getImageViewLevelCount() const;
385 
386     void releaseAndDeleteImageAndViews(ContextVk *contextVk);
387     angle::Result ensureImageAllocated(ContextVk *contextVk, const vk::Format &format);
388     void setImageHelper(ContextVk *contextVk,
389                         vk::ImageHelper *imageHelper,
390                         gl::TextureType imageType,
391                         uint32_t imageLevelOffset,
392                         uint32_t imageLayerOffset,
393                         bool selfOwned,
394                         UniqueSerial siblingSerial);
395 
getImageViews()396     vk::ImageViewHelper &getImageViews() { return mImageView; }
getImageViews()397     const vk::ImageViewHelper &getImageViews() const { return mImageView; }
398 
399     angle::Result ensureRenderableWithFormat(ContextVk *contextVk,
400                                              const vk::Format &format,
401                                              TextureUpdateResult *updateResultOut);
402     angle::Result ensureRenderableIfCopyTextureCannotTransfer(ContextVk *contextVk,
403                                                               const gl::InternalFormat &dstFormat,
404                                                               bool unpackFlipY,
405                                                               bool unpackPremultiplyAlpha,
406                                                               bool unpackUnmultiplyAlpha,
407                                                               TextureVk *source);
408     angle::Result ensureRenderableIfCopyTexImageCannotTransfer(
409         ContextVk *contextVk,
410         const gl::InternalFormat &internalFormat,
411         gl::Framebuffer *source);
412 
413     // Redefine a mip level of the texture.  If the new size and format don't match the allocated
414     // image, the image may be released.  When redefining a mip of a multi-level image, updates are
415     // forced to be staged, as another mip of the image may be bound to a framebuffer.  For example,
416     // assume texture has two mips, and framebuffer is bound to mip 0.  Redefining mip 1 to an
417     // incompatible size shouldn't affect the framebuffer, especially if the redefinition comes from
418     // something like glCopyTexSubImage2D() (which simultaneously is reading from said framebuffer,
419     // i.e. mip 0 of the texture).
420     angle::Result redefineLevel(const gl::Context *context,
421                                 const gl::ImageIndex &index,
422                                 const vk::Format &format,
423                                 const gl::Extents &size);
424 
425     angle::Result setImageImpl(const gl::Context *context,
426                                const gl::ImageIndex &index,
427                                const gl::InternalFormat &formatInfo,
428                                const gl::Extents &size,
429                                GLenum type,
430                                const gl::PixelUnpackState &unpack,
431                                gl::Buffer *unpackBuffer,
432                                const uint8_t *pixels);
433     angle::Result setSubImageImpl(const gl::Context *context,
434                                   const gl::ImageIndex &index,
435                                   const gl::Box &area,
436                                   const gl::InternalFormat &formatInfo,
437                                   GLenum type,
438                                   const gl::PixelUnpackState &unpack,
439                                   gl::Buffer *unpackBuffer,
440                                   const uint8_t *pixels,
441                                   const vk::Format &vkFormat);
442 
443     // Used to clear a texture to a given value in part or whole.
444     angle::Result clearSubImageImpl(const gl::Context *context,
445                                     GLint level,
446                                     const gl::Box &clearArea,
447                                     vk::ClearTextureMode clearMode,
448                                     GLenum format,
449                                     GLenum type,
450                                     const uint8_t *data);
451 
452     angle::Result ensureImageInitializedIfUpdatesNeedStageOrFlush(ContextVk *contextVk,
453                                                                   gl::LevelIndex level,
454                                                                   const vk::Format &vkFormat,
455                                                                   vk::ApplyImageUpdate applyUpdate,
456                                                                   bool usesBufferForUpdate);
457 
458     angle::Result copyImageDataToBufferAndGetData(ContextVk *contextVk,
459                                                   gl::LevelIndex sourceLevelGL,
460                                                   uint32_t layerCount,
461                                                   const gl::Box &sourceArea,
462                                                   RenderPassClosureReason reason,
463                                                   vk::BufferHelper *copyBuffer,
464                                                   uint8_t **outDataPtr);
465 
466     angle::Result copyBufferDataToImage(ContextVk *contextVk,
467                                         vk::BufferHelper *srcBuffer,
468                                         const gl::ImageIndex index,
469                                         uint32_t rowLength,
470                                         uint32_t imageHeight,
471                                         const gl::Box &sourceArea,
472                                         size_t offset,
473                                         VkImageAspectFlags aspectFlags);
474 
475     // Called from syncState to prepare the image for mipmap generation.
476     void prepareForGenerateMipmap(ContextVk *contextVk);
477 
478     // Generate mipmaps from level 0 into the rest of the mips.  This requires the image to have
479     // STORAGE usage.
480     angle::Result generateMipmapsWithCompute(ContextVk *contextVk);
481 
482     angle::Result generateMipmapsWithCPU(const gl::Context *context);
483 
484     angle::Result generateMipmapLevelsWithCPU(ContextVk *contextVk,
485                                               const angle::Format &sourceFormat,
486                                               GLuint layer,
487                                               gl::LevelIndex firstMipLevel,
488                                               gl::LevelIndex maxMipLevel,
489                                               const size_t sourceWidth,
490                                               const size_t sourceHeight,
491                                               const size_t sourceDepth,
492                                               const size_t sourceRowPitch,
493                                               const size_t sourceDepthPitch,
494                                               uint8_t *sourceData);
495 
496     angle::Result copySubImageImpl(const gl::Context *context,
497                                    const gl::ImageIndex &index,
498                                    const gl::Offset &destOffset,
499                                    const gl::Rectangle &sourceArea,
500                                    const gl::InternalFormat &internalFormat,
501                                    gl::Framebuffer *source);
502 
503     angle::Result copySubTextureImpl(ContextVk *contextVk,
504                                      const gl::ImageIndex &index,
505                                      const gl::Offset &dstOffset,
506                                      const gl::InternalFormat &dstFormat,
507                                      gl::LevelIndex sourceLevelGL,
508                                      const gl::Box &sourceBox,
509                                      bool unpackFlipY,
510                                      bool unpackPremultiplyAlpha,
511                                      bool unpackUnmultiplyAlpha,
512                                      TextureVk *source);
513 
514     angle::Result copySubImageImplWithTransfer(ContextVk *contextVk,
515                                                const gl::ImageIndex &index,
516                                                const gl::Offset &dstOffset,
517                                                const vk::Format &dstFormat,
518                                                gl::LevelIndex sourceLevelGL,
519                                                size_t sourceLayer,
520                                                const gl::Box &sourceBox,
521                                                vk::ImageHelper *srcImage);
522 
523     angle::Result copySubImageImplWithDraw(ContextVk *contextVk,
524                                            const gl::ImageIndex &index,
525                                            const gl::Offset &dstOffset,
526                                            const vk::Format &dstFormat,
527                                            gl::LevelIndex sourceLevelGL,
528                                            const gl::Box &sourceBox,
529                                            bool isSrcFlipY,
530                                            bool unpackFlipY,
531                                            bool unpackPremultiplyAlpha,
532                                            bool unpackUnmultiplyAlpha,
533                                            vk::ImageHelper *srcImage,
534                                            const vk::ImageView *srcView,
535                                            SurfaceRotation srcFramebufferRotation);
536 
537     angle::Result initImage(ContextVk *contextVk,
538                             angle::FormatID intendedImageFormatID,
539                             angle::FormatID actualImageFormatID,
540                             ImageMipLevels mipLevels);
541     void releaseImage(ContextVk *contextVk);
542     void releaseImageViews(ContextVk *contextVk);
543     void releaseStagedUpdates(ContextVk *contextVk);
544     uint32_t getMipLevelCount(ImageMipLevels mipLevels) const;
545     uint32_t getMaxLevelCount() const;
546     angle::Result copyAndStageImageData(ContextVk *contextVk,
547                                         gl::LevelIndex previousFirstAllocateLevel,
548                                         vk::ImageHelper *srcImage,
549                                         vk::ImageHelper *dstImage);
550     angle::Result reinitImageAsRenderable(ContextVk *contextVk, const vk::Format &format);
551     angle::Result initImageViews(ContextVk *contextVk, uint32_t levelCount);
552     void initSingleLayerRenderTargets(ContextVk *contextVk,
553                                       GLuint layerCount,
554                                       gl::LevelIndex levelIndexGL,
555                                       gl::RenderToTextureImageIndex renderToTextureIndex);
556     RenderTargetVk *getMultiLayerRenderTarget(ContextVk *contextVk,
557                                               gl::LevelIndex level,
558                                               GLuint layerIndex,
559                                               GLuint layerCount);
560     angle::Result getLevelLayerImageView(vk::Context *context,
561                                          gl::LevelIndex levelGL,
562                                          size_t layer,
563                                          const vk::ImageView **imageViewOut);
564 
565     // Flush image's staged updates for all levels and layers.
566     angle::Result flushImageStagedUpdates(ContextVk *contextVk);
567 
568     angle::Result performImageQueueTransferIfNecessary(ContextVk *contextVk);
569 
570     // For various reasons, the underlying image may need to be respecified.  For example because
571     // base/max level changed, usage/create flags have changed, the format needs modification to
572     // become renderable, generate mipmap is adding levels, etc.  This function is called by
573     // syncState and getAttachmentRenderTarget.  The latter calls this function to be able to sync
574     // the texture's image while an attached framebuffer is being synced.  Note that we currently
575     // sync framebuffers before textures so that the deferred clear optimization works.
576     angle::Result respecifyImageStorageIfNecessary(ContextVk *contextVk, gl::Command source);
577 
578     const gl::InternalFormat &getImplementationSizedFormat(const gl::Context *context) const;
579     const vk::Format &getBaseLevelFormat(vk::Renderer *renderer) const;
580     // Queues a flush of any modified image attributes. The image will be reallocated with its new
581     // attributes at the next opportunity.
582     angle::Result respecifyImageStorage(ContextVk *contextVk);
583 
584     // Update base and max levels, and re-create image if needed.
585     angle::Result maybeUpdateBaseMaxLevels(ContextVk *contextVk,
586                                            TextureUpdateResult *changeResultOut);
587 
588     bool isFastUnpackPossible(const vk::Format &vkFormat,
589                               size_t offset,
590                               const vk::Format &bufferVkFormat) const;
591 
592     bool updateMustBeStaged(gl::LevelIndex textureLevelIndexGL, angle::FormatID dstFormatID) const;
593     bool updateMustBeFlushed(gl::LevelIndex textureLevelIndexGL, angle::FormatID dstFormatID) const;
shouldUpdateBeFlushed(gl::LevelIndex textureLevelIndexGL,angle::FormatID dstFormatID)594     bool shouldUpdateBeFlushed(gl::LevelIndex textureLevelIndexGL,
595                                angle::FormatID dstFormatID) const
596     {
597         return updateMustBeFlushed(textureLevelIndexGL, dstFormatID) ||
598                !updateMustBeStaged(textureLevelIndexGL, dstFormatID);
599     }
600 
601     // We monitor the staging buffer and set dirty bits if the staging buffer changes. Note that we
602     // support changes in the staging buffer even outside the TextureVk class.
603     void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
604 
getTilingMode()605     ANGLE_INLINE VkImageTiling getTilingMode()
606     {
607         return mImage != nullptr && mImage->valid() ? mImage->getTilingMode()
608                                                     : VK_IMAGE_TILING_OPTIMAL;
609     }
610 
611     angle::Result ensureMutable(ContextVk *contextVk);
612     angle::Result refreshImageViews(ContextVk *contextVk);
613     void initImageUsageFlags(ContextVk *contextVk, angle::FormatID actualFormatID);
614     void handleImmutableSamplerTransition(const vk::ImageHelper *previousImage,
615                                           const vk::ImageHelper *nextImage);
616 
getRequiredImageAccess()617     vk::ImageAccess getRequiredImageAccess() const { return mRequiredImageAccess; }
618 
619     void stageSelfAsSubresourceUpdates(ContextVk *contextVk);
620 
621     vk::ImageOrBufferViewSubresourceSerial getImageViewSubresourceSerialImpl(
622         vk::ImageViewColorspace colorspace) const;
623 
624     void updateCachedImageViewSerials();
625 
626     angle::Result updateTextureLabel(ContextVk *contextVk);
627 
628     vk::BufferHelper *getRGBAConversionBufferHelper(vk::Renderer *renderer,
629                                                     angle::FormatID formatID) const;
630     angle::Result convertBufferToRGBA(ContextVk *contextVk, size_t &conversionBufferSize);
631     bool isCompressedFormatEmulated(const gl::Context *context,
632                                     const gl::TextureTarget target,
633                                     GLint level);
634 
635     angle::Result setStorageImpl(ContextVk *contextVk,
636                                  gl::TextureType type,
637                                  const vk::Format &format);
638 
639     GLint getFormatSupportedCompressionRatesImpl(vk::Renderer *renderer,
640                                                  const vk::Format &format,
641                                                  GLsizei bufSize,
642                                                  GLint *rates);
643 
644     bool mOwnsImage;
645     // Generated from ImageVk if EGLImage target, or from throw-away generator if Surface target.
646     UniqueSerial mImageSiblingSerial;
647 
648     bool mRequiresMutableStorage;
649     vk::ImageAccess mRequiredImageAccess;
650     bool mImmutableSamplerDirty;
651 
652     // Only valid if this texture is an "EGLImage target" and the associated EGL Image was
653     // originally sourced from an OpenGL texture. Such EGL Images can be a slice of the underlying
654     // resource. The layer and level offsets are used to track the location of the slice.
655     gl::TextureType mEGLImageNativeType;
656     uint32_t mEGLImageLayerOffset;
657     uint32_t mEGLImageLevelOffset;
658 
659     // If multisampled rendering to texture, an intermediate multisampled image is created for use
660     // as renderpass color attachment. A map of an array of images and image views are used where -
661     //
662     // The map is keyed based on the number of samples used with multisampled rendering to texture.
663     // Index 0 corresponds to the non-multisampled-render-to-texture usage of the texture.
664     // - index 0: Unused.  See description of |mImage|.
665     // - index N: intermediate multisampled image used for multisampled rendering to texture with
666     //            1 << N samples
667     //
668     // Each element in the array corresponds to a mip-level
669     //
670     // - mMultisampledImages[N][M]: intermediate multisampled image with 1 << N samples
671     //                              for level index M
672     using MultiSampleImages = gl::RenderToTextureImageMap<gl::TexLevelArray<vk::ImageHelper>>;
673     std::unique_ptr<MultiSampleImages> mMultisampledImages;
674 
675     // If multisampled rendering to texture, contains views for mMultisampledImages.
676     //
677     // - index 0: Unused.  See description of |mImageView|.
678     // - mMultisampledImageViews[N][M]: views for mMultisampledImages[N][M]
679     using MultiSampleImageViews =
680         gl::RenderToTextureImageMap<gl::TexLevelArray<vk::ImageViewHelper>>;
681     std::unique_ptr<MultiSampleImageViews> mMultisampledImageViews;
682 
683     // Texture buffers create texel buffer views instead.  |BufferViewHelper| contains the views
684     // corresponding to the attached buffer range.
685     vk::BufferViewHelper mBufferViews;
686 
687     // Render targets stored as array of vector of vectors
688     //
689     // - First dimension: index N contains render targets with views from mMultisampledImageViews[N]
690     // - Second dimension: level M contains render targets with views from
691     // mMultisampledImageViews[N][M]
692     // - Third dimension: layer
693     gl::RenderToTextureImageMap<std::vector<RenderTargetVector>> mSingleLayerRenderTargets;
694     // Multi-layer render targets stored as a hash map.  This is used for layered attachments
695     // which covers the entire layer (glFramebufferTextureLayer) or multiview attachments which
696     // cover a range of layers (glFramebufferTextureMultiviewOVR).
697     angle::HashMap<vk::ImageSubresourceRange, std::unique_ptr<RenderTargetVk>>
698         mMultiLayerRenderTargets;
699 
700     // |mImage| wraps a VkImage and VkDeviceMemory that represents the gl::Texture. |mOwnsImage|
701     // indicates that |TextureVk| owns the image. Otherwise it is a weak pointer shared with another
702     // class. Due to this sharing, for example through EGL images, the image must always be
703     // dynamically allocated as the texture can release ownership for example and it can be
704     // transferred to another |TextureVk|.
705     vk::ImageHelper *mImage;
706     // The view is always owned by the Texture and is not shared like |mImage|. It also has
707     // different lifetimes and can be reallocated independently of |mImage| on state changes.
708     vk::ImageViewHelper mImageView;
709 
710     // |mSampler| contains the relevant Vulkan sampler states representing the OpenGL Texture
711     // sampling states for the Texture.
712     vk::SharedSamplerPtr mSampler;
713     // |mY2YSampler| contains a version of mSampler that is meant for use with
714     // __samplerExternal2DY2YEXT (i.e., skipping conversion of YUV to RGB).
715     vk::SharedSamplerPtr mY2YSampler;
716 
717     // The created vkImage usage flag.
718     VkImageUsageFlags mImageUsageFlags;
719 
720     // Additional image create flags
721     VkImageCreateFlags mImageCreateFlags;
722 
723     // If an image level is incompatibly redefined, the image lives through the call that did this
724     // (i.e. set and copy levels), because the image may be used by the framebuffer in the very same
725     // call.  As a result, updates to this redefined level are staged (in both the call that
726     // redefines it, and any future calls such as subimage updates).  This array flags redefined
727     // levels so that their updates will be force-staged until image is recreated.  Each member of
728     // the array is a bitmask per level, and it's an array of cube faces because GL allows
729     // redefining each cube map face separately.  For other texture types, only index 0 is
730     // meaningful as all array levels are redefined simultaneously.
731     //
732     // In common cases with mipmapped textures, the base/max level would need adjusting as the
733     // texture is no longer mip-complete.  However, if every level is redefined such that at the end
734     // the image becomes mip-complete again, no reinitialization of the image is done.  This array
735     // is additionally used to ensure the image is recreated in the next syncState, if not already.
736     //
737     // Note: the elements of this array are bitmasks indexed by gl::LevelIndex, not vk::LevelIndex
738     gl::CubeFaceArray<gl::TexLevelMask> mRedefinedLevels;
739 
740     angle::ObserverBinding mImageObserverBinding;
741 
742     // Saved between updates.
743     gl::LevelIndex mCurrentBaseLevel;
744     gl::LevelIndex mCurrentMaxLevel;
745 
746     // Cached subresource indexes.
747     vk::ImageOrBufferViewSubresourceSerial mCachedImageViewSubresourceSerialSRGBDecode;
748     vk::ImageOrBufferViewSubresourceSerial mCachedImageViewSubresourceSerialSkipDecode;
749 
750     // Manages the texture descriptor set cache that created with this texture
751     vk::DescriptorSetCacheManager mDescriptorSetCacheManager;
752 };
753 
754 }  // namespace rx
755 
756 #endif  // LIBANGLE_RENDERER_VULKAN_TEXTUREVK_H_
757