Commit 77db6f4a by Jamie Madill Committed by Commit Bot

Use global Context lookup in single-threaded cases.

In single-threaded cases we don't need to use a TLS lookup for the current Context. Assume a global context has 3 states: unset, set, and multi-threaded: * global context unset -> set the global context * global context set, matches TLS context -> set the global context * global context set, doesn't match TLS -> set multi-threaded * global context multi-threaded -> leave it This also inlines the global context/TLS check into global_state.h. Increases performance of the binding perf overhead test by up to 25% and the draw call perf test by up to 3%. Bug: angleproject:2824 Change-Id: Ib95953ca918f2408fe72ca83061f4e2d1bd1adad Reviewed-on: https://chromium-review.googlesource.com/1231993 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org>
parent 55e57f96
......@@ -2637,11 +2637,6 @@ void Context::markContextLost()
mContextLost = true;
}
bool Context::isContextLost() const
{
return mContextLost;
}
GLenum Context::getGraphicsResetStatus()
{
// Even if the application doesn't want to know about resets, we want to know
......
......@@ -1517,7 +1517,9 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl
GLenum getError();
void markContextLost();
bool isContextLost() const;
bool isContextLost() const { return mContextLost; }
GLenum getGraphicsResetStatus();
bool isResetNotificationEnabled();
......
......@@ -107,7 +107,7 @@ EGLBoolean EGLAPIENTRY Terminate(EGLDisplay dpy)
if (display->isValidContext(thread->getContext()))
{
thread->setCurrent(nullptr);
SetContextCurrent(thread, nullptr);
}
ANGLE_EGL_TRY_RETURN(thread, display->terminate(thread), "eglTerminate",
......@@ -405,7 +405,7 @@ EGLBoolean EGLAPIENTRY DestroyContext(EGLDisplay dpy, EGLContext ctx)
if (contextWasCurrent)
{
thread->setCurrent(nullptr);
SetContextCurrent(thread, nullptr);
}
thread->setSuccess();
......@@ -447,7 +447,7 @@ EGLBoolean EGLAPIENTRY MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface r
ANGLE_EGL_TRY_RETURN(thread, display->makeCurrent(drawSurface, readSurface, context),
"eglMakeCurrent", GetContextIfValid(display, context), EGL_FALSE);
thread->setCurrent(context);
SetContextCurrent(thread, context);
}
thread->setSuccess();
......
......@@ -12,32 +12,27 @@
#include "common/platform.h"
#include "common/tls.h"
#include "libANGLE/Debug.h"
#include "libANGLE/Thread.h"
namespace gl
{
Context *GetGlobalContext()
{
egl::Thread *thread = egl::GetCurrentThread();
return thread->getContext();
}
Context *GetValidGlobalContext()
{
egl::Thread *thread = egl::GetCurrentThread();
return thread->getValidContext();
}
// In single-threaded cases we can avoid a TLS lookup for the current Context.
//
// Let a global single-threaded context have 3 states: unset, set, and multi-threaded.
// Initially it is unset. Then, on MakeCurrent:
//
// * if the ST context is unset -> set the global context.
// * if the ST context is set and matches the TLS -> set the global context.
// * if the ST context is set and does not match TLS -> set multi-threaded mode.
// * if in multi-threaded mode, unset and subsequently ignore the global context.
//
// Implementation-wise we can use a pointer and a boolean to represent the three modes.
Context *gSingleThreadedContext = nullptr;
bool gIsMultiThreadedContext = false;
} // namespace gl
namespace egl
{
namespace
{
static TLSIndex threadTLS = TLS_INVALID_INDEX;
Debug *g_Debug = nullptr;
......@@ -91,6 +86,27 @@ Debug *GetDebug()
return g_Debug;
}
void SetContextCurrent(Thread *thread, gl::Context *context)
{
// See above comment on gGlobalContext.
// If the context is in multi-threaded mode, ignore the global context.
if (!gl::gIsMultiThreadedContext)
{
// If the global context is unset or matches the current TLS, set the global context.
if (gl::gSingleThreadedContext == nullptr ||
gl::gSingleThreadedContext == thread->getContext())
{
gl::gSingleThreadedContext = context;
}
else
{
// If the global context is set and does not match TLS, set multi-threaded mode.
gl::gSingleThreadedContext = nullptr;
gl::gIsMultiThreadedContext = true;
}
}
thread->setCurrent(context);
}
} // namespace egl
#if ANGLE_FORCE_THREAD_SAFETY == ANGLE_ENABLED
......
......@@ -9,19 +9,13 @@
#ifndef LIBGLESV2_GLOBALSTATE_H_
#define LIBGLESV2_GLOBALSTATE_H_
#include "libANGLE/Context.h"
#include "libANGLE/Debug.h"
#include "libANGLE/Thread.h"
#include "libANGLE/features.h"
#include <mutex>
namespace gl
{
class Context;
Context *GetGlobalContext();
Context *GetValidGlobalContext();
} // namespace gl
namespace egl
{
class Debug;
......@@ -29,9 +23,37 @@ class Thread;
Thread *GetCurrentThread();
Debug *GetDebug();
void SetContextCurrent(Thread *thread, gl::Context *context);
} // namespace egl
namespace gl
{
extern Context *gSingleThreadedContext;
ANGLE_INLINE Context *GetGlobalContext()
{
if (gSingleThreadedContext)
{
return gSingleThreadedContext;
}
egl::Thread *thread = egl::GetCurrentThread();
return thread->getContext();
}
ANGLE_INLINE Context *GetValidGlobalContext()
{
if (gSingleThreadedContext && !gSingleThreadedContext->isContextLost())
{
return gSingleThreadedContext;
}
egl::Thread *thread = egl::GetCurrentThread();
return thread->getValidContext();
}
} // namespace gl
#if ANGLE_FORCE_THREAD_SAFETY == ANGLE_ENABLED
namespace angle
{
......
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