gfx-rs / gfx

[maintenance mode] A low-overhead Vulkan-like GPU API for Rust.
http://gfx-rs.github.io/
Apache License 2.0
5.35k stars 548 forks source link

Debian Linux: GLFW/SDL window providers do not work. #1114

Closed icefoxen closed 7 years ago

icefoxen commented 7 years ago

Discovered as kind of a sub-bug of https://github.com/gfx-rs/gfx/issues/1101 , but it is a different error happening in a different place so it seems wise to split it off into its own issue.

To recap:

Trying to run basic example code (triangle or cube) fails to build a window using GLFW or SDL, on Debian Stretch using NVidia drivers. It panics with "Error after executing command BindProgram(0): InvalidEnum". Altering the OpenGL version from 3.3 to 2.1 and everything between does not appear to affect anything, nor does using different shader version profiles. apitrace does not record any OpenGL calls but does produce some warnings:

apitrace: warning: _gl_param_size: unknown GLenum 0x92F5
apitrace: warning: _gl_param_size: unknown GLenum 0x92F5

Full code:


#[macro_use]
extern crate gfx;
extern crate gfx_window_glfw;
extern crate glfw;

use gfx::traits::FactoryExt;
use gfx::Device;
use glfw::{Action, Context, Key};

pub type ColorFormat = gfx::format::Rgba8;
pub type DepthFormat = gfx::format::DepthStencil;

gfx_defines!{
    vertex Vertex {
        pos: [f32; 2] = "a_Pos",
        color: [f32; 3] = "a_Color",
    }

    pipeline pipe {
        vbuf: gfx::VertexBuffer<Vertex> = (),
        out: gfx::RenderTarget<ColorFormat> = "Target0",
    }
}

const TRIANGLE: [Vertex; 3] = [Vertex {
                                   pos: [-0.5, -0.5],
                                   color: [1.0, 0.0, 0.0],
                               },
                               Vertex {
                                   pos: [0.5, -0.5],
                                   color: [0.0, 1.0, 0.0],
                               },
                               Vertex {
                                   pos: [0.0, 0.5],
                                   color: [0.0, 0.0, 1.0],
                               }];

const CLEAR_COLOR: [f32; 4] = [0.1, 0.2, 0.3, 1.0];

pub fn main() {
    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS)
        .ok()
        .expect("Failed to initialize GLFW");

    glfw.window_hint(glfw::WindowHint::ContextVersion(3, 2));
    glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
    glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));

    let (mut window, events) = glfw.create_window(800, 600, "Example", glfw::WindowMode::Windowed)
        .expect("Failed to create GLFW window.");

    window.make_current();
    glfw.set_error_callback(glfw::FAIL_ON_ERRORS);
    let (mut device, mut factory, color_view, depth_view) = gfx_window_glfw::init(&mut window);

    let mut encoder: gfx::Encoder<_, _> = factory.create_command_buffer().into();
    let pso = factory.create_pipeline_simple(include_bytes!("shader/triangle_120.glslv"),
                                include_bytes!("shader/triangle_120.glslf"),
                                pipe::new())
        .unwrap();
    let (vertex_buffer, slice) = factory.create_vertex_buffer_with_slice(&TRIANGLE, ());
    let data = pipe::Data {
        vbuf: vertex_buffer,
        out: color_view,
    };

    'main: loop {
        glfw.poll_events();

        for (_, event) in glfw::flush_messages(&events) {
            println!("{:?}", event);
            match event {
                glfw::WindowEvent::Key(Key::Escape, _, Action::Press, _) => {
                    break 'main;
                }
                _ => {}
            }
        }

        // draw a frame
        encoder.clear(&data.out, CLEAR_COLOR);
        encoder.draw(&slice, &pso, &data);
        encoder.flush(&mut device);
        window.swap_buffers();
        device.cleanup();
    }
}

Full stack trace:

> env RUST_BACKTRACE=1 cargo run
thread 'main' panicked at 'Error after executing command BindProgram(0): InvalidEnum', /home/icefox/.cargo/registry/src/github.com-1ecc6299db9ec823/gfx_device_gl-0.12.0/src/lib.rs:337
stack backtrace:
   1:     0x55fa68e2d12a - std::sys::imp::backtrace::tracing::imp::write::h917062bce4ff48c3
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:42
   2:     0x55fa68e311af - std::panicking::default_hook::{{closure}}::h0bacac31b5ed1870
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:247
   3:     0x55fa68e2f526 - std::panicking::default_hook::h5897799da33ece67
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:263
   4:     0x55fa68e2fb77 - std::panicking::rust_panic_with_hook::h109e116a3a861224
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:451
   5:     0x55fa68e2fa04 - std::panicking::begin_panic::hbb38be1379e09df0
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:413
   6:     0x55fa68e2f929 - std::panicking::begin_panic_fmt::h26713cea9bce3ab0
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:397
   7:     0x55fa68e0884d - gfx_device_gl::Device::check::h90b1e6010be96c4c
                        at /home/icefox/.cargo/registry/src/github.com-1ecc6299db9ec823/gfx_device_gl-0.12.0/src/lib.rs:337
   8:     0x55fa68e0a5f9 - gfx_device_gl::Device::process::h21bc7ed03a8334a6
                        at /home/icefox/.cargo/registry/src/github.com-1ecc6299db9ec823/gfx_device_gl-0.12.0/src/lib.rs:774
   9:     0x55fa68e0942b - gfx_device_gl::Device::reset_state::h6b8dd3b836e57daf
                        at /home/icefox/.cargo/registry/src/github.com-1ecc6299db9ec823/gfx_device_gl-0.12.0/src/lib.rs:436
  10:     0x55fa68e0cf18 - gfx_device_gl::Device::no_fence_submit::h5387d4f20deb72bd
                        at /home/icefox/.cargo/registry/src/github.com-1ecc6299db9ec823/gfx_device_gl-0.12.0/src/lib.rs:778
  11:     0x55fa68e0de55 - <gfx_device_gl::Device as gfx_core::Device>::submit::hb57ea237c103ce28
                        at /home/icefox/.cargo/registry/src/github.com-1ecc6299db9ec823/gfx_device_gl-0.12.0/src/lib.rs:901
  12:     0x55fa68d1351f - <gfx::encoder::Encoder<R, C>>::flush::hd37e88903533567d
                        at /home/icefox/.cargo/registry/src/github.com-1ecc6299db9ec823/gfx-0.13.0/src/encoder.rs:112
  13:     0x55fa68d33eed - gfx_particles::main::h40e2e46cf7cc27a7
                        at /home/icefox/my.src/gfx-particles/src/main.rs:97
  14:     0x55fa68e38c8a - __rust_maybe_catch_panic
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libpanic_unwind/lib.rs:97
  15:     0x55fa68e30595 - std::rt::lang_start::hd661476ce2fc2931
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:332
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panic.rs:351
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/rt.rs:57
  16:     0x55fa68d386c2 - main
  17:     0x7f7dee4e22b0 - __libc_start_main
  18:     0x55fa68d00239 - _start
  19:                0x0 - <unknown>
