Commit 362876b1 by Jamie Madill Committed by Commit Bot

Cache Framebuffer completeness.

Improves performance on the render-to-texture microbenchmark by ~3x on the OpenGL back-end. Wipes out several of the top profling hotspots on that benchmark. BUG=angleproject:1388 Change-Id: I6a35a0b435b2ed3c83d32acdb9df090df98214ad Reviewed-on: https://chromium-review.googlesource.com/348957Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
parent 73d417ed
......@@ -12,12 +12,14 @@
#include <vector>
#include "common/Optional.h"
#include "common/angleutils.h"
#include "libANGLE/Constants.h"
#include "libANGLE/Debug.h"
#include "libANGLE/Error.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/RefCountObject.h"
#include "libANGLE/signal_utils.h"
namespace rx
{
......@@ -86,7 +88,7 @@ class FramebufferState final : angle::NonCopyable
GLenum mReadBufferState;
};
class Framebuffer final : public LabeledObject
class Framebuffer final : public LabeledObject, public angle::SignalReceiver
{
public:
Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id);
......@@ -140,10 +142,8 @@ class Framebuffer final : public LabeledObject
int getSamples(const ContextState &state);
GLenum checkStatus(const ContextState &state);
// These methods do not change any state.
// TODO(jmadill): Remove ContextState parameter when able.
int getCachedSamples(const ContextState &state) const;
GLenum getCachedStatus(const ContextState &state) const;
// Helper for checkStatus == GL_FRAMEBUFFER_COMPLETE.
bool complete(const ContextState &state);
bool hasValidDepthStencil() const;
......@@ -200,19 +200,31 @@ class Framebuffer final : public LabeledObject
typedef std::bitset<DIRTY_BIT_MAX> DirtyBits;
bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
void syncState() const;
void syncState();
protected:
// angle::SignalReceiver implementation
void signal(angle::SignalToken token) override;
private:
void detachResourceById(GLenum resourceType, GLuint resourceId);
void detachMatchingAttachment(FramebufferAttachment *attachment,
GLenum matchType,
GLuint matchId,
size_t dirtyBit);
GLenum checkStatusImpl(const ContextState &state);
FramebufferState mState;
rx::FramebufferImpl *mImpl;
GLuint mId;
// TODO(jmadill): See if we can make this non-mutable.
mutable DirtyBits mDirtyBits;
Optional<GLenum> mCachedStatus;
std::vector<angle::ChannelBinding> mDirtyColorAttachmentBindings;
angle::ChannelBinding mDirtyDepthAttachmentBinding;
angle::ChannelBinding mDirtyStencilAttachmentBinding;
DirtyBits mDirtyBits;
};
}
} // namespace gl
#endif // LIBANGLE_FRAMEBUFFER_H_
......@@ -233,4 +233,9 @@ Error FramebufferAttachmentObject::getAttachmentRenderTarget(
return getAttachmentImpl()->getAttachmentRenderTarget(target, rtOut);
}
angle::BroadcastChannel *FramebufferAttachmentObject::getDirtyChannel()
{
return &mDirtyChannel;
}
} // namespace gl
......@@ -15,6 +15,7 @@
#include "libANGLE/angletypes.h"
#include "libANGLE/Error.h"
#include "libANGLE/ImageIndex.h"
#include "libANGLE/signal_utils.h"
namespace egl
{
......@@ -165,8 +166,12 @@ class FramebufferAttachmentObject
Error getAttachmentRenderTarget(const FramebufferAttachment::Target &target,
rx::FramebufferAttachmentRenderTarget **rtOut) const;
angle::BroadcastChannel *getDirtyChannel();
protected:
virtual rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const = 0;
angle::BroadcastChannel mDirtyChannel;
};
inline Extents FramebufferAttachment::getSize() const
......
......@@ -49,47 +49,39 @@ Error Renderbuffer::setStorage(GLenum internalformat, size_t width, size_t heigh
{
orphanImages();
Error error = mRenderbuffer->setStorage(internalformat, width, height);
if (error.isError())
{
return error;
}
ANGLE_TRY(mRenderbuffer->setStorage(internalformat, width, height));
mWidth = static_cast<GLsizei>(width);
mHeight = static_cast<GLsizei>(height);
mInternalFormat = internalformat;
mSamples = 0;
return Error(GL_NO_ERROR);
mDirtyChannel.signal();
return NoError();
}
Error Renderbuffer::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height)
{
orphanImages();
Error error = mRenderbuffer->setStorageMultisample(samples, internalformat, width, height);
if (error.isError())
{
return error;
}
ANGLE_TRY(mRenderbuffer->setStorageMultisample(samples, internalformat, width, height));
mWidth = static_cast<GLsizei>(width);
mHeight = static_cast<GLsizei>(height);
mInternalFormat = internalformat;
mSamples = static_cast<GLsizei>(samples);
return Error(GL_NO_ERROR);
mDirtyChannel.signal();
return NoError();
}
Error Renderbuffer::setStorageEGLImageTarget(egl::Image *image)
{
orphanImages();
Error error = mRenderbuffer->setStorageEGLImageTarget(image);
if (error.isError())
{
return error;
}
ANGLE_TRY(mRenderbuffer->setStorageEGLImageTarget(image));
setTargetImage(image);
......@@ -98,7 +90,9 @@ Error Renderbuffer::setStorageEGLImageTarget(egl::Image *image)
mInternalFormat = image->getInternalFormat();
mSamples = 0;
return Error(GL_NO_ERROR);
mDirtyChannel.signal();
return NoError();
}
rx::RenderbufferImpl *Renderbuffer::getImplementation()
......@@ -181,4 +175,4 @@ Extents Renderbuffer::getAttachmentSize(const FramebufferAttachment::Target & /*
{
return Extents(mWidth, mHeight, 1);
}
}
} // namespace gl
......@@ -779,17 +779,14 @@ Error Texture::setImage(const PixelUnpackState &unpackState,
releaseTexImageInternal();
orphanImages();
Error error =
mTexture->setImage(target, level, internalFormat, size, format, type, unpackState, pixels);
if (error.isError())
{
return error;
}
ANGLE_TRY(
mTexture->setImage(target, level, internalFormat, size, format, type, unpackState, pixels));
mState.setImageDesc(target, level,
ImageDesc(size, GetSizedInternalFormat(internalFormat, type)));
mDirtyChannel.signal();
return Error(GL_NO_ERROR);
return NoError();
}
Error Texture::setSubImage(const PixelUnpackState &unpackState,
......@@ -820,17 +817,14 @@ Error Texture::setCompressedImage(const PixelUnpackState &unpackState,
releaseTexImageInternal();
orphanImages();
Error error = mTexture->setCompressedImage(target, level, internalFormat, size, unpackState,
imageSize, pixels);
if (error.isError())
{
return error;
}
ANGLE_TRY(mTexture->setCompressedImage(target, level, internalFormat, size, unpackState,
imageSize, pixels));
mState.setImageDesc(target, level,
ImageDesc(size, GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
mDirtyChannel.signal();
return Error(GL_NO_ERROR);
return NoError();
}
Error Texture::setCompressedSubImage(const PixelUnpackState &unpackState,
......@@ -858,17 +852,14 @@ Error Texture::copyImage(GLenum target, size_t level, const Rectangle &sourceAre
releaseTexImageInternal();
orphanImages();
Error error = mTexture->copyImage(target, level, sourceArea, internalFormat, source);
if (error.isError())
{
return error;
}
ANGLE_TRY(mTexture->copyImage(target, level, sourceArea, internalFormat, source));
mState.setImageDesc(target, level,
ImageDesc(Extents(sourceArea.width, sourceArea.height, 1),
GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
mDirtyChannel.signal();
return Error(GL_NO_ERROR);
return NoError();
}
Error Texture::copySubImage(GLenum target, size_t level, const Offset &destOffset, const Rectangle &sourceArea,
......@@ -888,17 +879,15 @@ Error Texture::setStorage(GLenum target, GLsizei levels, GLenum internalFormat,
releaseTexImageInternal();
orphanImages();
Error error = mTexture->setStorage(target, levels, internalFormat, size);
if (error.isError())
{
return error;
}
ANGLE_TRY(mTexture->setStorage(target, levels, internalFormat, size));
mState.mImmutableFormat = true;
mState.mImmutableLevels = static_cast<GLuint>(levels);
mState.clearImageDescs();
mState.setImageDescChain(0, static_cast<GLuint>(levels - 1), size, internalFormat);
return Error(GL_NO_ERROR);
mDirtyChannel.signal();
return NoError();
}
Error Texture::generateMipmap()
......@@ -926,6 +915,8 @@ Error Texture::generateMipmap()
baseImageInfo.internalFormat);
}
mDirtyChannel.signal();
return NoError();
}
......@@ -946,6 +937,7 @@ void Texture::bindTexImageFromSurface(egl::Surface *surface)
Extents size(surface->getWidth(), surface->getHeight(), 1);
ImageDesc desc(size, surface->getConfig()->renderTargetFormat);
mState.setImageDesc(mState.mTarget, 0, desc);
mDirtyChannel.signal();
}
void Texture::releaseTexImageFromSurface()
......@@ -957,6 +949,7 @@ void Texture::releaseTexImageFromSurface()
// Erase the image info for level 0
ASSERT(mState.mTarget == GL_TEXTURE_2D);
mState.clearImageDesc(mState.mTarget, 0);
mDirtyChannel.signal();
}
void Texture::bindStream(egl::Stream *stream)
......@@ -984,6 +977,7 @@ void Texture::acquireImageFromStream(const egl::Stream::GLTextureDescription &de
Extents size(desc.width, desc.height, 1);
mState.setImageDesc(mState.mTarget, 0, ImageDesc(size, desc.internalFormat));
mDirtyChannel.signal();
}
void Texture::releaseImageFromStream()
......@@ -993,6 +987,7 @@ void Texture::releaseImageFromStream()
// Set to incomplete
mState.clearImageDesc(mState.mTarget, 0);
mDirtyChannel.signal();
}
void Texture::releaseTexImageInternal()
......@@ -1016,11 +1011,7 @@ Error Texture::setEGLImageTarget(GLenum target, egl::Image *imageTarget)
releaseTexImageInternal();
orphanImages();
Error error = mTexture->setEGLImageTarget(target, imageTarget);
if (error.isError())
{
return error;
}
ANGLE_TRY(mTexture->setEGLImageTarget(target, imageTarget));
setTargetImage(imageTarget);
......@@ -1031,8 +1022,9 @@ Error Texture::setEGLImageTarget(GLenum target, egl::Image *imageTarget)
mState.clearImageDescs();
mState.setImageDesc(target, 0, ImageDesc(size, GetSizedInternalFormat(internalFormat, type)));
mDirtyChannel.signal();
return Error(GL_NO_ERROR);
return NoError();
}
Extents Texture::getAttachmentSize(const gl::FramebufferAttachment::Target &target) const
......@@ -1070,4 +1062,4 @@ rx::FramebufferAttachmentObjectImpl *Texture::getAttachmentImpl() const
{
return mTexture;
}
}
} // namespace gl
......@@ -56,19 +56,14 @@ gl::Error RenderbufferD3D::setStorageMultisample(size_t samples, GLenum internal
}
RenderTargetD3D *newRT = NULL;
gl::Error error =
mRenderer->createRenderTarget(static_cast<int>(width), static_cast<int>(height),
creationFormat, static_cast<GLsizei>(samples), &newRT);
if (error.isError())
{
return error;
}
ANGLE_TRY(mRenderer->createRenderTarget(static_cast<int>(width), static_cast<int>(height),
creationFormat, static_cast<GLsizei>(samples), &newRT));
SafeDelete(mRenderTarget);
mImage = nullptr;
mRenderTarget = newRT;
return gl::Error(GL_NO_ERROR);
return gl::NoError();
}
gl::Error RenderbufferD3D::setStorageEGLImageTarget(egl::Image *image)
......@@ -76,7 +71,7 @@ gl::Error RenderbufferD3D::setStorageEGLImageTarget(egl::Image *image)
mImage = GetImplAs<EGLImageD3D>(image);
SafeDelete(mRenderTarget);
return gl::Error(GL_NO_ERROR);
return gl::NoError();
}
gl::Error RenderbufferD3D::getRenderTarget(RenderTargetD3D **outRenderTarget)
......@@ -88,7 +83,7 @@ gl::Error RenderbufferD3D::getRenderTarget(RenderTargetD3D **outRenderTarget)
else
{
*outRenderTarget = mRenderTarget;
return gl::Error(GL_NO_ERROR);
return gl::NoError();
}
}
......
......@@ -66,6 +66,7 @@ class Framebuffer11 : public FramebufferD3D, public angle::SignalReceiver
const gl::Framebuffer *sourceFramebuffer) override;
gl::Error invalidateBase(size_t count, const GLenum *attachments, bool useEXTBehavior) const;
gl::Error invalidateAttachment(const gl::FramebufferAttachment *attachment) const;
GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override;
......
......@@ -1498,16 +1498,14 @@ gl::Error Renderer11::updateState(const gl::ContextState &data, GLenum drawMode)
// Applies the render target surface, depth stencil surface, viewport rectangle and
// scissor rectangle to the renderer
gl::Framebuffer *framebufferObject = glState.getDrawFramebuffer();
ASSERT(framebufferObject &&
framebufferObject->getCachedStatus(data) == GL_FRAMEBUFFER_COMPLETE);
ANGLE_TRY(applyRenderTarget(framebufferObject));
gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit() && framebuffer->complete(data));
ANGLE_TRY(applyRenderTarget(framebuffer));
// Set the present path state
const bool presentPathFastActive =
UsePresentPathFast(this, framebufferObject->getFirstColorbuffer());
mStateManager.updatePresentPath(presentPathFastActive,
framebufferObject->getFirstColorbuffer());
auto firstColorAttachment = framebuffer->getFirstColorbuffer();
const bool presentPathFastActive = UsePresentPathFast(this, firstColorAttachment);
mStateManager.updatePresentPath(presentPathFastActive, firstColorAttachment);
// Setting viewport state
mStateManager.setViewport(&data.getCaps(), glState.getViewport(), glState.getNearPlane(),
......@@ -1517,7 +1515,7 @@ gl::Error Renderer11::updateState(const gl::ContextState &data, GLenum drawMode)
mStateManager.setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
// Applying rasterizer state to D3D11 device
int samples = framebufferObject->getCachedSamples(data);
int samples = framebuffer->getSamples(data);
gl::RasterizerState rasterizer = glState.getRasterizerState();
rasterizer.pointDrawMode = (drawMode == GL_POINTS);
rasterizer.multiSample = (samples != 0);
......@@ -1526,7 +1524,7 @@ gl::Error Renderer11::updateState(const gl::ContextState &data, GLenum drawMode)
// Setting blend state
unsigned int mask = GetBlendSampleMask(data, samples);
ANGLE_TRY(mStateManager.setBlendState(framebufferObject, glState.getBlendState(),
ANGLE_TRY(mStateManager.setBlendState(framebuffer, glState.getBlendState(),
glState.getBlendColor(), mask));
// Setting depth stencil state
......
......@@ -893,11 +893,10 @@ gl::Error Renderer9::updateState(Context9 *context, GLenum drawMode)
// Applies the render target surface, depth stencil surface, viewport rectangle and
// scissor rectangle to the renderer
const gl::Framebuffer *framebufferObject = glState.getDrawFramebuffer();
ASSERT(framebufferObject &&
framebufferObject->getCachedStatus(data) == GL_FRAMEBUFFER_COMPLETE);
gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit() && framebuffer->complete(data));
ANGLE_TRY(applyRenderTarget(context, framebufferObject));
ANGLE_TRY(applyRenderTarget(context, framebuffer));
// Setting viewport state
setViewport(glState.getViewport(), glState.getNearPlane(), glState.getFarPlane(), drawMode,
......@@ -907,7 +906,7 @@ gl::Error Renderer9::updateState(Context9 *context, GLenum drawMode)
setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
// Setting blend, depth stencil, and rasterizer states
int samples = framebufferObject->getCachedSamples(data);
int samples = framebuffer->getSamples(data);
gl::RasterizerState rasterizer = glState.getRasterizerState();
rasterizer.pointDrawMode = (drawMode == GL_POINTS);
rasterizer.multiSample = (samples != 0);
......@@ -927,8 +926,10 @@ void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
gl::Error Renderer9::setBlendDepthRasterStates(const gl::ContextState &glData, GLenum drawMode)
{
const auto &glState = glData.getState();
int samples = glState.getDrawFramebuffer()->getCachedSamples(glData);
const auto &glState = glData.getState();
auto drawFramebuffer = glState.getDrawFramebuffer();
ASSERT(!drawFramebuffer->hasAnyDirtyBit());
int samples = drawFramebuffer->getSamples(glData);
gl::RasterizerState rasterizer = glState.getRasterizerState();
rasterizer.pointDrawMode = (drawMode == GL_POINTS);
rasterizer.multiSample = (samples != 0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment