Hash :
1fbc59fe
Author :
Date :
2016-02-24T15:25:51
D3D11: Enable dirty bits for Framebuffer11. This patch works using a notification scheme - whenever a Texture or Renderbuffer changes in such a way as to recreate its RenderTarget, we pass a signal to the Framebuffer to invalidate some internal state. Everything is entirely tracked in the Renderer11 layer, and the GL layer is left untouched. A RenderTarget11 now tracks points to which it is bound, and the Framebuffer11 is mostly responsible for managing those links. The three locations where we notify a Framebuffer when its bound RenderTargets might be dirty are: 1) RenderTarget11::~RenderTarget 2) EGLImageD3D::copyToLocalRendertarget 3) TextureStorage11_2D::useLevelZeroWorkaroundTexture This patch gives about a 10% score increase in the D3D11 draw call benchmark on my system. BUG=angleproject:1260 Change-Id: Ide38aeadff4a2681bf5bd685e8ca3c9e2612a380 Reviewed-on: https://chromium-review.googlesource.com/327255 Reviewed-by: Geoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@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
//
// Copyright (c) 2015 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.
//
// EGLImageD3D.cpp: Implements the rx::EGLImageD3D class, the D3D implementation of EGL images
#include "libANGLE/renderer/d3d/EGLImageD3D.h"
#include "common/debug.h"
#include "common/utilities.h"
#include "libANGLE/AttributeMap.h"
#include "libANGLE/Texture.h"
#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
#include "libANGLE/renderer/d3d/TextureD3D.h"
#include "libANGLE/renderer/d3d/TextureStorage.h"
#include <EGL/eglext.h>
namespace rx
{
static gl::ImageIndex GetImageIndex(GLenum target, size_t mip, size_t layer)
{
if (target == GL_TEXTURE_3D)
{
return gl::ImageIndex::Make3D(static_cast<GLint>(mip), static_cast<GLint>(layer));
}
else
{
ASSERT(layer == 0);
return gl::ImageIndex::MakeGeneric(target, static_cast<GLint>(mip));
}
}
EGLImageD3D::EGLImageD3D(RendererD3D *renderer,
EGLenum target,
egl::ImageSibling *buffer,
const egl::AttributeMap &attribs)
: mRenderer(renderer), mBuffer(buffer), mAttachmentBuffer(nullptr), mRenderTarget(nullptr)
{
ASSERT(renderer != nullptr);
ASSERT(buffer != nullptr);
if (egl::IsTextureTarget(target))
{
mAttachmentBuffer = GetImplAs<TextureD3D>(GetAs<gl::Texture>(buffer));
mAttachmentTarget = gl::FramebufferAttachment::Target(
GL_NONE, GetImageIndex(egl_gl::EGLImageTargetToGLTextureTarget(target),
attribs.get(EGL_GL_TEXTURE_LEVEL_KHR, 0),
attribs.get(EGL_GL_TEXTURE_ZOFFSET_KHR, 0)));
}
else if (egl::IsRenderbufferTarget(target))
{
mAttachmentBuffer = GetImplAs<RenderbufferD3D>(GetAs<gl::Renderbuffer>(buffer));
mAttachmentTarget =
gl::FramebufferAttachment::Target(GL_NONE, gl::ImageIndex::MakeInvalid());
}
else
{
UNREACHABLE();
}
}
EGLImageD3D::~EGLImageD3D()
{
SafeDelete(mRenderTarget);
}
egl::Error EGLImageD3D::initialize()
{
return egl::Error(EGL_SUCCESS);
}
gl::Error EGLImageD3D::orphan(egl::ImageSibling *sibling)
{
if (sibling == mBuffer)
{
gl::Error error = copyToLocalRendertarget();
if (error.isError())
{
return error;
}
}
return gl::Error(GL_NO_ERROR);
}
gl::Error EGLImageD3D::getRenderTarget(RenderTargetD3D **outRT) const
{
if (mAttachmentBuffer)
{
FramebufferAttachmentRenderTarget *rt = nullptr;
gl::Error error = mAttachmentBuffer->getAttachmentRenderTarget(mAttachmentTarget, &rt);
if (error.isError())
{
return error;
}
*outRT = static_cast<RenderTargetD3D *>(rt);
return gl::Error(GL_NO_ERROR);
}
else
{
ASSERT(mRenderTarget);
*outRT = mRenderTarget;
return gl::Error(GL_NO_ERROR);
}
}
gl::Error EGLImageD3D::copyToLocalRendertarget()
{
ASSERT(mBuffer != nullptr);
ASSERT(mAttachmentBuffer != nullptr);
ASSERT(mRenderTarget == nullptr);
RenderTargetD3D *curRenderTarget = nullptr;
gl::Error error = getRenderTarget(&curRenderTarget);
if (error.isError())
{
return error;
}
// This only currently applies do D3D11, where it invalidates FBOs with this Image attached.
curRenderTarget->signalDirty();
// Clear the source image buffers
mBuffer = nullptr;
mAttachmentBuffer = nullptr;
return mRenderer->createRenderTargetCopy(curRenderTarget, &mRenderTarget);
}
}