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() ...@@ -2637,11 +2637,6 @@ void Context::markContextLost()
mContextLost = true; mContextLost = true;
} }
bool Context::isContextLost() const
{
return mContextLost;
}
GLenum Context::getGraphicsResetStatus() GLenum Context::getGraphicsResetStatus()
{ {
// Even if the application doesn't want to know about resets, we want to know // 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 ...@@ -1517,7 +1517,9 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl
GLenum getError(); GLenum getError();
void markContextLost(); void markContextLost();
bool isContextLost() const;
bool isContextLost() const { return mContextLost; }
GLenum getGraphicsResetStatus(); GLenum getGraphicsResetStatus();
bool isResetNotificationEnabled(); bool isResetNotificationEnabled();
......
...@@ -107,7 +107,7 @@ EGLBoolean EGLAPIENTRY Terminate(EGLDisplay dpy) ...@@ -107,7 +107,7 @@ EGLBoolean EGLAPIENTRY Terminate(EGLDisplay dpy)
if (display->isValidContext(thread->getContext())) if (display->isValidContext(thread->getContext()))
{ {
thread->setCurrent(nullptr); SetContextCurrent(thread, nullptr);
} }
ANGLE_EGL_TRY_RETURN(thread, display->terminate(thread), "eglTerminate", ANGLE_EGL_TRY_RETURN(thread, display->terminate(thread), "eglTerminate",
...@@ -405,7 +405,7 @@ EGLBoolean EGLAPIENTRY DestroyContext(EGLDisplay dpy, EGLContext ctx) ...@@ -405,7 +405,7 @@ EGLBoolean EGLAPIENTRY DestroyContext(EGLDisplay dpy, EGLContext ctx)
if (contextWasCurrent) if (contextWasCurrent)
{ {
thread->setCurrent(nullptr); SetContextCurrent(thread, nullptr);
} }
thread->setSuccess(); thread->setSuccess();
...@@ -447,7 +447,7 @@ EGLBoolean EGLAPIENTRY MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface r ...@@ -447,7 +447,7 @@ EGLBoolean EGLAPIENTRY MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface r
ANGLE_EGL_TRY_RETURN(thread, display->makeCurrent(drawSurface, readSurface, context), ANGLE_EGL_TRY_RETURN(thread, display->makeCurrent(drawSurface, readSurface, context),
"eglMakeCurrent", GetContextIfValid(display, context), EGL_FALSE); "eglMakeCurrent", GetContextIfValid(display, context), EGL_FALSE);
thread->setCurrent(context); SetContextCurrent(thread, context);
} }
thread->setSuccess(); thread->setSuccess();
......
...@@ -12,32 +12,27 @@ ...@@ -12,32 +12,27 @@
#include "common/platform.h" #include "common/platform.h"
#include "common/tls.h" #include "common/tls.h"
#include "libANGLE/Debug.h"
#include "libANGLE/Thread.h"
namespace gl namespace gl
{ {
// In single-threaded cases we can avoid a TLS lookup for the current Context.
Context *GetGlobalContext() //
{ // Let a global single-threaded context have 3 states: unset, set, and multi-threaded.
egl::Thread *thread = egl::GetCurrentThread(); // Initially it is unset. Then, on MakeCurrent:
return thread->getContext(); //
} // * if the ST context is unset -> set the global context.
// * if the ST context is set and matches the TLS -> set the global context.
Context *GetValidGlobalContext() // * 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.
egl::Thread *thread = egl::GetCurrentThread(); //
return thread->getValidContext(); // Implementation-wise we can use a pointer and a boolean to represent the three modes.
} Context *gSingleThreadedContext = nullptr;
bool gIsMultiThreadedContext = false;
} // namespace gl } // namespace gl
namespace egl namespace egl
{ {
namespace namespace
{ {
static TLSIndex threadTLS = TLS_INVALID_INDEX; static TLSIndex threadTLS = TLS_INVALID_INDEX;
Debug *g_Debug = nullptr; Debug *g_Debug = nullptr;
...@@ -91,6 +86,27 @@ Debug *GetDebug() ...@@ -91,6 +86,27 @@ Debug *GetDebug()
return g_Debug; 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 } // namespace egl
#if ANGLE_FORCE_THREAD_SAFETY == ANGLE_ENABLED #if ANGLE_FORCE_THREAD_SAFETY == ANGLE_ENABLED
......
...@@ -9,19 +9,13 @@ ...@@ -9,19 +9,13 @@
#ifndef LIBGLESV2_GLOBALSTATE_H_ #ifndef LIBGLESV2_GLOBALSTATE_H_
#define LIBGLESV2_GLOBALSTATE_H_ #define LIBGLESV2_GLOBALSTATE_H_
#include "libANGLE/Context.h"
#include "libANGLE/Debug.h"
#include "libANGLE/Thread.h"
#include "libANGLE/features.h" #include "libANGLE/features.h"
#include <mutex> #include <mutex>
namespace gl
{
class Context;
Context *GetGlobalContext();
Context *GetValidGlobalContext();
} // namespace gl
namespace egl namespace egl
{ {
class Debug; class Debug;
...@@ -29,9 +23,37 @@ class Thread; ...@@ -29,9 +23,37 @@ class Thread;
Thread *GetCurrentThread(); Thread *GetCurrentThread();
Debug *GetDebug(); Debug *GetDebug();
void SetContextCurrent(Thread *thread, gl::Context *context);
} // namespace egl } // 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 #if ANGLE_FORCE_THREAD_SAFETY == ANGLE_ENABLED
namespace angle 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