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 @@ ...@@ -35,6 +35,7 @@
#include "libANGLE/VertexArray.h" #include "libANGLE/VertexArray.h"
#include "libANGLE/formatutils.h" #include "libANGLE/formatutils.h"
#include "libANGLE/validationES.h" #include "libANGLE/validationES.h"
#include "libANGLE/Workarounds.h"
#include "libANGLE/renderer/ContextImpl.h" #include "libANGLE/renderer/ContextImpl.h"
#include "libANGLE/renderer/EGLImplFactory.h" #include "libANGLE/renderer/EGLImplFactory.h"
#include "libANGLE/queryconversions.h" #include "libANGLE/queryconversions.h"
...@@ -247,6 +248,7 @@ Context::Context(rx::EGLImplFactory *implFactory, ...@@ -247,6 +248,7 @@ Context::Context(rx::EGLImplFactory *implFactory,
mHasBeenCurrent(false), mHasBeenCurrent(false),
mContextLost(false), mContextLost(false),
mResetStatus(GL_NO_ERROR), mResetStatus(GL_NO_ERROR),
mContextLostForced(false),
mResetStrategy(GetResetStrategy(attribs)), mResetStrategy(GetResetStrategy(attribs)),
mRobustAccess(GetRobustAccess(attribs)), mRobustAccess(GetRobustAccess(attribs)),
mCurrentSurface(nullptr), mCurrentSurface(nullptr),
...@@ -255,6 +257,7 @@ Context::Context(rx::EGLImplFactory *implFactory, ...@@ -255,6 +257,7 @@ Context::Context(rx::EGLImplFactory *implFactory,
ASSERT(!mRobustAccess); // Unimplemented ASSERT(!mRobustAccess); // Unimplemented
initCaps(GetWebGLContext(attribs)); initCaps(GetWebGLContext(attribs));
initWorkarounds();
mGLState.initialize(mCaps, mExtensions, mClientMajorVersion, GetDebug(attribs), mGLState.initialize(mCaps, mExtensions, mClientMajorVersion, GetDebug(attribs),
GetBindGeneratesResource(attribs)); GetBindGeneratesResource(attribs));
...@@ -1926,7 +1929,12 @@ void Context::handleError(const Error &error) ...@@ -1926,7 +1929,12 @@ void Context::handleError(const Error &error)
{ {
if (error.isError()) 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()) if (!error.getMessage().empty())
{ {
...@@ -1957,7 +1965,10 @@ GLenum Context::getError() ...@@ -1957,7 +1965,10 @@ GLenum Context::getError()
void Context::markContextLost() void Context::markContextLost()
{ {
if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT) if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT)
{
mResetStatus = GL_UNKNOWN_CONTEXT_RESET_EXT; mResetStatus = GL_UNKNOWN_CONTEXT_RESET_EXT;
mContextLostForced = true;
}
mContextLost = true; mContextLost = true;
} }
...@@ -1996,8 +2007,11 @@ GLenum Context::getResetStatus() ...@@ -1996,8 +2007,11 @@ GLenum Context::getResetStatus()
mContextLost = true; 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(); mResetStatus = mImplementation->getResetStatus();
} }
...@@ -2480,6 +2494,13 @@ void Context::updateCaps() ...@@ -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() void Context::syncRendererState()
{ {
const State::DirtyBits &dirtyBits = mGLState.getDirtyBits(); const State::DirtyBits &dirtyBits = mGLState.getDirtyBits();
...@@ -3550,4 +3571,9 @@ void Context::bufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, con ...@@ -3550,4 +3571,9 @@ void Context::bufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, con
handleError(buffer->bufferSubData(target, data, size, offset)); handleError(buffer->bufferSubData(target, data, size, offset));
} }
const Workarounds &Context::getWorkarounds() const
{
return mWorkarounds;
}
} // namespace gl } // namespace gl
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "libANGLE/Error.h" #include "libANGLE/Error.h"
#include "libANGLE/HandleAllocator.h" #include "libANGLE/HandleAllocator.h"
#include "libANGLE/VertexAttribute.h" #include "libANGLE/VertexAttribute.h"
#include "libANGLE/Workarounds.h"
#include "libANGLE/angletypes.h" #include "libANGLE/angletypes.h"
namespace rx namespace rx
...@@ -595,6 +596,7 @@ class Context final : public ValidationContext ...@@ -595,6 +596,7 @@ class Context final : public ValidationContext
size_t getExtensionStringCount() const; size_t getExtensionStringCount() const;
rx::ContextImpl *getImplementation() const { return mImplementation.get(); } rx::ContextImpl *getImplementation() const { return mImplementation.get(); }
const Workarounds &getWorkarounds() const;
private: private:
void syncRendererState(); void syncRendererState();
...@@ -620,6 +622,7 @@ class Context final : public ValidationContext ...@@ -620,6 +622,7 @@ class Context final : public ValidationContext
void initCaps(bool webGLContext); void initCaps(bool webGLContext);
void updateCaps(); void updateCaps();
void initWorkarounds();
LabeledObject *getLabeledObject(GLenum identifier, GLuint name) const; LabeledObject *getLabeledObject(GLenum identifier, GLuint name) const;
LabeledObject *getLabeledObjectFromPtr(const void *ptr) const; LabeledObject *getLabeledObjectFromPtr(const void *ptr) const;
...@@ -672,6 +675,7 @@ class Context final : public ValidationContext ...@@ -672,6 +675,7 @@ class Context final : public ValidationContext
bool mHasBeenCurrent; bool mHasBeenCurrent;
bool mContextLost; bool mContextLost;
GLenum mResetStatus; GLenum mResetStatus;
bool mContextLostForced;
GLenum mResetStrategy; GLenum mResetStrategy;
bool mRobustAccess; bool mRobustAccess;
egl::Surface *mCurrentSurface; egl::Surface *mCurrentSurface;
...@@ -686,6 +690,8 @@ class Context final : public ValidationContext ...@@ -686,6 +690,8 @@ class Context final : public ValidationContext
State::DirtyObjects mClearDirtyObjects; State::DirtyObjects mClearDirtyObjects;
State::DirtyBits mBlitDirtyBits; State::DirtyBits mBlitDirtyBits;
State::DirtyObjects mBlitDirtyObjects; State::DirtyObjects mBlitDirtyObjects;
Workarounds mWorkarounds;
}; };
} // namespace gl } // 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