Vulkano: Vulkano.rs graphics pipeline guide does not compile

Created on 11 Sep 2018  路  10Comments  路  Source: vulkano-rs/vulkano

So following the guide posted here

When coming to the "drawing" part and setting up the command buffer that will be submit. The program fails to compile with following error:

error[E0277]: the trait bound `vulkano::pipeline::vertex::SingleBufferDefinition<Vertex>: vulkano::pipeline::vertex::VertexSource<std::sync::Arc<vulkano::buffer::CpuAccessibleBuffer<[Vertex; 3]>>>` is not satisfied
   --> src/main.rs:394:6
    |
394 |     .draw(pipeline.clone(), &state, vertex_buffer.clone(), (), ()).unwrap()
    |      ^^^^ the trait `vulkano::pipeline::vertex::VertexSource<std::sync::Arc<vulkano::buffer::CpuAccessibleBuffer<[Vertex; 3]>>>` is not implemented for `vulkano::pipeline::vertex::SingleBufferDefinition<Vertex>`
    |
    = help: the following implementations were found:
              <vulkano::pipeline::vertex::SingleBufferDefinition<V> as vulkano::pipeline::vertex::VertexSource<B>>
              <vulkano::pipeline::vertex::SingleBufferDefinition<V> as vulkano::pipeline::vertex::VertexSource<std::vec::Vec<std::sync::Arc<vulkano::buffer::BufferAccess + std::marker::Send + std::marker::Sync + 'static>>>>
    = note: required because of the requirements on the impl of `vulkano::pipeline::vertex::VertexSource<std::sync::Arc<vulkano::buffer::CpuAccessibleBuffer<[Vertex; 3]>>>` for `vulkano::pipeline::GraphicsPipeline<vulkano::pipeline::vertex::SingleBufferDefinition<Vertex>, std::boxed::Box<vulkano::descriptor::PipelineLayoutAbstract + std::marker::Send + std::marker::Sync>, std::sync::Arc<vulkano::framebuffer::RenderPass<setup_graphics_pipeline::scope::CustomRenderPassDesc>>>`
    = note: required because of the requirements on the impl of `vulkano::pipeline::vertex::VertexSource<std::sync::Arc<vulkano::buffer::CpuAccessibleBuffer<[Vertex; 3]>>>` for `std::sync::Arc<vulkano::pipeline::GraphicsPipeline<vulkano::pipeline::vertex::SingleBufferDefinition<Vertex>, std::boxed::Box<vulkano::descriptor::PipelineLayoutAbstract + std::marker::Send + std::marker::Sync>, std::sync::Arc<vulkano::framebuffer::RenderPass<setup_graphics_pipeline::scope::CustomRenderPassDesc>>>>`

I'm quite new to rust so still practicing deciphering these kinds of compile errors. Although it seems like something might be wrong with the vertex implementation or pipeline creation:

#[derive(Copy,Clone)]
pub struct Vertex{
    position : [f32;3]
}
impl_vertex!(Vertex, position);

let pipeline = Arc::new(
        GraphicsPipeline::start()
        .vertex_input_single_buffer::<Vertex>()
        .vertex_shader(vs_shader.main_entry_point(), ())
        .triangle_list()
        .viewports_dynamic_scissors_irrelevant(1)
        .fragment_shader(fs_shader.main_entry_point(),())
        .render_pass(Subpass::from(render_pass.clone(),0).unwrap())
        .build(device.clone()).unwrap()
        );

Any ideas?

Most helpful comment

@jonathansty I think you got the right idea :) Just to clarify one point...

I think I understand the use case and difference between from_data and from_iter. Sorry if these questions were a bit annoying I just got confused. In C and C++ this would use the same function for both cases.

I think the fundamental reason why the idiomatic Rust and C/++ abstractions differ here is that a Rust [T] knows what its size is and a C/++ T* doesn't.

This is one key ingredient of Rust's memory safety (you are not memory-safe if you can dereference pointers at unchecked offsets), but the price to pay for it is that you no longer have a unified abstraction for pointing to one object and one array of object.

All 10 comments

I've narrowed it down to the way of creating the CpuAccessibleBuffer for the vertex buffer.

    let vertices = [
        Vertex{position: [-0.5,-0.5,0.0]},
        Vertex{position: [0.0,0.5,0.0]},
        Vertex{position: [0.5,0.25,0.0]},
    ];

    let vertex_buffer = CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::vertex_buffer(), vertices).unwrap(); // doesn't compile
    let vertex_buffer = CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::vertex_buffer(), vertices.iter().cloned()).unwrap(); // compiles correctly

The draw call wants a CpuAccessibleBuffer<[Vertex]>, whereas you are trying to feed it with a CpuAccessibleBuffer<[Vertex; 3]> (check the CpuAccessibleBuffer::from_data() definition). Arrays and slices are not the same type in Rust, which is why this does not compile.

@HadrienG2 How would I go about using the CpuAccessibleBuffer::from_data function correctly in this case? I'm having trouble seeing the use case of this function. Any way I'm trying to use this seems to not compile.

The only work around I've found is to just always use the an iterator to my data and use the from_iter function.

I think the from_data constructor is meant to be used for "scalar" data like uniforms, not for arrays of vertices. If you look at the official example matching this part of the guide most closely, you will see that it uses the from_iter constructor.

Am I wrong in saying that following code should compile:

    let v = Vertex{position: [-0.5,-0.5,0.0]};
    let vertex_buffer = CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::vertex_buffer(), v).unwrap();

I can not get this to compile either though...

As HadrienG2 said, you want from_iter
There is a runnable example of the code in that section of the guide here: https://github.com/vulkano-rs/vulkano-www/blob/master/examples/guide-triangle.rs

@jonathansty The code you posted does not work, because it will produce a CpuAccessibleBuffer<Vertex> whereas you want a CpuAccessibleBuffer<[Vertex]> (notice the brackets: a slice with one element is not the same type as a single object).

So if I understand correctly from_data would be used to create buffers that can be bound as uniforms using descriptor sets and such?

I think I understand the use case and difference between from_data and from_iter. Sorry if these questions were a bit annoying I just got confused. In C and C++ this would use the same function for both cases.

I suggest adding an example that uses the from_data buffer to initialize a uniform buffer.

Go ahead and close this issue.

I wouldn't create an example solely to demonstrate from_data. hopefully we get an example in the future that uses it naturally as part of a larger example.
This PR should add one: https://github.com/vulkano-rs/vulkano-examples/pull/24/files

@jonathansty I think you got the right idea :) Just to clarify one point...

I think I understand the use case and difference between from_data and from_iter. Sorry if these questions were a bit annoying I just got confused. In C and C++ this would use the same function for both cases.

I think the fundamental reason why the idiomatic Rust and C/++ abstractions differ here is that a Rust [T] knows what its size is and a C/++ T* doesn't.

This is one key ingredient of Rust's memory safety (you are not memory-safe if you can dereference pointers at unchecked offsets), but the price to pay for it is that you no longer have a unified abstraction for pointing to one object and one array of object.

Was this page helpful?
0 / 5 - 0 ratings