• 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     // 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::ErrorContext *context, const vk::ImageView **imageViewOut) const;
96     angle::Result getImageViewWithColorspace(vk::ErrorContext *context,
97                                              gl::SrgbWriteControlMode srgbWriteContrlMode,
98                                              const vk::ImageView **imageViewOut) const;
99     angle::Result getResolveImageView(vk::ErrorContext *context,
100                                       const vk::ImageView **imageViewOut) const;
101     angle::Result getDepthOrStencilImageView(vk::ErrorContext *context,
102                                              VkImageAspectFlagBits aspect,
103                                              const vk::ImageView **imageViewOut) const;
104     angle::Result getDepthOrStencilImageViewForCopy(vk::ErrorContext *context,
105                                                     VkImageAspectFlagBits aspect,
106                                                     const vk::ImageView **imageViewOut) const;
107     angle::Result getResolveDepthOrStencilImageView(vk::ErrorContext *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::ErrorContext *context,
114                                    const vk::ImageView **imageViewOut) const;
115 
116     angle::FormatID getImageActualFormatID() const;
117     const angle::Format &getImageActualFormat() const;
118     angle::FormatID getImageIntendedFormatID() const;
119     const angle::Format &getImageIntendedFormat() const;
120 
121     gl::Extents getExtents() const;
122     gl::Extents getRotatedExtents() const;
getLevelIndex()123     gl::LevelIndex getLevelIndex() const { return mLevelIndexGL; }
124     gl::LevelIndex getLevelIndexForImage(const vk::ImageHelper &image) const;
getLayerIndex()125     uint32_t getLayerIndex() const { return mLayerIndex; }
getLayerCount()126     uint32_t getLayerCount() const { return mLayerCount; }
is3DImage()127     bool is3DImage() const { return getOwnerOfData()->getType() == VK_IMAGE_TYPE_3D; }
128 
129     gl::ImageIndex getImageIndexForClear(uint32_t layerCount) const;
130 
131     // Special mutator for Surface RenderTargets. Allows the Framebuffer to keep a single
132     // RenderTargetVk pointer.
133     void updateSwapchainImage(vk::ImageHelper *image,
134                               vk::ImageViewHelper *imageViews,
135                               vk::ImageHelper *resolveImage,
136                               vk::ImageViewHelper *resolveImageViews);
137 
138     angle::Result flushStagedUpdates(ContextVk *contextVk,
139                                      vk::ClearValuesArray *deferredClears,
140                                      uint32_t deferredClearIndex,
141                                      uint32_t framebufferLayerCount);
142 
143     bool hasDefinedContent() const;
144     bool hasDefinedStencilContent() const;
145     // Mark content as undefined so that certain optimizations are possible such as using DONT_CARE
146     // as loadOp of the render target in the next renderpass.  If |preferToKeepContentsDefinedOut|
147     // is set to true, it's preferred to ignore the invalidation due to image format and device
148     // architecture properties.
149     void invalidateEntireContent(ContextVk *contextVk, bool *preferToKeepContentsDefinedOut);
150     void invalidateEntireStencilContent(ContextVk *contextVk, bool *preferToKeepContentsDefinedOut);
151 
152     // See the description of mTransience for details of how the following two can interact.
hasResolveAttachment()153     bool hasResolveAttachment() const { return mResolveImage != nullptr && !isEntirelyTransient(); }
isImageTransient()154     bool isImageTransient() const { return mTransience != RenderTargetTransience::Default; }
isEntirelyTransient()155     bool isEntirelyTransient() const
156     {
157         return mTransience == RenderTargetTransience::EntirelyTransient;
158     }
isYuvResolve()159     bool isYuvResolve() const
160     {
161         return mResolveImage != nullptr ? mResolveImage->isYuvResolve() : false;
162     }
163 
onNewFramebuffer(const vk::SharedFramebufferCacheKey & sharedFramebufferCacheKey)164     void onNewFramebuffer(const vk::SharedFramebufferCacheKey &sharedFramebufferCacheKey)
165     {
166         mFramebufferCacheManager.addKey(sharedFramebufferCacheKey);
167     }
releaseFramebuffers(ContextVk * contextVk)168     void releaseFramebuffers(ContextVk *contextVk)
169     {
170         mFramebufferCacheManager.releaseKeys(contextVk);
171     }
172     // Resets all members to the initial state without releasing framebuffers since Window Surface
173     // framebuffers are not managed by the cache.
releaseSwapchainImage()174     void releaseSwapchainImage() { reset(); }
175     // Releases framebuffers and resets all members to the initial state.
release(ContextVk * contextVk)176     void release(ContextVk *contextVk)
177     {
178         releaseFramebuffers(contextVk);
179         reset();
180     }
181     // Destroys framebuffers and resets all members to the initial state.
destroy(vk::Renderer * renderer)182     void destroy(vk::Renderer *renderer)
183     {
184         mFramebufferCacheManager.destroyKeys(renderer);
185         reset();
186     }
187 
188     // Helpers to update rendertarget colorspace
updateWriteColorspace(gl::SrgbWriteControlMode srgbWriteControlMode)189     void updateWriteColorspace(gl::SrgbWriteControlMode srgbWriteControlMode)
190     {
191         ASSERT(mImage && mImage->valid() && mImageViews);
192         mImageViews->updateSrgbWiteControlMode(*mImage, srgbWriteControlMode);
193     }
hasColorspaceOverrideForRead()194     bool hasColorspaceOverrideForRead() const
195     {
196         ASSERT(mImage && mImage->valid() && mImageViews);
197         return mImageViews->hasColorspaceOverrideForRead(*mImage);
198     }
hasColorspaceOverrideForWrite()199     bool hasColorspaceOverrideForWrite() const
200     {
201         ASSERT(mImage && mImage->valid() && mImageViews);
202         return mImageViews->hasColorspaceOverrideForWrite(*mImage);
203     }
getColorspaceOverrideFormatForWrite(angle::FormatID format)204     angle::FormatID getColorspaceOverrideFormatForWrite(angle::FormatID format) const
205     {
206         ASSERT(mImage && mImage->valid() && mImageViews);
207         return mImageViews->getColorspaceOverrideFormatForWrite(format);
208     }
209 
210   private:
211     void reset();
212 
213     angle::Result getImageViewImpl(vk::ErrorContext *context,
214                                    const vk::ImageHelper &image,
215                                    vk::ImageViewHelper *imageViews,
216                                    const vk::ImageView **imageViewOut) const;
217     angle::Result getDepthOrStencilImageViewImpl(vk::ErrorContext *context,
218                                                  const vk::ImageHelper &image,
219                                                  vk::ImageViewHelper *imageViews,
220                                                  VkImageAspectFlagBits aspect,
221                                                  const vk::ImageView **imageViewOut) const;
222 
223     vk::ImageOrBufferViewSubresourceSerial getSubresourceSerialImpl(
224         vk::ImageViewHelper *imageViews) const;
225 
226     bool isResolveImageOwnerOfData() const;
227     vk::ImageHelper *getOwnerOfData() const;
228 
229     // The color or depth/stencil attachment of the framebuffer and its view.
230     vk::ImageHelper *mImage;
231     vk::ImageViewHelper *mImageViews;
232 
233     // If present, this is the corresponding resolve attachment and its view.  This is used to
234     // implement GL_EXT_multisampled_render_to_texture, so while the rendering is done on mImage
235     // during the renderpass, the resolved image is the one that actually holds the data.  This
236     // means that data uploads and blit are done on this image, copies are done out of this image
237     // etc.  This means that if there is no clear, and hasDefined*Content(), the contents of
238     // mResolveImage must be copied to mImage since the loadOp of the attachment must be set to
239     // LOAD.
240     vk::ImageHelper *mResolveImage;
241     vk::ImageViewHelper *mResolveImageViews;
242 
243     UniqueSerial mImageSiblingSerial;
244 
245     // Which subresource of the image is used as render target.
246     //
247     // |mLevelIndexGL| applies to the level index of mImage unless there is a resolve attachment,
248     // in which case |mLevelIndexGL| applies to the mResolveImage since mImage is always
249     // single-level.
250     //
251     // For single-layer render targets, |mLayerIndex| will contain the layer index and |mLayerCount|
252     // will be 1.  For layered render targets, |mLayerIndex| will be 0 and |mLayerCount| will be the
253     // number of layers in the image (or level depth, if image is 3D).  Note that blit and other
254     // functions that read or write to the render target always use layer 0, so this works out for
255     // users of |getLayerIndex()|.
256     gl::LevelIndex mLevelIndexGL;
257     uint32_t mLayerIndex;
258     uint32_t mLayerCount;
259 
260     // If resolve attachment exists, |mTransience| could be *Transient if the multisampled results
261     // need to be discarded.
262     //
263     // - GL_EXT_multisampled_render_to_texture[2]: this is |MultisampledTransient| for render
264     //   targets created from color textures, as well as color or depth/stencil renderbuffers.
265     // - GL_EXT_multisampled_render_to_texture2: this is |EntirelyTransient| for depth/stencil
266     //   textures per this extension, even though a resolve attachment is not even provided.
267     //
268     // Based on the above, we have:
269     //
270     //                     mResolveImage == nullptr
271     //                        Normal rendering
272     // Default                   No resolve
273     //                         storeOp = STORE
274     //                      Owner of data: mImage
275     //
276     //      ---------------------------------------------
277     //
278     //                     mResolveImage != nullptr
279     //               GL_EXT_multisampled_render_to_texture
280     // Multisampled               Resolve
281     // Transient             storeOp = DONT_CARE
282     //                     resolve storeOp = STORE
283     //                   Owner of data: mResolveImage
284     //
285     //      ---------------------------------------------
286     //
287     //                     mResolveImage != nullptr
288     //               GL_EXT_multisampled_render_to_texture2
289     // Entirely                  No Resolve
290     // Transient             storeOp = DONT_CARE
291     //                   Owner of data: mResolveImage
292     //
293     // In the above, storeOp of the resolve attachment is always STORE.  If |Default|, storeOp is
294     // affected by a framebuffer invalidate call.  Note that even though |EntirelyTransient| has a
295     // resolve attachment, it is not used.  The only purpose of |mResolveImage| is to store deferred
296     // clears.
297     RenderTargetTransience mTransience;
298 
299     // Track references to the cached Framebuffer object that created out of this object
300     vk::FramebufferCacheManager mFramebufferCacheManager;
301 };
302 
303 // A vector of rendertargets
304 using RenderTargetVector = std::vector<RenderTargetVk>;
305 }  // namespace rx
306 
307 #endif  // LIBANGLE_RENDERER_VULKAN_RENDERTARGETVK_H_
308