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}