• 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                               size_t sourceLevel,
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                                  size_t sourceLevel,
97                                  const gl::Box &sourceBox,
98                                  bool unpackFlipY,
99                                  bool unpackPremultiplyAlpha,
100                                  bool unpackUnmultiplyAlpha,
101                                  const gl::Texture *source) override;
102 
103     angle::Result copyCompressedTexture(const gl::Context *context,
104                                         const gl::Texture *source) override;
105 
106     angle::Result setStorage(const gl::Context *context,
107                              gl::TextureType type,
108                              size_t levels,
109                              GLenum internalFormat,
110                              const gl::Extents &size) override;
111 
112     angle::Result setStorageExternalMemory(const gl::Context *context,
113                                            gl::TextureType type,
114                                            size_t levels,
115                                            GLenum internalFormat,
116                                            const gl::Extents &size,
117                                            gl::MemoryObject *memoryObject,
118                                            GLuint64 offset) override;
119 
120     angle::Result setEGLImageTarget(const gl::Context *context,
121                                     gl::TextureType type,
122                                     egl::Image *image) override;
123 
124     angle::Result setImageExternal(const gl::Context *context,
125                                    gl::TextureType type,
126                                    egl::Stream *stream,
127                                    const egl::Stream::GLTextureDescription &desc) override;
128 
129     angle::Result generateMipmap(const gl::Context *context) override;
130 
131     angle::Result setBaseLevel(const gl::Context *context, GLuint baseLevel) override;
132 
133     angle::Result bindTexImage(const gl::Context *context, egl::Surface *surface) override;
134     angle::Result releaseTexImage(const gl::Context *context) override;
135 
136     angle::Result getAttachmentRenderTarget(const gl::Context *context,
137                                             GLenum binding,
138                                             const gl::ImageIndex &imageIndex,
139                                             GLsizei samples,
140                                             FramebufferAttachmentRenderTarget **rtOut) override;
141 
142     angle::Result syncState(const gl::Context *context,
143                             const gl::Texture::DirtyBits &dirtyBits) override;
144 
145     angle::Result setStorageMultisample(const gl::Context *context,
146                                         gl::TextureType type,
147                                         GLsizei samples,
148                                         GLint internalformat,
149                                         const gl::Extents &size,
150                                         bool fixedSampleLocations) override;
151 
152     angle::Result initializeContents(const gl::Context *context,
153                                      const gl::ImageIndex &imageIndex) override;
154 
isFastUnpackPossible(const vk::Format & vkFormat,size_t offset)155     ANGLE_INLINE bool isFastUnpackPossible(const vk::Format &vkFormat, size_t offset)
156     {
157         // Conditions to determine if fast unpacking is possible
158         // 1. Image must be well defined to unpack directly to it
159         //    TODO(http://anglebug.com/3777) Create and stage a temp image instead
160         // 2. Can't perform a fast copy for emulated formats
161         // 3. vkCmdCopyBufferToImage requires byte offset to be a multiple of 4
162         if (mImage->valid() && (vkFormat.intendedFormatID == vkFormat.actualImageFormatID) &&
163             ((offset & (kBufferOffsetMultiple - 1)) == 0))
164         {
165             return true;
166         }
167 
168         return false;
169     }
170 
getImage()171     const vk::ImageHelper &getImage() const
172     {
173         ASSERT(mImage && mImage->valid());
174         return *mImage;
175     }
176 
getImage()177     vk::ImageHelper &getImage()
178     {
179         ASSERT(mImage && mImage->valid());
180         return *mImage;
181     }
182 
retainImageViews(vk::ResourceUseList * resourceUseList)183     void retainImageViews(vk::ResourceUseList *resourceUseList)
184     {
185         mImageViews.retain(resourceUseList);
186     }
187 
retainSampler(vk::ResourceUseList * resourceUseList)188     void retainSampler(vk::ResourceUseList *resourceUseList) { mSampler.retain(resourceUseList); }
189 
190     void releaseOwnershipOfImage(const gl::Context *context);
191 
192     const vk::ImageView &getReadImageViewAndRecordUse(ContextVk *contextVk) const;
193     // A special view for cube maps as a 2D array, used with shaders that do texelFetch() and for
194     // seamful cube map emulation.
195     const vk::ImageView &getFetchImageViewAndRecordUse(ContextVk *contextVk) const;
196     angle::Result getStorageImageView(ContextVk *contextVk,
197                                       bool allLayers,
198                                       size_t level,
199                                       size_t singleLayer,
200                                       const vk::ImageView **imageViewOut);
201 
getSampler()202     const vk::Sampler &getSampler() const
203     {
204         ASSERT(mSampler.valid());
205         return mSampler.get();
206     }
207 
208     // Normally, initialize the image with enabled mipmap level counts.
209     angle::Result ensureImageInitialized(ContextVk *contextVk, ImageMipLevels mipLevels);
210 
getSerial()211     Serial getSerial() const { return mSerial; }
212 
overrideStagingBufferSizeForTesting(size_t initialSizeForTesting)213     void overrideStagingBufferSizeForTesting(size_t initialSizeForTesting)
214     {
215         mStagingBufferInitialSize = initialSizeForTesting;
216     }
217 
218     GLenum getColorReadFormat(const gl::Context *context) override;
219     GLenum getColorReadType(const gl::Context *context) override;
220 
221     angle::Result getTexImage(const gl::Context *context,
222                               const gl::PixelPackState &packState,
223                               gl::Buffer *packBuffer,
224                               gl::TextureTarget target,
225                               GLint level,
226                               GLenum format,
227                               GLenum type,
228                               void *pixels) override;
229 
isBoundAsImageTexture(gl::ContextID contextID)230     ANGLE_INLINE bool isBoundAsImageTexture(gl::ContextID contextID) const
231     {
232         return mState.isBoundAsImageTexture(contextID);
233     }
234 
235   private:
236     // Transform an image index from the frontend into one that can be used on the backing
237     // ImageHelper, taking into account mipmap or cube face offsets
238     gl::ImageIndex getNativeImageIndex(const gl::ImageIndex &inputImageIndex) const;
239     uint32_t getNativeImageLevel(uint32_t frontendLevel) const;
240     uint32_t getNativeImageLayer(uint32_t frontendLayer) const;
241 
242     void releaseAndDeleteImage(ContextVk *contextVk);
243     angle::Result ensureImageAllocated(ContextVk *contextVk, const vk::Format &format);
244     void setImageHelper(ContextVk *contextVk,
245                         vk::ImageHelper *imageHelper,
246                         gl::TextureType imageType,
247                         const vk::Format &format,
248                         uint32_t imageLevelOffset,
249                         uint32_t imageLayerOffset,
250                         uint32_t imageBaseLevel,
251                         bool selfOwned);
252     void updateImageHelper(ContextVk *contextVk, const vk::Format &internalFormat);
253 
254     angle::Result redefineImage(const gl::Context *context,
255                                 const gl::ImageIndex &index,
256                                 const vk::Format &format,
257                                 const gl::Extents &size);
258 
259     angle::Result setImageImpl(const gl::Context *context,
260                                const gl::ImageIndex &index,
261                                const gl::InternalFormat &formatInfo,
262                                const gl::Extents &size,
263                                GLenum type,
264                                const gl::PixelUnpackState &unpack,
265                                gl::Buffer *unpackBuffer,
266                                const uint8_t *pixels);
267     angle::Result setSubImageImpl(const gl::Context *context,
268                                   const gl::ImageIndex &index,
269                                   const gl::Box &area,
270                                   const gl::InternalFormat &formatInfo,
271                                   GLenum type,
272                                   const gl::PixelUnpackState &unpack,
273                                   gl::Buffer *unpackBuffer,
274                                   const uint8_t *pixels,
275                                   const vk::Format &vkFormat);
276 
277     angle::Result copyImageDataToBufferAndGetData(ContextVk *contextVk,
278                                                   size_t sourceLevel,
279                                                   uint32_t layerCount,
280                                                   const gl::Box &sourceArea,
281                                                   uint8_t **outDataPtr);
282 
283     angle::Result copyBufferDataToImage(ContextVk *contextVk,
284                                         vk::BufferHelper *srcBuffer,
285                                         const gl::ImageIndex index,
286                                         uint32_t rowLength,
287                                         uint32_t imageHeight,
288                                         const gl::Box &sourceArea,
289                                         size_t offset);
290 
291     angle::Result generateMipmapsWithCPU(const gl::Context *context);
292 
293     angle::Result generateMipmapLevelsWithCPU(ContextVk *contextVk,
294                                               const angle::Format &sourceFormat,
295                                               GLuint layer,
296                                               GLuint firstMipLevel,
297                                               GLuint maxMipLevel,
298                                               const size_t sourceWidth,
299                                               const size_t sourceHeight,
300                                               const size_t sourceDepth,
301                                               const size_t sourceRowPitch,
302                                               const size_t sourceDepthPitch,
303                                               uint8_t *sourceData);
304 
305     angle::Result copySubImageImpl(const gl::Context *context,
306                                    const gl::ImageIndex &index,
307                                    const gl::Offset &destOffset,
308                                    const gl::Rectangle &sourceArea,
309                                    const gl::InternalFormat &internalFormat,
310                                    gl::Framebuffer *source);
311 
312     angle::Result copySubTextureImpl(ContextVk *contextVk,
313                                      const gl::ImageIndex &index,
314                                      const gl::Offset &destOffset,
315                                      const gl::InternalFormat &destFormat,
316                                      size_t sourceLevel,
317                                      const gl::Rectangle &sourceArea,
318                                      bool unpackFlipY,
319                                      bool unpackPremultiplyAlpha,
320                                      bool unpackUnmultiplyAlpha,
321                                      TextureVk *source);
322 
323     angle::Result copySubImageImplWithTransfer(ContextVk *contextVk,
324                                                const gl::ImageIndex &index,
325                                                const gl::Offset &destOffset,
326                                                const vk::Format &destFormat,
327                                                size_t sourceLevel,
328                                                size_t sourceLayer,
329                                                const gl::Rectangle &sourceArea,
330                                                vk::ImageHelper *srcImage);
331 
332     angle::Result copySubImageImplWithDraw(ContextVk *contextVk,
333                                            const gl::ImageIndex &index,
334                                            const gl::Offset &destOffset,
335                                            const vk::Format &destFormat,
336                                            size_t sourceLevel,
337                                            const gl::Rectangle &sourceArea,
338                                            bool isSrcFlipY,
339                                            bool unpackFlipY,
340                                            bool unpackPremultiplyAlpha,
341                                            bool unpackUnmultiplyAlpha,
342                                            vk::ImageHelper *srcImage,
343                                            const vk::ImageView *srcView);
344 
345     angle::Result initImage(ContextVk *contextVk,
346                             const vk::Format &format,
347                             const bool sized,
348                             const gl::Extents &extents,
349                             const uint32_t levelCount);
350     void releaseImage(ContextVk *contextVk);
351     void releaseStagingBuffer(ContextVk *contextVk);
352     uint32_t getMipLevelCount(ImageMipLevels mipLevels) const;
353     uint32_t getMaxLevelCount() const;
354     // Used when the image is being redefined (for example to add mips or change base level) to copy
355     // each subresource of the image and stage it for another subresource.  When all subresources
356     // are taken care of, the image is recreated.
357     angle::Result copyAndStageImageSubresource(ContextVk *contextVk,
358                                                const gl::ImageDesc &desc,
359                                                bool ignoreLayerCount,
360                                                uint32_t currentLayer,
361                                                uint32_t sourceLevel,
362                                                uint32_t stagingDstMipLevel);
363     angle::Result initImageViews(ContextVk *contextVk,
364                                  const vk::Format &format,
365                                  const bool sized,
366                                  uint32_t levelCount,
367                                  uint32_t layerCount);
368     angle::Result initRenderTargets(ContextVk *contextVk, GLuint layerCount, GLuint levelIndex);
369     angle::Result getLevelLayerImageView(ContextVk *contextVk,
370                                          size_t level,
371                                          size_t layer,
372                                          const vk::ImageView **imageViewOut);
373 
374     angle::Result ensureImageInitializedImpl(ContextVk *contextVk,
375                                              const gl::Extents &baseLevelExtents,
376                                              uint32_t levelCount,
377                                              const vk::Format &format);
378 
379     const gl::InternalFormat &getImplementationSizedFormat(const gl::Context *context) const;
380     const vk::Format &getBaseLevelFormat(RendererVk *renderer) const;
381     // Re-create the image.
382     angle::Result changeLevels(ContextVk *contextVk,
383                                GLuint previousBaseLevel,
384                                GLuint baseLevel,
385                                GLuint maxLevel);
386 
387     // Update base and max levels, and re-create image if needed.
388     angle::Result updateBaseMaxLevels(ContextVk *contextVk, GLuint baseLevel, GLuint maxLevel);
389 
390     // We monitor the staging buffer and set dirty bits if the staging buffer changes. Note that we
391     // support changes in the staging buffer even outside the TextureVk class.
392     void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
393 
394     bool mOwnsImage;
395 
396     gl::TextureType mImageNativeType;
397 
398     // The layer offset to apply when converting from a frontend texture layer to a texture layer in
399     // mImage. Used when this texture sources a cube map face or 3D texture layer from an EGL image.
400     uint32_t mImageLayerOffset;
401 
402     // The level offset to apply when converting from a frontend texture level to texture level in
403     // mImage.
404     uint32_t mImageLevelOffset;
405 
406     // |mImage| wraps a VkImage and VkDeviceMemory that represents the gl::Texture. |mOwnsImage|
407     // indicates that |TextureVk| owns the image. Otherwise it is a weak pointer shared with another
408     // class.
409     vk::ImageHelper *mImage;
410 
411     // |mImageViews| contains all the current views for the Texture. The views are always owned by
412     // the Texture and are not shared like |mImage|. They also have different lifetimes and can be
413     // reallocated independently of |mImage| on state changes.
414     vk::ImageViewHelper mImageViews;
415 
416     // |mSampler| contains the relevant Vulkan sampler states reprensenting the OpenGL Texture
417     // sampling states for the Texture.
418     vk::SamplerHelper mSampler;
419 
420     // Render targets stored as vector of vectors
421     // Level is first dimension, layer is second
422     std::vector<RenderTargetVector> mRenderTargets;
423 
424     // The serial is used for cache indexing.
425     Serial mSerial;
426 
427     // Overridden in some tests.
428     size_t mStagingBufferInitialSize;
429 
430     // The created vkImage usage flag.
431     VkImageUsageFlags mImageUsageFlags;
432 
433     angle::ObserverBinding mStagingBufferObserverBinding;
434 };
435 
436 }  // namespace rx
437 
438 #endif  // LIBANGLE_RENDERER_VULKAN_TEXTUREVK_H_
439