Commit 0a1eeb80 by Jamie Madill Committed by Commit Bot

Call robust resource init before object sync.

This should let the Vulkan back-end only need to sync the Image data once before we use them. Bug: angleproject:3427 Change-Id: I8c6e8794e861f855bddbf651997351e8415e3479 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1602912 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent cc5199af
......@@ -489,6 +489,8 @@ void Context::initialize()
mComputeDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM);
mComputeDirtyObjects.set(State::DIRTY_OBJECT_SAMPLERS);
mCopyImageDirtyObjects.set(State::DIRTY_OBJECT_READ_FRAMEBUFFER);
ANGLE_CONTEXT_TRY(mImplementation->initialize());
}
......@@ -3428,13 +3430,18 @@ void Context::updateCaps()
mThreadPool = angle::WorkerThreadPool::Create(mState.mExtensions.parallelShaderCompile);
// Reinitialize some dirty bits that depend on extensions.
bool robustInit = mState.isRobustResourceInitEnabled();
mDrawDirtyObjects.set(State::DIRTY_OBJECT_DRAW_ATTACHMENTS, robustInit);
mDrawDirtyObjects.set(State::DIRTY_OBJECT_TEXTURES_INIT, robustInit);
mDrawDirtyObjects.set(State::DIRTY_OBJECT_IMAGES_INIT, robustInit);
mBlitDirtyObjects.set(State::DIRTY_OBJECT_DRAW_ATTACHMENTS, robustInit);
mComputeDirtyObjects.set(State::DIRTY_OBJECT_TEXTURES_INIT, robustInit);
mComputeDirtyObjects.set(State::DIRTY_OBJECT_IMAGES_INIT, robustInit);
if (mState.isRobustResourceInitEnabled())
{
mDrawDirtyObjects.set(State::DIRTY_OBJECT_DRAW_ATTACHMENTS);
mDrawDirtyObjects.set(State::DIRTY_OBJECT_TEXTURES_INIT);
mDrawDirtyObjects.set(State::DIRTY_OBJECT_IMAGES_INIT);
mBlitDirtyObjects.set(State::DIRTY_OBJECT_DRAW_ATTACHMENTS);
mBlitDirtyObjects.set(State::DIRTY_OBJECT_READ_ATTACHMENTS);
mComputeDirtyObjects.set(State::DIRTY_OBJECT_TEXTURES_INIT);
mComputeDirtyObjects.set(State::DIRTY_OBJECT_IMAGES_INIT);
mReadPixelsDirtyObjects.set(State::DIRTY_OBJECT_READ_ATTACHMENTS);
mCopyImageDirtyObjects.set(State::DIRTY_OBJECT_READ_ATTACHMENTS);
}
// We need to validate buffer bounds if we are in a WebGL or robust access context and the
// back-end does not support robust buffer access behaviour.
......@@ -3678,8 +3685,7 @@ void Context::copyTexImage2D(TextureTarget target,
GLsizei height,
GLint border)
{
// Only sync the read FBO
ANGLE_CONTEXT_TRY(mState.syncDirtyObject(this, GL_READ_FRAMEBUFFER));
ANGLE_CONTEXT_TRY(mState.syncDirtyObjects(this, mCopyImageDirtyObjects));
Rectangle sourceArea(x, y, width, height);
......@@ -3703,8 +3709,7 @@ void Context::copyTexSubImage2D(TextureTarget target,
return;
}
// Only sync the read FBO
ANGLE_CONTEXT_TRY(mState.syncDirtyObject(this, GL_READ_FRAMEBUFFER));
ANGLE_CONTEXT_TRY(mState.syncDirtyObjects(this, mCopyImageDirtyObjects));
Offset destOffset(xoffset, yoffset, 0);
Rectangle sourceArea(x, y, width, height);
......@@ -3731,8 +3736,7 @@ void Context::copyTexSubImage3D(TextureTarget target,
return;
}
// Only sync the read FBO
ANGLE_CONTEXT_TRY(mState.syncDirtyObject(this, GL_READ_FRAMEBUFFER));
ANGLE_CONTEXT_TRY(mState.syncDirtyObjects(this, mCopyImageDirtyObjects));
Offset destOffset(xoffset, yoffset, zoffset);
Rectangle sourceArea(x, y, width, height);
......@@ -8137,17 +8141,13 @@ void Context::onSubjectStateChange(const Context *context,
break;
case kReadFramebufferSubjectIndex:
if (message == angle::SubjectMessage::DirtyBitsFlagged)
{
mState.setObjectDirty(GL_READ_FRAMEBUFFER);
}
ASSERT(message == angle::SubjectMessage::DirtyBitsFlagged);
mState.setReadFramebufferDirty();
break;
case kDrawFramebufferSubjectIndex:
if (message == angle::SubjectMessage::DirtyBitsFlagged)
{
mState.setDrawFramebufferDirty();
}
ASSERT(message == angle::SubjectMessage::DirtyBitsFlagged);
mState.setDrawFramebufferDirty();
mStateCache.onDrawFramebufferChange(this);
break;
......
......@@ -2014,6 +2014,7 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl
State::DirtyObjects mBlitDirtyObjects;
State::DirtyBits mComputeDirtyBits;
State::DirtyObjects mComputeDirtyObjects;
State::DirtyObjects mCopyImageDirtyObjects;
Workarounds mWorkarounds;
......
......@@ -955,8 +955,8 @@ void Framebuffer::invalidateCompletenessCache(const Context *context)
if (mState.mId != 0)
{
mCachedStatus.reset();
onStateChange(context, angle::SubjectMessage::SubjectChanged);
}
onStateChange(context, angle::SubjectMessage::DirtyBitsFlagged);
}
GLenum Framebuffer::checkStatusImpl(const Context *context)
......@@ -1494,7 +1494,6 @@ angle::Result Framebuffer::readPixels(const Context *context,
GLenum type,
void *pixels)
{
ANGLE_TRY(ensureReadAttachmentInitialized(context, GL_COLOR_BUFFER_BIT));
ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Buffer *unpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
......@@ -1536,12 +1535,6 @@ angle::Result Framebuffer::blit(const Context *context,
return angle::Result::Continue;
}
auto *sourceFBO = context->getState().getReadFramebuffer();
ANGLE_TRY(sourceFBO->ensureReadAttachmentInitialized(context, blitMask));
// TODO(jmadill): Only clear if not the full FBO dimensions, and only specified bitmask.
ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
}
......@@ -1862,7 +1855,6 @@ void Framebuffer::onSubjectStateChange(const Context *context,
ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(index));
mDirtyBits.set(index);
onStateChange(context, angle::SubjectMessage::DirtyBitsFlagged);
invalidateCompletenessCache(context);
......@@ -2153,15 +2145,16 @@ angle::Result Framebuffer::ensureDrawAttachmentsInitialized(const Context *conte
return angle::Result::Continue;
}
angle::Result Framebuffer::ensureReadAttachmentInitialized(const Context *context,
GLbitfield blitMask)
angle::Result Framebuffer::ensureReadAttachmentsInitialized(const Context *context)
{
if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
ASSERT(context->isRobustResourceInitEnabled());
if (mState.mResourceNeedsInit.none())
{
return angle::Result::Continue;
}
if ((blitMask & GL_COLOR_BUFFER_BIT) != 0 && mState.mReadBufferState != GL_NONE)
if (mState.mReadBufferState != GL_NONE)
{
size_t readIndex = mState.getReadIndex();
if (mState.mResourceNeedsInit[readIndex])
......@@ -2171,7 +2164,8 @@ angle::Result Framebuffer::ensureReadAttachmentInitialized(const Context *contex
}
}
if ((blitMask & GL_DEPTH_BUFFER_BIT) != 0 && hasDepth())
// Conservatively init depth since it can be read by BlitFramebuffer.
if (hasDepth())
{
if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
{
......@@ -2180,7 +2174,8 @@ angle::Result Framebuffer::ensureReadAttachmentInitialized(const Context *contex
}
}
if ((blitMask & GL_STENCIL_BUFFER_BIT) != 0 && hasStencil())
// Conservatively init stencil since it can be read by BlitFramebuffer.
if (hasStencil())
{
if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
{
......
......@@ -352,7 +352,9 @@ class Framebuffer final : public angle::ObserverInterface,
GLenum buffer,
GLint drawbuffer);
angle::Result ensureDrawAttachmentsInitialized(const Context *context);
angle::Result ensureReadAttachmentInitialized(const Context *context, GLbitfield blitMask);
// Conservatively initializes both read color and depth. Blit can access the depth buffer.
angle::Result ensureReadAttachmentsInitialized(const Context *context);
Box getDimensions() const;
private:
......
......@@ -2552,26 +2552,65 @@ void State::getBooleani_v(GLenum target, GLuint index, GLboolean *data)
}
}
angle::Result State::syncReadFramebuffer(const Context *context)
angle::Result State::syncTexturesInit(const Context *context)
{
ASSERT(mReadFramebuffer);
return mReadFramebuffer->syncState(context);
ASSERT(mRobustResourceInit);
if (!mProgram)
return angle::Result::Continue;
for (size_t textureUnitIndex : mProgram->getActiveSamplersMask())
{
Texture *texture = mActiveTexturesCache[textureUnitIndex];
if (texture)
{
ANGLE_TRY(texture->ensureInitialized(context));
}
}
return angle::Result::Continue;
}
angle::Result State::syncDrawFramebuffer(const Context *context)
angle::Result State::syncImagesInit(const Context *context)
{
ASSERT(mDrawFramebuffer);
return mDrawFramebuffer->syncState(context);
ASSERT(mRobustResourceInit);
ASSERT(mProgram);
for (size_t imageUnitIndex : mProgram->getActiveImagesMask())
{
Texture *texture = mImageUnits[imageUnitIndex].texture.get();
if (texture)
{
ANGLE_TRY(texture->ensureInitialized(context));
}
}
return angle::Result::Continue;
}
angle::Result State::syncReadAttachments(const Context *context)
{
ASSERT(mReadFramebuffer);
ASSERT(mRobustResourceInit);
return mReadFramebuffer->ensureReadAttachmentsInitialized(context);
}
angle::Result State::syncDrawAttachments(const Context *context)
{
ASSERT(mDrawFramebuffer);
ASSERT(!mDrawFramebuffer->hasAnyDirtyBit());
ASSERT(mRobustResourceInit);
return mDrawFramebuffer->ensureDrawAttachmentsInitialized(context);
}
angle::Result State::syncReadFramebuffer(const Context *context)
{
ASSERT(mReadFramebuffer);
return mReadFramebuffer->syncState(context);
}
angle::Result State::syncDrawFramebuffer(const Context *context)
{
ASSERT(mDrawFramebuffer);
return mDrawFramebuffer->syncState(context);
}
angle::Result State::syncTextures(const Context *context)
{
if (mDirtyTextures.none())
......@@ -2620,39 +2659,6 @@ angle::Result State::syncProgram(const Context *context)
return mProgram->syncState(context);
}
angle::Result State::syncTexturesInit(const Context *context)
{
ASSERT(mRobustResourceInit);
if (!mProgram)
return angle::Result::Continue;
for (size_t textureUnitIndex : mProgram->getActiveSamplersMask())
{
Texture *texture = mActiveTexturesCache[textureUnitIndex];
if (texture)
{
ANGLE_TRY(texture->ensureInitialized(context));
}
}
return angle::Result::Continue;
}
angle::Result State::syncImagesInit(const Context *context)
{
ASSERT(mRobustResourceInit);
ASSERT(mProgram);
for (size_t imageUnitIndex : mProgram->getActiveImagesMask())
{
Texture *texture = mImageUnits[imageUnitIndex].texture.get();
if (texture)
{
ANGLE_TRY(texture->ensureInitialized(context));
}
}
return angle::Result::Continue;
}
angle::Result State::syncDirtyObject(const Context *context, GLenum target)
{
DirtyObjects localSet;
......
......@@ -558,15 +558,16 @@ class State : angle::NonCopyable
// TODO(jmadill): Consider storing dirty objects in a list instead of by binding.
enum DirtyObjectType
{
DIRTY_OBJECT_READ_FRAMEBUFFER = 0,
DIRTY_OBJECT_DRAW_FRAMEBUFFER,
DIRTY_OBJECT_TEXTURES_INIT,
DIRTY_OBJECT_IMAGES_INIT,
DIRTY_OBJECT_READ_ATTACHMENTS,
DIRTY_OBJECT_DRAW_ATTACHMENTS,
DIRTY_OBJECT_READ_FRAMEBUFFER,
DIRTY_OBJECT_DRAW_FRAMEBUFFER,
DIRTY_OBJECT_VERTEX_ARRAY,
DIRTY_OBJECT_TEXTURES, // Top-level dirty bit. Also see mDirtyTextures.
DIRTY_OBJECT_SAMPLERS, // Top-level dirty bit. Also see mDirtySamplers.
DIRTY_OBJECT_PROGRAM,
DIRTY_OBJECT_TEXTURES_INIT,
DIRTY_OBJECT_IMAGES_INIT,
DIRTY_OBJECT_UNKNOWN,
DIRTY_OBJECT_MAX = DIRTY_OBJECT_UNKNOWN,
};
......@@ -590,6 +591,12 @@ class State : angle::NonCopyable
void setTextureDirty(size_t textureUnitIndex);
void setSamplerDirty(size_t samplerIndex);
ANGLE_INLINE void setReadFramebufferDirty()
{
mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
mDirtyObjects.set(DIRTY_OBJECT_READ_ATTACHMENTS);
}
ANGLE_INLINE void setDrawFramebufferDirty()
{
mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER);
......@@ -665,32 +672,41 @@ class State : angle::NonCopyable
Texture *texture);
// Functions to synchronize dirty states
angle::Result syncTexturesInit(const Context *context);
angle::Result syncImagesInit(const Context *context);
angle::Result syncReadAttachments(const Context *context);
angle::Result syncDrawAttachments(const Context *context);
angle::Result syncReadFramebuffer(const Context *context);
angle::Result syncDrawFramebuffer(const Context *context);
angle::Result syncDrawAttachments(const Context *context);
angle::Result syncVertexArray(const Context *context);
angle::Result syncTextures(const Context *context);
angle::Result syncSamplers(const Context *context);
angle::Result syncProgram(const Context *context);
angle::Result syncTexturesInit(const Context *context);
angle::Result syncImagesInit(const Context *context);
using DirtyObjectHandler = angle::Result (State::*)(const Context *context);
static constexpr DirtyObjectHandler kDirtyObjectHandlers[DIRTY_OBJECT_MAX] = {
&State::syncReadFramebuffer, &State::syncDrawFramebuffer, &State::syncDrawAttachments,
&State::syncTexturesInit, &State::syncImagesInit, &State::syncReadAttachments,
&State::syncDrawAttachments, &State::syncReadFramebuffer, &State::syncDrawFramebuffer,
&State::syncVertexArray, &State::syncTextures, &State::syncSamplers,
&State::syncProgram, &State::syncTexturesInit, &State::syncImagesInit};
static_assert(DIRTY_OBJECT_READ_FRAMEBUFFER == 0, "check DIRTY_OBJECT_READ_FRAMEBUFFER index");
static_assert(DIRTY_OBJECT_DRAW_FRAMEBUFFER == 1, "check DIRTY_OBJECT_DRAW_FRAMEBUFFER index");
static_assert(DIRTY_OBJECT_DRAW_ATTACHMENTS == 2, "check DIRTY_OBJECT_DRAW_ATTACHMENTS index");
static_assert(DIRTY_OBJECT_VERTEX_ARRAY == 3, "check DIRTY_OBJECT_VERTEX_ARRAY index");
static_assert(DIRTY_OBJECT_TEXTURES == 4, "check DIRTY_OBJECT_TEXTURES index");
static_assert(DIRTY_OBJECT_SAMPLERS == 5, "check DIRTY_OBJECT_SAMPLERS index");
static_assert(DIRTY_OBJECT_PROGRAM == 6, "check DIRTY_OBJECT_PROGRAM index");
static_assert(DIRTY_OBJECT_TEXTURES_INIT == 7, "check DIRTY_OBJECT_TEXTURES_INIT index");
static_assert(DIRTY_OBJECT_IMAGES_INIT == 8, "check DIRTY_OBJECT_IMAGES_INIT index");
static_assert(DIRTY_OBJECT_MAX == 9, "check DIRTY_OBJECT_MAX");
&State::syncProgram,
};
// Robust init must happen before Framebuffer init for the Vulkan back-end.
static_assert(DIRTY_OBJECT_TEXTURES_INIT < DIRTY_OBJECT_DRAW_FRAMEBUFFER, "init order");
static_assert(DIRTY_OBJECT_IMAGES_INIT < DIRTY_OBJECT_DRAW_FRAMEBUFFER, "init order");
static_assert(DIRTY_OBJECT_DRAW_ATTACHMENTS < DIRTY_OBJECT_DRAW_FRAMEBUFFER, "init order");
static_assert(DIRTY_OBJECT_READ_ATTACHMENTS < DIRTY_OBJECT_READ_FRAMEBUFFER, "init order");
static_assert(DIRTY_OBJECT_TEXTURES_INIT == 0, "check DIRTY_OBJECT_TEXTURES_INIT index");
static_assert(DIRTY_OBJECT_IMAGES_INIT == 1, "check DIRTY_OBJECT_IMAGES_INIT index");
static_assert(DIRTY_OBJECT_READ_ATTACHMENTS == 2, "check DIRTY_OBJECT_READ_ATTACHMENTS index");
static_assert(DIRTY_OBJECT_DRAW_ATTACHMENTS == 3, "check DIRTY_OBJECT_DRAW_ATTACHMENTS index");
static_assert(DIRTY_OBJECT_READ_FRAMEBUFFER == 4, "check DIRTY_OBJECT_READ_FRAMEBUFFER index");
static_assert(DIRTY_OBJECT_DRAW_FRAMEBUFFER == 5, "check DIRTY_OBJECT_DRAW_FRAMEBUFFER index");
static_assert(DIRTY_OBJECT_VERTEX_ARRAY == 6, "check DIRTY_OBJECT_VERTEX_ARRAY index");
static_assert(DIRTY_OBJECT_TEXTURES == 7, "check DIRTY_OBJECT_TEXTURES index");
static_assert(DIRTY_OBJECT_SAMPLERS == 8, "check DIRTY_OBJECT_SAMPLERS index");
static_assert(DIRTY_OBJECT_PROGRAM == 9, "check DIRTY_OBJECT_PROGRAM index");
// Dispatch table for buffer update functions.
static const angle::PackedEnumMap<BufferBinding, BufferBindingSetter> kBufferSetters;
......
......@@ -1120,9 +1120,6 @@ angle::Result Texture::copyImage(Context *context,
ANGLE_TRY(releaseTexImageInternal(context));
ANGLE_TRY(orphanImages(context));
// Ensure source FBO is initialized.
ANGLE_TRY(source->ensureReadAttachmentInitialized(context, GL_COLOR_BUFFER_BIT));
// Use the source FBO size as the init image area.
Box destBox(0, 0, 0, sourceArea.width, sourceArea.height, 1);
ANGLE_TRY(ensureSubImageInitialized(context, target, level, destBox));
......@@ -1154,9 +1151,6 @@ angle::Result Texture::copySubImage(Context *context,
{
ASSERT(TextureTargetToType(index.getTarget()) == mState.mType);
// Ensure source FBO is initialized.
ANGLE_TRY(source->ensureReadAttachmentInitialized(context, GL_COLOR_BUFFER_BIT));
Box destBox(destOffset.x, destOffset.y, destOffset.z, sourceArea.width, sourceArea.height, 1);
ANGLE_TRY(
ensureSubImageInitialized(context, index.getTarget(), index.getLevelIndex(), destBox));
......
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