icefoxen commented 7 years ago

Like issue #1101 , this works fine on a system using an AMD GPU with the Gallium drivers. So something is happening that, one way or another, the NVidia official driver does not like. Might have been premature in splitting the issues.

kvark commented 7 years ago

@icefoxen please provide the SDL example code as well, if you have it

icefoxen commented 7 years ago
#[macro_use]
extern crate gfx;
extern crate gfx_window_sdl;
extern crate sdl2;

use gfx::traits::FactoryExt;
use gfx::Device;

pub type ColorFormat = gfx::format::Srgba8;
pub type DepthFormat = gfx::format::DepthStencil;

gfx_defines!{
    vertex Vertex {
        pos: [f32; 2] = "a_Pos",
        color: [f32; 3] = "a_Color",
    }

    pipeline pipe {
        vbuf: gfx::VertexBuffer<Vertex> = (),
        out: gfx::RenderTarget<ColorFormat> = "Target0",
    }
}

const TRIANGLE: [Vertex; 3] = [Vertex {
                                   pos: [-0.5, -0.5],
                                   color: [1.0, 0.0, 0.0],
                               },
                               Vertex {
                                   pos: [0.5, -0.5],
                                   color: [0.0, 1.0, 0.0],
                               },
                               Vertex {
                                   pos: [0.0, 0.5],
                                   color: [0.0, 0.0, 1.0],
                               }];

const CLEAR_COLOR: [f32; 4] = [0.1, 0.2, 0.3, 1.0];

pub fn main() {
    let sdl_context = sdl2::init().unwrap();
    let video = sdl_context.video().unwrap();
    let mut builder = video.window("Example", 800, 600);

    let (mut window, mut gl_context, mut device, mut factory, color_view, depth_view) =
        gfx_window_sdl::init(&mut builder);
    let mut renderer = window.renderer().build().unwrap();

    let mut encoder: gfx::Encoder<_, _> = factory.create_command_buffer().into();
    let pso = factory.create_pipeline_simple(include_bytes!("shader/triangle_120.glslv"),
                                include_bytes!("shader/triangle_120.glslf"),
                                pipe::new())
        .unwrap();
    let (vertex_buffer, slice) = factory.create_vertex_buffer_with_slice(&TRIANGLE, ());
    let data = pipe::Data {
        vbuf: vertex_buffer,
        out: color_view,
    };

    'main: loop {
        let mut event_pump = sdl_context.event_pump().unwrap();

        for event in event_pump.poll_iter() {
            println!("{:?}", event);
            match event {
                sdl2::event::Event::Quit { .. } => {
                    break 'main;
                }
                _ => {}
            }
        }

        // draw a frame
        encoder.clear(&data.out, CLEAR_COLOR);
        encoder.draw(&slice, &pso, &data);
        encoder.flush(&mut device);
        renderer.present();
        device.cleanup();
    }
}

Also looked up GLenum 0x92F5, it appears to be GL_ACTIVE_RESOURCES, which seems a strange thing for a driver not to have. The error does happen on encoder.flush(), if I remove that then it displays a blank window just fine.

kvark commented 7 years ago

@icefoxen thanks! If you remove encoder.flush() then there is nothing checking for GL errors in the first place. It should be validating the resource creation too, but not implemented yet. I guess for the lack of another way, this is where we start - I'll add more GL error checks and will ask you to test the latest afterwise.

icefoxen commented 7 years ago

Uh, well, it's different at least, though upon inspection my test code was using the 0.13 released version of gfx, not current master. So, I'm kinda incompetent? Or at least, it's late and I'm sleepy.

Using the current master, running the above SDL code as an example in gfx because I can't figure out how to make it build as a standalone project, I get this result:

thread 'main' panicked at 'Error InvalidOperation executing command: BindVao', src/backend/gl/src/lib.rs:740
stack backtrace:
   1:     0x557737380f0a - std::sys::imp::backtrace::tracing::imp::write::h917062bce4ff48c3
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:42
   2:     0x557737384ccf - std::panicking::default_hook::{{closure}}::h0bacac31b5ed1870
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:247
   3:     0x557737383046 - std::panicking::default_hook::h5897799da33ece67
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:263
   4:     0x557737383697 - std::panicking::rust_panic_with_hook::h109e116a3a861224
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:451
   5:     0x557737383524 - std::panicking::begin_panic::hbb38be1379e09df0
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:413
   6:     0x557737383449 - std::panicking::begin_panic_fmt::h26713cea9bce3ab0
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:397
   7:     0x557737362335 - gfx_device_gl::Device::process::h28ac9f4450ec5fbb
                        at /home/icefox/src/gfx/src/backend/gl/src/lib.rs:740
   8:     0x55773735e71b - gfx_device_gl::Device::reset_state::hb7886d3e0476e2d3
                        at /home/icefox/src/gfx/src/backend/gl/src/lib.rs:401
   9:     0x5577373623f8 - gfx_device_gl::Device::no_fence_submit::h238ca26625e23072
                        at /home/icefox/src/gfx/src/backend/gl/src/lib.rs:745
  10:     0x557737363265 - <gfx_device_gl::Device as gfx_core::Device>::submit::hb8358c57442c9fe8
                        at /home/icefox/src/gfx/src/backend/gl/src/lib.rs:872
  11:     0x55773729387f - <gfx::encoder::Encoder<R, C>>::flush::hd9be9f3a97f19eca
                        at /home/icefox/src/gfx/src/render/src/encoder.rs:125
  12:     0x5577372a8f20 - triangle_sdl::main::hd1f80edfff3acad5
                        at /home/icefox/src/gfx/examples/triangle-sdl/main.rs:76
  13:     0x55773738c7aa - __rust_maybe_catch_panic
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libpanic_unwind/lib.rs:97
  14:     0x5577373840b5 - std::rt::lang_start::hd661476ce2fc2931
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:332
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panic.rs:351
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/rt.rs:57
  15:     0x5577372ad202 - main
  16:     0x7f6f1e9c92b0 - __libc_start_main
  17:     0x5577372858e9 - _start
  18:                0x0 - <unknown>

