TinyEngine icon indicating copy to clipboard operation
TinyEngine copied to clipboard

Examples won't start

Open zeitgeist314 opened this issue 3 years ago • 10 comments

Hello,

Get the error

$ cd examples/9_Scene
$ make all
g++ -std=c++17 main.cpp -Wfatal-errors -O -I/usr/local/include -L/usr/local/lib -lTinyEngine -lX11 -lGL -lpthread -lSDL2 -lSDL2_image -lSDL2_mixer -lSDL2_ttf -lGLEW -lboost_system -lboost_filesystem -o main
$ ./main
Window could not be created! SDL_Error: Couldn't find matching GLX visual
Failed to launch visual interface.
Adres-eraro(nekropsio elŝutita) = "Segmentation fault" in esperanto

and

$ export SDL_VIDEO_X11_VISUALID=0x179
$ ./main
Adres-eraro(nekropsio elŝutita) = "Segmentation fault" in esperanto

for all examples on Fedora and Win11/WSL/Ubunutu Jammy. It seems something with the gui-system, I use wayland.

Greets and thanks for this program!

zeitgeist314 avatar Jan 21 '22 19:01 zeitgeist314

Hi! Sorry for the alte reply. This is an issue that I have encountered before, and I believe it has to do with your available versions of OpenGL. Have you tried compiling with compatibility mode?

weigert avatar Jan 27 '22 09:01 weigert

I was running into the seg faults as well on ubuntu with MESA drivers. Switching over to proprietary drivers seemed to made the error go away. I did notice when using the MESA drivers opengl never got initialized while debugging through the code.

the-brickster avatar Feb 01 '22 20:02 the-brickster

Hi @the-brickster, do you know which version of the MESA drivers you were using when it wasn't working? This is interesting. Apparently there are frequent problems with driver mismatch issues and I want to locate what versions fail.

weigert avatar Feb 03 '22 18:02 weigert

Hello @weigert this was the version of MESA drivers I was running:

Extended renderer info (GLX_MESA_query_renderer):
    Vendor: Mesa/X.org (0xffffffff)
    Device: llvmpipe (LLVM 13.0.0, 256 bits) (0xffffffff)
    Version: 21.3.4
    Accelerated: no
    Video memory: 25616MB
    Unified memory: no
    Preferred profile: core (0x1)
    Max core profile version: 4.5
    Max compat profile version: 4.5
    Max GLES1 profile version: 1.1
    Max GLES[23] profile version: 3.2

the-brickster avatar Feb 03 '22 22:02 the-brickster

At least on linux + wayland, one thing to compare is output between a run of 0.0_Empty with export SDL_VIDEODRIVER=x11

(gdb) run
Starting program: /media/sd/Projects/TermFun/VoxelSpace/TinyEngine/examples/0.0_Empty/main 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1".
[Detaching after fork from child process 259202]
Window could not be created! SDL_Error: Couldn't find matching GLX visual
Failed to launch visual interface.

Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) bt
#0  0x0000000000000000 in  ()
#1  0x0000aaaaaaaac084 in View::target(glm::vec<3, float, (glm::qualifier)0>, bool, bool) ()
#2  0x0000aaaaaaaa7020 in std::_Function_handler<void (), main::{lambda()#3}>::_M_invoke(std::_Any_data const&)
    ()
#3  0x0000aaaaaaaac010 in View::render() ()
#4  0x0000aaaaaaaa8d2c in main ()
(gdb) 

and SDL_VIDEODRIVER=wayland

(gdb) run
Starting program: /media/sd/Projects/TermFun/VoxelSpace/TinyEngine/examples/0.0_Empty/main 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1".
[Detaching after fork from child process 259220]
Window could not be created! SDL_Error: Couldn't find matching EGL config (call to eglChooseConfig failed, reporting an error of EGL_SUCCESS)
Failed to launch visual interface.

Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) bt
#0  0x0000000000000000 in  ()
#1  0x0000aaaaaaaac084 in View::target(glm::vec<3, float, (glm::qualifier)0>, bool, bool) ()
#2  0x0000aaaaaaaa7020 in std::_Function_handler<void (), main::{lambda()#3}>::_M_invoke(std::_Any_data const&)
    ()
#3  0x0000aaaaaaaac010 in View::render() ()
#4  0x0000aaaaaaaa8d2c in main ()
(gdb) 

Looking at include/view.cpp around SDL_CreateWindow maybe we're missing some SDL_GL_* setup. I see other programs doing stuff like:

SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
SDL_GL_SetAttribute(SDL_GL_CONTEXT_NO_ERROR, 1); // Requires OpenGL 2.0
SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);

I see ArxLibertatis is running with SDL driver x11 [I] SDL2Window:489 Window: X11 r:8 g:8 b:8 a:0 depth:24 aa:4x doublebuffer:1

so let's check out their src/window/SDL2Window.cpp


        arx_assert(!m_displayModes.empty());

        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

        #if ARX_PLATFORM == ARX_PLATFORM_WIN32
        // Used on Windows to prevent software opengl fallback.
        // The linux situation:
        // Causes SDL to require visuals without caveats.
        // On linux some drivers only supply multisample capable GLX Visuals
        // with a GLX_NON_CONFORMANT_VISUAL_EXT caveat.
        // see: https://www.opengl.org/registry/specs/EXT/visual_rating.txt
        SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
        #endif

        bool autoRenderer = (config.video.renderer == "auto");
        
        gldebug::Mode debugMode = gldebug::mode();
        
        int samples = 0;
        for(int api = 0; api < 2 && samples == 0; api++) {
                bool first = (api == 0);
                
                bool matched = false;
                
                if(samples == 0 && first == (autoRenderer || config.video.renderer == "OpenGL")) {
                        matched = true;
                        
                        for(int type = 0; type < ((debugMode == gldebug::Enabled) ? 2 : 1) && samples == 0; type++) {
                                
                                int flags = 0;
                                if(debugMode == gldebug::Enabled && type == 0) {
                                        flags |= SDL_GL_CONTEXT_DEBUG_FLAG;
                                }
                                SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, flags);
                                
                                // TODO core profile are not supported yet
                                #if SDL_VERSION_ATLEAST(2, 0, 6)
                                if(debugMode == gldebug::NoError) {
                                        // Set SDL_GL_CONTEXT_PROFILE_MASK to != 0 so SDL won't ignore SDL_GL_CONTEXT_NO_ERROR
                                        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
                                        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
                                        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
                                        SDL_GL_SetAttribute(SDL_GL_CONTEXT_NO_ERROR, 1); // Requires OpenGL 2.0
                                        samples = createWindowAndGLContext("Desktop OpenGL");
                                }
                                #endif
                                if(samples == 0) {
                                        // Set SDL_GL_CONTEXT_PROFILE_MASK to 0 so SDL will try the legacy glXCreateContext() path
                                        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0);
                                        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
                                        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5);
                                        #if SDL_VERSION_ATLEAST(2, 0, 6)
                                        SDL_GL_SetAttribute(SDL_GL_CONTEXT_NO_ERROR, 0);
                                        #endif
                                        samples = createWindowAndGLContext("Desktop OpenGL");
                                }
                                
                        }
                        
                }
               
                #if ARX_HAVE_EPOXY
                if(samples == 0 && first == (autoRenderer || config.video.renderer == "OpenGL ES")) {
                        matched = true;
                        
                        for(int type = 0; type < ((debugMode == gldebug::Enabled) ? 2 : 1) && samples == 0; type++) {
                                
                                int flags = 0;
                                if(debugMode == gldebug::Enabled && type == 0) {
                                        flags |= SDL_GL_CONTEXT_DEBUG_FLAG;
                                }
                                SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, flags);
                        
                                // TODO OpenGL ES 2.0+ is not supported yet
                                SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
                                SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
                                SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
                                // SDL_GL_CONTEXT_NO_ERROR requires OpenGL ES 2.0
                                samples = createWindowAndGLContext("OpenGL ES");
                                
                        }
                        
                }
                #endif
                
                if(first && !matched) {
                        LogError << "Unknown renderer: " << config.video.renderer;
                }
        }
        
        if(samples == 0) {
                return false;
        }
        
        // All good
        {
                const char * windowSystem = "(unknown)";
                {
                  ARX_SDL_SysWMinfo info;
                        info.version.major = 2;
                        info.version.minor = 0;
                        info.version.patch = 6;
                        if(SDL_GetWindowWMInfo(m_window, reinterpret_cast<SDL_SysWMinfo *>(&info))) {
                                m_sdlSubsystem = info.subsystem;
                                switch(info.subsystem) {
                                        case ARX_SDL_SYSWM_UNKNOWN:   break;
                                        case ARX_SDL_SYSWM_WINDOWS:   windowSystem = "Windows"; break;
                                        case ARX_SDL_SYSWM_X11:       windowSystem = "X11"; break;
                                        case ARX_SDL_SYSWM_DIRECTFB:  windowSystem = "DirectFB"; break;
                                        case ARX_SDL_SYSWM_COCOA:     windowSystem = "Cocoa"; break;
                                        case ARX_SDL_SYSWM_UIKIT:     windowSystem = "UIKit"; break;
                                        case ARX_SDL_SYSWM_WAYLAND:   windowSystem = "Wayland"; break;
                                        case ARX_SDL_SYSWM_MIR:       windowSystem = "Mir"; break;
                                        case ARX_SDL_SYSWM_WINRT:     windowSystem = "WinRT"; break;
                                        case ARX_SDL_SYSWM_ANDROID:   windowSystem = "Android"; break;
                                        case ARX_SDL_SYSWM_VIVANTE:   windowSystem = "Vivante"; break;
                                        case ARX_SDL_SYSWM_OS2:       windowSystem = "OS2"; break;
                                        default: LogWarning << "Unknown SDL video backend: " << int(info.subsystem);
                                }
                                #if ARX_PLATFORM != ARX_PLATFORM_WIN32 && ARX_PLATFORM != ARX_PLATFORM_MACOS
                                #if ARX_HAVE_EPOXY
                                const char * wrangler = "libepoxy";
                                #else
                                const char * wrangler = "GLEW";
                                #endif
                                switch(info.subsystem) {
                                        case ARX_SDL_SYSWM_X11: {
                                                if(m_sdlVersion < SDL_VERSIONNUM(2, 0, 9)) {
                                                        // Work around a bug causing dbus-daemon memory usage to continually rise while AL is running
                                                        // if the org.gnome.ScreenSaver service does not exist.
                                                        if(m_allowScreensaver != AlwaysDisabled && m_allowScreensaver != AlwaysEnabled) {
                                                                SDL_EnableScreenSaver();
                                                                m_allowScreensaver = AlwaysEnabled;
                                                        }                                                                                                                                              
                                                }
                                                #if ARX_HAVE_GL_STATIC || !ARX_HAVE_DLSYM || !defined(RTLD_DEFAULT)
                                                const bool haveGLX = ARX_HAVE_GLX;
                                                #elif ARX_HAVE_EPOXY
                                                const bool haveGLX = (dlsym(RTLD_DEFAULT, "epoxy_has_glx") != NULL);
                                                #else
                                                const bool haveGLX = (dlsym(RTLD_DEFAULT, "glxewInit") != NULL);
                                                #endif
                                                if(!haveGLX) {
                                                        LogWarning << "SDL is using the X11 video backend but " << wrangler
                                                                   << " was built without GLX support";
                                                        LogWarning << "Try setting the SDL_VIDEODRIVER=wayland environment variable";
                                                }
                                                break;
                                        }
                                        case ARX_SDL_SYSWM_WAYLAND:
                                        case ARX_SDL_SYSWM_MIR: {
                                                #if ARX_HAVE_GL_STATIC || !ARX_HAVE_DLSYM || !defined(RTLD_DEFAULT)
                                                const bool haveEGL = ARX_HAVE_EGL;
                                                #elif ARX_HAVE_EPOXY
                                                const bool haveEGL = (dlsym(RTLD_DEFAULT, "epoxy_has_egl") != NULL);
                                                #else
                                                const bool haveEGL = (dlsym(RTLD_DEFAULT, "eglewInit") != NULL);
                                                #endif
                                                if(!haveEGL) {
                                                        LogWarning << "SDL is using the " << windowSystem << " video backend but " << wrangler
                                                                   << " was built without EGL support";
                                                        LogWarning << "Try setting the SDL_VIDEODRIVER=x11 environment variable";
                                                }
                                                break;
                                        }
                                        default: break;
                                }
                                #endif
                        }
                }
                
                int red = 0, green = 0, blue = 0, alpha = 0, depth = 0, doublebuffer = 0;
                SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &red);
                SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &green);
                SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &blue);
                SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &alpha);
                SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &depth);
                SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &doublebuffer);
                LogInfo << "Window: " << windowSystem << " r:" << red << " g:" << green << " b:" << blue
                        << " a:" << alpha << " depth:" << depth << " aa:" << samples << "x"
                        << " doublebuffer:" << doublebuffer;
        }
        // Use the executable icon for the window
        u64 nativeWindow = 0;
        #if ARX_PLATFORM == ARX_PLATFORM_WIN32
        if(!nativeWindow) {
                SDL_SysWMinfo info;
                SDL_VERSION(&info.version);
                if(SDL_GetWindowWMInfo(m_window, &info) && info.subsystem == SDL_SYSWM_WINDOWS) {
                        nativeWindow = u64(info.info.win.window);
                        platform::WideString filename;
                        filename.allocate(filename.capacity());
                        while(true) {
                                DWORD size = GetModuleFileNameW(NULL, filename.data(), filename.size());
                                if(size < filename.size()) {
                                        filename.resize(size);
                                        break;
                                }
                                filename.allocate(filename.size() * 2);
                        }
                        HICON largeIcon = 0;
                        HICON smallIcon = 0;
                        ExtractIconExW(filename, 0, &largeIcon, &smallIcon, 1);
                        if(smallIcon) {
                                SendMessage(info.info.win.window, WM_SETICON, ICON_SMALL, LPARAM(smallIcon));
                        }
                        if(largeIcon) {
                                SendMessage(info.info.win.window, WM_SETICON, ICON_BIG, LPARAM(largeIcon));
                        }
                }
        }
        #endif
        #if ARX_HAVE_SDL2_X11
        if(!nativeWindow) {
                nativeWindow = SDL2X11_getNativeWindowHandle(m_window);
        }
        #endif
        CrashHandler::setWindow(nativeWindow);
        
        setVSync(m_vsync);
        
        SDL_ShowWindow(m_window);
        SDL_ShowCursor(SDL_DISABLE);
        
        setGamma(m_gamma);
        
        m_renderer->initialize();
        
        onCreate();
        onToggleFullscreen(m_fullscreen);
        updateSize(true);
        
        onShow(true);
        onFocus(true);
        
        return true;
}

