Как использовать вычислительный шейдер Vulkano для вычисления образа подкачки? - PullRequest
0 голосов
/ 22 января 2019

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

Я получаю следующее сообщение об ошибке:

поток 'main' запаниковал в 'вызванном Result::unwrap() значении Err: AccessError {error: ImageNotInitialized {требуемый: PresentSrc}, имя_команды: "vkCmdBindDescriptorSets", command_param: "Изображение привязано к дескриптору 0 из набора 0" , command_offset: 1} ', libcore \ result.rs: 1009: 5 примечание: запустить с RUST_BACKTRACE=1 для возврата. ошибка: процесс не завершился успешно: target\debug\vulkan_test.exe (код выхода: 101)

main.rs

extern crate vulkano;
extern crate vulkano_shaders;
extern crate vulkano_win;
extern crate winit;

use std::sync::Arc;
use vulkano::command_buffer::AutoCommandBufferBuilder;
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
use vulkano::device::{Device, DeviceExtensions};
use vulkano::instance::{Instance, PhysicalDevice};
use vulkano::pipeline::ComputePipeline;
use vulkano::swapchain;
use vulkano::swapchain::{
    AcquireError, PresentMode, SurfaceTransform, Swapchain, SwapchainCreationError,
};
use vulkano::sync;
use vulkano::sync::{FlushError, GpuFuture};
use vulkano_win::VkSurfaceBuild;
use winit::{EventsLoop, WindowBuilder};

mod cs {
    vulkano_shaders::shader! {
    ty: "compute",
    // path: "shaders/compute.glsl"
        src: "
#version 450

layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;

layout(set = 0, binding = 0, rgba8) uniform writeonly image2D img;

void main() {
    imageStore(img, ivec2(gl_GlobalInvocationID.xy), vec4(1,0,1,1));
}        
        "
    }
}

