Skip to content

Universal approach to OpenGL error handling #550

@k06a

Description

@k06a

I've wrote cool macro to wrap every gl call (now works for some) to handle different OpenGL errors universally:
https://github.com/k06a/playder/blob/406ff6ea89541f79ef0cd1b452a6983d8270c2a4/src/main.rs#L12-L67

// Universal approach to OpenGL error handling
// Wrap every OpenGL call with gl_safe!(...) instead of unsafe { ... }
macro_rules! gl_safe {
    (gl::CompileShader($shader:expr), $step_name:expr) => {{
        let shader = $shader; // compute expression once
        let result = unsafe { gl::CompileShader(shader) };
        
        // Check for compilation errors
        let mut success = gl::FALSE as gl::types::GLint;
        unsafe { gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut success);}
        if success != gl::TRUE as gl::types::GLint {
            let mut len = 0;
            unsafe { gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len); }
            let mut buffer = vec![0u8; len as usize];
            unsafe { gl::GetShaderInfoLog(shader, len, ptr::null_mut(), buffer.as_mut_ptr() as *mut GLchar); }
            
            panic!("Shader compilation failed at \"{}\": {}. Check the shader source code for errors.", $step_name, str::from_utf8(&buffer).unwrap());
        }
        result
    }};
    (gl::LinkProgram($program:expr), $step_name:expr) => {{
        let program = $program; // compute expression once
        let result = unsafe { gl::LinkProgram($program) };
        
        // Check for linker errors
        let mut success = gl::FALSE as GLint;
        gl_safe!(gl::GetProgramiv(program, gl::LINK_STATUS, &mut success), "check link status: verify program linking success");
        if success != gl::TRUE as GLint {
            let mut len = 0;
            gl_safe!(gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len), "get program info log length: determine length of linking log");
            let mut buffer = vec![0u8; len as usize];
            gl_safe!(gl::GetProgramInfoLog(program, len, ptr::null_mut(), buffer.as_mut_ptr() as *mut GLchar), "get program info log: retrieve linking log");
            
            panic!("Program linking failed: {}. Verify that all shaders are correctly attached and compiled.", str::from_utf8(&buffer).unwrap());
        }
        result
    }};
    (gl::load_with($func:expr), $step_name:expr) => {{
        let result = gl::load_with($func); // safe call

        // Check for errors
        let err_code = unsafe { gl::GetError() };
        if err_code != gl::NO_ERROR {
            panic!("OpenGL error code {} at \"{}\"", err_code, $step_name);
        }
        result
    }};
    ($block:expr, $step_name:expr) => {{
        let result = unsafe { $block };

        // Check for errors
        let err_code = unsafe { gl::GetError() };
        if err_code != gl::NO_ERROR {
            panic!("OpenGL error code {} at \"{}\"", err_code, $step_name);
        }
        result
    }};
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions