• 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/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::ErrorContext *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::ErrorContext *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::ErrorContext *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::ErrorContext *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     // For various reasons, the underlying image may need to be respecified.  For example because
569     // base/max level changed, usage/create flags have changed, the format needs modification to
570     // become renderable, generate mipmap is adding levels, etc.  This function is called by
571     // syncState and getAttachmentRenderTarget.  The latter calls this function to be able to sync
572     // the texture's image while an attached framebuffer is being synced.  Note that we currently
573     // sync framebuffers before textures so that the deferred clear optimization works.
574     angle::Result respecifyImageStorageIfNecessary(ContextVk *contextVk, gl::Command source);
575 
576     const gl::InternalFormat &getImplementationSizedFormat(const gl::Context *context) const;
577     const vk::Format &getBaseLevelFormat(vk::Renderer *renderer) const;
578     // Queues a flush of any modified image attributes. The image will be reallocated with its new
579     // attributes at the next opportunity.
580     angle::Result respecifyImageStorage(ContextVk *contextVk);
581 
582     // Update base and max levels, and re-create image if needed.
583     angle::Result maybeUpdateBaseMaxLevels(ContextVk *contextVk,
584                                            TextureUpdateResult *changeResultOut);
585 
586     bool isFastUnpackPossible(const vk::Format &vkFormat,
587                               size_t offset,
588                               const vk::Format &bufferVkFormat) const;
589 
590     bool updateMustBeStaged(gl::LevelIndex textureLevelIndexGL, angle::FormatID dstFormatID) const;
591     bool updateMustBeFlushed(gl::LevelIndex textureLevelIndexGL, angle::FormatID dstFormatID) const;
shouldUpdateBeFlushed(gl::LevelIndex textureLevelIndexGL,angle::FormatID dstFormatID)592     bool shouldUpdateBeFlushed(gl::LevelIndex textureLevelIndexGL,
593                                angle::FormatID dstFormatID) const
594     {
595         return updateMustBeFlushed(textureLevelIndexGL, dstFormatID) ||
596                !updateMustBeStaged(textureLevelIndexGL, dstFormatID);
597     }
598 
599     // We monitor the staging buffer and set dirty bits if the staging buffer changes. Note that we
600     // support changes in the staging buffer even outside the TextureVk class.
601     void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
602 
getTilingMode()603     ANGLE_INLINE VkImageTiling getTilingMode()
604     {
605         return mImage != nullptr && mImage->valid() ? mImage->getTilingMode()
606                                                     : VK_IMAGE_TILING_OPTIMAL;
607     }
608 
609     angle::Result ensureMutable(ContextVk *contextVk);
610     angle::Result refreshImageViews(ContextVk *contextVk);
611     void initImageUsageFlags(ContextVk *contextVk, angle::FormatID actualFormatID);
612     void handleImmutableSamplerTransition(const vk::ImageHelper *previousImage,
613                                           const vk::ImageHelper *nextImage);
614 
getRequiredImageAccess()615     vk::ImageAccess getRequiredImageAccess() const { return mRequiredImageAccess; }
616 
617     void stageSelfAsSubresourceUpdates(ContextVk *contextVk);
618 
619     vk::ImageOrBufferViewSubresourceSerial getImageViewSubresourceSerialImpl(
620         vk::ImageViewColorspace colorspace) const;
621 
622     void updateCachedImageViewSerials();
623 
624     angle::Result updateTextureLabel(ContextVk *contextVk);
625 
626     vk::BufferHelper *getRGBAConversionBufferHelper(vk::Renderer *renderer,
627                                                     angle::FormatID formatID) const;
628     angle::Result convertBufferToRGBA(ContextVk *contextVk, size_t &conversionBufferSize);
629     bool isCompressedFormatEmulated(const gl::Context *context,
630                                     const gl::TextureTarget target,
631                                     GLint level);
632 
633     angle::Result setStorageImpl(ContextVk *contextVk,
634                                  gl::TextureType type,
635                                  const vk::Format &format);
636 
637     bool mOwnsImage;
638     // Generated from ImageVk if EGLImage target, or from throw-away generator if Surface target.
639     UniqueSerial mImageSiblingSerial;
640 
641     bool mRequiresMutableStorage;
642     vk::ImageAccess mRequiredImageAccess;
643     bool mImmutableSamplerDirty;
644 
645     // Only valid if this texture is an "EGLImage target" and the associated EGL Image was
646     // originally sourced from an OpenGL texture. Such EGL Images can be a slice of the underlying
647     // resource. The layer and level offsets are used to track the location of the slice.
648     gl::TextureType mEGLImageNativeType;
649     uint32_t mEGLImageLayerOffset;
650     uint32_t mEGLImageLevelOffset;
651 
652     // If multisampled rendering to texture, an intermediate multisampled image is created for use
653     // as renderpass color attachment. A map of an array of images and image views are used where -
654     //
655     // The map is keyed based on the number of samples used with multisampled rendering to texture.
656     // Index 0 corresponds to the non-multisampled-render-to-texture usage of the texture.
657     // - index 0: Unused.  See description of |mImage|.
658     // - index N: intermediate multisampled image used for multisampled rendering to texture with
659     //            1 << N samples
660     //
661     // Each element in the array corresponds to a mip-level
662     //
663     // - mMultisampledImages[N][M]: intermediate multisampled image with 1 << N samples
664     //                              for level index M
665     using MultiSampleImages = gl::RenderToTextureImageMap<gl::TexLevelArray<vk::ImageHelper>>;
666     std::unique_ptr<MultiSampleImages> mMultisampledImages;
667 
668     // If multisampled rendering to texture, contains views for mMultisampledImages.
669     //
670     // - index 0: Unused.  See description of |mImageView|.
671     // - mMultisampledImageViews[N][M]: views for mMultisampledImages[N][M]
672     using MultiSampleImageViews =
673         gl::RenderToTextureImageMap<gl::TexLevelArray<vk::ImageViewHelper>>;
674     std::unique_ptr<MultiSampleImageViews> mMultisampledImageViews;
675 
676     // Texture buffers create texel buffer views instead.  |BufferViewHelper| contains the views
677     // corresponding to the attached buffer range.
678     vk::BufferViewHelper mBufferViews;
679 
680     // Render targets stored as array of vector of vectors
681     //
682     // - First dimension: index N contains render targets with views from mMultisampledImageViews[N]
683     // - Second dimension: level M contains render targets with views from
684     // mMultisampledImageViews[N][M]
685     // - Third dimension: layer
686     gl::RenderToTextureImageMap<std::vector<RenderTargetVector>> mSingleLayerRenderTargets;
687     // Multi-layer render targets stored as a hash map.  This is used for layered attachments
688     // which covers the entire layer (glFramebufferTextureLayer) or multiview attachments which
689     // cover a range of layers (glFramebufferTextureMultiviewOVR).
690     angle::HashMap<vk::ImageSubresourceRange, std::unique_ptr<RenderTargetVk>>
691         mMultiLayerRenderTargets;
692 
693     // |mImage| wraps a VkImage and VkDeviceMemory that represents the gl::Texture. |mOwnsImage|
694     // indicates that |TextureVk| owns the image. Otherwise it is a weak pointer shared with another
695     // class. Due to this sharing, for example through EGL images, the image must always be
696     // dynamically allocated as the texture can release ownership for example and it can be
697     // transferred to another |TextureVk|.
698     vk::ImageHelper *mImage;
699     // The view is always owned by the Texture and is not shared like |mImage|. It also has
700     // different lifetimes and can be reallocated independently of |mImage| on state changes.
701     vk::ImageViewHelper mImageView;
702 
703     // |mSampler| contains the relevant Vulkan sampler states representing the OpenGL Texture
704     // sampling states for the Texture.
705     vk::SharedSamplerPtr mSampler;
706     // |mY2YSampler| contains a version of mSampler that is meant for use with
707     // __samplerExternal2DY2YEXT (i.e., skipping conversion of YUV to RGB).
708     vk::SharedSamplerPtr mY2YSampler;
709 
710     // The created vkImage usage flag.
711     VkImageUsageFlags mImageUsageFlags;
712 
713     // Additional image create flags
714     VkImageCreateFlags mImageCreateFlags;
715 
716     // If an image level is incompatibly redefined, the image lives through the call that did this
717     // (i.e. set and copy levels), because the image may be used by the framebuffer in the very same
718     // call.  As a result, updates to this redefined level are staged (in both the call that
719     // redefines it, and any future calls such as subimage updates).  This array flags redefined
720     // levels so that their updates will be force-staged until image is recreated.  Each member of
721     // the array is a bitmask per level, and it's an array of cube faces because GL allows
722     // redefining each cube map face separately.  For other texture types, only index 0 is
723     // meaningful as all array levels are redefined simultaneously.
724     //
725     // In common cases with mipmapped textures, the base/max level would need adjusting as the
726     // texture is no longer mip-complete.  However, if every level is redefined such that at the end
727     // the image becomes mip-complete again, no reinitialization of the image is done.  This array
728     // is additionally used to ensure the image is recreated in the next syncState, if not already.
729     //
730     // Note: the elements of this array are bitmasks indexed by gl::LevelIndex, not vk::LevelIndex
731     gl::CubeFaceArray<gl::TexLevelMask> mRedefinedLevels;
732 
733     angle::ObserverBinding mImageObserverBinding;
734 
735     // Saved between updates.
736     gl::LevelIndex mCurrentBaseLevel;
737     gl::LevelIndex mCurrentMaxLevel;
738 
739     // Cached subresource indexes.
740     vk::ImageOrBufferViewSubresourceSerial mCachedImageViewSubresourceSerialSRGBDecode;
741     vk::ImageOrBufferViewSubresourceSerial mCachedImageViewSubresourceSerialSkipDecode;
742 
743     // Manages the texture descriptor set cache that created with this texture
744     vk::DescriptorSetCacheManager mDescriptorSetCacheManager;
745 };
746 
747 }  // namespace rx
748 
749 #endif  // LIBANGLE_RENDERER_VULKAN_TEXTUREVK_H_
750