grovesNL / glow

GL on Whatever: a set of bindings to run GL anywhere and avoid target-specific code
Apache License 2.0
1.2k stars 130 forks source link

Bad perfomance with instancing on Mac #194

Closed Nazariglez closed 3 years ago

Nazariglez commented 3 years ago

Hi @grovesNL, this is not an issue but it's the only way that I found to ask you about it.

I'm working on this project which is powered by glow. I'm adding support for instancing in the f/instancing branch and I noticed that instancing is way slower than batching on Mac. I'm not sure about windows because I have no one right now to test it. This doesn't surprise me because OpenGL has not been updated on Mac since the beginning of the time ;).

The performance is so bad that the window froze a little and it's hard to drag it from the screen. I use a FPS counter on my project, and with 10ks instances the FPS are around 40 and with 30ks around 19.

But as I'm using a really old version (3.3) I was hoping to be doing something wrong, this is the simplest test I made (no targeting 3.3 for the test but same results):


use glow::*;

//language=glsl
const VERTEX: &'static str = r#"
layout(location = 0) in vec2 a_pos;
out vec3 v_color;

const vec2 verts[3] = vec2[3](
    vec2(-0.2f, -0.2f),
    vec2(0.2f, -0.2f),
    vec2(0.0f, 0.2f)
);

void main() {
    float value = gl_InstanceID * 0.1;
    v_color = vec3(fract(value), 1.0 - fract(value), fract(value));

    vec2 pos = verts[gl_VertexID] - vec2(sin(value), cos(value)) * 0.5;
    gl_Position = vec4(pos, 0.0, 1.0);
}"#;

//language=glsl
const FRAGMENT: &'static str = r#"
precision mediump float;

in vec3 v_color;
out vec4 color;

void main() {
    color = vec4(v_color, 1.0);
}"#;

fn main() {
    unsafe {
        let (gl, shader_version, window, event_loop) = {
            let event_loop = glutin::event_loop::EventLoop::new();
            let window_builder = glutin::window::WindowBuilder::new()
                .with_title("Hello triangle!")
                .with_inner_size(glutin::dpi::LogicalSize::new(1024.0, 768.0));
            let window = glutin::ContextBuilder::new()
                .with_vsync(true)
                .build_windowed(window_builder, &event_loop)
                .unwrap()
                .make_current()
                .unwrap();
            let gl =
                glow::Context::from_loader_function(|s| window.get_proc_address(s) as *const _);
            (gl, "#version 330", window, event_loop)
        };

        let vertex_array = gl
            .create_vertex_array()
            .expect("Cannot create vertex array");
        gl.bind_vertex_array(Some(vertex_array));

        let program = gl.create_program().expect("Cannot create program");

        let shader_sources = [
            (glow::VERTEX_SHADER, VERTEX),
            (glow::FRAGMENT_SHADER, FRAGMENT),
        ];

        let mut shaders = Vec::with_capacity(shader_sources.len());

        for (shader_type, shader_source) in shader_sources.iter() {
            let shader = gl
                .create_shader(*shader_type)
                .expect("Cannot create shader");
            gl.shader_source(shader, &format!("{}\n{}", shader_version, shader_source));
            gl.compile_shader(shader);
            if !gl.get_shader_compile_status(shader) {
                panic!("{}", gl.get_shader_info_log(shader));
            }
            gl.attach_shader(program, shader);
            shaders.push(shader);
        }

        gl.link_program(program);
        if !gl.get_program_link_status(program) {
            panic!("{}", gl.get_program_info_log(program));
        }

        gl.use_program(Some(program));
        gl.clear_color(0.1, 0.2, 0.3, 1.0);

        {
            use glutin::event::{Event, WindowEvent};
            use glutin::event_loop::ControlFlow;

            event_loop.run(move |event, _, control_flow| {
                *control_flow = ControlFlow::Wait;
                match event {
                    Event::LoopDestroyed => {
                        return;
                    }
                    Event::MainEventsCleared => {
                        window.window().request_redraw();
                    }
                    Event::RedrawRequested(_) => {
                        gl.clear(glow::COLOR_BUFFER_BIT);
                        gl.draw_arrays_instanced(glow::TRIANGLES, 0, 3, 10000);
                        window.swap_buffers().unwrap();
                    }
                    Event::WindowEvent { ref event, .. } => match event {
                        WindowEvent::Resized(physical_size) => {
                            window.resize(*physical_size);
                        }
                        WindowEvent::CloseRequested => {
                            gl.delete_program(program);
                            gl.delete_vertex_array(vertex_array);
                            *control_flow = ControlFlow::Exit
                        }
                        _ => (),
                    },
                    _ => (),
                }
            });
        }
    }
}

Do you think that there is something wrong with my code?

Thanks!

Nazariglez commented 3 years ago

I don't think that this is related to Mac or that there is something wrong with my code anymore. It's a high-resolution issue related to the retina display. In a monitor with a 1.0 DPI it works great while it works poorly on the retina display due to being rendering 4x pixels.

This is not related to glow but I'm leaving this here just in case somebody has the same issue and ends up here. Glutin/Winit has an option called with_disallow_hidpi that I think it's meant to address this issue but seems like it's not working.

Thanks @grovesNL!