Running the glfw example:

> ./target/debug/examples/triangle-glfw 
fish: “./target/debug/examples/triangl…” terminated by signal SIGSEGV (Address boundary error)

So that at least is new, if not welcome. Backtrace:

(gdb) bt
#0  0x00007fffefa6c3a0 in ?? ()
#1  0x00007ffff4f4b579 in ?? () from /usr/lib/x86_64-linux-gnu/libGL.so.1
#2  0x00007ffff4f45a19 in ?? () from /usr/lib/x86_64-linux-gnu/libGL.so.1
#3  0x00007ffff4f3848d in glXGetClientString () from /usr/lib/x86_64-linux-gnu/libGL.so.1
#4  0x00005555555f8fa8 in chooseFBConfig (desired=0x7fffffffcab0, result=0x7fffffffc9d0)
    at /home/icefox/.cargo/registry/src/github.com-1ecc6299db9ec823/glfw-sys-3.2.1/src/glx_context.c:61
#5  0x00005555555fa5d3 in _glfwChooseVisualGLX (ctxconfig=0x7fffffffca80, fbconfig=0x7fffffffcab0, visual=0x7fffffffca18, 
    depth=0x7fffffffca14) at /home/icefox/.cargo/registry/src/github.com-1ecc6299db9ec823/glfw-sys-3.2.1/src/glx_context.c:596
#6  0x00005555555f7798 in _glfwPlatformCreateWindow (window=0x7ffff55bb180, wndconfig=0x7fffffffca50, ctxconfig=0x7fffffffca80, 
    fbconfig=0x7fffffffcab0) at /home/icefox/.cargo/registry/src/github.com-1ecc6299db9ec823/glfw-sys-3.2.1/src/x11_window.c:1517
#7  0x00005555555f0858 in glfwCreateWindow (width=800, height=600, title=0x7ffff54203b8 "Example", monitor=0x0, share=0x0)
    at /home/icefox/.cargo/registry/src/github.com-1ecc6299db9ec823/glfw-sys-3.2.1/src/window.c:195
#8  0x00005555555ed8ef in glfw::{{impl}}::create_window_intern::{{closure}} (title=0x7ffff54203b8 "Example")
    at /home/icefox/.cargo/registry/src/github.com-1ecc6299db9ec823/glfw-0.11.0/src/lib.rs:893
#9  0x00005555555e9649 in glfw::with_c_str<closure,*mut glfw::ffi::GLFWwindow> (s=..., f=...)
    at /home/icefox/.cargo/registry/src/github.com-1ecc6299db9ec823/glfw-0.11.0/src/lib.rs:1123
#10 0x00005555555e8f24 in glfw::Glfw::create_window_intern (self=0x7fffffffe450, width=800, height=600, title=..., mode=..., share=...)
    at /home/icefox/.cargo/registry/src/github.com-1ecc6299db9ec823/glfw-0.11.0/src/lib.rs:892
#11 0x00005555555e8e33 in glfw::Glfw::create_window (self=0x7fffffffe450, width=800, height=600, title=..., mode=...)
    at /home/icefox/.cargo/registry/src/github.com-1ecc6299db9ec823/glfw-0.11.0/src/lib.rs:886
#12 0x000055555559273b in triangle_glfw::main () at /home/icefox/src/gfx/examples/triangle-glfw/main.rs:50
#13 0x00005555556716db in panic_unwind::__rust_maybe_catch_panic ()
    at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libpanic_unwind/lib.rs:97
#14 0x0000555555668fe6 in std::panicking::try<(),fn()> ()
    at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:332
#15 std::panic::catch_unwind<fn(),()> () at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panic.rs:351
#16 std::rt::lang_start () at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/rt.rs:57
#17 0x0000555555597573 in main ()

This happens even when I comment out encoder.flush() and such, so it's actually failing to create the window.

This is bonkers and I hate it. When I get a chance I'm going to try it out on a few different versions of Linux and see what's what.

kvark commented 7 years ago

@icefoxen thank you! The SDL issue appears to be related to VAO support. We actually check for the capability and test for it at start (private.array_buffer_supported), but then we aren't checking for it when executing the command buffer initialization, which includes BindVao call. This should be fixed. The GLFW is... god knows what :/

icefoxen commented 7 years ago

Finally, something kind of interesting comes out of my random poking:

On Debian Stable (8) GLFW works!

On Debian Stable, the SDL example dies with the exact same error as on Testing.

So at some point on my Testing system, something strange happened with the glfw version installed. :/ I'm going to assume that something weirdly inconsistent happened to cause the segfault and not worry about it too much, because when I did a fresh install of Debian Testing I got a much more reasonable error:

