The primary problem with high-level graphics crates in Rust (WGPU and its family in particular) is that they attempt to model ownership of driver-managed objects that they don't actually own. The driver owns them. The application only owns handles (numeric indices) to these objects.
This leads to a situation where these crates introduce a non-optional validation layer, causing performance penalties. Another issue is that the model proposed by a specific crate limits certain use cases compared to what the original raw graphics API offers (bindless is one such example).
What these crates are really trying to do is express the original API model in terms of Rust's memory model. This is not necessarily a bad idea, but it raises the question of whether the misuse of the Vulkan API is actually unsound from Rust's perspective.
The primary goal of Rust's memory model, as I see it, is to provide both the programmer and the compiler with a contract that allows the compiler to confidently perform MIR optimizations on CPU-based code. Passing two active mutable references to the same object to a function is unsafe (and unsound) because the compiler assumes that mutable borrows in Rust are always exclusive, allowing it to reorder stack memory accordingly.
Of course, Rust does not yet have a well-established definition of "undefined behavior", leaving room for broad interpretations. For example, WGPU and Vulkano consider simultaneous recording of command buffers (originating from the same pool) as undefined behavior. This may be true from Vulkan's perspective, but Rust's compiler gains nothing from enforcing exclusivity on command pools. Rust neither owns the command pool nor the command buffer. The driver owns and manages their memory independently of the application's source code, and the application code merely holds numeric indices (handles) to these objects.
Low-level crates such as Ash, therefore, do not introduce heavyweight abstractions. Instead, they provide access to raw graphics API bindings more or less as they are. These APIs are designed to be low-level, and as long as you follow the specification, they are ready to use. That's why I believe using them as they are is safe from Rust's point of view, regardless of what you do in Rust code. After all, C/C++ developers use them without additional abstractions, so why shouldn't we?
However, this still does not answer the question of how we should build high-level abstractions for community use. To address this, we must acknowledge that any higher-level abstraction on top of a low-level API comes at a cost, whether we build it in Rust or C++.
I would describe WGPU's niche as entry-level. It is certainly easier for newcomers who want to learn the basics of graphics or develop applications that are not critically dependent on performance. However, when developing a higher-level graphics engine or a performance-sensitive video game, we should probably avoid using this layer. Two layers of abstraction are too much.
I believe that a high-level Rust graphics library should be designed with a deep understanding of what end users will actually do with it. It does not necessarily need to cover all theoretical possibilities of computer graphics. Rather, it should focus on clear goals and address a limited but well-understood domain.
For example, if we were building a high-performance sprite graphics engine, the end user shouldn't have to deal with low-level details such as memory allocation or even writing shaders by hand. The crate should handle all of this under the hood, allowing us, as its developers, to provide the most performant, safe, and correct internal design using raw bindings without unnecessary abstraction layers.
To sum up, there is still a lack of diversity among such domain-specific crates in Rust. Essentially, we need more specialized, end-user-focused game engines.
I believe Rust has the potential to shine in games where cutting-edge graphics are not the primary focus, allowing developers to concentrate on interesting game logic rather than high-end rendering. A game like Factorio, which started in raw C++ over a decade ago, could perhaps be developed in Rust today. However, such a project would be unlikely to benefit from engines like Unity (or Bevy!).
Many of these games don't require heavyweight graphics, and to be realistic, I don't expect Rust to produce direct competitors to Unreal Engine or Red Dead Redemption 2 in the foreseeable future. However, developing specialized, performant, and user-friendly graphics infrastructure for games like Civilization, Age of Empires, Fallout, or Diablo 1 is an achievable and worthwhile goal.