Browse Source

Platform: new "android-generic-hostname-might-be-swiftshader" workaround.

As documented. Yes, Android, I hate you, in case that wasn't clear. And
all other Google code as well.
pull/539/head
Vladimír Vondruš 4 years ago
parent
commit
e0b20107be
  1. 3
      doc/changelog.dox
  2. 25
      src/Magnum/GL/Implementation/driverSpecific.cpp
  3. 30
      src/Magnum/Platform/WindowlessEglApplication.cpp

3
doc/changelog.dox

@ -136,6 +136,9 @@ See also:
- A new @cpp "angle-chatty-shader-compiler" @ce workaround for silencing - A new @cpp "angle-chatty-shader-compiler" @ce workaround for silencing
useless linker output on ANGLE. See @ref opengl-workarounds for more useless linker output on ANGLE. See @ref opengl-workarounds for more
information. information.
- A new @cpp "android-generic-hostname-might-be-swiftshader" @ce workaround
needed for testing against Android Emulator SwiftShader GPU. See
@ref opengl-workarounds for more information.
@subsubsection changelog-latest-new-math Math library @subsubsection changelog-latest-new-math Math library

25
src/Magnum/GL/Implementation/driverSpecific.cpp

@ -44,6 +44,18 @@ using namespace Containers::Literals;
/* Search the code for the following strings to see where they are implemented */ /* Search the code for the following strings to see where they are implemented */
constexpr Containers::StringView KnownWorkarounds[]{ constexpr Containers::StringView KnownWorkarounds[]{
/* [workarounds] */ /* [workarounds] */
#if defined(CORRADE_TARGET_ANDROID) && defined(MAGNUM_TARGET_GLES)
/* Android Emulator can run with a SwiftShader GPU and thus needs some of the
SwiftShader context creation workarounds. However, it's impossible to
detect, as EGL_VERSION is always "1.4 Android META-EGL" and EGL_VENDOR
always "Android". As there's nothing that would hint at SwiftShader being
used, we conservatively assume every emulator can be a SwiftShader. But
that's not easy either, the only vague hint that we're dealing with an
emulator is the HOSTNAME env var, which is set to e.g. generic_x86, but to
e.g. HWVTR on a device, so try that. */
"android-generic-hostname-might-be-swiftshader"_s,
#endif
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL)
/* ANGLE's shader linker insists on returning a message consisting of a /* ANGLE's shader linker insists on returning a message consisting of a
single newline on success, causing annoying noise in the console. Similar to single newline on success, causing annoying noise in the console. Similar to
@ -212,13 +224,18 @@ constexpr Containers::StringView KnownWorkarounds[]{
#endif #endif
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL)
/* Empty EGL_CONTEXT_FLAGS_KHR cause SwiftShader 3.3.0.1 to fail context /* Empty EGL_CONTEXT_FLAGS_KHR cause SwiftShader 3.3 to fail context creation
creation with EGL_BAD_ATTRIBUTE. Not sending the flags then. Relevant code: with EGL_BAD_ATTRIBUTE. Not sending the flags then. Relevant code:
https://github.com/google/swiftshader/blob/5fb5e817a20d3e60f29f7338493f922b5ac9d7c4/src/OpenGL/libEGL/libEGL.cpp#L794-L810 */ https://github.com/google/swiftshader/blob/5fb5e817a20d3e60f29f7338493f922b5ac9d7c4/src/OpenGL/libEGL/libEGL.cpp#L794-L810
Version 4.1 suffers from the same thing, but 4.0 on Android not, for some
reason. */
"swiftshader-no-empty-egl-context-flags"_s, "swiftshader-no-empty-egl-context-flags"_s,
/* SwiftShader 3.3.0.1 crashes deep inside eglMakeCurrent() when using /* SwiftShader 3.3.0.1 crashes deep inside eglMakeCurrent() when using
EGL_NO_SURFACE. Supplying a 32x32 PBuffer to work around that. */ EGL_NO_SURFACE. Supplying a 32x32 PBuffer to work around that. (Android's)
SwiftShader 4.0 needs it too, but doesn't crash, only fails to make the
context current with EGL_BAD_MATCH. Version 4.1 doesn't seem to need this
workaround anymore. */
"swiftshader-egl-context-needs-pbuffer"_s, "swiftshader-egl-context-needs-pbuffer"_s,
#endif #endif

30
src/Magnum/Platform/WindowlessEglApplication.cpp

@ -364,7 +364,11 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G
/* SwiftShader 3.3.0.1 blows up on encountering EGL_CONTEXT_FLAGS_KHR with /* SwiftShader 3.3.0.1 blows up on encountering EGL_CONTEXT_FLAGS_KHR with
a zero value, so erase these. It also doesn't handle them as correct a zero value, so erase these. It also doesn't handle them as correct
flags, but instead checks for the whole value, so a combination won't flags, but instead checks for the whole value, so a combination won't
work either: https://github.com/google/swiftshader/blob/5fb5e817a20d3e60f29f7338493f922b5ac9d7c4/src/OpenGL/libEGL/libEGL.cpp#L794-L8104 */ work either: https://github.com/google/swiftshader/blob/5fb5e817a20d3e60f29f7338493f922b5ac9d7c4/src/OpenGL/libEGL/libEGL.cpp#L794-L8104
Interestingly, on Android Emulator SwiftShader 4.0 this workaround isn't
needed, so we don't need to use the isSwiftShader variable (from below)
in this case. */
if(!(UnsignedLong(flags) & 0xffffffffu) && version.contains("SwiftShader"_s) && (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("swiftshader-no-empty-egl-context-flags"_s))) { if(!(UnsignedLong(flags) & 0xffffffffu) && version.contains("SwiftShader"_s) && (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("swiftshader-no-empty-egl-context-flags"_s))) {
auto& contextFlags = attributes[nextAttribute - 2]; auto& contextFlags = attributes[nextAttribute - 2];
CORRADE_INTERNAL_ASSERT(contextFlags == EGL_CONTEXT_FLAGS_KHR); CORRADE_INTERNAL_ASSERT(contextFlags == EGL_CONTEXT_FLAGS_KHR);
@ -486,9 +490,27 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G
} }
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL)
/* SwiftShader 3.3.0.1 needs some pbuffer, otherwise it crashes somewhere /* Android Emulator can run with a SwiftShader GPU and thus needs some of
deep inside when making the context current */ the SwiftShader context creation workarounds. However, it's impossible
if(version.contains("SwiftShader"_s) && (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("swiftshader-egl-context-needs-pbuffer"_s))) { to detect, as EGL_VERSION is always "1.4 Android META-EGL" and
EGL_VENDOR always "Android". As there's nothing that would hint at
SwiftShader being used, we conservatively assume every emulator can be a
SwiftShader. But that's not easy either, the only vague hint that we're
dealing with an emulator is the HOSTNAME env var, which is set to e.g.
generic_x86, but to e.g. HWVTR on a device, so try that. */
const bool isSwiftShader =
#ifndef CORRADE_TARGET_ANDROID
version.contains("SwiftShader"_s)
#else
Containers::StringView{std::getenv("HOSTNAME")}.contains("generic"_s) && (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("android-generic-hostname-might-be-swiftshader"_s))
#endif
;
/* SwiftShader 3.3 needs some pbuffer, otherwise it crashes somewhere deep
inside when making the context current. (Android's) SwiftShader 4.0
needs it too, but doesn't crash, only fails to make the context current
with EGL_BAD_MATCH. Version 4.1 doesn't need this workaround anymore. */
if(isSwiftShader && (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("swiftshader-egl-context-needs-pbuffer"_s))) {
EGLint surfaceAttributes[] = { EGLint surfaceAttributes[] = {
EGL_WIDTH, 32, EGL_WIDTH, 32,
EGL_HEIGHT, 32, EGL_HEIGHT, 32,

Loading…
Cancel
Save