• 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               UniqueSerial imageSiblingSerial,
60               gl::LevelIndex levelIndexGL,
61               uint32_t layerIndex,
62               uint32_t layerCount,
63               RenderTargetTransience transience);
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(vk::Context *contextVk, const vk::ImageView **imageViewOut) const;
86     angle::Result getImageViewWithColorspace(vk::Context *context,
87                                              gl::SrgbWriteControlMode srgbWriteContrlMode,
88                                              const vk::ImageView **imageViewOut) const;
89     angle::Result getResolveImageView(vk::Context *context,
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 getCopyImageView(vk::Context *context, const vk::ImageView **imageViewOut) const;
95 
96     angle::FormatID getImageActualFormatID() const;
97     const angle::Format &getImageActualFormat() const;
98     angle::FormatID getImageIntendedFormatID() const;
99     const angle::Format &getImageIntendedFormat() const;
100 
101     gl::Extents getExtents() const;
102     gl::Extents getRotatedExtents() const;
getLevelIndex()103     gl::LevelIndex getLevelIndex() const { return mLevelIndexGL; }
getLayerIndex()104     uint32_t getLayerIndex() const { return mLayerIndex; }
getLayerCount()105     uint32_t getLayerCount() const { return mLayerCount; }
106 
107     gl::ImageIndex getImageIndexForClear(uint32_t layerCount) const;
108 
109     // Special mutator for Surface RenderTargets. Allows the Framebuffer to keep a single
110     // RenderTargetVk pointer.
111     void updateSwapchainImage(vk::ImageHelper *image,
112                               vk::ImageViewHelper *imageViews,
113                               vk::ImageHelper *resolveImage,
114                               vk::ImageViewHelper *resolveImageViews);
115 
116     angle::Result flushStagedUpdates(ContextVk *contextVk,
117                                      vk::ClearValuesArray *deferredClears,
118                                      uint32_t deferredClearIndex,
119                                      uint32_t framebufferLayerCount);
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.  If |preferToKeepContentsDefinedOut|
125     // is set to true, it's preferred to ignore the invalidation due to image format and device
126     // architecture properties.
127     void invalidateEntireContent(ContextVk *contextVk, bool *preferToKeepContentsDefinedOut);
128     void invalidateEntireStencilContent(ContextVk *contextVk, bool *preferToKeepContentsDefinedOut);
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 
onNewFramebuffer(const vk::SharedFramebufferCacheKey & sharedFramebufferCacheKey)138     void onNewFramebuffer(const vk::SharedFramebufferCacheKey &sharedFramebufferCacheKey)
139     {
140         ASSERT(!mFramebufferCacheManager.containsKey(sharedFramebufferCacheKey));
141         mFramebufferCacheManager.addKey(sharedFramebufferCacheKey);
142     }
release(ContextVk * contextVk)143     void release(ContextVk *contextVk) { mFramebufferCacheManager.releaseKeys(contextVk); }
destroy(RendererVk * renderer)144     void destroy(RendererVk *renderer) { mFramebufferCacheManager.destroyKeys(renderer); }
145 
146   private:
147     void reset();
148 
149     angle::Result getImageViewImpl(vk::Context *context,
150                                    const vk::ImageHelper &image,
151                                    gl::SrgbWriteControlMode mode,
152                                    vk::ImageViewHelper *imageViews,
153                                    const vk::ImageView **imageViewOut) const;
154 
155     vk::ImageOrBufferViewSubresourceSerial getSubresourceSerialImpl(
156         vk::ImageViewHelper *imageViews) const;
157 
158     bool isResolveImageOwnerOfData() const;
159     vk::ImageHelper *getOwnerOfData() const;
160 
161     // The color or depth/stencil attachment of the framebuffer and its view.
162     vk::ImageHelper *mImage;
163     vk::ImageViewHelper *mImageViews;
164 
165     // If present, this is the corresponding resolve attachment and its view.  This is used to
166     // implement GL_EXT_multisampled_render_to_texture, so while the rendering is done on mImage
167     // during the renderpass, the resolved image is the one that actually holds the data.  This
168     // means that data uploads and blit are done on this image, copies are done out of this image
169     // etc.  This means that if there is no clear, and hasDefined*Content(), the contents of
170     // mResolveImage must be copied to mImage since the loadOp of the attachment must be set to
171     // LOAD.
172     vk::ImageHelper *mResolveImage;
173     vk::ImageViewHelper *mResolveImageViews;
174 
175     UniqueSerial mImageSiblingSerial;
176 
177     // Which subresource of the image is used as render target.  For single-layer render targets,
178     // |mLayerIndex| will contain the layer index and |mLayerCount| will be 1.  For layered render
179     // targets, |mLayerIndex| will be 0 and |mLayerCount| will be the number of layers in the image
180     // (or level depth, if image is 3D).  Note that blit and other functions that read or write to
181     // the render target always use layer 0, so this works out for users of |getLayerIndex()|.
182     gl::LevelIndex mLevelIndexGL;
183     uint32_t mLayerIndex;
184     uint32_t mLayerCount;
185 
186     // If resolve attachment exists, |mTransience| could be *Transient if the multisampled results
187     // need to be discarded.
188     //
189     // - GL_EXT_multisampled_render_to_texture[2]: this is |MultisampledTransient| for render
190     //   targets created from color textures, as well as color or depth/stencil renderbuffers.
191     // - GL_EXT_multisampled_render_to_texture2: this is |EntirelyTransient| for depth/stencil
192     //   textures per this extension, even though a resolve attachment is not even provided.
193     //
194     // Based on the above, we have:
195     //
196     //                     mResolveImage == nullptr
197     //                        Normal rendering
198     // Default                   No resolve
199     //                         storeOp = STORE
200     //                      Owner of data: mImage
201     //
202     //      ---------------------------------------------
203     //
204     //                     mResolveImage != nullptr
205     //               GL_EXT_multisampled_render_to_texture
206     // Multisampled               Resolve
207     // Transient             storeOp = DONT_CARE
208     //                     resolve storeOp = STORE
209     //                   Owner of data: mResolveImage
210     //
211     //      ---------------------------------------------
212     //
213     //                     mResolveImage != nullptr
214     //               GL_EXT_multisampled_render_to_texture2
215     // Entirely                  No Resolve
216     // Transient             storeOp = DONT_CARE
217     //                   Owner of data: mResolveImage
218     //
219     // In the above, storeOp of the resolve attachment is always STORE.  If |Default|, storeOp is
220     // affected by a framebuffer invalidate call.  Note that even though |EntirelyTransient| has a
221     // resolve attachment, it is not used.  The only purpose of |mResolveImage| is to store deferred
222     // clears.
223     RenderTargetTransience mTransience;
224 
225     // Track references to the cached Framebuffer object that created out of this object
226     vk::FramebufferCacheManager mFramebufferCacheManager;
227 };
228 
229 // A vector of rendertargets
230 using RenderTargetVector = std::vector<RenderTargetVk>;
231 }  // namespace rx
232 
233 #endif  // LIBANGLE_RENDERER_VULKAN_RENDERTARGETVK_H_
234