naga_rust_back/
lib.rs

1//! [`naga`] backend allowing you to translate shader code in any language supported by Naga
2//! to Rust code.
3//!
4//! The generated code requires the [`naga_rust_rt`] library.
5//! Alternatively, you can use [`naga_rust_embed`], which combines this library with
6//! [`naga_rust_rt`] and provides convenient macros for embedding translated WGSL in your Rust code.
7//!
8//! This library is in an early stage of development and many features do not work yet;
9//! this may be indicated by returned errors or by the generated code failing to compile.
10//! Broadly, simple mathematical functions will work, and bindings, textures, atomics,
11//! derivatives, and workgroup operations will not.
12//!
13//! [`naga_rust_rt`]: https://docs.rs/naga-rust-rt
14//! [`naga_rust_embed`]: https://docs.rs/naga-rust-embed
15
16#![no_std]
17
18extern crate alloc;
19
20use alloc::string::String;
21use core::fmt;
22
23use naga::valid::Capabilities;
24
25// -------------------------------------------------------------------------------------------------
26
27mod config;
28mod conv;
29mod util;
30mod writer;
31
32pub use config::Config;
33pub use writer::Writer;
34
35/// The version of Naga we are compatible with.
36pub use naga;
37
38// -------------------------------------------------------------------------------------------------
39
40/// The [`Capabilities`] supported by our Rust runtime library.
41///
42/// Pass this to [`naga::valid::Validator`] when validating a module that is to be translated to
43/// Rust.
44// TODO: There are probably some additional capabilities which should be enabled here
45// either because we can support them or they don’t affect us.
46pub const CAPABILITIES: Capabilities = Capabilities::FLOAT64;
47
48/// Errors returned by the Rust-generating backend.
49#[derive(Debug)]
50#[non_exhaustive]
51pub enum Error {
52    /// The provided [`fmt::Write`] implementation returned an error.
53    FmtError(fmt::Error),
54
55    /// The Rust backend currently does not support this particular shader functionality.
56    // TODO: this should not be a thing when finished; everything should be either supported
57    // or fall into a well-defined category of unsupportedness.
58    Unimplemented(String),
59
60    /// We don’t (yet) support texture operations in Rust,
61    /// and this is a notably broad category so it gets its own variant.
62    #[non_exhaustive]
63    TexturesAreUnsupported {
64        /// The specific kind of thing found that is unsupported.
65        /// Represented as a WGSL-flavored string.
66        found: &'static str,
67    },
68
69    /// To use a shader with global variables, [`Config::global_struct()`] must be set.
70    #[non_exhaustive]
71    GlobalVariablesNotEnabled {
72        /// The name of one of the prohibited global variables.
73        example: String,
74    },
75}
76
77impl From<fmt::Error> for Error {
78    fn from(value: fmt::Error) -> Self {
79        Self::FmtError(value)
80    }
81}
82
83impl core::error::Error for Error {}
84impl fmt::Display for Error {
85    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86        match self {
87            Error::FmtError(fmt::Error) => write!(f, "formatting cancelled"),
88            Error::Unimplemented(msg) => write!(f, "not yet implemented for Rust: {msg}"),
89            Error::TexturesAreUnsupported { found } => {
90                write!(f, "texture operations, such as {found}, are not supported")
91            }
92            Error::GlobalVariablesNotEnabled { example } => write!(
93                f,
94                "global variable `{example}` found in shader, but not enabled in Config"
95            ),
96        }
97    }
98}
99
100/// Converts `module` to a string of Rust code.
101///
102/// # Errors
103///
104/// Returns an error if the module cannot be represented as Rust.
105pub fn write_string(
106    module: &naga::Module,
107    info: &naga::valid::ModuleInfo,
108    config: Config,
109) -> Result<String, Error> {
110    let mut w = Writer::new(config);
111    let mut output = String::new();
112    w.write(&mut output, module, info)?;
113    Ok(output)
114}