• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2018 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 // RenderTargetCache:
7 // The RenderTargetCache pattern is used in the D3D9, D3D11 and Vulkan back-ends. It is a
8 // cache of the various back-end objects (RenderTargets) associated with each Framebuffer
9 // attachment, be they Textures, Renderbuffers, or Surfaces. The cache is updated in Framebuffer's
10 // syncState method.
11 //
12 
13 #ifndef LIBANGLE_RENDERER_RENDER_TARGET_CACHE_H_
14 #define LIBANGLE_RENDERER_RENDER_TARGET_CACHE_H_
15 
16 #include "libANGLE/Framebuffer.h"
17 #include "libANGLE/FramebufferAttachment.h"
18 
19 namespace rx
20 {
21 
22 template <typename RenderTargetT>
23 class RenderTargetCache final : angle::NonCopyable
24 {
25   public:
26     RenderTargetCache();
27     ~RenderTargetCache();
28 
29     // Update all RenderTargets from the dirty bits.
30     angle::Result update(const gl::Context *context,
31                          const gl::FramebufferState &state,
32                          const gl::Framebuffer::DirtyBits &dirtyBits);
33 
34     // Update individual RenderTargets.
35     angle::Result updateColorRenderTarget(const gl::Context *context,
36                                           const gl::FramebufferState &state,
37                                           size_t colorIndex);
38     angle::Result updateDepthStencilRenderTarget(const gl::Context *context,
39                                                  const gl::FramebufferState &state);
40 
41     using RenderTargetArray = gl::AttachmentArray<RenderTargetT *>;
42 
43     const RenderTargetArray &getColors() const;
44     RenderTargetT *getDepthStencil() const;
45 
46     RenderTargetT *getColorRead(const gl::FramebufferState &state) const;
47 
48   private:
49     angle::Result updateCachedRenderTarget(const gl::Context *context,
50                                            const gl::FramebufferAttachment *attachment,
51                                            RenderTargetT **cachedRenderTarget);
52 
53     gl::AttachmentArray<RenderTargetT *> mColorRenderTargets;
54     // We only support a single Depth/Stencil RenderTarget currently.
55     RenderTargetT *mDepthStencilRenderTarget;
56 };
57 
58 template <typename RenderTargetT>
RenderTargetCache()59 RenderTargetCache<RenderTargetT>::RenderTargetCache()
60     : mColorRenderTargets{{nullptr}}, mDepthStencilRenderTarget(nullptr)
61 {}
62 
63 template <typename RenderTargetT>
~RenderTargetCache()64 RenderTargetCache<RenderTargetT>::~RenderTargetCache()
65 {}
66 
67 template <typename RenderTargetT>
update(const gl::Context * context,const gl::FramebufferState & state,const gl::Framebuffer::DirtyBits & dirtyBits)68 angle::Result RenderTargetCache<RenderTargetT>::update(const gl::Context *context,
69                                                        const gl::FramebufferState &state,
70                                                        const gl::Framebuffer::DirtyBits &dirtyBits)
71 {
72     for (auto dirtyBit : dirtyBits)
73     {
74         switch (dirtyBit)
75         {
76             case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
77             case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
78                 ANGLE_TRY(updateDepthStencilRenderTarget(context, state));
79                 break;
80             case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
81             case gl::Framebuffer::DIRTY_BIT_READ_BUFFER:
82             case gl::Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
83             case gl::Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
84             case gl::Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
85             case gl::Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
86                 break;
87             default:
88             {
89                 static_assert(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0, "FB dirty bits");
90                 if (dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX)
91                 {
92                     size_t colorIndex = static_cast<size_t>(
93                         dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
94                     ANGLE_TRY(updateColorRenderTarget(context, state, colorIndex));
95                 }
96                 break;
97             }
98         }
99     }
100 
101     return angle::Result::Continue;
102 }
103 
104 template <typename RenderTargetT>
getColors()105 const gl::AttachmentArray<RenderTargetT *> &RenderTargetCache<RenderTargetT>::getColors() const
106 {
107     return mColorRenderTargets;
108 }
109 
110 template <typename RenderTargetT>
getDepthStencil()111 RenderTargetT *RenderTargetCache<RenderTargetT>::getDepthStencil() const
112 {
113     return mDepthStencilRenderTarget;
114 }
115 
116 template <typename RenderTargetT>
updateColorRenderTarget(const gl::Context * context,const gl::FramebufferState & state,size_t colorIndex)117 angle::Result RenderTargetCache<RenderTargetT>::updateColorRenderTarget(
118     const gl::Context *context,
119     const gl::FramebufferState &state,
120     size_t colorIndex)
121 {
122     return updateCachedRenderTarget(context, state.getColorAttachment(colorIndex),
123                                     &mColorRenderTargets[colorIndex]);
124 }
125 
126 template <typename RenderTargetT>
updateDepthStencilRenderTarget(const gl::Context * context,const gl::FramebufferState & state)127 angle::Result RenderTargetCache<RenderTargetT>::updateDepthStencilRenderTarget(
128     const gl::Context *context,
129     const gl::FramebufferState &state)
130 {
131     return updateCachedRenderTarget(context, state.getDepthOrStencilAttachment(),
132                                     &mDepthStencilRenderTarget);
133 }
134 
135 template <typename RenderTargetT>
updateCachedRenderTarget(const gl::Context * context,const gl::FramebufferAttachment * attachment,RenderTargetT ** cachedRenderTarget)136 angle::Result RenderTargetCache<RenderTargetT>::updateCachedRenderTarget(
137     const gl::Context *context,
138     const gl::FramebufferAttachment *attachment,
139     RenderTargetT **cachedRenderTarget)
140 {
141     RenderTargetT *newRenderTarget = nullptr;
142     if (attachment)
143     {
144         ASSERT(attachment->isAttached());
145         ANGLE_TRY(attachment->getRenderTarget(context, &newRenderTarget));
146     }
147     *cachedRenderTarget = newRenderTarget;
148     return angle::Result::Continue;
149 }
150 
151 template <typename RenderTargetT>
getColorRead(const gl::FramebufferState & state)152 RenderTargetT *RenderTargetCache<RenderTargetT>::getColorRead(
153     const gl::FramebufferState &state) const
154 {
155     ASSERT(mColorRenderTargets[state.getReadIndex()] &&
156            state.getReadIndex() < mColorRenderTargets.size());
157     return mColorRenderTargets[state.getReadIndex()];
158 }
159 
160 }  // namespace rx
161 
162 #endif  // LIBANGLE_RENDERER_RENDER_TARGET_CACHE_H_
163