187 lines
6.9 KiB
C
187 lines
6.9 KiB
C
|
|
//
|
||
|
|
// Copyright 2018 The ANGLE Project Authors. All rights reserved.
|
||
|
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
|
// found in the LICENSE file.
|
||
|
|
//
|
||
|
|
// RenderTargetCache:
|
||
|
|
// The RenderTargetCache pattern is used in the D3D9, D3D11 and Vulkan back-ends. It is a
|
||
|
|
// cache of the various back-end objects (RenderTargets) associated with each Framebuffer
|
||
|
|
// attachment, be they Textures, Renderbuffers, or Surfaces. The cache is updated in Framebuffer's
|
||
|
|
// syncState method.
|
||
|
|
//
|
||
|
|
|
||
|
|
#ifndef LIBANGLE_RENDERER_RENDER_TARGET_CACHE_H_
|
||
|
|
#define LIBANGLE_RENDERER_RENDER_TARGET_CACHE_H_
|
||
|
|
|
||
|
|
#include "libANGLE/Framebuffer.h"
|
||
|
|
#include "libANGLE/FramebufferAttachment.h"
|
||
|
|
|
||
|
|
namespace rx
|
||
|
|
{
|
||
|
|
|
||
|
|
template <typename RenderTargetT>
|
||
|
|
class RenderTargetCache final : angle::NonCopyable
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
RenderTargetCache();
|
||
|
|
~RenderTargetCache();
|
||
|
|
|
||
|
|
// Update all RenderTargets from the dirty bits.
|
||
|
|
angle::Result update(const gl::Context *context,
|
||
|
|
const gl::FramebufferState &state,
|
||
|
|
const gl::Framebuffer::DirtyBits &dirtyBits);
|
||
|
|
|
||
|
|
// Update individual RenderTargets.
|
||
|
|
angle::Result updateReadColorRenderTarget(const gl::Context *context,
|
||
|
|
const gl::FramebufferState &state);
|
||
|
|
angle::Result updateColorRenderTarget(const gl::Context *context,
|
||
|
|
const gl::FramebufferState &state,
|
||
|
|
size_t colorIndex);
|
||
|
|
angle::Result updateDepthStencilRenderTarget(const gl::Context *context,
|
||
|
|
const gl::FramebufferState &state);
|
||
|
|
|
||
|
|
using RenderTargetArray = gl::AttachmentArray<RenderTargetT *>;
|
||
|
|
|
||
|
|
const RenderTargetArray &getColors() const;
|
||
|
|
RenderTargetT *getDepthStencil() const;
|
||
|
|
|
||
|
|
RenderTargetT *getColorDraw(const gl::FramebufferState &state, size_t colorIndex) const;
|
||
|
|
RenderTargetT *getColorRead(const gl::FramebufferState &state) const;
|
||
|
|
|
||
|
|
private:
|
||
|
|
angle::Result updateCachedRenderTarget(const gl::Context *context,
|
||
|
|
const gl::FramebufferAttachment *attachment,
|
||
|
|
RenderTargetT **cachedRenderTarget);
|
||
|
|
|
||
|
|
RenderTargetT *mReadRenderTarget = nullptr;
|
||
|
|
gl::AttachmentArray<RenderTargetT *> mColorRenderTargets = {};
|
||
|
|
// We only support a single Depth/Stencil RenderTarget currently.
|
||
|
|
RenderTargetT *mDepthStencilRenderTarget = nullptr;
|
||
|
|
};
|
||
|
|
|
||
|
|
template <typename RenderTargetT>
|
||
|
|
RenderTargetCache<RenderTargetT>::RenderTargetCache() = default;
|
||
|
|
|
||
|
|
template <typename RenderTargetT>
|
||
|
|
RenderTargetCache<RenderTargetT>::~RenderTargetCache() = default;
|
||
|
|
|
||
|
|
template <typename RenderTargetT>
|
||
|
|
angle::Result RenderTargetCache<RenderTargetT>::update(const gl::Context *context,
|
||
|
|
const gl::FramebufferState &state,
|
||
|
|
const gl::Framebuffer::DirtyBits &dirtyBits)
|
||
|
|
{
|
||
|
|
for (auto dirtyBit : dirtyBits)
|
||
|
|
{
|
||
|
|
switch (dirtyBit)
|
||
|
|
{
|
||
|
|
case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
|
||
|
|
case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
|
||
|
|
ANGLE_TRY(updateDepthStencilRenderTarget(context, state));
|
||
|
|
break;
|
||
|
|
case gl::Framebuffer::DIRTY_BIT_READ_BUFFER:
|
||
|
|
ANGLE_TRY(updateReadColorRenderTarget(context, state));
|
||
|
|
break;
|
||
|
|
case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
|
||
|
|
case gl::Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
|
||
|
|
case gl::Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
|
||
|
|
case gl::Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
|
||
|
|
case gl::Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
{
|
||
|
|
static_assert(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0, "FB dirty bits");
|
||
|
|
if (dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX)
|
||
|
|
{
|
||
|
|
size_t colorIndex = static_cast<size_t>(
|
||
|
|
dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
|
||
|
|
ANGLE_TRY(updateColorRenderTarget(context, state, colorIndex));
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return angle::Result::Continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
template <typename RenderTargetT>
|
||
|
|
const gl::AttachmentArray<RenderTargetT *> &RenderTargetCache<RenderTargetT>::getColors() const
|
||
|
|
{
|
||
|
|
return mColorRenderTargets;
|
||
|
|
}
|
||
|
|
|
||
|
|
template <typename RenderTargetT>
|
||
|
|
RenderTargetT *RenderTargetCache<RenderTargetT>::getDepthStencil() const
|
||
|
|
{
|
||
|
|
return mDepthStencilRenderTarget;
|
||
|
|
}
|
||
|
|
|
||
|
|
template <typename RenderTargetT>
|
||
|
|
angle::Result RenderTargetCache<RenderTargetT>::updateReadColorRenderTarget(
|
||
|
|
const gl::Context *context,
|
||
|
|
const gl::FramebufferState &state)
|
||
|
|
{
|
||
|
|
return updateCachedRenderTarget(context, state.getReadAttachment(), &mReadRenderTarget);
|
||
|
|
}
|
||
|
|
|
||
|
|
template <typename RenderTargetT>
|
||
|
|
angle::Result RenderTargetCache<RenderTargetT>::updateColorRenderTarget(
|
||
|
|
const gl::Context *context,
|
||
|
|
const gl::FramebufferState &state,
|
||
|
|
size_t colorIndex)
|
||
|
|
{
|
||
|
|
// If the color render target we're updating is also the read buffer, make sure we update the
|
||
|
|
// read render target also so it's not stale.
|
||
|
|
if (state.getReadBufferState() != GL_NONE && state.getReadIndex() == colorIndex)
|
||
|
|
{
|
||
|
|
ANGLE_TRY(updateReadColorRenderTarget(context, state));
|
||
|
|
}
|
||
|
|
|
||
|
|
return updateCachedRenderTarget(context, state.getColorAttachment(colorIndex),
|
||
|
|
&mColorRenderTargets[colorIndex]);
|
||
|
|
}
|
||
|
|
|
||
|
|
template <typename RenderTargetT>
|
||
|
|
angle::Result RenderTargetCache<RenderTargetT>::updateDepthStencilRenderTarget(
|
||
|
|
const gl::Context *context,
|
||
|
|
const gl::FramebufferState &state)
|
||
|
|
{
|
||
|
|
return updateCachedRenderTarget(context, state.getDepthOrStencilAttachment(),
|
||
|
|
&mDepthStencilRenderTarget);
|
||
|
|
}
|
||
|
|
|
||
|
|
template <typename RenderTargetT>
|
||
|
|
angle::Result RenderTargetCache<RenderTargetT>::updateCachedRenderTarget(
|
||
|
|
const gl::Context *context,
|
||
|
|
const gl::FramebufferAttachment *attachment,
|
||
|
|
RenderTargetT **cachedRenderTarget)
|
||
|
|
{
|
||
|
|
RenderTargetT *newRenderTarget = nullptr;
|
||
|
|
if (attachment)
|
||
|
|
{
|
||
|
|
ASSERT(attachment->isAttached());
|
||
|
|
ANGLE_TRY(attachment->getRenderTarget(context, attachment->getRenderToTextureSamples(),
|
||
|
|
&newRenderTarget));
|
||
|
|
}
|
||
|
|
*cachedRenderTarget = newRenderTarget;
|
||
|
|
return angle::Result::Continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
template <typename RenderTargetT>
|
||
|
|
RenderTargetT *RenderTargetCache<RenderTargetT>::getColorDraw(const gl::FramebufferState &state,
|
||
|
|
size_t colorIndex) const
|
||
|
|
{
|
||
|
|
return mColorRenderTargets[colorIndex];
|
||
|
|
}
|
||
|
|
|
||
|
|
template <typename RenderTargetT>
|
||
|
|
RenderTargetT *RenderTargetCache<RenderTargetT>::getColorRead(
|
||
|
|
const gl::FramebufferState &state) const
|
||
|
|
{
|
||
|
|
return mReadRenderTarget;
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace rx
|
||
|
|
|
||
|
|
#endif // LIBANGLE_RENDERER_RENDER_TARGET_CACHE_H_
|