3

我目前在wgpu工作,以获得优于 OpenGl 的效率优势。我之前的图形代码中的一个常见模式是使用单独的缓冲区、单独的统一数据、但相同的着色器绘制许多网格。它看起来像这样(在 C++ 中):

glUseProgram(m_myProgram();
for(Mesh &mesh : m_meshes){
    glBindVertexArray(mesh.vaoId());
    glUniformMatrix4fv(m_transformationMatrixId, camera.getMatrix(mesh.getLocation());
    glDrawElements(GL_TRIANGLES, mesh.indexCount(), GL_UINT, nullptr);    
}

(可能有一些微妙且不相关的错误——我有一段时间没用过 OpenGl)

然而,当我尝试使用 wgpu 在 Rust 中复制相同的模式时,我遇到了问题。

            let view_projection = self.camera.build_view_projection_matrix();

            let mut render_pass = encoder.begin_render_pass(&RenderPassDescriptor {
                color_attachments: &[RenderPassColorAttachmentDescriptor {
                    attachment: &frame.view,
                    resolve_target: None,
                    load_op: LoadOp::Clear,
                    store_op: StoreOp::Store,
                    clear_color: Color {
                        r: 0.1,
                        g: 0.2,
                        b: 0.3,
                        a: 1.0,
                    },
                }],
                depth_stencil_attachment: None,
            });

            render_pass.set_pipeline(&self.render_pipeline);
            render_pass.set_bind_group(0, &self.uniform_buffer_bind_group, &[]);
            for mesh in &self.mesh{
                mesh.render(&mut encoder, &mut render_pass, &view_projection, &self.uniform_buffer, &self.device); //ERROR! Can't borrow `encoder` mutably becuase `render_pass` is itself a mutable borrow, which already exists
            }

渲染函数如下所示:

        //build matrix
        let model_matrix = Matrix4::from_translation(self.location);
        let final_matrix = view_projection*model_matrix;

        //send matrix to gpu
        let uniforms = Uniforms::new_from_matrix(final_matrix);
        let buffer = device.create_buffer_with_data(
            bytemuck::cast_slice(&[uniforms]),
            BufferUsage::COPY_SRC
        );
        command_encoder.copy_buffer_to_buffer(&buffer, 0, &uniform_buffer, 0, std::mem::size_of_val(&uniforms) as BufferAddress); //A mutable borrow to the command encoder is needed here in order to update uniforms

        //setup buffers
        render_pass.set_vertex_buffer(0, &self.vertex_buffer, 0, 0);
        render_pass.set_index_buffer(&self.index_buffer, 0, 0);

        //render
        render_pass.draw(0..self.index_count, 0..1);

显然,需要可变借用来更新制服。为了提高效率,我强烈希望不要为每个网格开始新的渲染通道。所以,我问,如何在渲染过程中更新 wgpu 中的统一数据,以渲染许多具有相同设置的网格(除了统一)?是否有其他更好的方法来完成我想要的(使用自己的缓冲区和制服渲染许多网格,但共享着色器)?

我非常彻底地阅读了 wgpu 的 docs.rs 条目,但找不到与我想要的内容相关的任何内容。我也尝试过,但失败了,找到一个使用 wgpu 的严肃的 FOSS 项目,以便我可以看到它是如何处理这个问题的。

请注意,我使用的是 wgpu 0.5.0 而不是 0.6.0,因为这是我能找到的最好的 wgpu 介绍性文档

4

0 回答 0