That's a lot of stuff to learn and digest, beyond my time allocatable atm.

clort81 avatar Jan 20 '23 02:01 clort81

Had a bit more time and made a simple SDL2 opengl window without error:

include <iostream>

#include <SDL2/SDL.h>


void sdl_exception(std::string operation) {
    std::cout << operation << ": " << SDL_GetError() << std::endl;
    std::exit(1);
}

int main() {
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        sdl_exception("SDL_Init");
    }

    auto window = SDL_CreateWindow(
            "Simple",
            SDL_WINDOWPOS_UNDEFINED,
            SDL_WINDOWPOS_UNDEFINED,
            1366,
            768,
            SDL_WINDOW_OPENGL  | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE                                                            
    );
    if (window == nullptr) {
        sdl_exception("SDL_CreateWindow");
    }

    auto renderer = SDL_CreateRenderer(
            window,
            -1,
            SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC
    );
    if (renderer == nullptr) {
        sdl_exception("SDL_CreateRenderer");
    }

    auto running = true;

    while (running) {
        SDL_Event event;
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_KEYDOWN and event.key.keysym.sym == SDLK_ESCAPE) {
                running = false;
            }
        }
        if (SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0) < 0) {
            sdl_exception("SDL_SetRenderDrawColor");
        }
        if (SDL_RenderClear(renderer) < 0) {
            sdl_exception("SDL_RenderClear");
        }
        SDL_RenderPresent(renderer);
    }

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}

clort81 avatar Jan 20 '23 03:01 clort81

i don't see where SDL_Init() is being called, come to think of it. Very confused now.

clort81 avatar Jan 20 '23 03:01 clort81

It's a shame that we can't use this awesome library, any fixes 2 months later? I believe it has something to do with the View class and ImGUI.

ghost avatar Mar 03 '23 14:03 ghost

Hi guys!

I am really sorry for the late reply and that you can't run TinyEngine.

It's really difficult for me to debug this because it appears to be an issue only on specific hardware.

I can break-down the initialization procedure for you if you like @clort81

Note in TinyEngine.h, that calling Tiny::window launches SDL and finally calls view::init. Note that this creates an SDL_GL_Context, and not a renderer. I believe that this is where the hardware differences appear.

All of the "SDL_GL" setup stuff you mentioned before, I also do appropriately.

The stack trace you posted above that gets caught in view::target appears to give a segfault because it failed to initialize the OpenGL context and that is usually the first function call which attempts to actively alter OpenGL context state.

So it still appears to be a driver issue. The best thing would be for you to post your mesa driver version, cpu / gpu version / general hardware specs, so we can try to see if there is a pattern.

And just as an absolute sanity check, make sure SDL and all that good stuff is up to date.

Maybe if I get GitHub actions set up, we can guarantee builds for different architectures.

weigert avatar Mar 08 '23 10:03 weigert

Here's the output of glxinfo: glxinfo-out.txt Running on Debian Bullseye. @weigert It feels like it's more of a system compatability issue more than a hardware issue. It's been tested on MacOS, right?

ghost avatar Mar 08 '23 14:03 ghost