在Rust中通过结构体使用OpenGL方法而不是全局访问它们有什么好处?

fkaflof6  于 2023-08-04  发布在  其他
关注(0)|答案(1)|浏览(168)

我目前正在将一个用C++编写的OpenGL应用程序移植到Rust上,遇到了一个设计问题,这个问题可能会有其他的影响,因为我对Rust很陌生。
目前我使用的是glutingl_generator的组合。在bindings模块中生成全局函数会生成以下API:

gl::load_with(|symbol| context.get_proc_address(symbol));
// anywhere else since it's global
gl::CreateProgram();

字符集
这与我在C++中用于访问全局方法的 Package 类的范例几乎相同:

// ...
FShader::~FShader() {
  if (Handle != 0) {
    glDeleteProgram(Handle);
  }
}

auto FShader::bind() const -> void { glUseProgram(Handle); }
// ...


在阅读了更多的帖子之后,我注意到一些人建议使用结构生成器,并使用对象而不是全局方法。

let gl = Rc::new(gl::Gl::load_with(|symbol| context.get_proc_address(symbol)));
// ...
pub struct Shader {
    gl: Rc<gl::Gl>,
    handle: u32,
}

impl Drop for Shader {
    fn drop(&mut self) {
        unsafe {
            self.gl.DeleteProgram(self.handle);
        }
    }
}

impl Shader {
    pub fn new(gl: Rc<gl::Gl>) -> Result<Shader, ()> {
        let handle = unsafe { gl.CreateProgram() };
        // ...
        Ok(Shader { gl, handle })
    }
}


这种方法无疑更加冗长,因为所有的 Package 类都必须存储一个指向gl::Gl对象的引用,以便能够释放资源。Drop::drop的签名似乎是为什么在对象之间共享引用是必要的原因。这样做还有其他好处吗?使用Rc是最好的方法还是使用常规引用更合理?

rm5edbpk

rm5edbpk1#

使用常规引用在性能方面可能会更好,因为Rc s具有引用计数的开销。
但是,如果要使用引用,则必须处理大量的生存期注解,这可能会使代码更加冗长。此外,你还必须保持gl::GL对象的活动,只要你使用OpenGL(我认为这是程序的整个生命周期)。

相关问题