Используйте входные и выходные буферы в конвейере вычислений Vulkan - PullRequest
0 голосов
/ 07 марта 2020

Я новичок в Vulkan и графическом программировании. Я использую vulkano Библиотека Rust https://github.com/vulkano-rs/vulkano (v0.17).

Я хочу использовать конвейер вычислений для вычисления чего-либо на большом наборе окружностей. Круги описываются как входной кортеж (x, y). 2048 из них на данный момент. Я сделаю для них вычисления и выведу 2048 логических значений в зависимости от результата.

Я использую один буфер для введенных окружностей, а другой буфер для выведенных логических величин.

Сначала я просто хочу чтобы все выходные данные были равны true с.

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);
    }

Но я получаю вывод:

0 true
1 false
2 false
3 false
4 true
5 false
6 false
7 false
8 true
9 false
...
2047 false

1 Ответ

0 голосов
/ 11 марта 2020

Макет по умолчанию для буферов хранения требует, чтобы каждый элемент массива начинался с 16-байтовой границы. Итак, то, что вы видите, ожидаемо: buf_out.data [i] записывается, начиная с байта 16 * i в буфере вывода.

Вы можете либо сопоставить это в коде вашего хоста, либо добавить std430 модификатор внутри layout() для DataOut. Обратите внимание, что та же проблема затронет DataIn.

...