• 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 // 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     // Multisampled-render-to-texture depth/stencil textures.
40     EntirelyTransient,
41 };
42 
43 // This is a very light-weight class that does not own to the resources it points to.
44 // It's meant only to copy across some information from a FramebufferAttachment to the
45 // business rendering logic. It stores Images and ImageViews by pointer for performance.
46 class RenderTargetVk final : public FramebufferAttachmentRenderTarget
47 {
48   public:
49     RenderTargetVk();
50     ~RenderTargetVk() override;
51 
52     // Used in std::vector initialization.
53     RenderTargetVk(RenderTargetVk &&other);
54 
55     void init(vk::ImageHelper *image,
56               vk::ImageViewHelper *imageViews,
57               vk::ImageHelper *resolveImage,
58               vk::ImageViewHelper *resolveImageViews,
59               gl::LevelIndex levelIndexGL,
60               uint32_t layerIndex,
61               uint32_t layerCount,
62               RenderTargetTransience transience);
63     void reset();
64 
65     vk::ImageOrBufferViewSubresourceSerial getDrawSubresourceSerial() const;
66     vk::ImageOrBufferViewSubresourceSerial getResolveSubresourceSerial() const;
67 
68     // Note: RenderTargets should be called in order, with the depth/stencil onRender last.
69     void onColorDraw(ContextVk *contextVk,
70                      uint32_t framebufferLayerCount,
71                      vk::PackedAttachmentIndex index);
72     void onColorResolve(ContextVk *contextVk, uint32_t framebufferLayerCount);
73     void onDepthStencilDraw(ContextVk *contextVk, uint32_t framebufferLayerCount);
74 
75     vk::ImageHelper &getImageForRenderPass();
76     const vk::ImageHelper &getImageForRenderPass() const;
77 
78     vk::ImageHelper &getResolveImageForRenderPass();
79     const vk::ImageHelper &getResolveImageForRenderPass() const;
80 
81     vk::ImageHelper &getImageForCopy() const;
82     vk::ImageHelper &getImageForWrite() const;
83 
84     // For cube maps we use single-level single-layer 2D array views.
85     angle::Result getImageView(ContextVk *contextVk, const vk::ImageView **imageViewOut) const;
86     angle::Result getImageViewWithColorspace(ContextVk *contextVk,
87                                              gl::SrgbWriteControlMode srgbWriteContrlMode,
88                                              const vk::ImageView **imageViewOut) const;
89     angle::Result getResolveImageView(ContextVk *contextVk,
90                                       const vk::ImageView **imageViewOut) const;
91 
92     // For 3D textures, the 2D view created for render target is invalid to read from.  The
93     // following will return a view to the whole image (for all types, including 3D and 2DArray).
94     angle::Result getAndRetainCopyImageView(ContextVk *contextVk,
95                                             const vk::ImageView **imageViewOut) const;
96 
97     angle::FormatID getImageActualFormatID() const;
98     const angle::Format &getImageActualFormat() const;
99     angle::FormatID getImageIntendedFormatID() const;
100     const angle::Format &getImageIntendedFormat() const;
101 
102     gl::Extents getExtents() const;
103     gl::Extents getRotatedExtents() const;
getLevelIndex()104     gl::LevelIndex getLevelIndex() const { return mLevelIndexGL; }
getLayerIndex()105     uint32_t getLayerIndex() const { return mLayerIndex; }
getLayerCount()106     uint32_t getLayerCount() const { return mLayerCount; }
107 
108     gl::ImageIndex getImageIndexForClear(uint32_t layerCount) const;
109 
110     // Special mutator for Surface RenderTargets. Allows the Framebuffer to keep a single
111     // RenderTargetVk pointer.
112     void updateSwapchainImage(vk::ImageHelper *image,
113                               vk::ImageViewHelper *imageViews,
114                               vk::ImageHelper *resolveImage,
115                               vk::ImageViewHelper *resolveImageViews);
116 
117     angle::Result flushStagedUpdates(ContextVk *contextVk,
118                                      vk::ClearValuesArray *deferredClears,
119                                      uint32_t deferredClearIndex,
120                                      uint32_t framebufferLayerCount);
121 
122     void retainImageViews(ContextVk *contextVk) const;
123 
124     bool hasDefinedContent() const;
125     bool hasDefinedStencilContent() const;
126     // Mark content as undefined so that certain optimizations are possible such as using DONT_CARE
127     // as loadOp of the render target in the next renderpass.
128     void invalidateEntireContent(ContextVk *contextVk);
129     void invalidateEntireStencilContent(ContextVk *contextVk);
130     void restoreEntireContent();
131     void restoreEntireStencilContent();
132 
133     // See the description of mTransience for details of how the following two can interact.
hasResolveAttachment()134     bool hasResolveAttachment() const { return mResolveImage != nullptr && !isEntirelyTransient(); }
isImageTransient()135     bool isImageTransient() const { return mTransience != RenderTargetTransience::Default; }
isEntirelyTransient()136     bool isEntirelyTransient() const
137     {
138         return mTransience == RenderTargetTransience::EntirelyTransient;
139     }
140 
141   private:
142     angle::Result getImageViewImpl(ContextVk *contextVk,
143                                    const vk::ImageHelper &image,
144                                    gl::SrgbWriteControlMode mode,
145                                    vk::ImageViewHelper *imageViews,
146                                    const vk::ImageView **imageViewOut) const;
147 
148     vk::ImageOrBufferViewSubresourceSerial getSubresourceSerialImpl(
149         vk::ImageViewHelper *imageViews) const;
150 
151     bool isResolveImageOwnerOfData() const;
152     vk::ImageHelper *getOwnerOfData() const;
153 
154     // The color or depth/stencil attachment of the framebuffer and its view.
155     vk::ImageHelper *mImage;
156     vk::ImageViewHelper *mImageViews;
157 
158     // If present, this is the corresponding resolve attachment and its view.  This is used to
159     // implement GL_EXT_multisampled_render_to_texture, so while the rendering is done on mImage
160     // during the renderpass, the resolved image is the one that actually holds the data.  This
161     // means that data uploads and blit are done on this image, copies are done out of this image
162     // etc.  This means that if there is no clear, and hasDefined*Content(), the contents of
163     // mResolveImage must be copied to mImage since the loadOp of the attachment must be set to
164     // LOAD.
165     vk::ImageHelper *mResolveImage;
166     vk::ImageViewHelper *mResolveImageViews;
167 
168     // Which subresource of the image is used as render target.  For single-layer render targets,
169     // |mLayerIndex| will contain the layer index and |mLayerCount| will be 1.  For layered render
170     // targets, |mLayerIndex| will be 0 and |mLayerCount| will be the number of layers in the image
171     // (or level depth, if image is 3D).  Note that blit and other functions that read or write to
172     // the render target always use layer 0, so this works out for users of |getLayerIndex()|.
173     gl::LevelIndex mLevelIndexGL;
174     uint32_t mLayerIndex;
175     uint32_t mLayerCount;
176 
177     // If resolve attachment exists, |mTransience| could be *Transient if the multisampled results
178     // need to be discarded.
179     //
180     // - GL_EXT_multisampled_render_to_texture[2]: this is |MultisampledTransient| for render
181     //   targets created from color textures, as well as color or depth/stencil renderbuffers.
182     // - GL_EXT_multisampled_render_to_texture2: this is |EntirelyTransient| for depth/stencil
183     //   textures per this extension, even though a resolve attachment is not even provided.
184     //
185     // Based on the above, we have:
186     //
187     //                     mResolveImage == nullptr
188     //                        Normal rendering
189     // Default                   No resolve
190     //                         storeOp = STORE
191     //                      Owner of data: mImage
192     //
193     //      ---------------------------------------------
194     //
195     //                     mResolveImage != nullptr
196     //               GL_EXT_multisampled_render_to_texture
197     // Multisampled               Resolve
198     // Transient             storeOp = DONT_CARE
199     //                     resolve storeOp = STORE
200     //                   Owner of data: mResolveImage
201     //
202     //      ---------------------------------------------
203     //
204     //                     mResolveImage != nullptr
205     //               GL_EXT_multisampled_render_to_texture2
206     // Entirely                  No Resolve
207     // Transient             storeOp = DONT_CARE
208     //                   Owner of data: mResolveImage
209     //
210     // In the above, storeOp of the resolve attachment is always STORE.  If |Default|, storeOp is
211     // affected by a framebuffer invalidate call.  Note that even though |EntirelyTransient| has a
212     // resolve attachment, it is not used.  The only purpose of |mResolveImage| is to store deferred
213     // clears.
214     RenderTargetTransience mTransience;
215 };
216 
217 // A vector of rendertargets
218 using RenderTargetVector = std::vector<RenderTargetVk>;
219 }  // namespace rx
220 
221 #endif  // LIBANGLE_RENDERER_VULKAN_RENDERTARGETVK_H_
222