Reputation: 4720
I'm new to Vulkan and graphics programming. I'm using vulkano
Rust library https://github.com/vulkano-rs/vulkano (v0.17).
I want to use a compute pipeline to calculate something on a large set of circles. Circles are described as an input tuple (x, y). 2048 of them at the moment. I will make a calculation on them and output 2048 booleans depending on the outcome.
I use one buffer for inputted circles, and the other buffer for the outputted booleans.
At first I just want to make the output to be all true
s.
let data_in_iter = (0..2048).map(|i| (i, i));
let data_in_buffer =
CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), false, data_in_iter)
.expect("failed to create buffer");
let data_out_iter = (0..2048).map(|_| false);
let data_out_buffer =
CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), false, data_out_iter)
.expect("failed to create buffer");
let compute_pipeline = Arc::new({
mod cs {
vulkano_shaders::shader! {
ty: "compute",
src:
"
#version 450
layout(local_size_x = 1024, local_size_y = 1, local_size_z = 1) in;
layout(set = 0, binding = 0) buffer DataIn {
uvec2 data[];
} buf_in;
layout(set = 0, binding = 1) buffer DataOut {
bool data[];
} buf_out;
void main() {
uint idx = gl_GlobalInvocationID.x;
buf_out.data[idx] = true /* buf_in.data[idx].x + buf_in.data[idx].y < 2048 */;
}
"
}
}
let shader = cs::Shader::load(device.clone()).expect("failed to create shader module");
ComputePipeline::new(device.clone(), &shader.main_entry_point(), &())
.expect("failed to create compute pipeline")
});
let layout = compute_pipeline.layout().descriptor_set_layout(0).unwrap();
let set = Arc::new(
PersistentDescriptorSet::start(layout.clone())
.add_buffer(data_in_buffer.clone())
.unwrap()
.add_buffer(data_out_buffer.clone())
.unwrap()
.build()
.unwrap(),
);
let command_buffer =
AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family())
.unwrap()
.dispatch([2, 1, 1], compute_pipeline.clone(), set.clone(), ())
.unwrap()
.build()
.unwrap();
let future = sync::now(device.clone())
.then_execute(queue.clone(), command_buffer)
.unwrap()
.then_signal_fence_and_flush()
.unwrap();
future.wait(None).unwrap();
let content = data_out_buffer.read().unwrap();
for (n, val) in content.iter().enumerate() {
println!("{} {:?}", n, val);
}
But the output I get is:
0 true
1 false
2 false
3 false
4 true
5 false
6 false
7 false
8 true
9 false
...
2047 false
Upvotes: 0
Views: 547
Reputation: 6787
The default layout for storage buffers requires that each element of an array start at a 16-byte boundary. So what you're seeing is expected: buf_out.data[i] is written starting at byte 16*i in the output buffer.
You can either match that in your host code, or add the std430
modifier inside the layout()
for DataOut
. Note the same issue will affect DataIn
.
Upvotes: 1