xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/vulkan/RenderTargetVk.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 // RenderTargetVk:
7 //   Wrapper around a Vulkan renderable resource, using an ImageView.
8 //
9 
10 #ifndef LIBANGLE_RENDERER_VULKAN_RENDERTARGETVK_H_
11 #define LIBANGLE_RENDERER_VULKAN_RENDERTARGETVK_H_
12 
13 #include "common/vulkan/vk_headers.h"
14 #include "libANGLE/FramebufferAttachment.h"
15 #include "libANGLE/renderer/renderer_utils.h"
16 #include "libANGLE/renderer/vulkan/vk_helpers.h"
17 
18 namespace rx
19 {
20 namespace vk
21 {
22 class FramebufferHelper;
23 class ImageHelper;
24 class ImageView;
25 class Resource;
26 class RenderPassDesc;
27 }  // namespace vk
28 
29 class ContextVk;
30 class TextureVk;
31 
32 enum class RenderTargetTransience
33 {
34     // Regular render targets that load and store from the image.
35     Default,
36     // Multisampled-render-to-texture textures, where the implicit multisampled image is transient,
37     // but the resolved image is persistent.
38     MultisampledTransient,
39     // Renderable YUV textures, where the color attachment (if it exists at all) is transient,
40     // but the resolved image is persistent.
41     YuvResolveTransient,
42     // Multisampled-render-to-texture depth/stencil textures.
43     EntirelyTransient,
44 };
45 
46 // This is a very light-weight class that does not own to the resources it points to.
47 // It's meant only to copy across some information from a FramebufferAttachment to the
48 // business rendering logic. It stores Images and ImageViews by pointer for performance.
49 class RenderTargetVk final : public FramebufferAttachmentRenderTarget
50 {
51   public:
52     RenderTargetVk();
53     ~RenderTargetVk() override;
54 
55     // Used in std::vector initialization.
56     RenderTargetVk(RenderTargetVk &&other);
57 
58     void init(vk::ImageHelper *image,
59               vk::ImageViewHelper *imageViews,
60               vk::ImageHelper *resolveImage,
61               vk::ImageViewHelper *resolveImageViews,
62               UniqueSerial imageSiblingSerial,
63               gl::LevelIndex levelIndexGL,
64               uint32_t layerIndex,
65               uint32_t layerCount,
66               RenderTargetTransience transience);
67 
68     vk::ImageOrBufferViewSubresourceSerial getDrawSubresourceSerial() const;
69     vk::ImageOrBufferViewSubresourceSerial getResolveSubresourceSerial() const;
70 
71     // Note: RenderTargets should be called in order, with the depth/stencil onRender last.
72     void onColorDraw(ContextVk *contextVk,
73                      uint32_t framebufferLayerCount,
74                      vk::PackedAttachmentIndex index);
75     void onColorResolve(ContextVk *contextVk,
76                         uint32_t framebufferLayerCount,
77                         size_t readColorIndexGL,
78                         const vk::ImageView &view);
79     void onDepthStencilDraw(ContextVk *contextVk, uint32_t framebufferLayerCount);
80     void onDepthStencilResolve(ContextVk *contextVk,
81                                uint32_t framebufferLayerCount,
82                                VkImageAspectFlags aspects,
83                                const vk::ImageView &view);
84 
85     vk::ImageHelper &getImageForRenderPass();
86     const vk::ImageHelper &getImageForRenderPass() const;
87 
88     vk::ImageHelper &getResolveImageForRenderPass();
89     const vk::ImageHelper &getResolveImageForRenderPass() const;
90 
91     vk::ImageHelper &getImageForCopy() const;
92     vk::ImageHelper &getImageForWrite() const;
93 
94     // For cube maps we use single-level single-layer 2D array views.
95     angle::Result getImageView(vk::Context *context, const vk::ImageView **imageViewOut) const;
96     angle::Result getImageViewWithColorspace(vk::Context *context,
97                                              gl::SrgbWriteControlMode srgbWriteContrlMode,
98                                              const vk::ImageView **imageViewOut) const;
99     angle::Result getResolveImageView(vk::Context *context,
100                                       const vk::ImageView **imageViewOut) const;
101     angle::Result getDepthOrStencilImageView(vk::Context *context,
102                                              VkImageAspectFlagBits aspect,
103                                              const vk::ImageView **imageViewOut) const;
104     angle::Result getDepthOrStencilImageViewForCopy(vk::Context *context,
105                                                     VkImageAspectFlagBits aspect,
106                                                     const vk::ImageView **imageViewOut) const;
107     angle::Result getResolveDepthOrStencilImageView(vk::Context *context,
108                                                     VkImageAspectFlagBits aspect,
109                                                     const vk::ImageView **imageViewOut) const;
110 
111     // For 3D textures, the 2D view created for render target is invalid to read from.  The
112     // following will return a view to the whole image (for all types, including 3D and 2DArray).
113     angle::Result getCopyImageView(vk::Context *context, const vk::ImageView **imageViewOut) const;
114 
115     angle::FormatID getImageActualFormatID() const;
116     const angle::Format &getImageActualFormat() const;
117     angle::FormatID getImageIntendedFormatID() const;
118     const angle::Format &getImageIntendedFormat() const;
119 
120     gl::Extents getExtents() const;
121     gl::Extents getRotatedExtents() const;
getLevelIndex()122     gl::LevelIndex getLevelIndex() const { return mLevelIndexGL; }
123     gl::LevelIndex getLevelIndexForImage(const vk::ImageHelper &image) const;
getLayerIndex()124     uint32_t getLayerIndex() const { return mLayerIndex; }
getLayerCount()125     uint32_t getLayerCount() const { return mLayerCount; }
is3DImage()126     bool is3DImage() const { return getOwnerOfData()->getType() == VK_IMAGE_TYPE_3D; }
127 
128     gl::ImageIndex getImageIndexForClear(uint32_t layerCount) const;
129 
130     // Special mutator for Surface RenderTargets. Allows the Framebuffer to keep a single
131     // RenderTargetVk pointer.
132     void updateSwapchainImage(vk::ImageHelper *image,
133                               vk::ImageViewHelper *imageViews,
134                               vk::ImageHelper *resolveImage,
135                               vk::ImageViewHelper *resolveImageViews);
136 
137     angle::Result flushStagedUpdates(ContextVk *contextVk,
138                                      vk::ClearValuesArray *deferredClears,
139                                      uint32_t deferredClearIndex,
140                                      uint32_t framebufferLayerCount);
141 
142     bool hasDefinedContent() const;
143     bool hasDefinedStencilContent() const;
144     // Mark content as undefined so that certain optimizations are possible such as using DONT_CARE
145     // as loadOp of the render target in the next renderpass.  If |preferToKeepContentsDefinedOut|
146     // is set to true, it's preferred to ignore the invalidation due to image format and device
147     // architecture properties.
148     void invalidateEntireContent(ContextVk *contextVk, bool *preferToKeepContentsDefinedOut);
149     void invalidateEntireStencilContent(ContextVk *contextVk, bool *preferToKeepContentsDefinedOut);
150 
151     // See the description of mTransience for details of how the following two can interact.
hasResolveAttachment()152     bool hasResolveAttachment() const { return mResolveImage != nullptr && !isEntirelyTransient(); }
isImageTransient()153     bool isImageTransient() const { return mTransience != RenderTargetTransience::Default; }
isEntirelyTransient()154     bool isEntirelyTransient() const
155     {
156         return mTransience == RenderTargetTransience::EntirelyTransient;
157     }
isYuvResolve()158     bool isYuvResolve() const
159     {
160         return mResolveImage != nullptr ? mResolveImage->isYuvResolve() : false;
161     }
162 
onNewFramebuffer(const vk::SharedFramebufferCacheKey & sharedFramebufferCacheKey)163     void onNewFramebuffer(const vk::SharedFramebufferCacheKey &sharedFramebufferCacheKey)
164     {
165         mFramebufferCacheManager.addKey(sharedFramebufferCacheKey);
166     }
releaseFramebuffers(ContextVk * contextVk)167     void releaseFramebuffers(ContextVk *contextVk)
168     {
169         mFramebufferCacheManager.releaseKeys(contextVk);
170     }
171     // Releases framebuffers and resets Image and ImageView pointers, while keeping other
172     // members intact, in order to allow |updateSwapchainImage| call later.
releaseImageAndViews(ContextVk * contextVk)173     void releaseImageAndViews(ContextVk *contextVk)
174     {
175         releaseFramebuffers(contextVk);
176         invalidateImageAndViews();
177     }
178     // Releases framebuffers and resets all members to the initial state.
destroy(vk::Renderer * renderer)179     void destroy(vk::Renderer *renderer)
180     {
181         mFramebufferCacheManager.destroyKeys(renderer);
182         reset();
183     }
184 
185     // Helpers to update rendertarget colorspace
updateWriteColorspace(gl::SrgbWriteControlMode srgbWriteControlMode)186     void updateWriteColorspace(gl::SrgbWriteControlMode srgbWriteControlMode)
187     {
188         ASSERT(mImage && mImage->valid() && mImageViews);
189         mImageViews->updateSrgbWiteControlMode(*mImage, srgbWriteControlMode);
190     }
hasColorspaceOverrideForRead()191     bool hasColorspaceOverrideForRead() const
192     {
193         ASSERT(mImage && mImage->valid() && mImageViews);
194         return mImageViews->hasColorspaceOverrideForRead(*mImage);
195     }
hasColorspaceOverrideForWrite()196     bool hasColorspaceOverrideForWrite() const
197     {
198         ASSERT(mImage && mImage->valid() && mImageViews);
199         return mImageViews->hasColorspaceOverrideForWrite(*mImage);
200     }
getColorspaceOverrideFormatForWrite(angle::FormatID format)201     angle::FormatID getColorspaceOverrideFormatForWrite(angle::FormatID format) const
202     {
203         ASSERT(mImage && mImage->valid() && mImageViews);
204         return mImageViews->getColorspaceOverrideFormatForWrite(format);
205     }
206 
207   private:
208     void invalidateImageAndViews();
209     void reset();
210 
211     angle::Result getImageViewImpl(vk::Context *context,
212                                    const vk::ImageHelper &image,
213                                    vk::ImageViewHelper *imageViews,
214                                    const vk::ImageView **imageViewOut) const;
215     angle::Result getDepthOrStencilImageViewImpl(vk::Context *context,
216                                                  const vk::ImageHelper &image,
217                                                  vk::ImageViewHelper *imageViews,
218                                                  VkImageAspectFlagBits aspect,
219                                                  const vk::ImageView **imageViewOut) const;
220 
221     vk::ImageOrBufferViewSubresourceSerial getSubresourceSerialImpl(
222         vk::ImageViewHelper *imageViews) const;
223 
224     bool isResolveImageOwnerOfData() const;
225     vk::ImageHelper *getOwnerOfData() const;
226 
227     // The color or depth/stencil attachment of the framebuffer and its view.
228     vk::ImageHelper *mImage;
229     vk::ImageViewHelper *mImageViews;
230 
231     // If present, this is the corresponding resolve attachment and its view.  This is used to
232     // implement GL_EXT_multisampled_render_to_texture, so while the rendering is done on mImage
233     // during the renderpass, the resolved image is the one that actually holds the data.  This
234     // means that data uploads and blit are done on this image, copies are done out of this image
235     // etc.  This means that if there is no clear, and hasDefined*Content(), the contents of
236     // mResolveImage must be copied to mImage since the loadOp of the attachment must be set to
237     // LOAD.
238     vk::ImageHelper *mResolveImage;
239     vk::ImageViewHelper *mResolveImageViews;
240 
241     UniqueSerial mImageSiblingSerial;
242 
243     // Which subresource of the image is used as render target.
244     //
245     // |mLevelIndexGL| applies to the level index of mImage unless there is a resolve attachment,
246     // in which case |mLevelIndexGL| applies to the mResolveImage since mImage is always
247     // single-level.
248     //
249     // For single-layer render targets, |mLayerIndex| will contain the layer index and |mLayerCount|
250     // will be 1.  For layered render targets, |mLayerIndex| will be 0 and |mLayerCount| will be the
251     // number of layers in the image (or level depth, if image is 3D).  Note that blit and other
252     // functions that read or write to the render target always use layer 0, so this works out for
253     // users of |getLayerIndex()|.
254     gl::LevelIndex mLevelIndexGL;
255     uint32_t mLayerIndex;
256     uint32_t mLayerCount;
257 
258     // If resolve attachment exists, |mTransience| could be *Transient if the multisampled results
259     // need to be discarded.
260     //
261     // - GL_EXT_multisampled_render_to_texture[2]: this is |MultisampledTransient| for render
262     //   targets created from color textures, as well as color or depth/stencil renderbuffers.
263     // - GL_EXT_multisampled_render_to_texture2: this is |EntirelyTransient| for depth/stencil
264     //   textures per this extension, even though a resolve attachment is not even provided.
265     //
266     // Based on the above, we have:
267     //
268     //                     mResolveImage == nullptr
269     //                        Normal rendering
270     // Default                   No resolve
271     //                         storeOp = STORE
272     //                      Owner of data: mImage
273     //
274     //      ---------------------------------------------
275     //
276     //                     mResolveImage != nullptr
277     //               GL_EXT_multisampled_render_to_texture
278     // Multisampled               Resolve
279     // Transient             storeOp = DONT_CARE
280     //                     resolve storeOp = STORE
281     //                   Owner of data: mResolveImage
282     //
283     //      ---------------------------------------------
284     //
285     //                     mResolveImage != nullptr
286     //               GL_EXT_multisampled_render_to_texture2
287     // Entirely                  No Resolve
288     // Transient             storeOp = DONT_CARE
289     //                   Owner of data: mResolveImage
290     //
291     // In the above, storeOp of the resolve attachment is always STORE.  If |Default|, storeOp is
292     // affected by a framebuffer invalidate call.  Note that even though |EntirelyTransient| has a
293     // resolve attachment, it is not used.  The only purpose of |mResolveImage| is to store deferred
294     // clears.
295     RenderTargetTransience mTransience;
296 
297     // Track references to the cached Framebuffer object that created out of this object
298     vk::FramebufferCacheManager mFramebufferCacheManager;
299 };
300 
301 // A vector of rendertargets
302 using RenderTargetVector = std::vector<RenderTargetVk>;
303 }  // namespace rx
304 
305 #endif  // LIBANGLE_RENDERER_VULKAN_RENDERTARGETVK_H_
306