Browse Source

Platform: how did Linus say it, fuck NVidia?

Thanks a lot, there goes my morning.
findsdl-include-root
Vladimír Vondruš 7 years ago
parent
commit
bc3451a593
  1. 37
      src/Magnum/Platform/WindowlessEglApplication.cpp
  2. 32
      src/Magnum/Platform/WindowlessEglApplication.h

37
src/Magnum/Platform/WindowlessEglApplication.cpp

@ -29,6 +29,8 @@
#include <string> #include <string>
#include <Corrade/Utility/Assert.h> #include <Corrade/Utility/Assert.h>
#include <Corrade/Utility/Debug.h> #include <Corrade/Utility/Debug.h>
#include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/String.h>
#include "Magnum/GL/Version.h" #include "Magnum/GL/Version.h"
#include "Magnum/Platform/GLContext.h" #include "Magnum/Platform/GLContext.h"
@ -47,6 +49,18 @@ typedef void *EGLDeviceEXT;
#define EGL_PLATFORM_DEVICE_EXT 0x313F #define EGL_PLATFORM_DEVICE_EXT 0x313F
#endif #endif
#ifndef EGL_VERSION_1_5
typedef intptr_t EGLAttrib;
#endif
#ifndef EGL_KHR_debug
#define EGL_DEBUG_MSG_WARN_KHR 0x33BB
#define EGL_DEBUG_MSG_INFO_KHR 0x33BC
typedef void* EGLObjectKHR;
typedef void* EGLLabelKHR;
typedef void (APIENTRY *EGLDEBUGPROCKHR)(EGLenum error, const char* command, EGLint messageType, EGLLabelKHR threadLabel, EGLLabelKHR objectLabel, const char* message);
#endif
namespace Magnum { namespace Platform { namespace Magnum { namespace Platform {
namespace { namespace {
@ -83,6 +97,24 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G
thousand extensions?!). This is supported only since Mesa 19.2. */ thousand extensions?!). This is supported only since Mesa 19.2. */
extensionSupported(extensions, "EGL_EXT_platform_device") extensionSupported(extensions, "EGL_EXT_platform_device")
) { ) {
/* When libEGL_nvidia.so is present on a system w/o a NV GPU,
eglQueryDevicesEXT() fails there with EGL_BAD_ALLOC, but that is
never propagated to the glvnd wrapper. Enable debug output if
--magnum-gpu-validation is enabled because otherwise it's fucking
hard to discover what's to blame (lost > 3 hours already). See class
docs for more info and a workaround. */
if(extensionSupported(extensions, "EGL_KHR_debug") && magnumContext && (magnumContext->internalFlags() & GL::Context::InternalFlag::GpuValidation)) {
auto eglDebugMessageControl = reinterpret_cast<EGLint(*)(EGLDEBUGPROCKHR, const EGLAttrib*)>(eglGetProcAddress("eglDebugMessageControlKHR"));
const EGLAttrib debugAttribs[] = {
EGL_DEBUG_MSG_WARN_KHR, EGL_TRUE,
EGL_DEBUG_MSG_INFO_KHR, EGL_TRUE,
EGL_NONE
};
CORRADE_INTERNAL_ASSERT_OUTPUT(eglDebugMessageControl([](EGLenum, const char* const command, EGLint, EGLLabelKHR, EGLLabelKHR, const char* message) {
Debug{} << command << Debug::nospace << "():" << Utility::String::rtrim(message);
}, debugAttribs) == EGL_SUCCESS);
}
EGLint count; EGLint count;
auto eglQueryDevices = reinterpret_cast<EGLBoolean(*)(EGLint, EGLDeviceEXT*, EGLint*)>(eglGetProcAddress("eglQueryDevicesEXT")); auto eglQueryDevices = reinterpret_cast<EGLBoolean(*)(EGLint, EGLDeviceEXT*, EGLint*)>(eglGetProcAddress("eglQueryDevicesEXT"));
if(!eglQueryDevices(0, nullptr, &count)) { if(!eglQueryDevices(0, nullptr, &count)) {
@ -91,7 +123,10 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G
} }
if(!count) { if(!count) {
Error{} << "Platform::WindowlessEglApplication::tryCreateContext(): no EGL devices found"; Error e;
e << "Platform::WindowlessEglApplication::tryCreateContext(): no EGL devices found, likely a driver issue";
if(!magnumContext || !(magnumContext->internalFlags() & GL::Context::InternalFlag::GpuValidation))
e << Debug::nospace << "; enable --magnum-gpu-validation to see additional info";
return; return;
} }

32
src/Magnum/Platform/WindowlessEglApplication.h

@ -358,6 +358,38 @@ The application prefers to use the @m_class{m-doc-external}
@m_class{m-doc-external} [EGL_EXT_platform_device](https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_platform_device.txt) @m_class{m-doc-external} [EGL_EXT_platform_device](https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_platform_device.txt)
where available instead of `EGL_DEFAULT_DISPLAY` to work better on headless where available instead of `EGL_DEFAULT_DISPLAY` to work better on headless
setups. The application always chooses the first found device. setups. The application always chooses the first found device.
@m_class{m-block m-danger}
@par No EGL devices found
@parblock
Systems running Mesa 19.2 (which has the above extensions) that also have
`libEGL_nvidia.so` installed (for example as a CUDA dependency) may fail
to create the context with the following error (with additional output
produced when the `--magnum-gpu-validation`
@ref GL-Context-command-line "command-line option" is enabled):
@m_class{m-console-wrap}
@code{.shell-session}
eglQueryDevicesEXT(): EGL_BAD_ALLOC error: In internal function: Additional INFO may be available
eglQueryDevicesEXT(): EGL_BAD_ALLOC error: In function eglQueryDevicesEXT(), backend failed to query devices
Platform::WindowlessEglApplication::tryCreateContext(): no EGL devices found
@endcode
This is due to the NVidia's EGL implementation failing to enumerate devices
(because there aren't any), which then causes the GLVND wrapper to stop
instead of enumerating the Mesa devices as well. The solution is
whitelisting all EGL implementations except the NVidia one
<a href="https://github.com/NVIDIA/libglvnd/blob/master/src/EGL/icd_enumeration.md">as described in the libglvnd documentation</a>
using the `__EGL_VENDOR_LIBRARY_FILENAMES` environment variable, for example:
@m_class{m-console-wrap}
@code{.sh}
__EGL_VENDOR_LIBRARY_FILENAMES=/usr/share/glvnd/egl_vendor.d/50_mesa.json ./my-application
@endcode
@endparblock
*/ */
class WindowlessEglApplication { class WindowlessEglApplication {
public: public:

Loading…
Cancel
Save