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 // FramebufferVk.h:
7 //    Defines the class interface for FramebufferVk, implementing FramebufferImpl.
8 //
9 
10 #ifndef LIBANGLE_RENDERER_VULKAN_FRAMEBUFFERVK_H_
11 #define LIBANGLE_RENDERER_VULKAN_FRAMEBUFFERVK_H_
12 
13 #include "libANGLE/angletypes.h"
14 #include "libANGLE/renderer/FramebufferImpl.h"
15 #include "libANGLE/renderer/RenderTargetCache.h"
16 #include "libANGLE/renderer/vulkan/BufferVk.h"
17 #include "libANGLE/renderer/vulkan/ResourceVk.h"
18 #include "libANGLE/renderer/vulkan/UtilsVk.h"
19 #include "libANGLE/renderer/vulkan/vk_cache_utils.h"
20 #include "libANGLE/renderer/vulkan/vk_helpers.h"
21 
22 namespace rx
23 {
24 class RendererVk;
25 class RenderTargetVk;
26 class WindowSurfaceVk;
27 
28 // FramebufferVk Cache
29 class FramebufferCache final : angle::NonCopyable
30 {
31   public:
32     FramebufferCache() = default;
~FramebufferCache()33     ~FramebufferCache() { ASSERT(mPayload.empty()); }
34 
35     void destroy(RendererVk *rendererVk);
36 
37     bool get(ContextVk *contextVk,
38              const vk::FramebufferDesc &desc,
39              vk::FramebufferHelper **framebufferOut);
40     void insert(const vk::FramebufferDesc &desc, vk::FramebufferHelper &&framebufferHelper);
41     void clear(ContextVk *contextVk);
42 
43   private:
44     angle::HashMap<vk::FramebufferDesc, vk::FramebufferHelper> mPayload;
45     CacheStats mCacheStats;
46 };
47 
48 class FramebufferVk : public FramebufferImpl
49 {
50   public:
51     // Factory methods so we don't have to use constructors with overloads.
52     static FramebufferVk *CreateUserFBO(RendererVk *renderer, const gl::FramebufferState &state);
53 
54     // The passed-in SurfaceVk must be destroyed after this FBO is destroyed. Our Surface code is
55     // ref-counted on the number of 'current' contexts, so we shouldn't get any dangling surface
56     // references. See Surface::setIsCurrent(bool).
57     static FramebufferVk *CreateDefaultFBO(RendererVk *renderer,
58                                            const gl::FramebufferState &state,
59                                            WindowSurfaceVk *backbuffer);
60 
61     ~FramebufferVk() override;
62     void destroy(const gl::Context *context) override;
63 
64     angle::Result discard(const gl::Context *context,
65                           size_t count,
66                           const GLenum *attachments) override;
67     angle::Result invalidate(const gl::Context *context,
68                              size_t count,
69                              const GLenum *attachments) override;
70     angle::Result invalidateSub(const gl::Context *context,
71                                 size_t count,
72                                 const GLenum *attachments,
73                                 const gl::Rectangle &area) override;
74 
75     angle::Result clear(const gl::Context *context, GLbitfield mask) override;
76     angle::Result clearBufferfv(const gl::Context *context,
77                                 GLenum buffer,
78                                 GLint drawbuffer,
79                                 const GLfloat *values) override;
80     angle::Result clearBufferuiv(const gl::Context *context,
81                                  GLenum buffer,
82                                  GLint drawbuffer,
83                                  const GLuint *values) override;
84     angle::Result clearBufferiv(const gl::Context *context,
85                                 GLenum buffer,
86                                 GLint drawbuffer,
87                                 const GLint *values) override;
88     angle::Result clearBufferfi(const gl::Context *context,
89                                 GLenum buffer,
90                                 GLint drawbuffer,
91                                 GLfloat depth,
92                                 GLint stencil) override;
93 
94     const gl::InternalFormat &getImplementationColorReadFormat(
95         const gl::Context *context) const override;
96     angle::Result readPixels(const gl::Context *context,
97                              const gl::Rectangle &area,
98                              GLenum format,
99                              GLenum type,
100                              const gl::PixelPackState &pack,
101                              gl::Buffer *packBuffer,
102                              void *pixels) override;
103 
104     angle::Result blit(const gl::Context *context,
105                        const gl::Rectangle &sourceArea,
106                        const gl::Rectangle &destArea,
107                        GLbitfield mask,
108                        GLenum filter) override;
109 
110     gl::FramebufferStatus checkStatus(const gl::Context *context) const override;
111 
112     angle::Result syncState(const gl::Context *context,
113                             GLenum binding,
114                             const gl::Framebuffer::DirtyBits &dirtyBits,
115                             gl::Command command) override;
116 
117     angle::Result getSamplePosition(const gl::Context *context,
118                                     size_t index,
119                                     GLfloat *xy) const override;
120     RenderTargetVk *getDepthStencilRenderTarget() const;
121 
122     // Internal helper function for readPixels operations.
123     angle::Result readPixelsImpl(ContextVk *contextVk,
124                                  const gl::Rectangle &area,
125                                  const PackPixelsParams &packPixelsParams,
126                                  VkImageAspectFlagBits copyAspectFlags,
127                                  RenderTargetVk *renderTarget,
128                                  void *pixels);
129 
130     gl::Extents getReadImageExtents() const;
131     gl::Rectangle getNonRotatedCompleteRenderArea() const;
132     gl::Rectangle getRotatedCompleteRenderArea(ContextVk *contextVk) const;
133     gl::Rectangle getRotatedScissoredRenderArea(ContextVk *contextVk) const;
134 
135     const gl::DrawBufferMask &getEmulatedAlphaAttachmentMask() const;
136     RenderTargetVk *getColorDrawRenderTarget(size_t colorIndex) const;
137     RenderTargetVk *getColorReadRenderTarget() const;
138 
139     angle::Result startNewRenderPass(ContextVk *contextVk,
140                                      const gl::Rectangle &scissoredRenderArea,
141                                      vk::CommandBuffer **commandBufferOut,
142                                      bool *renderPassDescChangedOut);
143 
144     GLint getSamples() const;
145 
getRenderPassDesc()146     const vk::RenderPassDesc &getRenderPassDesc() const { return mRenderPassDesc; }
147 
148     angle::Result getFramebuffer(ContextVk *contextVk,
149                                  vk::Framebuffer **framebufferOut,
150                                  const vk::ImageView *resolveImageViewIn);
151 
hasDeferredClears()152     bool hasDeferredClears() const { return !mDeferredClears.empty(); }
153     angle::Result flushDeferredClears(ContextVk *contextVk);
setReadOnlyDepthFeedbackLoopMode(bool readOnlyDepthFeedbackModeEnabled)154     void setReadOnlyDepthFeedbackLoopMode(bool readOnlyDepthFeedbackModeEnabled)
155     {
156         mReadOnlyDepthFeedbackLoopMode = readOnlyDepthFeedbackModeEnabled;
157     }
isReadOnlyDepthFeedbackLoopMode()158     bool isReadOnlyDepthFeedbackLoopMode() const { return mReadOnlyDepthFeedbackLoopMode; }
159     void updateRenderPassReadOnlyDepthMode(ContextVk *contextVk,
160                                            vk::CommandBufferHelper *renderPass);
161 
162     void onSwitchProgramFramebufferFetch(ContextVk *contextVk, bool programUsesFramebufferFetch);
163 
164   private:
165     FramebufferVk(RendererVk *renderer,
166                   const gl::FramebufferState &state,
167                   WindowSurfaceVk *backbuffer);
168 
169     // The 'in' rectangles must be clipped to the scissor and FBO. The clipping is done in 'blit'.
170     angle::Result blitWithCommand(ContextVk *contextVk,
171                                   const gl::Rectangle &sourceArea,
172                                   const gl::Rectangle &destArea,
173                                   RenderTargetVk *readRenderTarget,
174                                   RenderTargetVk *drawRenderTarget,
175                                   GLenum filter,
176                                   bool colorBlit,
177                                   bool depthBlit,
178                                   bool stencilBlit,
179                                   bool flipX,
180                                   bool flipY);
181 
182     // Resolve color with subpass attachment
183     angle::Result resolveColorWithSubpass(ContextVk *contextVk,
184                                           const UtilsVk::BlitResolveParameters &params);
185 
186     // Resolve color with vkCmdResolveImage
187     angle::Result resolveColorWithCommand(ContextVk *contextVk,
188                                           const UtilsVk::BlitResolveParameters &params,
189                                           vk::ImageHelper *srcImage);
190 
191     angle::Result clearImpl(const gl::Context *context,
192                             gl::DrawBufferMask clearColorBuffers,
193                             bool clearDepth,
194                             bool clearStencil,
195                             const VkClearColorValue &clearColorValue,
196                             const VkClearDepthStencilValue &clearDepthStencilValue);
197 
198     void mergeClearsWithDeferredClears(gl::DrawBufferMask clearColorBuffers,
199                                        bool clearDepth,
200                                        bool clearStencil,
201                                        const VkClearColorValue &clearColorValue,
202                                        const VkClearDepthStencilValue &clearDepthStencilValue);
203     angle::Result clearWithDraw(ContextVk *contextVk,
204                                 const gl::Rectangle &clearArea,
205                                 gl::DrawBufferMask clearColorBuffers,
206                                 bool clearDepth,
207                                 bool clearStencil,
208                                 gl::BlendStateExt::ColorMaskStorage::Type colorMasks,
209                                 uint8_t stencilMask,
210                                 const VkClearColorValue &clearColorValue,
211                                 const VkClearDepthStencilValue &clearDepthStencilValue);
212     void redeferClears(ContextVk *contextVk);
213     angle::Result clearWithCommand(ContextVk *contextVk,
214                                    vk::CommandBufferHelper *renderpassCommands,
215                                    const gl::Rectangle &scissoredRenderArea);
216     void updateActiveColorMasks(size_t colorIndex, bool r, bool g, bool b, bool a);
217     void updateRenderPassDesc(ContextVk *contextVk);
218     angle::Result updateColorAttachment(const gl::Context *context, uint32_t colorIndex);
219     angle::Result updateDepthStencilAttachment(const gl::Context *context);
220     void updateDepthStencilAttachmentSerial(ContextVk *contextVk);
221     angle::Result flushColorAttachmentUpdates(const gl::Context *context,
222                                               bool deferClears,
223                                               uint32_t colorIndex);
224     angle::Result flushDepthStencilAttachmentUpdates(const gl::Context *context, bool deferClears);
225     angle::Result invalidateImpl(ContextVk *contextVk,
226                                  size_t count,
227                                  const GLenum *attachments,
228                                  bool isSubInvalidate,
229                                  const gl::Rectangle &invalidateArea);
230 
231     RenderTargetVk *getReadPixelsRenderTarget(GLenum format) const;
232     VkImageAspectFlagBits getReadPixelsAspectFlags(GLenum format) const;
233 
234     VkClearValue getCorrectedColorClearValue(size_t colorIndexGL,
235                                              const VkClearColorValue &clearColor) const;
236 
237     void updateColorResolveAttachment(
238         uint32_t colorIndexGL,
239         vk::ImageOrBufferViewSubresourceSerial resolveImageViewSerial);
240     void removeColorResolveAttachment(uint32_t colorIndexGL);
241 
242     void updateLayerCount();
243 
244     WindowSurfaceVk *mBackbuffer;
245 
246     vk::RenderPassDesc mRenderPassDesc;
247     vk::FramebufferHelper *mFramebuffer;
248     RenderTargetCache<RenderTargetVk> mRenderTargetCache;
249 
250     // This variable is used to quickly compute if we need to do a masked clear. If a color
251     // channel is masked out, we check against the Framebuffer Attachments (RenderTargets) to see
252     // if the masked out channel is present in any of the attachments.
253     gl::BlendStateExt::ColorMaskStorage::Type mActiveColorComponentMasksForClear;
254     vk::DynamicBuffer mReadPixelBuffer;
255 
256     // When we draw to the framebuffer, and the real format has an alpha channel but the format of
257     // the framebuffer does not, we need to mask out the alpha channel. This DrawBufferMask will
258     // contain the mask to apply to the alpha channel when drawing.
259     gl::DrawBufferMask mEmulatedAlphaAttachmentMask;
260 
261     vk::FramebufferDesc mCurrentFramebufferDesc;
262     FramebufferCache mFramebufferCache;
263 
264     vk::ClearValuesArray mDeferredClears;
265 
266     // Tracks if we are in depth feedback loop. Depth read only feedback loop is a special kind of
267     // depth stencil read only mode. When we are in feedback loop, we must flush renderpass to exit
268     // the loop instead of update the layout.
269     bool mReadOnlyDepthFeedbackLoopMode;
270 };
271 }  // namespace rx
272 
273 #endif  // LIBANGLE_RENDERER_VULKAN_FRAMEBUFFERVK_H_
274