|
|
|
@ -1,207 +1,206 @@
|
|
|
|
|
/*! A cross-platform unsafe graphics abstraction.
|
|
|
|
|
*
|
|
|
|
|
* This crate defines a set of traits abstracting over modern graphics APIs,
|
|
|
|
|
* with implementations ("backends") for Vulkan, Metal, Direct3D, and GL.
|
|
|
|
|
*
|
|
|
|
|
* `wgpu-hal` is a spiritual successor to
|
|
|
|
|
* [gfx-hal](https://github.com/gfx-rs/gfx), but with reduced scope, and
|
|
|
|
|
* oriented towards WebGPU implementation goals. It has no overhead for
|
|
|
|
|
* validation or tracking, and the API translation overhead is kept to the bare
|
|
|
|
|
* minimum by the design of WebGPU. This API can be used for resource-demanding
|
|
|
|
|
* applications and engines.
|
|
|
|
|
*
|
|
|
|
|
* The `wgpu-hal` crate's main design choices:
|
|
|
|
|
*
|
|
|
|
|
* - Our traits are meant to be *portable*: proper use
|
|
|
|
|
* should get equivalent results regardless of the backend.
|
|
|
|
|
*
|
|
|
|
|
* - Our traits' contracts are *unsafe*: implementations perform minimal
|
|
|
|
|
* validation, if any, and incorrect use will often cause undefined behavior.
|
|
|
|
|
* This allows us to minimize the overhead we impose over the underlying
|
|
|
|
|
* graphics system. If you need safety, the [`wgpu-core`] crate provides a
|
|
|
|
|
* safe API for driving `wgpu-hal`, implementing all necessary validation,
|
|
|
|
|
* resource state tracking, and so on. (Note that `wgpu-core` is designed for
|
|
|
|
|
* use via FFI; the [`wgpu`] crate provides more idiomatic Rust bindings for
|
|
|
|
|
* `wgpu-core`.) Or, you can do your own validation.
|
|
|
|
|
*
|
|
|
|
|
* - In the same vein, returned errors *only cover cases the user can't
|
|
|
|
|
* anticipate*, like running out of memory or losing the device. Any errors
|
|
|
|
|
* that the user could reasonably anticipate are their responsibility to
|
|
|
|
|
* avoid. For example, `wgpu-hal` returns no error for mapping a buffer that's
|
|
|
|
|
* not mappable: as the buffer creator, the user should already know if they
|
|
|
|
|
* can map it.
|
|
|
|
|
*
|
|
|
|
|
* - We use *static dispatch*. The traits are not
|
|
|
|
|
* generally object-safe. You must select a specific backend type
|
|
|
|
|
* like [`vulkan::Api`] or [`metal::Api`], and then use that
|
|
|
|
|
* according to the main traits, or call backend-specific methods.
|
|
|
|
|
*
|
|
|
|
|
* - We use *idiomatic Rust parameter passing*,
|
|
|
|
|
* taking objects by reference, returning them by value, and so on,
|
|
|
|
|
* unlike `wgpu-core`, which refers to objects by ID.
|
|
|
|
|
*
|
|
|
|
|
* - We map buffer contents *persistently*. This means that the buffer can
|
|
|
|
|
* remain mapped on the CPU while the GPU reads or writes to it. You must
|
|
|
|
|
* explicitly indicate when data might need to be transferred between CPU and
|
|
|
|
|
* GPU, if [`Device::map_buffer`] indicates that this is necessary.
|
|
|
|
|
*
|
|
|
|
|
* - You must record *explicit barriers* between different usages of a
|
|
|
|
|
* resource. For example, if a buffer is written to by a compute
|
|
|
|
|
* shader, and then used as and index buffer to a draw call, you
|
|
|
|
|
* must use [`CommandEncoder::transition_buffers`] between those two
|
|
|
|
|
* operations.
|
|
|
|
|
*
|
|
|
|
|
* - Pipeline layouts are *explicitly specified* when setting bind
|
|
|
|
|
* group. Incompatible layouts disturb groups bound at higher indices.
|
|
|
|
|
*
|
|
|
|
|
* - The API *accepts collections as iterators*, to avoid forcing the user to
|
|
|
|
|
* store data in particular containers. The implementation doesn't guarantee
|
|
|
|
|
* that any of the iterators are drained, unless stated otherwise by the
|
|
|
|
|
* function documentation. For this reason, we recommend that iterators don't
|
|
|
|
|
* do any mutating work.
|
|
|
|
|
*
|
|
|
|
|
* Unfortunately, `wgpu-hal`'s safety requirements are not fully documented.
|
|
|
|
|
* Ideally, all trait methods would have doc comments setting out the
|
|
|
|
|
* requirements users must meet to ensure correct and portable behavior. If you
|
|
|
|
|
* are aware of a specific requirement that a backend imposes that is not
|
|
|
|
|
* ensured by the traits' documented rules, please file an issue. Or, if you are
|
|
|
|
|
* a capable technical writer, please file a pull request!
|
|
|
|
|
*
|
|
|
|
|
* [`wgpu-core`]: https://crates.io/crates/wgpu-core
|
|
|
|
|
* [`wgpu`]: https://crates.io/crates/wgpu
|
|
|
|
|
* [`vulkan::Api`]: vulkan/struct.Api.html
|
|
|
|
|
* [`metal::Api`]: metal/struct.Api.html
|
|
|
|
|
*
|
|
|
|
|
* ## Primary backends
|
|
|
|
|
*
|
|
|
|
|
* The `wgpu-hal` crate has full-featured backends implemented on the following
|
|
|
|
|
* platform graphics APIs:
|
|
|
|
|
*
|
|
|
|
|
* - Vulkan, available on Linux, Android, and Windows, using the [`ash`] crate's
|
|
|
|
|
* Vulkan bindings. It's also available on macOS, if you install [MoltenVK].
|
|
|
|
|
*
|
|
|
|
|
* - Metal on macOS, using the [`metal`] crate's bindings.
|
|
|
|
|
*
|
|
|
|
|
* - Direct3D 12 on Windows, using the [`d3d12`] crate's bindings.
|
|
|
|
|
*
|
|
|
|
|
* [`ash`]: https://crates.io/crates/ash
|
|
|
|
|
* [MoltenVK]: https://github.com/KhronosGroup/MoltenVK
|
|
|
|
|
* [`metal`]: https://crates.io/crates/metal
|
|
|
|
|
* [`d3d12`]: ahttps://crates.io/crates/d3d12
|
|
|
|
|
*
|
|
|
|
|
* ## Secondary backends
|
|
|
|
|
*
|
|
|
|
|
* The `wgpu-hal` crate has a partial implementation based on the following
|
|
|
|
|
* platform graphics API:
|
|
|
|
|
*
|
|
|
|
|
* - The GL backend is available anywhere OpenGL, OpenGL ES, or WebGL are
|
|
|
|
|
* available. See the [`gles`] module documentation for details.
|
|
|
|
|
*
|
|
|
|
|
* [`gles`]: gles/index.html
|
|
|
|
|
*
|
|
|
|
|
* You can see what capabilities an adapter is missing by checking the
|
|
|
|
|
* [`DownlevelCapabilities`][tdc] in [`ExposedAdapter::capabilities`], available
|
|
|
|
|
* from [`Instance::enumerate_adapters`].
|
|
|
|
|
*
|
|
|
|
|
* The API is generally designed to fit the primary backends better than the
|
|
|
|
|
* secondary backends, so the latter may impose more overhead.
|
|
|
|
|
*
|
|
|
|
|
* [tdc]: wgt::DownlevelCapabilities
|
|
|
|
|
*
|
|
|
|
|
* ## Traits
|
|
|
|
|
*
|
|
|
|
|
* The `wgpu-hal` crate defines a handful of traits that together
|
|
|
|
|
* represent a cross-platform abstraction for modern GPU APIs.
|
|
|
|
|
*
|
|
|
|
|
* - The [`Api`] trait represents a `wgpu-hal` backend. It has no methods of its
|
|
|
|
|
* own, only a collection of associated types.
|
|
|
|
|
*
|
|
|
|
|
* - [`Api::Instance`] implements the [`Instance`] trait. [`Instance::init`]
|
|
|
|
|
* creates an instance value, which you can use to enumerate the adapters
|
|
|
|
|
* available on the system. For example, [`vulkan::Api::Instance::init`][Ii]
|
|
|
|
|
* returns an instance that can enumerate the Vulkan physical devices on your
|
|
|
|
|
* system.
|
|
|
|
|
*
|
|
|
|
|
* - [`Api::Adapter`] implements the [`Adapter`] trait, representing a
|
|
|
|
|
* particular device from a particular backend. For example, a Vulkan instance
|
|
|
|
|
* might have a Lavapipe software adapter and a GPU-based adapter.
|
|
|
|
|
*
|
|
|
|
|
* - [`Api::Device`] implements the [`Device`] trait, representing an active
|
|
|
|
|
* link to a device. You get a device value by calling [`Adapter::open`], and
|
|
|
|
|
* then use it to create buffers, textures, shader modules, and so on.
|
|
|
|
|
*
|
|
|
|
|
* - [`Api::Queue`] implements the [`Queue`] trait, which you use to submit
|
|
|
|
|
* command buffers to a given device.
|
|
|
|
|
*
|
|
|
|
|
* - [`Api::CommandEncoder`] implements the [`CommandEncoder`] trait, which you
|
|
|
|
|
* use to build buffers of commands to submit to a queue. This has all the
|
|
|
|
|
* methods for drawing and running compute shaders, which is presumably what
|
|
|
|
|
* you're here for.
|
|
|
|
|
*
|
|
|
|
|
* - [`Api::Surface`] implements the [`Surface`] trait, which represents a
|
|
|
|
|
* swapchain for presenting images on the screen, via interaction with the
|
|
|
|
|
* system's window manager.
|
|
|
|
|
*
|
|
|
|
|
* The [`Api`] trait has various other associated types like [`Api::Buffer`] and
|
|
|
|
|
* [`Api::Texture`] that represent resources the rest of the interface can
|
|
|
|
|
* operate on, but these generally do not have their own traits.
|
|
|
|
|
*
|
|
|
|
|
* [Ii]: Instance::init
|
|
|
|
|
*
|
|
|
|
|
* ## Validation is the calling code's responsibility, not `wgpu-hal`'s
|
|
|
|
|
*
|
|
|
|
|
* As much as possible, `wgpu-hal` traits place the burden of validation,
|
|
|
|
|
* resource tracking, and state tracking on the caller, not on the trait
|
|
|
|
|
* implementations themselves. Anything which can reasonably be handled in
|
|
|
|
|
* backend-independent code should be. A `wgpu_hal` backend's sole obligation is
|
|
|
|
|
* to provide portable behavior, and report conditions that the calling code
|
|
|
|
|
* can't reasonably anticipate, like device loss or running out of memory.
|
|
|
|
|
*
|
|
|
|
|
* The `wgpu` crate collection is intended for use in security-sensitive
|
|
|
|
|
* applications, like web browsers, where the API is available to untrusted
|
|
|
|
|
* code. This means that `wgpu-core`'s validation is not simply a service to
|
|
|
|
|
* developers, to be provided opportunistically when the performance costs are
|
|
|
|
|
* acceptable and the necessary data is ready at hand. Rather, `wgpu-core`'s
|
|
|
|
|
* validation must be exhaustive, to ensure that even malicious content cannot
|
|
|
|
|
* provoke and exploit undefined behavior in the platform's graphics API.
|
|
|
|
|
*
|
|
|
|
|
* Because graphics APIs' requirements are complex, the only practical way for
|
|
|
|
|
* `wgpu` to provide exhaustive validation is to comprehensively track the
|
|
|
|
|
* lifetime and state of all the resources in the system. Implementing this
|
|
|
|
|
* separately for each backend is infeasible; effort would be better spent
|
|
|
|
|
* making the cross-platform validation in `wgpu-core` legible and trustworthy.
|
|
|
|
|
* Fortunately, the requirements are largely similar across the various
|
|
|
|
|
* platforms, so cross-platform validation is practical.
|
|
|
|
|
*
|
|
|
|
|
* Some backends have specific requirements that aren't practical to foist off
|
|
|
|
|
* on the `wgpu-hal` user. For example, properly managing macOS Objective-C or
|
|
|
|
|
* Microsoft COM reference counts is best handled by using appropriate pointer
|
|
|
|
|
* types within the backend.
|
|
|
|
|
*
|
|
|
|
|
* A desire for "defense in depth" may suggest performing additional validation
|
|
|
|
|
* in `wgpu-hal` when the opportunity arises, but this must be done with
|
|
|
|
|
* caution. Even experienced contributors infer the expectations their changes
|
|
|
|
|
* must meet by considering not just requirements made explicit in types, tests,
|
|
|
|
|
* assertions, and comments, but also those implicit in the surrounding code.
|
|
|
|
|
* When one sees validation or state-tracking code in `wgpu-hal`, it is tempting
|
|
|
|
|
* to conclude, "Oh, `wgpu-hal` checks for this, so `wgpu-core` needn't worry
|
|
|
|
|
* about it - that would be redundant!" The responsibility for exhaustive
|
|
|
|
|
* validation always rests with `wgpu-core`, regardless of what may or may not
|
|
|
|
|
* be checked in `wgpu-hal`.
|
|
|
|
|
*
|
|
|
|
|
* To this end, any "defense in depth" validation that does appear in `wgpu-hal`
|
|
|
|
|
* for requirements that `wgpu-core` should have enforced should report failure
|
|
|
|
|
* via the `unreachable!` macro, because problems detected at this stage always
|
|
|
|
|
* indicate a bug in `wgpu-core`.
|
|
|
|
|
*
|
|
|
|
|
* ## Debugging
|
|
|
|
|
*
|
|
|
|
|
* Most of the information on the wiki [Debugging wgpu Applications][wiki-debug]
|
|
|
|
|
* page still applies to this API, with the exception of API tracing/replay
|
|
|
|
|
* functionality, which is only available in `wgpu-core`.
|
|
|
|
|
*
|
|
|
|
|
* [wiki-debug]: https://github.com/gfx-rs/wgpu/wiki/Debugging-wgpu-Applications
|
|
|
|
|
*/
|
|
|
|
|
//! A cross-platform unsafe graphics abstraction.
|
|
|
|
|
//!
|
|
|
|
|
//! This crate defines a set of traits abstracting over modern graphics APIs,
|
|
|
|
|
//! with implementations ("backends") for Vulkan, Metal, Direct3D, and GL.
|
|
|
|
|
//!
|
|
|
|
|
//! `wgpu-hal` is a spiritual successor to
|
|
|
|
|
//! [gfx-hal](https://github.com/gfx-rs/gfx), but with reduced scope, and
|
|
|
|
|
//! oriented towards WebGPU implementation goals. It has no overhead for
|
|
|
|
|
//! validation or tracking, and the API translation overhead is kept to the bare
|
|
|
|
|
//! minimum by the design of WebGPU. This API can be used for resource-demanding
|
|
|
|
|
//! applications and engines.
|
|
|
|
|
//!
|
|
|
|
|
//! The `wgpu-hal` crate's main design choices:
|
|
|
|
|
//!
|
|
|
|
|
//! - Our traits are meant to be *portable*: proper use
|
|
|
|
|
//! should get equivalent results regardless of the backend.
|
|
|
|
|
//!
|
|
|
|
|
//! - Our traits' contracts are *unsafe*: implementations perform minimal
|
|
|
|
|
//! validation, if any, and incorrect use will often cause undefined behavior.
|
|
|
|
|
//! This allows us to minimize the overhead we impose over the underlying
|
|
|
|
|
//! graphics system. If you need safety, the [`wgpu-core`] crate provides a
|
|
|
|
|
//! safe API for driving `wgpu-hal`, implementing all necessary validation,
|
|
|
|
|
//! resource state tracking, and so on. (Note that `wgpu-core` is designed for
|
|
|
|
|
//! use via FFI; the [`wgpu`] crate provides more idiomatic Rust bindings for
|
|
|
|
|
//! `wgpu-core`.) Or, you can do your own validation.
|
|
|
|
|
//!
|
|
|
|
|
//! - In the same vein, returned errors *only cover cases the user can't
|
|
|
|
|
//! anticipate*, like running out of memory or losing the device. Any errors
|
|
|
|
|
//! that the user could reasonably anticipate are their responsibility to
|
|
|
|
|
//! avoid. For example, `wgpu-hal` returns no error for mapping a buffer that's
|
|
|
|
|
//! not mappable: as the buffer creator, the user should already know if they
|
|
|
|
|
//! can map it.
|
|
|
|
|
//!
|
|
|
|
|
//! - We use *static dispatch*. The traits are not
|
|
|
|
|
//! generally object-safe. You must select a specific backend type
|
|
|
|
|
//! like [`vulkan::Api`] or [`metal::Api`], and then use that
|
|
|
|
|
//! according to the main traits, or call backend-specific methods.
|
|
|
|
|
//!
|
|
|
|
|
//! - We use *idiomatic Rust parameter passing*,
|
|
|
|
|
//! taking objects by reference, returning them by value, and so on,
|
|
|
|
|
//! unlike `wgpu-core`, which refers to objects by ID.
|
|
|
|
|
//!
|
|
|
|
|
//! - We map buffer contents *persistently*. This means that the buffer can
|
|
|
|
|
//! remain mapped on the CPU while the GPU reads or writes to it. You must
|
|
|
|
|
//! explicitly indicate when data might need to be transferred between CPU and
|
|
|
|
|
//! GPU, if [`Device::map_buffer`] indicates that this is necessary.
|
|
|
|
|
//!
|
|
|
|
|
//! - You must record *explicit barriers* between different usages of a
|
|
|
|
|
//! resource. For example, if a buffer is written to by a compute
|
|
|
|
|
//! shader, and then used as and index buffer to a draw call, you
|
|
|
|
|
//! must use [`CommandEncoder::transition_buffers`] between those two
|
|
|
|
|
//! operations.
|
|
|
|
|
//!
|
|
|
|
|
//! - Pipeline layouts are *explicitly specified* when setting bind
|
|
|
|
|
//! group. Incompatible layouts disturb groups bound at higher indices.
|
|
|
|
|
//!
|
|
|
|
|
//! - The API *accepts collections as iterators*, to avoid forcing the user to
|
|
|
|
|
//! store data in particular containers. The implementation doesn't guarantee
|
|
|
|
|
//! that any of the iterators are drained, unless stated otherwise by the
|
|
|
|
|
//! function documentation. For this reason, we recommend that iterators don't
|
|
|
|
|
//! do any mutating work.
|
|
|
|
|
//!
|
|
|
|
|
//! Unfortunately, `wgpu-hal`'s safety requirements are not fully documented.
|
|
|
|
|
//! Ideally, all trait methods would have doc comments setting out the
|
|
|
|
|
//! requirements users must meet to ensure correct and portable behavior. If you
|
|
|
|
|
//! are aware of a specific requirement that a backend imposes that is not
|
|
|
|
|
//! ensured by the traits' documented rules, please file an issue. Or, if you are
|
|
|
|
|
//! a capable technical writer, please file a pull request!
|
|
|
|
|
//!
|
|
|
|
|
//! [`wgpu-core`]: https://crates.io/crates/wgpu-core
|
|
|
|
|
//! [`wgpu`]: https://crates.io/crates/wgpu
|
|
|
|
|
//! [`vulkan::Api`]: vulkan/struct.Api.html
|
|
|
|
|
//! [`metal::Api`]: metal/struct.Api.html
|
|
|
|
|
//!
|
|
|
|
|
//! ## Primary backends
|
|
|
|
|
//!
|
|
|
|
|
//! The `wgpu-hal` crate has full-featured backends implemented on the following
|
|
|
|
|
//! platform graphics APIs:
|
|
|
|
|
//!
|
|
|
|
|
//! - Vulkan, available on Linux, Android, and Windows, using the [`ash`] crate's
|
|
|
|
|
//! Vulkan bindings. It's also available on macOS, if you install [MoltenVK].
|
|
|
|
|
//!
|
|
|
|
|
//! - Metal on macOS, using the [`metal`] crate's bindings.
|
|
|
|
|
//!
|
|
|
|
|
//! - Direct3D 12 on Windows, using the [`d3d12`] crate's bindings.
|
|
|
|
|
//!
|
|
|
|
|
//! [`ash`]: https://crates.io/crates/ash
|
|
|
|
|
//! [MoltenVK]: https://github.com/KhronosGroup/MoltenVK
|
|
|
|
|
//! [`metal`]: https://crates.io/crates/metal
|
|
|
|
|
//! [`d3d12`]: ahttps://crates.io/crates/d3d12
|
|
|
|
|
//!
|
|
|
|
|
//! ## Secondary backends
|
|
|
|
|
//!
|
|
|
|
|
//! The `wgpu-hal` crate has a partial implementation based on the following
|
|
|
|
|
//! platform graphics API:
|
|
|
|
|
//!
|
|
|
|
|
//! - The GL backend is available anywhere OpenGL, OpenGL ES, or WebGL are
|
|
|
|
|
//! available. See the [`gles`] module documentation for details.
|
|
|
|
|
//!
|
|
|
|
|
//! [`gles`]: gles/index.html
|
|
|
|
|
//!
|
|
|
|
|
//! You can see what capabilities an adapter is missing by checking the
|
|
|
|
|
//! [`DownlevelCapabilities`][tdc] in [`ExposedAdapter::capabilities`], available
|
|
|
|
|
//! from [`Instance::enumerate_adapters`].
|
|
|
|
|
//!
|
|
|
|
|
//! The API is generally designed to fit the primary backends better than the
|
|
|
|
|
//! secondary backends, so the latter may impose more overhead.
|
|
|
|
|
//!
|
|
|
|
|
//! [tdc]: wgt::DownlevelCapabilities
|
|
|
|
|
//!
|
|
|
|
|
//! ## Traits
|
|
|
|
|
//!
|
|
|
|
|
//! The `wgpu-hal` crate defines a handful of traits that together
|
|
|
|
|
//! represent a cross-platform abstraction for modern GPU APIs.
|
|
|
|
|
//!
|
|
|
|
|
//! - The [`Api`] trait represents a `wgpu-hal` backend. It has no methods of its
|
|
|
|
|
//! own, only a collection of associated types.
|
|
|
|
|
//!
|
|
|
|
|
//! - [`Api::Instance`] implements the [`Instance`] trait. [`Instance::init`]
|
|
|
|
|
//! creates an instance value, which you can use to enumerate the adapters
|
|
|
|
|
//! available on the system. For example, [`vulkan::Api::Instance::init`][Ii]
|
|
|
|
|
//! returns an instance that can enumerate the Vulkan physical devices on your
|
|
|
|
|
//! system.
|
|
|
|
|
//!
|
|
|
|
|
//! - [`Api::Adapter`] implements the [`Adapter`] trait, representing a
|
|
|
|
|
//! particular device from a particular backend. For example, a Vulkan instance
|
|
|
|
|
//! might have a Lavapipe software adapter and a GPU-based adapter.
|
|
|
|
|
//!
|
|
|
|
|
//! - [`Api::Device`] implements the [`Device`] trait, representing an active
|
|
|
|
|
//! link to a device. You get a device value by calling [`Adapter::open`], and
|
|
|
|
|
//! then use it to create buffers, textures, shader modules, and so on.
|
|
|
|
|
//!
|
|
|
|
|
//! - [`Api::Queue`] implements the [`Queue`] trait, which you use to submit
|
|
|
|
|
//! command buffers to a given device.
|
|
|
|
|
//!
|
|
|
|
|
//! - [`Api::CommandEncoder`] implements the [`CommandEncoder`] trait, which you
|
|
|
|
|
//! use to build buffers of commands to submit to a queue. This has all the
|
|
|
|
|
//! methods for drawing and running compute shaders, which is presumably what
|
|
|
|
|
//! you're here for.
|
|
|
|
|
//!
|
|
|
|
|
//! - [`Api::Surface`] implements the [`Surface`] trait, which represents a
|
|
|
|
|
//! swapchain for presenting images on the screen, via interaction with the
|
|
|
|
|
//! system's window manager.
|
|
|
|
|
//!
|
|
|
|
|
//! The [`Api`] trait has various other associated types like [`Api::Buffer`] and
|
|
|
|
|
//! [`Api::Texture`] that represent resources the rest of the interface can
|
|
|
|
|
//! operate on, but these generally do not have their own traits.
|
|
|
|
|
//!
|
|
|
|
|
//! [Ii]: Instance::init
|
|
|
|
|
//!
|
|
|
|
|
//! ## Validation is the calling code's responsibility, not `wgpu-hal`'s
|
|
|
|
|
//!
|
|
|
|
|
//! As much as possible, `wgpu-hal` traits place the burden of validation,
|
|
|
|
|
//! resource tracking, and state tracking on the caller, not on the trait
|
|
|
|
|
//! implementations themselves. Anything which can reasonably be handled in
|
|
|
|
|
//! backend-independent code should be. A `wgpu_hal` backend's sole obligation is
|
|
|
|
|
//! to provide portable behavior, and report conditions that the calling code
|
|
|
|
|
//! can't reasonably anticipate, like device loss or running out of memory.
|
|
|
|
|
//!
|
|
|
|
|
//! The `wgpu` crate collection is intended for use in security-sensitive
|
|
|
|
|
//! applications, like web browsers, where the API is available to untrusted
|
|
|
|
|
//! code. This means that `wgpu-core`'s validation is not simply a service to
|
|
|
|
|
//! developers, to be provided opportunistically when the performance costs are
|
|
|
|
|
//! acceptable and the necessary data is ready at hand. Rather, `wgpu-core`'s
|
|
|
|
|
//! validation must be exhaustive, to ensure that even malicious content cannot
|
|
|
|
|
//! provoke and exploit undefined behavior in the platform's graphics API.
|
|
|
|
|
//!
|
|
|
|
|
//! Because graphics APIs' requirements are complex, the only practical way for
|
|
|
|
|
//! `wgpu` to provide exhaustive validation is to comprehensively track the
|
|
|
|
|
//! lifetime and state of all the resources in the system. Implementing this
|
|
|
|
|
//! separately for each backend is infeasible; effort would be better spent
|
|
|
|
|
//! making the cross-platform validation in `wgpu-core` legible and trustworthy.
|
|
|
|
|
//! Fortunately, the requirements are largely similar across the various
|
|
|
|
|
//! platforms, so cross-platform validation is practical.
|
|
|
|
|
//!
|
|
|
|
|
//! Some backends have specific requirements that aren't practical to foist off
|
|
|
|
|
//! on the `wgpu-hal` user. For example, properly managing macOS Objective-C or
|
|
|
|
|
//! Microsoft COM reference counts is best handled by using appropriate pointer
|
|
|
|
|
//! types within the backend.
|
|
|
|
|
//!
|
|
|
|
|
//! A desire for "defense in depth" may suggest performing additional validation
|
|
|
|
|
//! in `wgpu-hal` when the opportunity arises, but this must be done with
|
|
|
|
|
//! caution. Even experienced contributors infer the expectations their changes
|
|
|
|
|
//! must meet by considering not just requirements made explicit in types, tests,
|
|
|
|
|
//! assertions, and comments, but also those implicit in the surrounding code.
|
|
|
|
|
//! When one sees validation or state-tracking code in `wgpu-hal`, it is tempting
|
|
|
|
|
//! to conclude, "Oh, `wgpu-hal` checks for this, so `wgpu-core` needn't worry
|
|
|
|
|
//! about it - that would be redundant!" The responsibility for exhaustive
|
|
|
|
|
//! validation always rests with `wgpu-core`, regardless of what may or may not
|
|
|
|
|
//! be checked in `wgpu-hal`.
|
|
|
|
|
//!
|
|
|
|
|
//! To this end, any "defense in depth" validation that does appear in `wgpu-hal`
|
|
|
|
|
//! for requirements that `wgpu-core` should have enforced should report failure
|
|
|
|
|
//! via the `unreachable!` macro, because problems detected at this stage always
|
|
|
|
|
//! indicate a bug in `wgpu-core`.
|
|
|
|
|
//!
|
|
|
|
|
//! ## Debugging
|
|
|
|
|
//!
|
|
|
|
|
//! Most of the information on the wiki [Debugging wgpu Applications][wiki-debug]
|
|
|
|
|
//! page still applies to this API, with the exception of API tracing/replay
|
|
|
|
|
//! functionality, which is only available in `wgpu-core`.
|
|
|
|
|
//!
|
|
|
|
|
//! [wiki-debug]: https://github.com/gfx-rs/wgpu/wiki/Debugging-wgpu-Applications
|
|
|
|
|
|
|
|
|
|
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
|
|
|
|
|
#![allow(
|
|
|
|
|