HomoVafer
HomoVafer

Reputation: 323

How to pass data to openGL functions correctly in Rust

I'm trying to abstract openGL in Rust. I use glutin to communicate with openGL (here is the code I started with). I'm having problems abstracting Uniforms in fact they randomly get -1 as location (the same code sometimes works and sometimes doesn't).

I checked if the program was in use and it was so I started wondering if there is a problem in the way I send the data to openGL:

// value is initialised here

let name = name.to_string();
let location;
unsafe {
  location = gl.GetUniformLocation(program.get_id(), name.as_ptr() as *const GLchar);
};

match value {
  UniformType::Float(v) => unsafe {
    gl.Uniform1f(location, v);
  },
  UniformType::Float4(v) => unsafe {
    gl.Uniform4fv(location, 1, &v[0]); 
  },
  UniformType::Texture(tex_id) => unsafe {
    gl.Uniform1i(location, tex_id);
  },
  UniformType::Mat4x4(v) => unsafe {
    gl.UniformMatrix4fv(location, 1, gl::FALSE, &v[0]);
  },
  _ => {
   panic!("Uniform::new This uniform type is unknown");
  }
}

// this scope ends and value if freed

Is it a problem the fact that value gets freed right after the call to gl.Uniform? If yes, why? I read online that only the draw calls are asynchronous.


Edited: Debugging

The uniforms are actively used inside the shaders.

Gives the right number of active uniforms counting even those that got -1 as location:

let mut param = 0;
unsafe {
  gl.GetProgramiv(program.get_id(), gl::ACTIVE_UNIFORMS, &mut param);
}
println!("Number of active uniforms: {}", param); 

Always gives 'no error':

let err;
unsafe {
  err = gl.GetError();
}
match err {
  gl::NO_ERROR => {
    println!("Uniform '{}': no error", name);
  }
  gl::INVALID_VALUE => {
    println!("Uniform '{}': invalid value", name);
  }
  gl::INVALID_OPERATION => {
    println!("Uniform '{}': invalid operation", name);
  }
  _ => {
    println!("Uniform: '{}' error: {}", name, err);
  }
}

Upvotes: 0

Views: 1065

Answers (2)

HomoVafer
HomoVafer

Reputation: 323

At the end I found the problem:

// getting a CString from name
let cname = std::ffi::CString::new(name).expect("CString::new failed");

let location;
unsafe {
  location = gl.GetUniformLocation(program.get_id(), cname.as_ptr());
}

(sometimes I tend to forget that I'm working with bindings)

Upvotes: 1

Masklinn
Masklinn

Reputation: 42217

According to the documentation for GetUniformLocation:

This function returns -1 if name​ does not correspond to an active uniform variable in program​, if name​ starts with the reserved prefix "gl_", or if name​ is associated with an atomic counter or a named uniform block.

So you're not error-checking your gl calls, and it looks like there are cases where you're calling GetUniformLocation incorrectly, which could account for "sometimes it works, sometimes it does not".

Upvotes: 1

Related Questions