thread 'main' panicked at 'Error InvalidEnum after initialization', src/backend/gl/src/lib.rs:288
stack backtrace:
   1:     0x55e1037f111a - std::sys::imp::backtrace::tracing::imp::write::h917062bce4ff48c3
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:42
   2:     0x55e1037f519f - std::panicking::default_hook::{{closure}}::h0bacac31b5ed1870
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:247
   3:     0x55e1037f3516 - std::panicking::default_hook::h5897799da33ece67
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:263
   4:     0x55e1037f3b67 - std::panicking::rust_panic_with_hook::h109e116a3a861224
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:451
   5:     0x55e1037f39f4 - std::panicking::begin_panic::hbb38be1379e09df0
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:413
   6:     0x55e1037f3919 - std::panicking::begin_panic_fmt::h26713cea9bce3ab0
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:397
   7:     0x55e1036fd912 - gfx_device_gl::Device::new::h376ce00b450b43c0
                        at /home/icefox/src/gfx/<std macros>:8
   8:     0x55e1036fdb9a - gfx_device_gl::create::h34aedc4956336910
                        at /home/icefox/src/gfx/src/backend/gl/src/lib.rs:174
   9:     0x55e10372ca62 - gfx_window_glfw::init::hc83668bbd81d152c
                        at /home/icefox/src/gfx/src/window/glfw/src/lib.rs:64
  10:     0x55e1036f5d09 - triangle_glfw::main::hf94cda67c87da62d
                        at /home/icefox/src/gfx/examples/triangle-glfw/main.rs:55
  11:     0x55e1037fcc7a - __rust_maybe_catch_panic
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libpanic_unwind/lib.rs:97
  12:     0x55e1037f4585 - std::rt::lang_start::hd661476ce2fc2931
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:332
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/panic.rs:351
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libstd/rt.rs:57
  13:     0x55e1036faa72 - main
  14:     0x7f0997fc82b0 - __libc_start_main
  15:     0x55e1036c2579 - _start
  16:                0x0 - <unknown>

ARB_program_interface_query IS supported by the driver, or at least the driver claims it is, which was my first thought. The only place GL_ACTIVE_RESOURCES is mentioned in all of gfx is in src/backend/gl/src/shade.rs line 609 or so:

fn query_outputs(gl: &gl::Gl, prog: super::Program) -> (Vec<s::OutputVar>, bool) {
    use std::ptr;

    let mut out_depth = false;
    let mut num_slots = 0;
    unsafe {
        gl.GetProgramInterfaceiv(prog,
                                 gl::PROGRAM_OUTPUT,
                                 gl::ACTIVE_RESOURCES,
                                 &mut num_slots);
    }
...

Commenting out the gl.GetProgramInterfaceiv() call and hardcoding num_slots to 1 mysteriously seems to have no effect.

Trying from a different angle... Inserted code to check glGetError() stepping backwards from where it panics, and narrowed it down to an info::get() call in Device::new(). Tracked it there into the Capabilities constructing code... The responsible line turned out to be in info::get():

max_patch_size: get_usize(gl, gl::MAX_PATCH_VERTICES)

Hardcoding this value to 64 made the example work.

It appears that this being undefined is valid, since afaict this value is defined in OpenGL 4.0 or the ARB_tessellation_shader extension, and I am trying to run this on a graphics card using OpenGL 3.2 that does not have this extension.

Maybe get_usize() should return a Result? :/

icefoxen commented 7 years ago

Less bewilderingly, the SDL error appears to happen exactly where you would expect it to: the gl.BindVertexArray(self.vao) call in Device::process() To make things confusing again though, self.vao does appear to be valid (its value is 1) and it IS generating a VAO with the same number before calling Device::process(). It checks whether the VAO extension is supported before generating the array, and it seems that it is, as it SHOULD be since this is running on OpenGL 3.2 and it says it has the GL_ARB_vertex_array_object extension.

Creating the VAO also involves calling gl.BindVertexArray() right after generating it and that goes off without a hitch. Replacing self.vao with 0 in the gl.BindVertexArray call works fine and displays correct output. So I thought that somehow the VAO might be getting deleted, but DeleteVertexArrays appears to only ever get called in one of the examples, never in gfx itself.

Weeeeeeird.

kvark commented 7 years ago

Thanks for your awesome investigation @icefoxen ! if VAO is deleted, we could easily track it with apitrace.

icefoxen commented 7 years ago

Okay, completely removing the Command::BindVao case in Device::process() and making it a no-op... makes the example work fine. gl.IsVertexArray(self.vao) returns 0. And the BindVao command itself is only ever actually used in Device::reset_state() (which is, I confess, used in a few other places).

Massive apitrace dump for this mess:

13 glXChooseVisual(dpy = 0x7fe3b0653000, screen = 0, attribList = {GLX_RGBA, GLX_RED_SIZE, 3, GLX_GREEN_SIZE, 3, GLX_BLUE_SIZE,
 2, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 16, GLX_X_VISUAL_TYPE, GLX_DIRECT_COLOR, 0}) = &{visual = 0x7fe3b0679fc0, visualid = 106,
 screen = 0, depth = 24, c_class = 5, red_mask = 16711680, green_mask = 65280, blue_mask = 255, colormap_size = 256, bits_per_r
gb = 8}
14 glXCreateContext(dpy = 0x7fe3b0653000, vis = &{visual = 0x7fe3b0679fc0, visualid = 106, screen = 0, depth = 24, c_class = 5,
 red_mask = 16711680, green_mask = 65280, blue_mask = 255, colormap_size = 256, bits_per_rgb = 8}, shareList = NULL, direct = T
rue) = 0x7fe3b072a140
15 glXMakeCurrent(dpy = 0x7fe3b0653000, drawable = 50331650, ctx = 0x7fe3b072a140) = True
16 glViewport(x = 0, y = 0, width = 32, height = 32)
17 glScissor(x = 0, y = 0, width = 32, height = 32)
20 glXMakeCurrent(dpy = 0x7fe3b0653000, drawable = 0, ctx = NULL) = True
21 glXDestroyContext(dpy = 0x7fe3b0653000, ctx = 0x7fe3b072a140)
35 glXChooseVisual(dpy = 0x7fe3b0653000, screen = 0, attribList = {GLX_RGBA, GLX_RED_SIZE, 3, GLX_GREEN_SIZE, 3, GLX_BLUE_SIZE,
 2, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 16, GLX_X_VISUAL_TYPE, GLX_DIRECT_COLOR, 0}) = &{visual = 0x7fe3b0679fc0, visualid = 106,
 screen = 0, depth = 24, c_class = 5, red_mask = 16711680, green_mask = 65280, blue_mask = 255, colormap_size = 256, bits_per_r
gb = 8}
36 glXCreateContext(dpy = 0x7fe3b0653000, vis = &{visual = 0x7fe3b0679fc0, visualid = 106, screen = 0, depth = 24, c_class = 5,
 red_mask = 16711680, green_mask = 65280, blue_mask = 255, colormap_size = 256, bits_per_rgb = 8}, shareList = NULL, direct = T
rue) = 0x7fe3b072a140
37 glXMakeCurrent(dpy = 0x7fe3b0653000, drawable = 50331653, ctx = 0x7fe3b072a140) = True
38 glViewport(x = 0, y = 0, width = 800, height = 600)
39 glScissor(x = 0, y = 0, width = 800, height = 600)
754 glGetIntegerv(pname = GL_NUM_EXTENSIONS, params = &256)
1015 glGetIntegerv(pname = GL_MAX_ELEMENTS_VERTICES, params = &1048576)
1016 glGetIntegerv(pname = GL_MAX_ELEMENTS_INDICES, params = &1048576)
1017 glGetIntegerv(pname = GL_MAX_TEXTURE_SIZE, params = &8192)
1021 glEnable(cap = GL_FRAMEBUFFER_SRGB)
1022 glPixelStorei(pname = GL_UNPACK_ALIGNMENT, param = 1)
1023 glEnable(cap = GL_PROGRAM_POINT_SIZE)
1025 glGenVertexArrays(n = 1, arrays = &1)
1026 glBindVertexArray(array = 1)
1029 glXCreateContext(dpy = 0x7fe3b0653000, vis = &{visual = 0x7fe3b0679fc0, visualid = 106, screen = 0, depth = 24, c_class = 
5, red_mask = 16711680, green_mask = 65280, blue_mask = 255, colormap_size = 256, bits_per_rgb = 8}, shareList = NULL, direct =
 True) = 0x7fe3b072c540
1030 glXMakeCurrent(dpy = 0x7fe3b0653000, drawable = 50331653, ctx = 0x7fe3b072c540) = True
1031 glViewport(x = 0, y = 0, width = 800, height = 600)
1032 glScissor(x = 0, y = 0, width = 800, height = 600)
1077 glXQueryDrawable(dpy = 0x7fe3b0653000, draw = 50331653, attribute = GLX_LATE_SWAPS_TEAR_EXT, value = &0)
1078 glXQueryDrawable(dpy = 0x7fe3b0653000, draw = 50331653, attribute = GLX_SWAP_INTERVAL_EXT, value = &1)
1079 glXSwapIntervalEXT(dpy = 0x7fe3b0653000, drawable = 50331653, interval = 1)
1080 glXSwapIntervalEXT(dpy = 0x7fe3b0653000, drawable = 50331653, interval = 0)
1081 glXQueryDrawable(dpy = 0x7fe3b0653000, draw = 50331653, attribute = GLX_LATE_SWAPS_TEAR_EXT, value = &0)
1082 glXQueryDrawable(dpy = 0x7fe3b0653000, draw = 50331653, attribute = GLX_SWAP_INTERVAL_EXT, value = &0)
1087 glGetIntegerv(pname = GL_NUM_EXTENSIONS, params = &256)
1173 glGetIntegerv(pname = GL_MAX_TEXTURE_SIZE, params = &8192)
1178 glGetIntegerv(pname = GL_NUM_EXTENSIONS, params = &256)
1225 glGetIntegerv(pname = GL_MAX_TEXTURE_UNITS, params = &4)
1230 glGetIntegerv(pname = GL_NUM_EXTENSIONS, params = &256)
1320 glGetIntegerv(pname = GL_NUM_EXTENSIONS, params = &256)
1385 glGetIntegerv(pname = GL_NUM_EXTENSIONS, params = &256)
1452 glGetIntegerv(pname = GL_NUM_EXTENSIONS, params = &256)
1563 glGetIntegerv(pname = GL_NUM_EXTENSIONS, params = &256)
1607 glCreateProgramObjectARB() = 1
1608 glCreateShaderObjectARB(shaderType = GL_VERTEX_SHADER) = 2
1609 glShaderSourceARB(shaderObj = 2, count = 2, string = {"", "varying vec4 v_color;

void main()
{
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    v_color = gl_Color;
}"}, length = NULL)
1610 glCompileShaderARB(shaderObj = 2)
1611 glGetObjectParameterivARB(obj = 2, pname = GL_COMPILE_STATUS, params = &1)
1612 glCreateShaderObjectARB(shaderType = GL_FRAGMENT_SHADER) = 3
1613 glShaderSourceARB(shaderObj = 3, count = 2, string = {"#define UVCoordScale 1.0
", "varying vec4 v_color;

void main()
{
    gl_FragColor = v_color;
}"}, length = NULL)
1614 glCompileShaderARB(shaderObj = 3)
1615 glGetObjectParameterivARB(obj = 3, pname = GL_COMPILE_STATUS, params = &1)
1616 glAttachObjectARB(containerObj = 1, obj = 2)
1617 glAttachObjectARB(containerObj = 1, obj = 3)
1618 glLinkProgramARB(programObj = 1)
1619 glUseProgramObjectARB(programObj = 1)
1620 glGetUniformLocationARB(programObj = 1, name = "tex0") = -1
1621 glGetUniformLocationARB(programObj = 1, name = "tex1") = -1
1622 glGetUniformLocationARB(programObj = 1, name = "tex2") = -1
1623 glGetUniformLocationARB(programObj = 1, name = "tex3") = -1
1624 glUseProgramObjectARB(programObj = 0)
1627 glCreateProgramObjectARB() = 4
1628 glCreateShaderObjectARB(shaderType = GL_VERTEX_SHADER) = 5
1629 glShaderSourceARB(shaderObj = 5, count = 2, string = {"", "varying vec4 v_color;
varying vec2 v_texCoord;

void main()
{
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    v_color = gl_Color;
    v_texCoord = vec2(gl_MultiTexCoord0);
}"}, length = NULL)
1630 glCompileShaderARB(shaderObj = 5)
1631 glGetObjectParameterivARB(obj = 5, pname = GL_COMPILE_STATUS, params = &1)
1632 glCreateShaderObjectARB(shaderType = GL_FRAGMENT_SHADER) = 6
1633 glShaderSourceARB(shaderObj = 6, count = 2, string = {"#define UVCoordScale 1.0
", "varying vec4 v_color;
varying vec2 v_texCoord;
uniform sampler2D tex0;

void main()
{
    gl_FragColor = texture2D(tex0, v_texCoord) * v_color;
}"}, length = NULL)
1634 glCompileShaderARB(shaderObj = 6)
1635 glGetObjectParameterivARB(obj = 6, pname = GL_COMPILE_STATUS, params = &1)
1636 glAttachObjectARB(containerObj = 4, obj = 5)
1637 glAttachObjectARB(containerObj = 4, obj = 6)
1638 glLinkProgramARB(programObj = 4)
1639 glUseProgramObjectARB(programObj = 4)
1640 glGetUniformLocationARB(programObj = 4, name = "tex0") = 0
1641 glUniform1iARB(location = 0, v0 = 0)
1642 glGetUniformLocationARB(programObj = 4, name = "tex1") = -1
1643 glGetUniformLocationARB(programObj = 4, name = "tex2") = -1
1644 glGetUniformLocationARB(programObj = 4, name = "tex3") = -1
1645 glUseProgramObjectARB(programObj = 0)
1648 glCreateProgramObjectARB() = 7
1649 glCreateShaderObjectARB(shaderType = GL_VERTEX_SHADER) = 8
1650 glShaderSourceARB(shaderObj = 8, count = 2, string = {"", "varying vec4 v_color;
varying vec2 v_texCoord;

void main()
{
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    v_color = gl_Color;
    v_texCoord = vec2(gl_MultiTexCoord0);
}"}, length = NULL)
1651 glCompileShaderARB(shaderObj = 8)
1652 glGetObjectParameterivARB(obj = 8, pname = GL_COMPILE_STATUS, params = &1)
1653 glCreateShaderObjectARB(shaderType = GL_FRAGMENT_SHADER) = 9
1654 glShaderSourceARB(shaderObj = 9, count = 2, string = {"#define UVCoordScale 1.0
", "varying vec4 v_color;
varying vec2 v_texCoord;
uniform sampler2D tex0; // Y 
uniform sampler2D tex1; // U 
uniform sampler2D tex2; // V 

// YUV offset 
const vec3 offset = vec3(-0.0627451017, -0.501960814, -0.501960814);

// RGB coefficients 
const vec3 Rcoeff = vec3(1.164,  0.000,  1.596);
const vec3 Gcoeff = vec3(1.164, -0.391, -0.813);
const vec3 Bcoeff = vec3(1.164,  2.018,  0.000);

void main()
{
    vec2 tcoord;
    vec3 yuv, rgb;

    // Get the Y value 
    tcoord = v_texCoord;
    yuv.x = texture2D(tex0, tcoord).r;

    // Get the U and V values 
   tcoord *= UVCoordScale;
    yuv.y = texture2D(tex1, tcoord).r;
    yuv.z = texture2D(tex2, tcoord).r;

    // Do the color transform 
    yuv += offset;
    rgb.r = dot(yuv, Rcoeff);
    rgb.g = dot(yuv, Gcoeff);
    rgb.b = dot(yuv, Bcoeff);

    // That was easy. :) 
    gl_FragColor = vec4(rgb, 1.0) * v_color;
}"}, length = NULL)
1655 glCompileShaderARB(shaderObj = 9)
1656 glGetObjectParameterivARB(obj = 9, pname = GL_COMPILE_STATUS, params = &1)
1657 glAttachObjectARB(containerObj = 7, obj = 8)
1658 glAttachObjectARB(containerObj = 7, obj = 9)
1659 glLinkProgramARB(programObj = 7)
1660 glUseProgramObjectARB(programObj = 7)
1661 glGetUniformLocationARB(programObj = 7, name = "tex0") = 0
1662 glUniform1iARB(location = 0, v0 = 0)
1663 glGetUniformLocationARB(programObj = 7, name = "tex1") = 1
1664 glUniform1iARB(location = 1, v0 = 1)
1665 glGetUniformLocationARB(programObj = 7, name = "tex2") = 2
1666 glUniform1iARB(location = 2, v0 = 2)
1667 glGetUniformLocationARB(programObj = 7, name = "tex3") = -1
1668 glUseProgramObjectARB(programObj = 0)
1671 glCreateProgramObjectARB() = 10
1672 glCreateShaderObjectARB(shaderType = GL_VERTEX_SHADER) = 11
1673 glShaderSourceARB(shaderObj = 11, count = 2, string = {"", "varying vec4 v_color;
varying vec2 v_texCoord;

void main()
{
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    v_color = gl_Color;
    v_texCoord = vec2(gl_MultiTexCoord0);
}"}, length = NULL)
1674 glCompileShaderARB(shaderObj = 11)
1675 glGetObjectParameterivARB(obj = 11, pname = GL_COMPILE_STATUS, params = &1)
1676 glCreateShaderObjectARB(shaderType = GL_FRAGMENT_SHADER) = 12
1677 glShaderSourceARB(shaderObj = 12, count = 2, string = {"#define UVCoordScale 1.0
", "varying vec4 v_color;
varying vec2 v_texCoord;
uniform sampler2D tex0; // Y 
uniform sampler2D tex1; // U/V 

// YUV offset 
const vec3 offset = vec3(-0.0627451017, -0.501960814, -0.501960814);

// RGB coefficients 
const vec3 Rcoeff = vec3(1.164,  0.000,  1.596);
const vec3 Gcoeff = vec3(1.164, -0.391, -0.813);
const vec3 Bcoeff = vec3(1.164,  2.018,  0.000);

void main()
{
    vec2 tcoord;
    vec3 yuv, rgb;

    // Get the Y value 
    tcoord = v_texCoord;
    yuv.x = texture2D(tex0, tcoord).r;

    // Get the U and V values 
    tcoord *= UVCoordScale;
    yuv.yz = texture2D(tex1, tcoord).ra;

    // Do the color transform 
    yuv += offset;
    rgb.r = dot(yuv, Rcoeff);
    rgb.g = dot(yuv, Gcoeff);
    rgb.b = dot(yuv, Bcoeff);

    // That was easy. :) 
    gl_FragColor = vec4(rgb, 1.0) * v_color;
}"}, length = NULL)
1678 glCompileShaderARB(shaderObj = 12)
1679 glGetObjectParameterivARB(obj = 12, pname = GL_COMPILE_STATUS, params = &1)
1680 glAttachObjectARB(containerObj = 10, obj = 11)
1681 glAttachObjectARB(containerObj = 10, obj = 12)
1682 glLinkProgramARB(programObj = 10)
1683 glUseProgramObjectARB(programObj = 10)
1684 glGetUniformLocationARB(programObj = 10, name = "tex0") = 0
1685 glUniform1iARB(location = 0, v0 = 0)
1686 glGetUniformLocationARB(programObj = 10, name = "tex1") = 1
1687 glUniform1iARB(location = 1, v0 = 1)
1688 glGetUniformLocationARB(programObj = 10, name = "tex2") = -1
1689 glGetUniformLocationARB(programObj = 10, name = "tex3") = -1
1690 glUseProgramObjectARB(programObj = 0)
1693 glCreateProgramObjectARB() = 13
1694 glCreateShaderObjectARB(shaderType = GL_VERTEX_SHADER) = 14
1695 glShaderSourceARB(shaderObj = 14, count = 2, string = {"", "varying vec4 v_color;
varying vec2 v_texCoord;

void main()
{
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    v_color = gl_Color;
    v_texCoord = vec2(gl_MultiTexCoord0);
}"}, length = NULL)
1696 glCompileShaderARB(shaderObj = 14)
1697 glGetObjectParameterivARB(obj = 14, pname = GL_COMPILE_STATUS, params = &1)
1698 glCreateShaderObjectARB(shaderType = GL_FRAGMENT_SHADER) = 15
1699 glShaderSourceARB(shaderObj = 15, count = 2, string = {"#define UVCoordScale 1.0
", "varying vec4 v_color;
varying vec2 v_texCoord;
uniform sampler2D tex0; // Y 
uniform sampler2D tex1; // U/V 

// YUV offset 
const vec3 offset = vec3(-0.0627451017, -0.501960814, -0.501960814);

// RGB coefficients 
const vec3 Rcoeff = vec3(1.164,  0.000,  1.596);
const vec3 Gcoeff = vec3(1.164, -0.391, -0.813);
const vec3 Bcoeff = vec3(1.164,  2.018,  0.000);
void main()
{
    vec2 tcoord;
    vec3 yuv, rgb;

    // Get the Y value 
    tcoord = v_texCoord;
    yuv.x = texture2D(tex0, tcoord).r;

    // Get the U and V values 
    tcoord *= UVCoordScale;
    yuv.yz = texture2D(tex1, tcoord).ar;

    // Do the color transform 
    yuv += offset;
    rgb.r = dot(yuv, Rcoeff);
    rgb.g = dot(yuv, Gcoeff);
    rgb.b = dot(yuv, Bcoeff);

    // That was easy. :) 
    gl_FragColor = vec4(rgb, 1.0) * v_color;
}"}, length = NULL)
1700 glCompileShaderARB(shaderObj = 15)
1701 glGetObjectParameterivARB(obj = 15, pname = GL_COMPILE_STATUS, params = &1)
1702 glAttachObjectARB(containerObj = 13, obj = 14)
1703 glAttachObjectARB(containerObj = 13, obj = 15)
1704 glLinkProgramARB(programObj = 13)
1705 glUseProgramObjectARB(programObj = 13)
1706 glGetUniformLocationARB(programObj = 13, name = "tex0") = 0
1707 glUniform1iARB(location = 0, v0 = 0)
1708 glGetUniformLocationARB(programObj = 13, name = "tex1") = 1
1709 glUniform1iARB(location = 1, v0 = 1)
1710 glGetUniformLocationARB(programObj = 13, name = "tex2") = -1
1711 glGetUniformLocationARB(programObj = 13, name = "tex3") = -1
1712 glUseProgramObjectARB(programObj = 0)
1718 glGetIntegerv(pname = GL_NUM_EXTENSIONS, params = &256)
1860 glDisable(cap = GL_DEPTH_TEST)
1861 glDisable(cap = GL_CULL_FACE)
1862 glMatrixMode(mode = GL_MODELVIEW)
1863 glLoadIdentity()
1864 glGenFramebuffers(n = 1, framebuffers = &1)
1865 glCreateShader(type = GL_VERTEX_SHADER) = 16
1866 glShaderSource(shader = 16, count = 1, string = &"#version 120

attribute vec2 a_Pos;
attribute vec3 a_Color;
varying vec4 v_Color;

void main() {
    v_Color = vec4(a_Color, 1.0);
    gl_Position = vec4(a_Pos, 0.0, 1.0);
}
", length = &174)
1867 glCompileShader(shader = 16)
1868 glGetShaderiv(shader = 16, pname = GL_COMPILE_STATUS, params = &1)
1869 glGetShaderiv(shader = 16, pname = GL_INFO_LOG_LENGTH, params = &1)
1870 glGetShaderInfoLog(shader = 16, bufSize = 1, length = &0, infoLog = "")
1871 glCreateShader(type = GL_FRAGMENT_SHADER) = 17
1872 glShaderSource(shader = 17, count = 1, string = &"#version 120

varying vec4 v_Color;

void main() {
    gl_FragColor = v_Color;
}
", length = &81)
1873 glCompileShader(shader = 17)
1874 glGetShaderiv(shader = 17, pname = GL_COMPILE_STATUS, params = &1)
1875 glGetShaderiv(shader = 17, pname = GL_INFO_LOG_LENGTH, params = &1)
1876 glGetShaderInfoLog(shader = 17, bufSize = 1, length = &0, infoLog = "")
1877 glCreateProgram() = 18
1878 glAttachShader(program = 18, shader = 16)
1879 glAttachShader(program = 18, shader = 17)
1880 glBindAttribLocation(program = 18, index = 1, name = "a_Color")
1881 glBindAttribLocation(program = 18, index = 0, name = "a_Pos")
1882 glLinkProgram(program = 18)
1883 glGetProgramiv(program = 18, pname = GL_LINK_STATUS, params = &1)
1884 glGetProgramiv(program = 18, pname = GL_INFO_LOG_LENGTH, params = &1)
1885 glGetProgramInfoLog(program = 18, bufSize = 1, length = &0, infoLog = "")
1886 glGetProgramiv(program = 18, pname = GL_ACTIVE_UNIFORMS, params = &0)
1887 glGetActiveUniformsiv(program = 18, uniformCount = 0, uniformIndices = {}, pname = GL_UNIFORM_BLOCK_INDEX, params = 0x1)
1888 glGetActiveUniformsiv(program = 18, uniformCount = 0, uniformIndices = {}, pname = GL_UNIFORM_OFFSET, params = 0x1)
1889 glGetProgramiv(program = 18, pname = GL_ACTIVE_UNIFORM_MAX_LENGTH, params = &0)
1890 glUseProgram(program = 18)
1891 glGetProgramiv(program = 18, pname = GL_ACTIVE_ATTRIBUTES, params = &2)
1892 glGetProgramiv(program = 18, pname = GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, params = &8)
1893 glGetActiveAttrib(program = 18, index = 0, bufSize = 8, length = &7, size = &1, type = &GL_FLOAT_VEC3, name = "a_Color")
1894 glGetAttribLocation(program = 18, name = "a_Color") = 1
1895 glGetActiveAttrib(program = 18, index = 1, bufSize = 8, length = &5, size = &1, type = &GL_FLOAT_VEC2, name = "a_Pos")
1896 glGetAttribLocation(program = 18, name = "a_Pos") = 0
1897 glGetProgramiv(program = 18, pname = GL_ACTIVE_UNIFORM_BLOCKS, params = &0)
1898 glGetProgramiv(program = 18, pname = GL_ACTIVE_UNIFORM_MAX_LENGTH, params = &0)
1899 glGetProgramResourceiv(program = 18, programInterface = GL_PROGRAM_OUTPUT, index = 0, propCount = 1, props = &GL_NAME_LENGTH, bufSize = 1, length = NULL, params = &13)
1900 glGetProgramResourceName(program = 18, programInterface = GL_PROGRAM_OUTPUT, index = 0, bufSize = 13, length = NULL, name = "gl_FragColor")
1901 glGetProgramResourceiv(program = 18, programInterface = GL_PROGRAM_OUTPUT, index = 0, propCount = 1, props = &GL_LOCATION, bufSize = 1, length = NULL, params = &-1)
1902 glGetProgramResourceiv(program = 18, programInterface = GL_PROGRAM_OUTPUT, index = 0, propCount = 1, props = &GL_TYPE, bufSize = 1, length = NULL, params = &35666)
1904 glGenBuffers(n = 1, buffer = &1)
1905 glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 1)
1906 glBufferData(target = GL_ARRAY_BUFFER, size = 60, data = blob(60), usage = GL_STATIC_DRAW)
1908 glUseProgram(program = 0)
1912 glBindVertexArray(array = 1)
1913 glGetError() = GL_INVALID_OPERATION
1914 glDeleteObjectARB(obj = 0)
1915 glDeleteObjectARB(obj = 0)
1916 glDeleteObjectARB(obj = 0)
1917 glDeleteObjectARB(obj = 2)
1918 glDeleteObjectARB(obj = 3)
1919 glDeleteObjectARB(obj = 1)
1920 glDeleteObjectARB(obj = 5)
1921 glDeleteObjectARB(obj = 6)
1922 glDeleteObjectARB(obj = 4)
1923 glDeleteObjectARB(obj = 8)
1924 glDeleteObjectARB(obj = 9)
1925 glDeleteObjectARB(obj = 7)
1926 glDeleteObjectARB(obj = 11)
1927 glDeleteObjectARB(obj = 12)
1928 glDeleteObjectARB(obj = 10)
1929 glDeleteObjectARB(obj = 14)
1930 glDeleteObjectARB(obj = 15)
1931 glDeleteObjectARB(obj = 13)
1932 glXMakeCurrent(dpy = 0x7fe3b0653000, drawable = 0, ctx = NULL) = True
1933 glXDestroyContext(dpy = 0x7fe3b0653000, ctx = 0x7fe3b072c540)

I think that's about all I'm doing for tonight though. Whew.

icefoxen commented 7 years ago

I don't know why or how, but I suspect this is the key:

1025 glGenVertexArrays(n = 1, arrays = &1)
1026 glBindVertexArray(array = 1)
1029 glXCreateContext(dpy = 0x7fe3b0653000, vis = &{visual = 0x7fe3b0679fc0, visualid = 106, screen = 0, depth = 24, c_class = 
5, red_mask = 16711680, green_mask = 65280, blue_mask = 255, colormap_size = 256, bits_per_rgb = 8}, shareList = NULL, direct =
 True) = 0x7fe3b072c540
1030 glXMakeCurrent(dpy = 0x7fe3b0653000, drawable = 50331653, ctx = 0x7fe3b072c540) = True

We create our VAO, then generate an entirely new OpenGL context, bind it, and never use the old context ever again.

kvark commented 7 years ago

Wait a sec, this line must be re-creating the context:

let mut renderer = window.renderer().build().unwrap();

If it does, why do we even need gl_context? Perhaps, the gfx_window_sdl code should return Renderer instead of it then. I'm looking into what is Renderer, assume that's something you need to draw alongside gfx? It doesn't seem right, we don't want anything breaking the GL state behind our backs.

icefoxen commented 7 years ago

The Renderer in SDL2 is basically what tracks the drawing state for you... So yes, it makes sense it would create a GL context. I suspect you've found the key there.

Unfortunately, we need a Renderer to do the present() call to tell the window to swap buffers. Hmmmm.

kvark commented 7 years ago

@icefoxen You don't need Renderer with gfx. It's for SDL's own high level drawing. Instead of calling Renderer::present(), you just need to call (Window::gl_swap_window)[https://docs.rs/sdl2/0.27.3/sdl2/video/struct.WindowRef.html#method.gl_swap_window]

icefoxen commented 7 years ago

Ok, SDL doesn't like the max_patch_size call either (because it's not supported on this laptop) but once that's done, and the Renderer calls are removed and Window::gl_swap_window()put in its place...

It works beautifully. Thank you so very much, kvark! You still sure you don't want me to contribute these examples? ...Actually, I'll just push them to my github and you can link to them from the docs if you want.

kvark commented 7 years ago

@icefoxen last time someone (other than me) tried to update all examples with a non-trivial change, they gave up. We've already accumulated quite a bit of maintenance. Also, since SDL is not currently CI-built, maybe we can have some of your code lines as comments in the original triangle example?

icefoxen commented 7 years ago

For now I've just made a fork of gfx and the glfw and sdl examples in that. I'll sync it with upstream and update the examples whenever it occurs to me, which is all I really need for now. :smirk_cat: