vulkano-rs / vulkano

Safe and rich Rust wrapper around the Vulkan API
Apache License 2.0
4.54k stars 438 forks source link

Segmentation fault! When creating Swapchains #2604

Closed Pixel300 closed 1 week ago

Pixel300 commented 1 week ago

System:

Instance Extentions :

let wm_info = get_wminfo(window.raw())?;
let mut extensions = InstanceExtensions {
    khr_surface: true,
    ..InstanceExtensions::none()
};

let wayland_or_x11: &str = &env::var("XDG_SESSION_TYPE").unwrap();

match wayland_or_x11 {
    "wayland" => extensions.khr_wayland_surface = true,
    "x11" => extensions.khr_xlib_surface = true,
    _ => return Err(ErrorType::PlatformNotSupported),
}

Creating A Swapchain :

let (mut swapchain, images) = {
    let surface_capabilities = device
        .physical_device()
        .surface_capabilities(&surface.clone().unwrap(), Default::default())
        .unwrap();

    let image_format = device
        .physical_device()
        .surface_formats(&surface.clone().unwrap(), Default::default())
        .unwrap()[0]
        .0;

    Swapchain::new(
        device.clone(),
        surface.clone().unwrap(),
        SwapchainCreateInfo {
            min_image_count: surface_capabilities.min_image_count.max(2),
            image_format,
            image_extent: window.size().into(),
            image_usage: ImageUsage::COLOR_ATTACHMENT,
            composite_alpha: surface_capabilities
                .supported_composite_alpha
                .into_iter()
                .next()
                .unwrap(),
                pre_transform: SurfaceTransform::Identity,
            ..Default::default()
        },
    )
    .unwrap()
};

My issue is i'm trying to set up and remake the swapchain. I have no idea what i'm doing wrong. I have never really dealt with a segmentation fault error on wayland before and I followed the tutorials. On x11 the swapchain get's created successfully but recreating it does not work. It just crashes.

Tutorial I'm Following -->: https://github.com/dariost/vulkano-sdl2/blob/master/examples/triangle.rs

If anyone is willing to help that would be very nice. Thank you for your time.

marc0246 commented 1 week ago

How are you creating the surface?

Pixel300 commented 1 week ago

Heres how im creating my surface:

//Main File

let mut window = video_subsystem
    .window("Test Window", 812, 420)
    .vulkan()
    .position_centered()
    .resizable()
    .build()
    .unwrap();

//Instance code above

let surface = unsafe { sdl2_to_surface(instance.clone(), &window) };
// Surface File
pub unsafe fn sdl2_to_surface(instance: Arc<Instance>, window: &Window) -> Result<Arc<Surface>, ErrorType> {
    let wayland_or_x11: &str = &env::var("XDG_SESSION_TYPE").unwrap();

    if wayland_or_x11 == "x11" {
        let display = wm_info.info.x11.display;
        let window = wm_info.info.x11.window;

        return Ok(Surface::from_xlib(instance, display, window, None).unwrap());
    } else if wayland_or_x11 == "wayland" {
        let display = wm_info.info.wl.display;
        let surface = wm_info.info.wl.surface;

        return Ok(Surface::from_wayland(instance, display, surface, None).unwrap());
    }
    return Err(ErrorType::UnknownUnix);
}

EDIT: Maybe this will help? (Surface Capabilities)

SurfaceCapabilities { min_image_count: 2, max_image_count: Some(8), current_extent: None, min_image_extent: [1, 1], max_image_extent: [16384, 16384], max_image_array_layers: 1, supported_transforms: IDENTITY, current_transform: Identity, supported_composite_alpha: INHERIT, supported_usage_flags: TRANSFER_SRC | TRANSFER_DST | SAMPLED | STORAGE | COLOR_ATTACHMENT | INPUT_ATTACHMENT, compatible_present_modes: [], supported_present_scaling: empty(), supported_present_gravity: [empty(), empty()], min_scaled_image_extent: Some([1, 1]), max_scaled_image_extent: Some([16384, 16384]), supports_protected: false, full_screen_exclusive_supported: false }
marc0246 commented 1 week ago

I don't think that's sound. SDL doesn't determine whether it uses X11 or Wayland based on a single enviroment variable. SDL_SysWMinfo has a field called subsystem which tells you which video driver is in use. If you don't follow this, you could be reading garbage when accessing the x11 or wl union fields. They are not struct fields (which is why they are unsafe to access).

Much more importantly however, I wouldn't be using an example that has been outdated for 7 years. The example for using the sdl2 crate together with vulkano can be found right in their readme. In today's day and age we have the raw-window-handle crate which serves as the bridging point between any windowing library and any graphics library. Note that this requires sdl2 0.36 and vulkano 0.34 or the version of raw-window-handle that they both use won't match up. Doing this manually like you're trying requires a lot of tricky-to-get-right unsafe code. So while my suggestion likely won't fix your issue immediately, it will reduce the unsafe code to a single line (Surface::from_window_ref), which eliminates a lot of factors.

Pixel300 commented 1 week ago

Thank you! That fixed it for me! However i'm getting another error that I can't wrap my head around.

X Error of failed request: BadWindow (invalid Window parameter) Major opcode of failed request: 3 (X_GetWindowAttributes) Resource id in failed request: 0x2200002 Serial number of failed request: 309 Current serial number in output stream: 310

Swapchain creation works now. So I wonder whats happening with this error?

marc0246 commented 1 week ago

And you have removed your use of unsafe code and replaced it with Surface::from_window_ref?

Pixel300 commented 1 week ago

I tried that it does not work. Surface::from_window_ref is still unsafe code and I get the same error. Thank you for the suggestion.

I even tried Surface::from_window as well.

let surface = unsafe { Surface::from_window_ref(instance.clone(), &window) };

marc0246 commented 1 week ago

Yes that function is unsafe, but the point is that this function has a single unsafe precondition, unlike the heaps of unsafe that you would have otherwise. So assuming you're following this one single precondition, and there's no other unsafe code in your application, it means your code is not at fault. At least, that's the promise of safe Rust and the purpose of isolating unsafe code.

Pixel300 commented 1 week ago

So is it SDL2's fault?

I did some more testing if I remove the code that recreates the swapchain I don't get any error. If I keep the code in my program it works just fine for 2 loops and on the 3rd loop it crashes.

marc0246 commented 1 week ago

I couldn't tell you. I've never seen that error and don't even know if it's coming from SDL2 itself, X11, or the video driver.

Pixel300 commented 1 week ago

Alright, I will try and debug it further. Hopefully I can get my code to work. Thank you for your time and help.

Pixel300 commented 1 week ago

I have one last question, have you seen this before?

thread 'main' panicked at src/Output/Window/mod.rs:446:24:
called `Result::unwrap()` on an `Err` value: a validation error occurred

Caused by:
    `PhysicalDevice::surface_capabilities` returned an error
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

(I switched to integrated intel GPU)

marc0246 commented 1 week ago

What I can tell you is that the following code works for me on X11 and NVIDIA:

```rs use sdl2::event::{Event, WindowEvent}; use vulkano::{ device::{Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo}, image::ImageUsage, instance::{Instance, InstanceCreateInfo, InstanceExtensions}, swapchain::{Surface, Swapchain, SwapchainCreateInfo}, VulkanLibrary, }; fn main() { let sdl_context = sdl2::init().unwrap(); let video_subsystem = sdl_context.video().unwrap(); let window = video_subsystem .window("Window Title - My Vulkano-SDL2 application", 1024, 768) .resizable() .vulkan() .build() .unwrap(); let instance_extensions = InstanceExtensions::from_iter(window.vulkan_instance_extensions().unwrap()); let instance = Instance::new( VulkanLibrary::new().unwrap(), InstanceCreateInfo { enabled_extensions: instance_extensions, ..Default::default() }, ) .unwrap(); let device_extensions = DeviceExtensions { khr_swapchain: true, ..Default::default() }; let physical_device = instance .enumerate_physical_devices() .unwrap() .next() .unwrap(); let (device, mut queues) = Device::new( physical_device, DeviceCreateInfo { queue_create_infos: vec![QueueCreateInfo { queue_family_index: 0, ..Default::default() }], enabled_extensions: device_extensions, ..Default::default() }, ) .unwrap(); let _queue = queues.next().unwrap(); let surface = unsafe { Surface::from_window_ref(instance.clone(), &window) }.unwrap(); let window_size = window.size(); let (mut swapchain, _images) = { let surface_capabilities = device .physical_device() .surface_capabilities(&surface, Default::default()) .unwrap(); let (image_format, _) = device .physical_device() .surface_formats(&surface, Default::default()) .unwrap()[0]; let composite_alpha = surface_capabilities .supported_composite_alpha .into_iter() .next() .unwrap(); Swapchain::new( device.clone(), surface, SwapchainCreateInfo { min_image_count: surface_capabilities.min_image_count.max(2), image_format, image_extent: window_size.into(), image_usage: ImageUsage::COLOR_ATTACHMENT, composite_alpha, ..Default::default() }, ) .unwrap() }; let mut event_pump = sdl_context.event_pump().unwrap(); 'running: loop { for event in event_pump.poll_iter() { match event { Event::Quit { .. } => { break 'running; } Event::Window { win_event, .. } => match win_event { WindowEvent::Resized(..) => { let (new_swapchain, _new_images) = swapchain .recreate(SwapchainCreateInfo { image_extent: window.size().into(), ..swapchain.create_info() }) .unwrap(); swapchain = new_swapchain; } _ => {} }, _ => {} } } } } ```

If this exact code does not work for you, then I would first look toward your system configuration or environment in which you're running the app. From what I've gathered you seem to be forcing the app to run under Xwayland for this testing, and I suspect the way you're doing that might have something to do with it.

Pixel300 commented 1 week ago

Seriously thank you. Your code works.

I found the real reason my code does not work is i'm using canvas in SDL2. If I remove that my code works!

Thank you! You solved my issue!

marc0246 commented 1 week ago

Great to hear.