RenderTargetCache.h (7089B)
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 updateReadColorRenderTarget(const gl::Context *context, 36 const gl::FramebufferState &state); 37 angle::Result updateColorRenderTarget(const gl::Context *context, 38 const gl::FramebufferState &state, 39 size_t colorIndex); 40 angle::Result updateDepthStencilRenderTarget(const gl::Context *context, 41 const gl::FramebufferState &state); 42 43 using RenderTargetArray = gl::AttachmentArray<RenderTargetT *>; 44 45 const RenderTargetArray &getColors() const; 46 RenderTargetT *getDepthStencil() const; 47 48 RenderTargetT *getColorDraw(const gl::FramebufferState &state, size_t colorIndex) const; 49 RenderTargetT *getColorRead(const gl::FramebufferState &state) const; 50 51 private: 52 angle::Result updateCachedRenderTarget(const gl::Context *context, 53 const gl::FramebufferAttachment *attachment, 54 RenderTargetT **cachedRenderTarget); 55 56 RenderTargetT *mReadRenderTarget = nullptr; 57 gl::AttachmentArray<RenderTargetT *> mColorRenderTargets = {}; 58 // We only support a single Depth/Stencil RenderTarget currently. 59 RenderTargetT *mDepthStencilRenderTarget = nullptr; 60 }; 61 62 template <typename RenderTargetT> 63 RenderTargetCache<RenderTargetT>::RenderTargetCache() = default; 64 65 template <typename RenderTargetT> 66 RenderTargetCache<RenderTargetT>::~RenderTargetCache() = default; 67 68 template <typename RenderTargetT> 69 angle::Result RenderTargetCache<RenderTargetT>::update(const gl::Context *context, 70 const gl::FramebufferState &state, 71 const gl::Framebuffer::DirtyBits &dirtyBits) 72 { 73 for (auto dirtyBit : dirtyBits) 74 { 75 switch (dirtyBit) 76 { 77 case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT: 78 case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT: 79 ANGLE_TRY(updateDepthStencilRenderTarget(context, state)); 80 break; 81 case gl::Framebuffer::DIRTY_BIT_READ_BUFFER: 82 ANGLE_TRY(updateReadColorRenderTarget(context, state)); 83 break; 84 case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS: 85 case gl::Framebuffer::DIRTY_BIT_DEFAULT_WIDTH: 86 case gl::Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT: 87 case gl::Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES: 88 case gl::Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS: 89 break; 90 default: 91 { 92 static_assert(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0, "FB dirty bits"); 93 if (dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX) 94 { 95 size_t colorIndex = static_cast<size_t>( 96 dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0); 97 ANGLE_TRY(updateColorRenderTarget(context, state, colorIndex)); 98 } 99 break; 100 } 101 } 102 } 103 104 return angle::Result::Continue; 105 } 106 107 template <typename RenderTargetT> 108 const gl::AttachmentArray<RenderTargetT *> &RenderTargetCache<RenderTargetT>::getColors() const 109 { 110 return mColorRenderTargets; 111 } 112 113 template <typename RenderTargetT> 114 RenderTargetT *RenderTargetCache<RenderTargetT>::getDepthStencil() const 115 { 116 return mDepthStencilRenderTarget; 117 } 118 119 template <typename RenderTargetT> 120 angle::Result RenderTargetCache<RenderTargetT>::updateReadColorRenderTarget( 121 const gl::Context *context, 122 const gl::FramebufferState &state) 123 { 124 return updateCachedRenderTarget(context, state.getReadAttachment(), &mReadRenderTarget); 125 } 126 127 template <typename RenderTargetT> 128 angle::Result RenderTargetCache<RenderTargetT>::updateColorRenderTarget( 129 const gl::Context *context, 130 const gl::FramebufferState &state, 131 size_t colorIndex) 132 { 133 // If the color render target we're updating is also the read buffer, make sure we update the 134 // read render target also so it's not stale. 135 if (state.getReadBufferState() != GL_NONE && state.getReadIndex() == colorIndex) 136 { 137 ANGLE_TRY(updateReadColorRenderTarget(context, state)); 138 } 139 140 return updateCachedRenderTarget(context, state.getColorAttachment(colorIndex), 141 &mColorRenderTargets[colorIndex]); 142 } 143 144 template <typename RenderTargetT> 145 angle::Result RenderTargetCache<RenderTargetT>::updateDepthStencilRenderTarget( 146 const gl::Context *context, 147 const gl::FramebufferState &state) 148 { 149 return updateCachedRenderTarget(context, state.getDepthOrStencilAttachment(), 150 &mDepthStencilRenderTarget); 151 } 152 153 template <typename RenderTargetT> 154 angle::Result RenderTargetCache<RenderTargetT>::updateCachedRenderTarget( 155 const gl::Context *context, 156 const gl::FramebufferAttachment *attachment, 157 RenderTargetT **cachedRenderTarget) 158 { 159 RenderTargetT *newRenderTarget = nullptr; 160 if (attachment) 161 { 162 ASSERT(attachment->isAttached()); 163 ANGLE_TRY(attachment->getRenderTarget(context, attachment->getRenderToTextureSamples(), 164 &newRenderTarget)); 165 } 166 *cachedRenderTarget = newRenderTarget; 167 return angle::Result::Continue; 168 } 169 170 template <typename RenderTargetT> 171 RenderTargetT *RenderTargetCache<RenderTargetT>::getColorDraw(const gl::FramebufferState &state, 172 size_t colorIndex) const 173 { 174 return mColorRenderTargets[colorIndex]; 175 } 176 177 template <typename RenderTargetT> 178 RenderTargetT *RenderTargetCache<RenderTargetT>::getColorRead( 179 const gl::FramebufferState &state) const 180 { 181 return mReadRenderTarget; 182 } 183 184 } // namespace rx 185 186 #endif // LIBANGLE_RENDERER_RENDER_TARGET_CACHE_H_