sotrh / learn-wgpu

Guide for using gfx-rs's wgpu library.
https://sotrh.github.io/learn-wgpu/
MIT License
1.49k stars 260 forks source link

Textures example in Instancing tutorial fails with segmentation fault #52

Closed yutannihilation closed 4 years ago

yutannihilation commented 4 years ago

Hi, I got segmentation fault with an example using textures in Instancing tutorial. Does this only happen on me? I'm using Wayland and GNOME3 on Manjaro Linux.

Note that my window manager behaves a bit strangely in that it resizes windows after it is created. I suspect the resize is the cause, so I want to know whether this is reproducible on other environments or a very rare issue.

What I did was adding this section to code/beginner/tutorial7-instancing/Cargo.toml

[[example]]
name = "tutorial7-texture"
path = "examples/texture_instances.rs"

and running the command below:

$ cargo run --example tutorial7-texture
warning: unused variable: `instance_buffer_size`
   --> code/beginner/tutorial7-instancing/examples/texture_instances.rs:393:13
    |
393 |         let instance_buffer_size = instance_data.len() * std::mem::size_of::<cgmath::Matrix4<f32>>();
    |             ^^^^^^^^^^^^^^^^^^^^ help: consider prefixing with an underscore: `_instance_buffer_size`
    |
    = note: `#[warn(unused_variables)]` on by default

warning: field is never read: `instances`
   --> code/beginner/tutorial7-instancing/examples/texture_instances.rs:278:5
    |
278 |     instances: Vec<Instance>,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(dead_code)]` on by default

    Finished dev [unoptimized + debuginfo] target(s) in 0.09s
     Running `target/debug/examples/tutorial7-texture`
Segmentation fault (core dumped)
sotrh commented 4 years ago

I tried it on the current commit. Seems to be working fine, though a bit slow. A seg fault suggests the crash is coming from native code. Do you know what line specifically is causing this? It may be helpful to run with RUST_BACKTRACE=1.

yutannihilation commented 4 years ago

Thanks, for taking a look. As you suggests, segfault happens outside of Rust, so RUST_BACKTRACE=1 doesn't reveal any new information...

$ RUST_BACKTRACE=1 cargo run --example tutorial7-texture
warning: unused variable: `instance_buffer_size`
   --> code/beginner/tutorial7-instancing/examples/texture_instances.rs:393:13
    |
393 |         let instance_buffer_size = instance_data.len() * std::mem::size_of::<cgmath::Matrix4<f32>>();
    |             ^^^^^^^^^^^^^^^^^^^^ help: consider prefixing with an underscore: `_instance_buffer_size`
    |
    = note: `#[warn(unused_variables)]` on by default

warning: field is never read: `instances`
   --> code/beginner/tutorial7-instancing/examples/texture_instances.rs:278:5
    |
278 |     instances: Vec<Instance>,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(dead_code)]` on by default

    Finished dev [unoptimized + debuginfo] target(s) in 0.18s
     Running `target/debug/examples/tutorial7-texture`
Segmentation fault (core dumped)

My system log says

[  317.405401] tutorial7-textu[2594]: segfault at 7f493c2d1da8 ip 00007efdf9d0b8ff sp 00007fffeccbc920 error 4 in libvulkan_intel.so[7efdf9b3d000+420000]

so it might be that something is wrong on libvulkan's side.

cwfitzgerald commented 4 years ago

Do you have the vulkan validation layers installed/enabled? They might give you hints as to the problem. Additionally, a backtrace (from gdb or similar) would help a lot. wgpu 0.5 is still lacking a good bit of validation that can cause issues with segmentation faults and such inside the vulkan driver.

Edit: make sure you aren't rendering to a swapchain image that came from an old swapchain. Once you remake the swapchain, the old images are invalid. Someone else ran into this issue, though not from this tutorial. (see https://github.com/gfx-rs/wgpu/pull/702)

yutannihilation commented 4 years ago

Do you have the vulkan validation layers installed/enabled?

Thanks, I installed and enabled as below, IIUC.

$ env VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation RUST_LOG=trace cargo run --example tutorial7-texture
...snip...
TRACE 2020-06-08T12:01:51Z: tokio_reactor: event Readable | Writable Token(0)
TRACE 2020-06-08T12:01:51Z: tokio_reactor: loop process - 1 events, 0.000s
DEBUG 2020-06-08T12:01:51Z: tokio_reactor::registration: scheduling Read for: 0
TRACE 2020-06-08T12:01:51Z: mio::poll: deregistering handle with poller
DEBUG 2020-06-08T12:01:51Z: tokio_reactor: dropping I/O source: 0
    Finished dev [unoptimized + debuginfo] target(s) in 0.10s
     Running `/home/yutani/repo/learn-wgpu/target/debug/examples/tutorial7-texture`
Segmentation fault (core dumped)

Here's the backtrace. Does this help?

(gdb) bt
#0  0x00007efc0ddca8ff in ?? () from /usr/lib/libvulkan_intel.so
#1  0x00007efc0dc0d929 in ?? () from /usr/lib/libvulkan_intel.so
#2  0x00007efc0dc0dafb in ?? () from /usr/lib/libvulkan_intel.so
#3  0x00007efc05681b5a in ?? () from /usr/lib/libVkLayer_khronos_validation.so
#4  0x000055a927e25749 in ash::vk::DeviceFnV1_0::cmd_copy_buffer_to_image (self=0x55a928fe1c98, command_buffer=..., src_buffer=..., dst_image=..., dst_image_layout=..., region_count=1, p_regions=0x7fff721cbfe0)
    at /home/yutani/.cargo/registry/src/github.com-1ecc6299db9ec823/ash-0.30.0/src/vk.rs:5900
#5  0x000055a927c8b456 in ash::device::DeviceV1_0::cmd_copy_buffer_to_image (self=0x55a928fe1c90, command_buffer=..., src_buffer=..., dst_image=..., dst_image_layout=..., regions=...)
    at /home/yutani/.cargo/registry/src/github.com-1ecc6299db9ec823/ash-0.30.0/src/device.rs:914
#6  0x000055a927b742b8 in <gfx_backend_vulkan::command::CommandBuffer as gfx_hal::command::CommandBuffer<gfx_backend_vulkan::Backend>>::copy_buffer_to_image (self=0x55a9291e1380, src=0x55a9291d5bb0, dst=0x55a9291e6c08,
    dst_layout=gfx_hal::image::Layout::TransferDstOptimal, regions=...) at /home/yutani/.cargo/registry/src/github.com-1ecc6299db9ec823/gfx-backend-vulkan-0.5.6/src/command.rs:752
#7  0x000055a927cf5881 in wgpu_core::command::transfer::<impl wgpu_core::hub::Global<G>>::command_encoder_copy_buffer_to_texture (self=0x55a928eb7020, command_encoder_id=..., source=0x7fff721ccc20, destination=0x7fff721ccc50, copy_size=...)
    at /home/yutani/.cargo/registry/src/github.com-1ecc6299db9ec823/wgpu-core-0.5.5/src/command/transfer.rs:193
#8  0x000055a927bb3bc0 in wgpu_command_encoder_copy_buffer_to_texture (command_encoder_id=..., source=0x7fff721ccc20, destination=0x7fff721ccc50, copy_size=...) at /home/yutani/.cargo/registry/src/github.com-1ecc6299db9ec823/wgpu-native-0.5.0/src/command.rs:44
#9  0x000055a927ad6610 in wgpu::CommandEncoder::copy_buffer_to_texture (self=0x7fff721cd4c0, source=..., destination=..., copy_size=...) at /home/yutani/.cargo/registry/src/github.com-1ecc6299db9ec823/wgpu-0.5.0/src/lib.rs:1303
#10 0x000055a9279bd711 in tutorial7_texture::State::new::{{closure}} () at code/beginner/tutorial7-instancing/examples/texture_instances.rs:463
#11 0x000055a9279b0f7e in <std::future::GenFuture<T> as core::future::future::Future>::poll (self=..., cx=0x7fff721ce328) at /rustc/4fb7144ed159f94491249e86d5bbd033b5d60550/src/libstd/future.rs:44
#12 0x000055a9279f4916 in futures_executor::local_pool::block_on::{{closure}} (cx=0x7fff721ce328) at /home/yutani/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-executor-0.3.5/src/local_pool.rs:317
#13 0x000055a9279f46ef in futures_executor::local_pool::run_executor::{{closure}} (thread_notify=0x7efc0e41ebf0) at /home/yutani/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-executor-0.3.5/src/local_pool.rs:87
#14 0x000055a9279a06c8 in std::thread::local::LocalKey<T>::try_with (self=0x55a928751040, f=...) at /rustc/4fb7144ed159f94491249e86d5bbd033b5d60550/src/libstd/thread/local.rs:262
#15 0x000055a9279a05b1 in std::thread::local::LocalKey<T>::with (self=0x55a928751040, f=...) at /rustc/4fb7144ed159f94491249e86d5bbd033b5d60550/src/libstd/thread/local.rs:239
#16 0x000055a9279f4616 in futures_executor::local_pool::run_executor (f=...) at /home/yutani/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-executor-0.3.5/src/local_pool.rs:83
#17 0x000055a9279f4881 in futures_executor::local_pool::block_on (f=...) at /home/yutani/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-executor-0.3.5/src/local_pool.rs:317
#18 0x000055a9279ca229 in tutorial7_texture::main () at code/beginner/tutorial7-instancing/examples/texture_instances.rs:709

make sure you aren't rendering to a swapchain image that came from an old swapchain

I just run the code as is in this tutorial, so I don't think the case this time. But, thanks for the advice. I'll remember your words when I face the similar problem with my own code :)

cwfitzgerald commented 4 years ago

Ah well, it was a shot in the dark there, hoped to get lucky :)

Did you publish the code that is crashing somewhere? This sounds worthy of an issue against wgpu.

yutannihilation commented 4 years ago

Did you publish the code that is crashing somewhere?

Sorry, I don't get your point... What do you mean by the word "publish"? (I'm very new to Rust)

This sounds worthy of an issue against wgpu.

Yeah, but before that I want to try the GitHub version of wgpu and am still struggling to change the code to pass the compiler.

cwfitzgerald commented 4 years ago

Sorry, I don't get your point... What do you mean by the word "publish"? (I'm very new to Rust)

In this case I was just referring to me being able to clone your exact code and run it on my machine to test it.

Yeah, but before that I want to try the GitHub version of wgpu and am still struggling to change the code to pass the compiler.

wgpu master moves very quickly, so if you don't want to do that, I'm perfectly fine updating code to master for testing.

yutannihilation commented 4 years ago

In this case I was just referring to me being able to clone your exact code and run it on my machine to test it.

Thanks, but, as I wrote above, I didn't write any code. I just run the code of this repo as it is.

yutannihilation commented 4 years ago

If you want me to quote myself, this is the steps I did:

What I did was adding this section to code/beginner/tutorial7-instancing/Cargo.toml

[[example]]
name = "tutorial7-texture"
path = "examples/texture_instances.rs"

and running the command below:

$ cargo run --example tutorial7-texture
sotrh commented 4 years ago

Have you pulled the repo since posting this? Can you resize on other tutorials?

yutannihilation commented 4 years ago

Thanks, I pulled and tried again, but the segmentation fault still occurs. I can resize other tutorials fine (e.g. tuotorial7-challenge, tutorial8-depth, tutorial9-models, tutorial10-lighting).

sotrh commented 4 years ago

Hmm.. might be a driver issue. I noticed that you were using Intel. Can you switch to a Nvidia/AMD driver? If so does the error persist?

yutannihilation commented 4 years ago

I use the Intel driver since my laptop uses Intel UHD Graphics. I don't think I can use a Nvidia/AMD driver for it. (Sorry, I have very little knowledge about the hardware. Let me know if I'm wrong here...)

sotrh commented 4 years ago

Have you updated the Intel driver?

yutannihilation commented 4 years ago

I use the latest vulkan mesa driver for intel available (20.1.1). Are there any other drivers that might matter? The Linux kernel version?

yutannihilation commented 4 years ago

Ah, sorry, a small correction. It seems a bit older one than upstream. But I think this is not too old (mesa 20.0.7 was released a month ago).

$ pacman -Si vulkan-intel | head -4
Repository      : extra
Name            : vulkan-intel
Version         : 20.0.7-3
Description     : Intel's Vulkan mesa driver
yutannihilation commented 4 years ago

Here's the error with the dev version of wgpu, but I'm afraid this is just something wrong with my code... The changes I needed to add is https://github.com/sotrh/learn-wgpu/commit/ee4364362198b9713d6f41eeeca67b67109403b7.

$ cargo run --example tutorial7-texture
warning: unused variable: `instance_buffer_size`
   --> code/beginner/tutorial7-instancing/examples/texture_instances.rs:431:13
    |
431 |         let instance_buffer_size =
    |             ^^^^^^^^^^^^^^^^^^^^ help: consider prefixing with an underscore: `_instance_buffer_size`
    |
    = note: `#[warn(unused_variables)]` on by default

warning: field is never read: `instances`
   --> code/beginner/tutorial7-instancing/examples/texture_instances.rs:295:5
    |
295 |     instances: Vec<Instance>,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(dead_code)]` on by default

    Finished dev [unoptimized + debuginfo] target(s) in 0.09s
     Running `target/debug/examples/tutorial7-texture`
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `16`,
 right: `0`: Source bytes per row (16) must be a multiple of 256', <::std::macros::panic macros>:5:6
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
VUID-vkDestroyInstance-instance-00629(ERROR / SPEC): msgNum: -1958900200 - Validation Error: [ VUID-vkDestroyInstance-instance-00629 ] Object 0: handle = 0x563d1ca98fc0, type = VK_OBJECT_TYPE_INSTANCE; Object 1: handle = 0x20000000002, type = VK_OBJECT_TYPE_SURFACE_KHR; | MessageID = 0x8b3d8e18 | OBJ ERROR : For VkInstance 0x563d1ca98fc0[], VkSurfaceKHR 0x20000000002[] has not been destroyed. The Vulkan spec states: All child objects created using instance must have been destroyed prior to destroying instance (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkDestroyInstance-instance-00629)
    Objects: 2
        [0] 0x563d1ca98fc0, type: 1, name: NULL
        [1] 0x20000000002, type: 1000000000, name: NULL
sotrh commented 4 years ago

Mind running that with RUST_BACKTRACE=1? It's a panic in Rust code, so we're getting somewhere.

cwfitzgerald commented 4 years ago

There is a requirement that all copy_buffer_to_texture calls must have bytes_per_row be a multiple of 256. This went unenforced in wgpu 0.5. However we also added queue.write_texture which does not need everything to be aligned just so, and will fix things automagically for you.

yutannihilation commented 4 years ago

Thanks! I tried it, and it runs fine without segfault this time! However I see some random glitch things so I think I'm doing something wrong....

image

Are there some example of how to rewrite copy_buffer_to_texture call into queue.write_texture? The changes I made is here:

https://github.com/yutannihilation/learn-wgpu/commit/3619c5da842b14f646948b83ec2e819af4219815

sotrh commented 4 years ago

I haven't messed around with much of the stuff in wgpu's master branch (I like to wait for there to be a release so I don't have to update things all the time). I'll have to revisit the instancing tutorial once there's a patch.

yutannihilation commented 4 years ago

Sure. Please feel free to close this as there seems nothing I can try any more and this is highly unlikely the fault of your tutorial. Thanks for all your supports (and of course for this wonderful tutorial itself!)

@cwfitzgerald Do you still think I should file an issue on wgpu's repo? If so, I will, though I'm not sure if I can describe the problem properly...

yutannihilation commented 4 years ago

Peeking at #75, it seems this chapter will get a major reform. Maybe I can just close this issue for now?

sotrh commented 4 years ago

Yeah it would probably be best to close it. I'm planning on removing the Texture instancing example entirely. It was a hack to begin with and standardizing it to work on multiple systems doesn't seem worth it to me.

I may revisit the topic in the future, but only when I can find an actually use case.

yutannihilation commented 4 years ago

Thanks. As a very newbie to shader things, it was really good to know there's multiple ways to achieve one thing and there's a lot to learn more. I really appreciate your effort on this :)