Commit 4e5f1451 by Kenneth Russell

Add cross-platform Workarounds to Context.

These are distinct from the renderer-level workarounds. Add the first workaround, loseContextOnOutOfMemory. This is enabled when the application enables reset notifications via KHR_robustness, and is intended for more robust handling of errors in key APIs for Chromium's correctness (in particular, sync objects). Change Context::getResetStatus to persistently return the "lost" status if it was set by calling Context::markContextLost. Previously, if markContextLost was called but the implementation hadn't actually received an error like a lost device, the "lost" reset status would be dropped. Returning it only once to the caller is also fragile. Tested this by manually injecting a failure in FenceSync11::clientWait and ensuring that Chromium detected it as expected. BUG=chromium:650138 Change-Id: Ie53069eacd1754ad5d64936e3fef315af24605fa Reviewed-on: https://chromium-review.googlesource.com/394233 Commit-Queue: Kenneth Russell <kbr@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/402250Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 873d00f4
......@@ -35,6 +35,7 @@
#include "libANGLE/VertexArray.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/validationES.h"
#include "libANGLE/Workarounds.h"
#include "libANGLE/renderer/ContextImpl.h"
#include "libANGLE/renderer/EGLImplFactory.h"
#include "libANGLE/queryconversions.h"
......@@ -247,6 +248,7 @@ Context::Context(rx::EGLImplFactory *implFactory,
mHasBeenCurrent(false),
mContextLost(false),
mResetStatus(GL_NO_ERROR),
mContextLostForced(false),
mResetStrategy(GetResetStrategy(attribs)),
mRobustAccess(GetRobustAccess(attribs)),
mCurrentSurface(nullptr),
......@@ -255,6 +257,7 @@ Context::Context(rx::EGLImplFactory *implFactory,
ASSERT(!mRobustAccess); // Unimplemented
initCaps(GetWebGLContext(attribs));
initWorkarounds();
mGLState.initialize(mCaps, mExtensions, mClientMajorVersion, GetDebug(attribs),
GetBindGeneratesResource(attribs));
......@@ -1926,7 +1929,12 @@ void Context::handleError(const Error &error)
{
if (error.isError())
{
mErrors.insert(error.getCode());
GLenum code = error.getCode();
mErrors.insert(code);
if (code == GL_OUT_OF_MEMORY && getWorkarounds().loseContextOnOutOfMemory)
{
markContextLost();
}
if (!error.getMessage().empty())
{
......@@ -1957,7 +1965,10 @@ GLenum Context::getError()
void Context::markContextLost()
{
if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT)
{
mResetStatus = GL_UNKNOWN_CONTEXT_RESET_EXT;
mContextLostForced = true;
}
mContextLost = true;
}
......@@ -1996,8 +2007,11 @@ GLenum Context::getResetStatus()
mContextLost = true;
}
}
else if (mResetStatus != GL_NO_ERROR)
else if (!mContextLostForced && mResetStatus != GL_NO_ERROR)
{
// If markContextLost was used to mark the context lost then
// assume that is not recoverable, and continue to report the
// lost reset status for the lifetime of this context.
mResetStatus = mImplementation->getResetStatus();
}
......@@ -2480,6 +2494,13 @@ void Context::updateCaps()
}
}
void Context::initWorkarounds()
{
// Lose the context upon out of memory error if the application is
// expecting to watch for those events.
mWorkarounds.loseContextOnOutOfMemory = (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT);
}
void Context::syncRendererState()
{
const State::DirtyBits &dirtyBits = mGLState.getDirtyBits();
......@@ -3550,4 +3571,9 @@ void Context::bufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, con
handleError(buffer->bufferSubData(target, data, size, offset));
}
const Workarounds &Context::getWorkarounds() const
{
return mWorkarounds;
}
} // namespace gl
......@@ -22,6 +22,7 @@
#include "libANGLE/Error.h"
#include "libANGLE/HandleAllocator.h"
#include "libANGLE/VertexAttribute.h"
#include "libANGLE/Workarounds.h"
#include "libANGLE/angletypes.h"
namespace rx
......@@ -595,6 +596,7 @@ class Context final : public ValidationContext
size_t getExtensionStringCount() const;
rx::ContextImpl *getImplementation() const { return mImplementation.get(); }
const Workarounds &getWorkarounds() const;
private:
void syncRendererState();
......@@ -620,6 +622,7 @@ class Context final : public ValidationContext
void initCaps(bool webGLContext);
void updateCaps();
void initWorkarounds();
LabeledObject *getLabeledObject(GLenum identifier, GLuint name) const;
LabeledObject *getLabeledObjectFromPtr(const void *ptr) const;
......@@ -672,6 +675,7 @@ class Context final : public ValidationContext
bool mHasBeenCurrent;
bool mContextLost;
GLenum mResetStatus;
bool mContextLostForced;
GLenum mResetStrategy;
bool mRobustAccess;
egl::Surface *mCurrentSurface;
......@@ -686,6 +690,8 @@ class Context final : public ValidationContext
State::DirtyObjects mClearDirtyObjects;
State::DirtyBits mBlitDirtyBits;
State::DirtyObjects mBlitDirtyObjects;
Workarounds mWorkarounds;
};
} // namespace gl
......
//
// Copyright (c) 2016 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.
//
// Workarounds.h: Workarounds for driver bugs and other behaviors seen
// on all platforms.
#ifndef LIBANGLE_WORKAROUNDS_H_
#define LIBANGLE_WORKAROUNDS_H_
namespace gl
{
struct Workarounds
{
// Force the context to be lost (via KHR_robustness) if a GL_OUT_OF_MEMORY error occurs. The
// driver may be in an inconsistent state if this happens, and some users of ANGLE rely on this
// notification to prevent further execution.
bool loseContextOnOutOfMemory = false;
};
} // namespace gl
#endif // LIBANGLE_WORKAROUNDS_H_
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