Gfx: How to update indices slice?

Created on 26 Dec 2017  路  7Comments  路  Source: gfx-rs/gfx

Hi,

I use
let (vertex_buffer, slice) = self.factory.create_vertex_buffer_with_slice(&self.vec_pos_color_uv_data, &*self.ind_data);
to create vertex buffer and indices slice. Do I need to call this function every frame when my data changes or is there another way to update vertex buffer and indices slice?
I noticed that my log is printing: Created buffer 4545, Created buffer 4546... when I do this every frame.

Thanks.

Most helpful comment

I managed to get it working.

  1. I create both buffers:
let test_vbuf:gfx::handle::Buffer<gfx_device_gl::Resources, VertexPosColorUV> = factory.create_buffer(
    10000, 
    gfx::buffer::Role::Vertex, 
    gfx::memory::Usage::Dynamic, 
    gfx::Bind::empty()
).unwrap();

let test_ibuf:gfx::handle::Buffer<gfx_device_gl::Resources, u16> = factory.create_buffer(
    10000, 
    gfx::buffer::Role::Index, 
    gfx::memory::Usage::Dynamic, 
    gfx::Bind::empty()
).unwrap();
  1. Update buffers, create slice and draw:
self.encoder.update_buffer(&self.pos_color_uv_data.vbuf, &self.vec_pos_color_uv, 0).unwrap();
self.encoder.update_buffer(&self.ib, &self.ind_data, 0).unwrap();

let s = Slice {
            start: 0,
            end: self.ind_data.len() as u32,
            base_vertex: 0,
            instances: None,
            buffer: gfx::IndexBuffer::Index16(self.ib.clone()),
};

self.encoder.draw(&s, &self.pso2, &self.pos_color_uv_data);

Thanks for all help.

All 7 comments

Hello!
Vertex buffers are stored in GPU memory, so you don't need to create them every frame.
You can use update_buffer function to upload new info in your buffer.
Usually there's no need in changing slice (if you have the same number of elements)

Hi.

I use the following code

if !self.buffers_created
{
    let (vertex_buffer, slice) = self.factory.create_vertex_buffer_with_slice(&self.vec_pos_color_uv_data, &*self.ind_data);
    self.slice = slice;
    self.pos_color_uv_data.vbuf = vertex_buffer;
    self.buffers_created = true;
}
else 
{
        let ok = self.encoder.update_buffer(&self.pos_color_uv_data.vbuf, &self.vec_pos_color_uv_data, 0);
        match ok
    {
        Ok(_) => 
        {
            self.encoder.draw(&self.slice, &self.pso2, &self.pos_color_uv_data);
        },
        Err(err) =>
        {
            println!("{:?}", err);
        }
    }
}
self.encoder.draw(&self.slice, &self.pso2, &self.pos_color_uv_data);

But it doesn't work. Update_buffer functions returns error _InvalidUsage(Data)_. I should probably change buffer Usage to Dynamic but I don't know how to do that.
The code works if I use only the top part.

You can also manually assemble the vertex buffers and index buffers/slices. create_vertex_buffer_with_slice is a high level helper function (static mesh, mostly). But for more specific use-cases the lower level functions can be called as seen in the implementation, allowing more control.

Can you point me to some tutorials or examples. I'm having a hard time finding them on internet.

I'm afraid, we don't have much in-depth tutorials at the moment.
With implementation, I meant this part right here: https://github.com/gfx-rs/gfx/blob/pre-ll/src/render/src/factory.rs#L131-L145

Instead of creating immutable buffers (as done by create_vertex_buffer and create_index_buffer), dynamic buffers could be created for example as done here: https://github.com/gfx-rs/gfx/blob/pre-ll/src/render/src/factory.rs#L152-L155 (note that Role should be Vertex or Index).

These buffers should be done updateable as in your snippet above.
For less frequent updates on dedicated GPUs, 'staging' is a common optimization technique by storing the data in device local memory and copy data from an upload buffer (create_upload_buffer) over to the buffer (needs to be created with TRANSFER_DST bind).

I managed to get it working.

  1. I create both buffers:
let test_vbuf:gfx::handle::Buffer<gfx_device_gl::Resources, VertexPosColorUV> = factory.create_buffer(
    10000, 
    gfx::buffer::Role::Vertex, 
    gfx::memory::Usage::Dynamic, 
    gfx::Bind::empty()
).unwrap();

let test_ibuf:gfx::handle::Buffer<gfx_device_gl::Resources, u16> = factory.create_buffer(
    10000, 
    gfx::buffer::Role::Index, 
    gfx::memory::Usage::Dynamic, 
    gfx::Bind::empty()
).unwrap();
  1. Update buffers, create slice and draw:
self.encoder.update_buffer(&self.pos_color_uv_data.vbuf, &self.vec_pos_color_uv, 0).unwrap();
self.encoder.update_buffer(&self.ib, &self.ind_data, 0).unwrap();

let s = Slice {
            start: 0,
            end: self.ind_data.len() as u32,
            base_vertex: 0,
            instances: None,
            buffer: gfx::IndexBuffer::Index16(self.ib.clone()),
};

self.encoder.draw(&s, &self.pso2, &self.pos_color_uv_data);

Thanks for all help.

I'm glad it works! Thanks for the sharing the snippets.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kvark picture kvark  路  5Comments

mjadczak picture mjadczak  路  4Comments

kvark picture kvark  路  3Comments

kvark picture kvark  路  3Comments

InMath picture InMath  路  5Comments