fn main() {
    let instance = {
        let extensions = vulkano_win::required_extensions();
        Instance::new(None, &extensions, None).expect("failed to create instance")
    };

    let physical = PhysicalDevice::enumerate(&instance)
        .next()
        .expect("no device available");

    println!("Name:    {}  (type: {:?})", physical.name(), physical.ty());
    println!("Version: {}", physical.api_version());

    let mut events_loop = EventsLoop::new();

    let surface = WindowBuilder::new()
        .with_title("Ray")
        .with_dimensions((1600.0, 900.0).into())
        .build_vk_surface(&events_loop, instance.clone())
        .expect("failed to create window");
    let window = surface.window();

    let queue_family = physical
        .queue_families()
        .find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
        .expect("failed to create queue family");

    let (device, mut queues) = {
        let device_ext = DeviceExtensions {
            khr_swapchain: true,
            ..DeviceExtensions::none()
        };
        Device::new(
            physical,
            physical.supported_features(),
            &device_ext,
            [(queue_family, 0.5)].iter().cloned(),
        )
        .expect("failed to create device")
    };
    let queue = queues.next().expect("failed to create queue");

    let shader = cs::Shader::load(device.clone()).expect("failed to create shader module");

    let compute_pipeline = Arc::new(
        ComputePipeline::new(device.clone(), &shader.main_entry_point(), &())
            .expect("failed to create compute pipeline"),
    );

    let (mut swapchain, mut images) = {
        let caps = surface.capabilities(physical).unwrap();

        let usage = caps.supported_usage_flags;
        let alpha = caps.supported_composite_alpha.iter().next().unwrap();
        let format = caps.supported_formats[0].0;

        let initial_dimensions = if let Some(dimensions) = window.get_inner_size() {
            let dimensions: (u32, u32) = dimensions.to_physical(window.get_hidpi_factor()).into();
            [dimensions.0, dimensions.1]
        } else {
            return;
        };
        Swapchain::new(
            device.clone(),
            surface.clone(),
            caps.min_image_count,
            format,
            initial_dimensions,
            1,
            usage,
            &queue,
            SurfaceTransform::Identity,
            alpha,
            PresentMode::Fifo,
            true,
            None,
        )
        .expect("failed to create swapchain")
    };

    let mut recreate_swapchain = false;
    let mut previous_frame_end = Box::new(sync::now(device.clone())) as Box<GpuFuture>;

    loop {
        previous_frame_end.cleanup_finished();

        if recreate_swapchain {
            let dimensions = if let Some(dimensions) = window.get_inner_size() {
                let dimensions: (u32, u32) =
                    dimensions.to_physical(window.get_hidpi_factor()).into();
                [dimensions.0, dimensions.1]
            } else {
                return;
            };

            let (new_swapchain, new_images) = match swapchain.recreate_with_dimension(dimensions) {
                Ok(r) => r,
                Err(SwapchainCreationError::UnsupportedDimensions) => continue,
                Err(err) => panic!("{:?}", err),
            };

            swapchain = new_swapchain;
            images = new_images;
            recreate_swapchain = false;
        }

        let (image_index, acquire_future) =
            match swapchain::acquire_next_image(swapchain.clone(), None) {
                Ok(r) => r,
                Err(AcquireError::OutOfDate) => {
                    recreate_swapchain = true;
                    continue;
                }
                Err(err) => panic!("{:?}", err),
            };

        let command_buffer = {
            let set = Arc::new(
                PersistentDescriptorSet::start(compute_pipeline.clone(), 0)
                    .add_image(images[image_index].clone())
                    .unwrap()
                    .build()
                    .unwrap(),
            );

            AutoCommandBufferBuilder::new(device.clone(), queue.family())
                .unwrap()
                .dispatch([200, 100, 1], compute_pipeline.clone(), set.clone(), ())
                .unwrap()
                .build()
                .unwrap()
        };

        let future = previous_frame_end
            .join(acquire_future)
            .then_execute(queue.clone(), command_buffer)
            .unwrap()
            .then_swapchain_present(queue.clone(), swapchain.clone(), image_index)
            .then_signal_fence_and_flush();

        match future {
            Ok(future) => {
                previous_frame_end = Box::new(future) as Box<_>;
            }
            Err(FlushError::OutOfDate) => {
                recreate_swapchain = true;
                previous_frame_end = Box::new(sync::now(device.clone())) as Box<_>;
            }
            Err(e) => {
                println!("{:?}", e);
                previous_frame_end = Box::new(sync::now(device.clone())) as Box<_>;
            }
        }

        let mut done = false;
        events_loop.poll_events(|ev| match ev {
            winit::Event::WindowEvent { event, .. } => match event {
                winit::WindowEvent::CloseRequested => done = true,
                winit::WindowEvent::KeyboardInput {
                    input:
                        winit::KeyboardInput {
                            virtual_keycode: Some(virtual_code),
                            state: winit::ElementState::Released,
                            ..
                        },
                    ..
                } => match virtual_code {
                    winit::VirtualKeyCode::Escape => done = true,
                    _ => (),
                },
                winit::WindowEvent::Resized(_) => recreate_swapchain = true,
                _ => (),
            },
            _ => (),
        });
        if done {
            return;
        }
    }
}

