Commit 33c28e35 by Mohan Maiya Committed by Commit Bot

Optimize thread specific storage and retrieval with native ASM

Android reserves specific TLS slots to store thread specific values. Given that the Context object gets queried on every call we leverage Android's ASM code to improve the speed of this operation. TLS_SLOT_OPENGL is an unused slot in Android and using that in combination with the ASM code,rather than using the pthread API, allows angle to store and retrieve thread specific context object much more efficiently. Bug: angleproject:4717 Change-Id: I27a117fe82e62407e01c8c372918b866aaea9ee5 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2231883 Commit-Queue: Mohan Maiya <m.maiya@samsung.com> Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent c8040e54
...@@ -174,6 +174,7 @@ Samsung Electronics, Inc. ...@@ -174,6 +174,7 @@ Samsung Electronics, Inc.
Peter Mowry Peter Mowry
Sangwon Park Sangwon Park
Saurabh Badenkal Saurabh Badenkal
Younggwan Kim
Arm Ltd. Arm Ltd.
Fei Yang Fei Yang
......
...@@ -34,6 +34,8 @@ static vector<DWORD> freeTlsIndices; ...@@ -34,6 +34,8 @@ static vector<DWORD> freeTlsIndices;
#endif #endif
bool gUseAndroidOpenGLTlsSlot = false;
TLSIndex CreateTLSIndex() TLSIndex CreateTLSIndex()
{ {
TLSIndex index; TLSIndex index;
...@@ -155,3 +157,10 @@ void *GetTLSValue(TLSIndex index) ...@@ -155,3 +157,10 @@ void *GetTLSValue(TLSIndex index)
return pthread_getspecific(index); return pthread_getspecific(index);
#endif #endif
} }
void SetUseAndroidOpenGLTlsSlot(bool platformTypeVulkan)
{
#if defined(ANGLE_PLATFORM_ANDROID)
gUseAndroidOpenGLTlsSlot = platformTypeVulkan;
#endif
}
...@@ -9,8 +9,14 @@ ...@@ -9,8 +9,14 @@
#ifndef COMMON_TLS_H_ #ifndef COMMON_TLS_H_
#define COMMON_TLS_H_ #define COMMON_TLS_H_
#include "common/angleutils.h"
#include "common/platform.h" #include "common/platform.h"
namespace gl
{
class Context;
}
#ifdef ANGLE_PLATFORM_WINDOWS #ifdef ANGLE_PLATFORM_WINDOWS
// TLS does not exist for Windows Store and needs to be emulated // TLS does not exist for Windows Store and needs to be emulated
...@@ -34,6 +40,96 @@ typedef pthread_key_t TLSIndex; ...@@ -34,6 +40,96 @@ typedef pthread_key_t TLSIndex;
# error Unsupported platform. # error Unsupported platform.
#endif #endif
#if defined(ANGLE_PLATFORM_ANDROID)
// The following ASM variant provides a much more performant store/retrieve interface
// compared to those provided by the pthread library. These have been derived from code
// in the bionic module of Android ->
// https://cs.android.com/android/platform/superproject/+/master:bionic/libc/platform/bionic/tls.h;l=30
# if defined(__aarch64__)
# define ANGLE_ANDROID_GET_GL_TLS() \
({ \
void **__val; \
__asm__("mrs %0, tpidr_el0" : "=r"(__val)); \
__val; \
})
# elif defined(__arm__)
# define ANGLE_ANDROID_GET_GL_TLS() \
({ \
void **__val; \
__asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__val)); \
__val; \
})
# elif defined(__mips__)
// On mips32r1, this goes via a kernel illegal instruction trap that's
// optimized for v1
# define ANGLE_ANDROID_GET_GL_TLS() \
({ \
register void **__val asm("v1"); \
__asm__( \
".set push\n" \
".set mips32r2\n" \
"rdhwr %0,$29\n" \
".set pop\n" \
: "=r"(__val)); \
__val; \
})
# elif defined(__i386__)
# define ANGLE_ANDROID_GET_GL_TLS() \
({ \
void **__val; \
__asm__("movl %%gs:0, %0" : "=r"(__val)); \
__val; \
})
# elif defined(__x86_64__)
# define ANGLE_ANDROID_GET_GL_TLS() \
({ \
void **__val; \
__asm__("mov %%fs:0, %0" : "=r"(__val)); \
__val; \
})
# else
# error unsupported architecture
# endif
#endif // ANGLE_PLATFORM_ANDROID
// - TLS_SLOT_OPENGL and TLS_SLOT_OPENGL_API: These two aren't used by bionic
// itself, but allow the graphics code to access TLS directly rather than
// using the pthread API.
//
// Choose the TLS_SLOT_OPENGL TLS slot with the value that matches value in the header file in
// bionic(tls_defines.h)
constexpr TLSIndex kAndroidOpenGLTlsSlot = 3;
extern bool gUseAndroidOpenGLTlsSlot;
ANGLE_INLINE bool SetContextToAndroidOpenGLTLSSlot(gl::Context *value)
{
#if defined(ANGLE_PLATFORM_ANDROID)
if (gUseAndroidOpenGLTlsSlot)
{
ANGLE_ANDROID_GET_GL_TLS()[kAndroidOpenGLTlsSlot] = static_cast<void *>(value);
return true;
}
#endif
return false;
}
ANGLE_INLINE bool GetContextFromAndroidOpenGLTLSSlot(gl::Context **value)
{
#if defined(ANGLE_PLATFORM_ANDROID)
if (gUseAndroidOpenGLTlsSlot)
{
*value = static_cast<gl::Context *>(ANGLE_ANDROID_GET_GL_TLS()[kAndroidOpenGLTlsSlot]);
return true;
}
#endif
return false;
}
void SetUseAndroidOpenGLTlsSlot(bool platformTypeVulkan);
// TODO(kbr): for POSIX platforms this will have to be changed to take // TODO(kbr): for POSIX platforms this will have to be changed to take
// in a destructor function pointer, to allow the thread-local storage // in a destructor function pointer, to allow the thread-local storage
// to be properly deallocated upon thread exit. // to be properly deallocated upon thread exit.
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "common/platform.h" #include "common/platform.h"
#include "common/string_utils.h" #include "common/string_utils.h"
#include "common/system_utils.h" #include "common/system_utils.h"
#include "common/tls.h"
#include "common/utilities.h" #include "common/utilities.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/Device.h" #include "libANGLE/Device.h"
...@@ -562,7 +563,7 @@ Display *Display::GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay ...@@ -562,7 +563,7 @@ Display *Display::GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay
// No valid display implementation for these attributes // No valid display implementation for these attributes
return nullptr; return nullptr;
} }
SetUseAndroidOpenGLTlsSlot(displayType == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE);
display->setupDisplayPlatform(impl); display->setupDisplayPlatform(impl);
} }
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include "common/debug.h" #include "common/debug.h"
#include "common/platform.h" #include "common/platform.h"
#include "common/system_utils.h" #include "common/system_utils.h"
#include "common/tls.h"
#include "libGLESv2/resource.h" #include "libGLESv2/resource.h"
#include <atomic> #include <atomic>
...@@ -59,6 +58,9 @@ Thread *AllocateCurrentThread() ...@@ -59,6 +58,9 @@ Thread *AllocateCurrentThread()
return nullptr; return nullptr;
} }
// Initialize fast TLS slot
SetContextToAndroidOpenGLTLSSlot(nullptr);
return thread; return thread;
} }
...@@ -133,6 +135,8 @@ void SetContextCurrent(Thread *thread, gl::Context *context) ...@@ -133,6 +135,8 @@ void SetContextCurrent(Thread *thread, gl::Context *context)
} }
} }
thread->setCurrent(context); thread->setCurrent(context);
SetContextToAndroidOpenGLTLSSlot(context);
} }
} // namespace egl } // namespace egl
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#ifndef LIBGLESV2_GLOBALSTATE_H_ #ifndef LIBGLESV2_GLOBALSTATE_H_
#define LIBGLESV2_GLOBALSTATE_H_ #define LIBGLESV2_GLOBALSTATE_H_
#include "common/tls.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/Debug.h" #include "libANGLE/Debug.h"
#include "libANGLE/Thread.h" #include "libANGLE/Thread.h"
...@@ -45,6 +46,15 @@ ANGLE_INLINE Context *GetGlobalContext() ...@@ -45,6 +46,15 @@ ANGLE_INLINE Context *GetGlobalContext()
{ {
return gSingleThreadedContext; return gSingleThreadedContext;
} }
else
{
Context *context;
bool fastTlsResult = GetContextFromAndroidOpenGLTLSSlot(&context);
if (fastTlsResult)
{
return context;
}
}
egl::Thread *thread = egl::GetCurrentThread(); egl::Thread *thread = egl::GetCurrentThread();
return thread->getContext(); return thread->getContext();
...@@ -56,6 +66,18 @@ ANGLE_INLINE Context *GetValidGlobalContext() ...@@ -56,6 +66,18 @@ ANGLE_INLINE Context *GetValidGlobalContext()
{ {
return gSingleThreadedContext; return gSingleThreadedContext;
} }
else if (!gSingleThreadedContext)
{
Context *context;
bool fastTlsResult = GetContextFromAndroidOpenGLTLSSlot(&context);
if (fastTlsResult)
{
if (context && !context->isContextLost())
{
return context;
}
}
}
egl::Thread *thread = egl::GetCurrentThread(); egl::Thread *thread = egl::GetCurrentThread();
return thread->getValidContext(); return thread->getValidContext();
......
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