gfx-rs/wgpu-rs

Error with Textures Using OpenGL Backend on Ubuntu 20.04

Pattakak opened this issue · 3 comments

I didn't have Vulkan drivers installed correctly, so I set the environment variable WGPU_BACKEND=gl to try to render the scene in OpenGL. What happened was that the program crashed on the glTexImage2D command. Here is the stacktrace.

Using Mesa Intel(R) UHD Graphics 620 (KBL GT2) (Gl)
[0.097388 ERROR]()(no module): [API/Error] ID 1 : GL_INVALID_OPERATION in glTexImage2D(format = GL_BGRA, type = GL_UNSIGNED_BYTE, internalformat = GL_SRGB8_ALPHA8)
thread 'main' panicked at 'Error creating image: InvalidOperation for kind D2(800, 600, 1, 1) of Bgra8Srgb', /home/patrick/.cargo/git/checkouts/gfx-e86e7f3ebdbc4218/0a201d1/src/backend/gl/src/device.rs:1586:13
stack backtrace:
   0: rust_begin_unwind
             at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/panicking.rs:483
   1: std::panicking::begin_panic_fmt
             at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/panicking.rs:437
   2: <gfx_backend_gl::device::Device as gfx_hal::device::Device<gfx_backend_gl::Backend>>::create_image
             at /home/patrick/.cargo/git/checkouts/gfx-e86e7f3ebdbc4218/0a201d1/src/backend/gl/src/device.rs:1586
   3: wgpu_core::device::Device<B>::create_texture
             at /home/patrick/.cargo/git/checkouts/wgpu-53e70f8674b08dd4/8a5668e/wgpu-core/src/device/mod.rs:675
   4: wgpu_core::device::<impl wgpu_core::hub::Global<G>>::device_create_texture
             at /home/patrick/.cargo/git/checkouts/wgpu-53e70f8674b08dd4/8a5668e/wgpu-core/src/device/mod.rs:2982
   5: <wgpu::backend::direct::Context as wgpu::Context>::device_create_texture
             at ./src/backend/direct.rs:1122
   6: wgpu::Device::create_texture
             at ./src/lib.rs:1595
   7: water::Example::initialize_resources
             at ./examples/water/main.rs:193
   8: <water::Example as water::framework::Example>::init
             at ./examples/water/main.rs:461
   9: water::framework::start
             at ./examples/water/../framework.rs:213
  10: water::framework::run
             at ./examples/water/../framework.rs:339
  11: water::main
             at ./examples/water/main.rs:790
  12: core::ops::function::FnOnce::call_once
             at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/ops/function.rs:227
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
[0.181532 ERROR]()(gpu_alloc::block): Memory block wasn't deallocated
[0.181591 ERROR]()(gpu_alloc::block): Memory block wasn't deallocated
[0.181631 ERROR]()(gpu_alloc::block): Memory block wasn't deallocated
[0.181670 ERROR]()(gpu_alloc::block): Memory block wasn't deallocated
[0.181711 ERROR]()(gpu_alloc::block): Memory block wasn't deallocated
[0.181805 ERROR]()(gpu_alloc::block): Memory block wasn't deallocated
[0.181852 ERROR]()(gpu_alloc::block): Memory block wasn't deallocated
[0.181892 ERROR]()(gpu_alloc::block): Memory block wasn't deallocated
[0.181935 ERROR]()(gpu_alloc::block): Memory block wasn't deallocated
[0.181968 ERROR]()(gpu_alloc::block): Memory block wasn't deallocated

This specific error was generated with cargo run --example water, but similar issues come from different examples.

kvark commented

Yes, this is what we have today. GL backend needs more work, and it's clear how to see the improvement!

A problem here in Bgra8Srgb texture format, that used in some examples.

Rgba8Srgb => FormatDescription::new(
    glow::SRGB8_ALPHA8, // internalFormat
    glow::RGBA, // format
    glow::UNSIGNED_BYTE, // type
    4,
    Float,
),

@kvark Any ideas on how we should handle Bgra8Srgb? There is no such combination of internal and external formats in texture table.

kvark commented

The examples don't use this directly. Instead, they rely on the get_swap_chain_preferred_format, which essentially goes here:

// Check the four formats mentioned in the WebGPU spec:
            // Bgra8UnormSrgb, Rgba8UnormSrgb, Bgra8Unorm, Rgba8Unorm
            // Also, prefer sRGB over linear as it is better in
            // representing perceived colors.
            if formats.contains(&hal::format::Format::Bgra8Srgb) {
                return Ok(wgt::TextureFormat::Bgra8UnormSrgb);
            }
            if formats.contains(&hal::format::Format::Rgba8Srgb) {
                return Ok(wgt::TextureFormat::Rgba8UnormSrgb);
            }
            if formats.contains(&hal::format::Format::Bgra8Unorm) {
                return Ok(wgt::TextureFormat::Bgra8Unorm);
            }
            if formats.contains(&hal::format::Format::Rgba8Unorm) {
                return Ok(wgt::TextureFormat::Rgba8Unorm);
            }

The GL backend currently reports Bgra8srgb to be available:

fn supported_formats(
        &self,
        _physical_device: &PhysicalDevice,
    ) -> Option<Vec<hal::format::Format>> {
        use hal::format::Format;
        Some(vec![Format::Rgba8Srgb, Format::Bgra8Srgb])
    }

And it's not wrong here. If all you do is rendering into the swapchain, then Bgra8srgb is indistinguishable from Rgba8srgb.

A quick fix would be to just change supported_formats there to not return Bgra8Srgb.
Another thing that we should do is, like I said, let GL backend treat Bgra8srgb the same way as Rgba8srgb. It should also not advertise this format to be copyable, so that we don't have to deal with the swizzling.