Полная ошибка возврата

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: AccessError { error: ImageNotInitialized { requested: PresentSrc }, command_name: "vkCmdBindDescriptorSets", command_param: "Image bound to descriptor 0 of set 0", command_offset: 1 }', libcore\result.rs:1009:5
stack backtrace:
   0: std::sys::windows::backtrace::set_frames
             at /rustc/b6c32da9b0481e3e9d737153286b3ff8aa39a22c\src/libstd\sys\windows\backtrace\mod.rs:104
   1: std::sys::windows::backtrace::set_frames
             at /rustc/b6c32da9b0481e3e9d737153286b3ff8aa39a22c\src/libstd\sys\windows\backtrace\mod.rs:104
   2: std::sys_common::backtrace::_print
             at /rustc/b6c32da9b0481e3e9d737153286b3ff8aa39a22c\src/libstd\sys_common\backtrace.rs:71
   3: std::sys_common::backtrace::_print
             at /rustc/b6c32da9b0481e3e9d737153286b3ff8aa39a22c\src/libstd\sys_common\backtrace.rs:71
   4: std::panicking::default_hook::{{closure}}
             at /rustc/b6c32da9b0481e3e9d737153286b3ff8aa39a22c\src/libstd\panicking.rs:211
   5: std::panicking::default_hook
             at /rustc/b6c32da9b0481e3e9d737153286b3ff8aa39a22c\src/libstd\panicking.rs:227
   6: std::panicking::rust_panic_with_hook
             at /rustc/b6c32da9b0481e3e9d737153286b3ff8aa39a22c\src/libstd\panicking.rs:476
   7: std::panicking::continue_panic_fmt
             at /rustc/b6c32da9b0481e3e9d737153286b3ff8aa39a22c\src/libstd\panicking.rs:390
   8: std::panicking::rust_begin_panic
             at /rustc/b6c32da9b0481e3e9d737153286b3ff8aa39a22c\src/libstd\panicking.rs:325
   9: core::panicking::panic_fmt
             at /rustc/b6c32da9b0481e3e9d737153286b3ff8aa39a22c\src/libcore\panicking.rs:77
  10: core::result::unwrap_failed<vulkano::command_buffer::traits::CommandBufferExecError>
             at \libcore\macros.rs:26
  11: core::result::Result<vulkano::command_buffer::traits::CommandBufferExecFuture<vulkano::sync::future::join::JoinFuture<alloc::boxed::Box<GpuFuture>, vulkano::swapchain::swapchain::SwapchainAcquireFuture<winit::Window>>, vulkano::command_buffer::auto::AutoCommandBuffer<vulkano::command_buffer::pool::standard::StandardCommandPoolAlloc>>, vulkano::command_buffer::traits::CommandBufferExecError>::unwrap<vulkano::command_buffer::traits::CommandBufferExecFuture<vulkano::sync::future::join::JoinFuture<alloc::boxed::Box<GpuFuture>, vulkano::swapchain::swapchain::SwapchainAcquireFuture<winit::Window>>, vulkano::command_buffer::auto::AutoCommandBuffer<vulkano::command_buffer::pool::standard::StandardCommandPoolAlloc>>,vulkano::command_buffer::traits::CommandBufferExecError>
             at \libcore\result.rs:808
  12: vulkan_test::main
             at .\src\main.rs:178
  13: std::rt::lang_start::{{closure}}<()>
             at \libstd\rt.rs:74
  14: std::rt::lang_start_internal::{{closure}}
             at /rustc/b6c32da9b0481e3e9d737153286b3ff8aa39a22c\src/libstd\rt.rs:59
  15: std::rt::lang_start_internal::{{closure}}
             at /rustc/b6c32da9b0481e3e9d737153286b3ff8aa39a22c\src/libstd\rt.rs:59
  16: panic_unwind::__rust_maybe_catch_panic
             at /rustc/b6c32da9b0481e3e9d737153286b3ff8aa39a22c\src/libpanic_unwind\lib.rs:102
  17: std::panicking::try
             at /rustc/b6c32da9b0481e3e9d737153286b3ff8aa39a22c\src/libstd\panicking.rs:289
  18: std::panicking::try
             at /rustc/b6c32da9b0481e3e9d737153286b3ff8aa39a22c\src/libstd\panicking.rs:289
  19: std::panicking::try
             at /rustc/b6c32da9b0481e3e9d737153286b3ff8aa39a22c\src/libstd\panicking.rs:289
  20: std::rt::lang_start<()>
             at \libstd\rt.rs:74
  21: main
  22: invoke_main
             at d:\agent\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
  23: invoke_main
             at d:\agent\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
  24: BaseThreadInitThunk
  25: RtlUserThreadStart

1 Ответ

0 голосов
/ 22 января 2019

Согласно документу Vulkano:

ImageNotInitialized
Попытка использовать изображение, не переводя его сначала из «неопределенных» или «предварительно инициализированных» макетов.

Предположительно, изображение находится в макете Undefined, но для трассировки требуется PresentSrc.

...