Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Println! causes OpenGL program to not work?

I am currently developing a simple program in rust to draw a colored triangle to the screen. I followed the instructions from OpenGL. My program was working fine and the triangle rendered as expected:

enter image description here

After that I tried abstracting the code: The VAO, VBO and the ShaderProgram became a struct that handled binding, attaching the shaders and so on. That worked. Now to the problem:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

When I tried to abstract the Attributes I ran into a problem. I added those two methods to the ShaderProgram struct, that should handle the enabling of attributes without having to hardcode things like the stride or the pointer at which position in the vector the attribute starts.

pub fn add_attribute(&mut self, name: &'a str, length: i32) {
    let mut props = VertexAttributeProps::new(name, length);
    self.attributes.push(props);
}
pub fn apply_attributes(&self) {
    const GL_FLOAT_SIZE: i32 = mem::size_of::<gl::types::GLfloat>() as i32;
    let stride = self
        .attributes
        .iter()
        .fold(0, |prev, attr| prev + attr.length)
        * GL_FLOAT_SIZE;

    let mut current_pos: i32 = 0;
    for attr_options in self.attributes.iter() {
        // println!("{:?}", current_pos);
        unsafe {
            let attribute = VertexAttribute::new(
                location,
                attr_options.length,
                gl::FLOAT,
                gl::FALSE,
                stride,
                (current_pos * GL_FLOAT_SIZE) as *const c_void,
            );
            attribute.enable();
        }
        current_pos = current_pos + attr_options.length;
    }
}

With that I wanted to add my attributes like this:

shader_program.add_attribute("position", 2);
shader_program.add_attribute("color", 3);
shader_program.apply_attributes();

instead of this nasty block:

let posAttrib: GLuint;
unsafe {
    posAttrib = gl::GetAttribLocation(
        shader_program.program_handle,
        "position".as_ptr() as *const i8,
    ) as u32;
    gl::EnableVertexAttribArray(posAttrib);
    gl::VertexAttribPointer(
        posAttrib,
        2,
        gl::FLOAT,
        gl::FALSE,
        5 * mem::size_of::<gl::types::GLfloat>() as i32,
        0 as *const c_void,
    )
}

let colAttrib: GLuint;
unsafe {
    colAttrib =
        gl::GetAttribLocation(shader_program.program_handle, "color".as_ptr() as *const i8)
            as u32;
    gl::EnableVertexAttribArray(colAttrib);
    gl::VertexAttribPointer(
        colAttrib,
        3,
        gl::FLOAT,
        gl::FALSE,
        5 * mem::size_of::<gl::types::GLfloat>() as i32,
        (2 * mem::size_of::<gl::types::GLfloat>()) as *const c_void,
    )
}

But that did not work.

So I tried debugging. (Yes, the source of the bug lies in this code, I have tested that). I tried comparing the nasty code with my abstraction. So I added this println! to the nasty code:

let posAttrib: GLuint;
unsafe {
    posAttrib = gl::GetAttribLocation(
        shader_program.program_handle,
        "position".as_ptr() as *const i8,
    ) as u32;

    // ???????
    println!("{}", posAttrib);
    // ???????

    gl::EnableVertexAttribArray(posAttrib);
    gl::VertexAttribPointer(
        posAttrib,
        2,
        gl::FLOAT,
        gl::FALSE,
        5 * mem::size_of::<gl::types::GLfloat>() as i32,
        0 as *const c_void,
    )
}

and the triangle stopped rendering. Removing it and the triangle is back. How can a simple println be so harmful? Is it some kind of timing issue where the println! takes to long and everything somehow breaks?

>Solution :

Your code has undefined behavior. Rust string literals are not null-terminated as glGetAttribLocation expects. So there’s an out-of-bounds read until who knows where.

You’d need to use "position\0" or CString to fix that.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading