Pixels / winit incompatible?

It seems the 'winit' crate has had some major changes and the 'pixels' crate seems incompatible with window handle traits.
Anyone any tips?
winit works ok! (version 0.30 I use)

let surface_texture = SurfaceTexture::new(width, height, window);

the trait bound Window: pixels::raw_window_handle::HasRawWindowHandle is not satisfied

pixels 0.13 uses raw-window-handle 0.5 while winit 0.30 defaults to raw-window-handle 0.6. You can enable winit compatibility with raw-window-handle 0.5 by enabling its rwh_05 feature.

wow... i encountered this somewhere. thanks! how do you know so fast?
Don't you think it is better to write my own 'pixels' code "inspired" by pixels?
The whole thing seems a cardhouse which can fall quite easily.

I already knew about the existence of the pseudo-standard raw-window-handle crate, and based on intuition I guessed that pixels and winit were using different versions of it. I then quickly checked the actual versions (I usually go on docs.rs for this) and saw that pixels depended on raw-window-handle 0.5:

while winit optionally depended on raw-window-handle 0.4, 0.5 and 0.6:

When a dependency is optional it usually means it is conditionally enabled based on some features. And in fact under the "Feature flags" section there were 3 features for the 3 versions of raw-window-handle, with only the one for raw-window-handle 0.6 enabled by default.

The solution is then to simply enable the feature needed.

Once you familiarize yourself with docs.rs this kind of stuff becomes really quick to check.

I have never used the pixels crate, but AFAIK the concept of setting individual pixels is far from how GPUs work nowadays, so anything using this approach will likely be suboptimal. This may not matter for your usecase though. What are you trying to do?

3 Likes

I wrote a 2d game, with my homemade bitmap (a simple Vec) which draws all its stuff to there, including scaling (up). I need only a way to 'blit' that bitmap to the window.
Using wgpu is quite complicated. I don't understand that stuff.

We have an open PR that increases rwh to 0.6: Bump `wgpu` to 0.19 and `winit` to 0.29 by mkrasnitski · Pull Request #391 · parasyte/pixels · GitHub (It is blocked on dependencies for the imgui example, but the branch should be usable with winit 0.30 and rwh 0.6 -- I have not personally tried it, however.)

maybe try out minifb or softbuffer?

minifb has its own windows and event loops, while softbuffer uses winit.

I got 'pixels' at least initializing ok.
But it takes a full second to intialize a pixel surface. And the executable went from 600 KB to 6 MB.

It sounds like you are building in debug mode. Release builds will be better.

No release mode is 6 MB. I was wondering why that is.
But because of the slowness I already discarded this one. My game should start immediately, that is a requirement.

softbuffer I cannot get to work yet.

I can probably help diagnose (I wrote the pixels crate) but I will need a lot more information from you. Specifically, the hardware and OS environment you are running on, whether GPU drivers are up to date, ensuring you aren't using a software rasterizer, determining which wgpu backend is being selected, and perhaps most importantly some details about your game compared to the pixels examples.

The binary size doesn't really matter, but it's all wgpu and its dependencies:

$ cargo bloat --release --crates --package minimal-winit
    Finished `release` profile [optimized] target(s) in 0.04s
    Analyzing target/release/minimal-winit

 File  .text      Size Crate
15.7%  29.8% 1008.1KiB wgpu
 8.7%  16.5%  557.7KiB naga
 8.3%  15.6%  528.4KiB std
 4.4%   8.3%  282.4KiB regex_automata
 3.3%   6.3%  212.0KiB wgpu_hal
 3.2%   6.1%  205.3KiB wgpu_core
 2.6%   4.9%  165.1KiB regex_syntax
 1.7%   3.3%  110.2KiB aho_corasick
 1.6%   3.1%  104.7KiB winit
 0.5%   1.0%   34.8KiB glow
 0.4%   0.8%   27.8KiB env_logger
 0.4%   0.7%   24.6KiB wgpu_types
 0.3%   0.6%   21.3KiB codespan_reporting
 0.3%   0.6%   20.8KiB metal
 0.2%   0.5%   15.6KiB hashbrown
 0.2%   0.3%   10.8KiB parking_lot
 0.1%   0.3%    9.1KiB objc2
 0.1%   0.2%    7.7KiB pixels
 0.1%   0.2%    7.4KiB memchr
 0.1%   0.2%    5.1KiB pollster
 0.5%   1.0%   32.3KiB And 22 more crates. Use -n N to show more.
52.9% 100.0%    3.3MiB .text section size, the file size is 6.3MiB

Note: numbers above are a result of guesswork. They are not 100% correct and never will be.

naga is wgpu's shader parsing.translation library, which transforms the WGLS shaders into Metal shaders (on macOS) or to SPIR-V for Vulkan (Linux, Windows). It is possible to cut down on many of these dependencies. For instance the regex crate is only used (in the minimal-winit example) by env_logger. You can either remove env_logger entirely or change its feature flags to shave off 1 MiB:

[dependencies]
env_logger = { version = "0.10", default-features = false }

You can also use most of the min-sized-rust tricks to get the binary down below 3 MiB:

$ RUSTFLAGS="-Z location-detail=none -C panic=abort" cargo bloat --crates --release --package minimal-winit -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort --target aarch64-apple-darwin
    Finished `release` profile [optimized] target(s) in 0.06s
    Analyzing target/aarch64-apple-darwin/release/minimal-winit

 File  .text     Size Crate
20.2%  26.2% 526.9KiB wgpu_core
16.8%  21.8% 439.6KiB naga
11.2%  14.5% 292.7KiB wgpu
10.4%  13.5% 271.4KiB core
 5.8%   7.5% 151.0KiB wgpu_hal
 2.7%   3.4%  69.4KiB winit
 2.1%   2.8%  55.7KiB hashbrown
 1.3%   1.7%  35.1KiB alloc
 1.2%   1.6%  32.6KiB std
 1.2%   1.6%  32.1KiB minimal_winit
 0.8%   1.1%  21.5KiB compiler_builtins
 0.8%   1.0%  20.4KiB codespan_reporting
 0.7%   1.0%  19.1KiB glow
 0.5%   0.7%  14.3KiB wgpu_types
 0.3%   0.4%   7.1KiB parking_lot
 0.2%   0.3%   6.0KiB env_logger
 0.2%   0.3%   5.9KiB libloading
 0.2%   0.2%   4.8KiB smallvec
 0.2%   0.2%   4.6KiB [Unknown]
 0.2%   0.2%   4.0KiB arrayvec
 0.8%   1.1%  21.7KiB And 19 more crates. Use -n N to show more.
77.0% 100.0%   2.0MiB .text section size, the file size is 2.6MiB

Note: numbers above are a result of guesswork. They are not 100% correct and never will be.

Aha. I am honored to see the pixels writer himself.
I did not check what happened internally, before discarding pixels. When pixels can work with winit 0.30 by default I will surely retry and check.
What I noticed is that I even was not drawing anything yet, just initialization context and surface, and that took (in release mode) almost a second for 640x400.
I am not aware of any software rasterization. The computer is a windows PC, a new and fast one. I am sure Vulkan is on it.

The game is originally a 320x200 game: The old DOS Lemmings game from around 1992, which I cloned and enhanced.

Those stats are too vague to be useful. What kind of GPU is in it? Is there an integrated GPU at all, or only a discrete GPU? Is the GPU driver up to date? How much of the heavy initialization is your game instead of pixels? Have you done any profiling? Be as specific as possible.


For reference, I'm running a MacBook Pro (late 2023 M3 Max with 40 GPU cores), and the release binary (minimal-winit) starts in under 150 ms. I can't get better timing info than that with a naive test (the actual value is likely closer to dozens of milliseconds, just a few frames). But "almost a second" indicates something highly unusual.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.