问题
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);
  }
}
    回答1:
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".
回答2:
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)
来源:https://stackoverflow.com/questions/63339027/how-to-pass-data-to-opengl-functions-correctly-in-rust