Hash :
6722009e
Author :
Date :
2019-05-20T11:12:53
Vulkan: Handle dirty RTs with state messages. Prior to this CL we were handling dirty state change notifications by flushing the RT Images just prior to use or just after they were changed. This could lead to a few redundant checks in several places. It also meant we needed an owner pointer from the RT to the parent Image. This pointer would be null for Surfaces and Renderbuffers. This cleans up the image flushing logic to be handled by dirty bit notifications. When an app updates an attached Texture with TexSubImage or related calls it will send a notification to the Framebuffer. The Framebuffer then sets a dirty contents bit that is handled in the implementation. In Vulkan this means flushing the dirty bits. Requires adding a flag to the FramebufferImpl class to determine if we need to syncState before we checkStatus. Adding the option allows us to only call syncState for the GL back-end. Not calling syncState allows the robust resource init operation to happen *before* we syncState. Which in turn allows FramebuffeVk to initialize the VkImages in one go. Added new regression tests for Texture updates. This might not cover all cases. I found it was very hard to trigger some of the resource update staging in TextureVk. Bug: angleproject:3427 Change-Id: Idfa177436ba7fcb9d398f2b67922e085f778f82a Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1601552 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
//
// 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 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 *getColorRead(const gl::FramebufferState &state) const;
private:
angle::Result updateCachedRenderTarget(const gl::Context *context,
const gl::FramebufferAttachment *attachment,
RenderTargetT **cachedRenderTarget);
gl::AttachmentArray<RenderTargetT *> mColorRenderTargets;
// We only support a single Depth/Stencil RenderTarget currently.
RenderTargetT *mDepthStencilRenderTarget;
};
template <typename RenderTargetT>
RenderTargetCache<RenderTargetT>::RenderTargetCache()
: mColorRenderTargets{{nullptr}}, mDepthStencilRenderTarget(nullptr)
{}
template <typename RenderTargetT>
RenderTargetCache<RenderTargetT>::~RenderTargetCache()
{}
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_DRAW_BUFFERS:
case gl::Framebuffer::DIRTY_BIT_READ_BUFFER:
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>::updateColorRenderTarget(
const gl::Context *context,
const gl::FramebufferState &state,
size_t colorIndex)
{
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, &newRenderTarget));
}
*cachedRenderTarget = newRenderTarget;
return angle::Result::Continue;
}
template <typename RenderTargetT>
RenderTargetT *RenderTargetCache<RenderTargetT>::getColorRead(
const gl::FramebufferState &state) const
{
ASSERT(mColorRenderTargets[state.getReadIndex()] &&
state.getReadIndex() < mColorRenderTargets.size());
return mColorRenderTargets[state.getReadIndex()];
}
} // namespace rx
#endif // LIBANGLE_RENDERER_RENDER_TARGET_CACHE_H_