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