Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rusty imports #41

Merged
merged 32 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
2b59afd
well it compiles
robtfm Jul 30, 2023
c5865ff
fix tests
robtfm Jul 30, 2023
a95c444
remove debug println
robtfm Jul 30, 2023
f88db5d
reorg
robtfm Jul 30, 2023
3cb1a22
fmt
robtfm Jul 30, 2023
0098baa
clippy
robtfm Jul 30, 2023
9ec6520
fix toplevel err source after preprocess
robtfm Jul 31, 2023
21ead57
disallow leading/trailing `:`s on ident tokens
robtfm Jul 31, 2023
23e7676
ci
robtfm Jul 31, 2023
3781ad9
allow trailing ':'s for imports
robtfm Jul 31, 2023
61ef532
better tokenizer
robtfm Jul 31, 2023
9d8b9ce
remove get_preprocessor_data unwrap()
robtfm Aug 3, 2023
343d95f
fix Token::Other offset
robtfm Aug 3, 2023
e4fa468
fix reported offset for import errors
robtfm Aug 3, 2023
e3b2aae
allow trailing semicolon for import defs
robtfm Aug 3, 2023
9043aac
ci
robtfm Aug 3, 2023
0cb845f
update readme
robtfm Aug 4, 2023
38eb7af
don't sub isolated idents for quoted fullpaths
robtfm Aug 8, 2023
3481b95
Merge branch 'master' into rusty-imports
robtfm Sep 10, 2023
a7716b3
fix test output
robtfm Sep 10, 2023
a6970a0
fmt
robtfm Sep 10, 2023
2e0b923
clippy
robtfm Sep 10, 2023
3ea057d
Merge branch 'master' into rusty-imports
robtfm Sep 23, 2023
8ef675c
fix atomics test output
robtfm Sep 23, 2023
cce4144
avoid unused warning
robtfm Oct 18, 2023
da0891d
warn on deprecated itemlist imports
robtfm Oct 18, 2023
80f0a4b
fix duplicate test
robtfm Oct 18, 2023
feb2bd0
add perf comment
robtfm Oct 18, 2023
6daace4
fmt
robtfm Oct 18, 2023
856136a
change feature to "allow_deprecated"
robtfm Oct 18, 2023
5d7eaaf
Fix unused import and swap ; for ` in warning message
cart Oct 18, 2023
39dd090
Add additional PERF comment and use PERF instead of TODO
cart Oct 18, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ repository = "https://github.com/bevyengine/naga_oil/"
readme = "README.md"

[features]
default = ["test_shader"]
default = ["test_shader", "warn_deprecated"]
# enable tests that need a graphical card
test_shader = []
prune = []
override_any = []
warn_deprecated = []

[dependencies]
naga = { version = "0.13", features = ["wgsl-in", "wgsl-out", "glsl-in", "glsl-out", "clone", "span"] }
Expand Down
31 changes: 25 additions & 6 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,34 +32,51 @@ fn my_func() -> f32 {
}
```

shaders can then import the module with an `#import` directive (with an optional `as` name). at point of use, imported items must be qualified:
alternatively the module name can be specified as an argument to `Composer::add_composable_module`.

shaders can then import the module with an `#import` directive (with an optional `as` name) :

```wgsl
#import my_module
#import my_other_module as Mod2
#import my_module;
#import my_other_module as mod2;

fn main() -> f32 {
let x = my_module::my_func();
let y = Mod2::my_other_func();
let y = mod2::my_other_func();
return x*y;
}
```

or import a comma-separated list of individual items :

```wgsl
#import my_module my_func, my_const
#import my_module::{my_func, my_const}

fn main() -> f32 {
return my_func(my_const);
}
```

Some rust-style import syntax is supported, and items can be directly imported using the fully qualified item name :

```wgsl
#import my_package::{
first_module::{item_one as item, item_two},
second_module::submodule,
}

fn main() -> f32 {
return item + item_two + submodule::subitem + my_package::third_module::item;
}
```

`module::self` and `module::*` are not currently supported.

imports can be nested - modules may import other modules, but not recursively. when a new module is added, all its `#import`s must already have been added.
the same module can be imported multiple times by different modules in the import tree.
there is no overlap of namespaces, so the same function names (or type, constant, or variable names) may be used in different modules.

note: when importing an item with the `#import module item` directive, the final shader will include the required dependencies (bindings, globals, consts, other functions) of the imported item, but will not include the rest of the imported module. it will however still include all of any modules imported by the imported module. this is probably not desired in general and may be fixed in a future version. currently for a more complete culling of unused dependencies the `prune` module can be used.
note: the final shader will include the required dependencies (bindings, globals, consts, other functions) of any imported items that are used, but will not include the rest of the imported module.

## overriding functions

Expand All @@ -79,6 +96,8 @@ override fn Lighting::point_light (world_position: vec3<f32>) -> vec3<f32> {
}
```

overrides must either be declared in the top-level shader, or the module containing the override must be imported as an `additional_import` in a `Composer::add_composable_module` or `Composer::make_naga_module` call. using `#import` to import a module with overrides will not work due to tree-shaking.

override function definitions cause *all* calls to the original function in the entire shader scope to be replaced by calls to the new function, with the exception of calls within the override function itself.

the function signature of the override must match the base function.
Expand Down
17 changes: 8 additions & 9 deletions src/compose/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ use codespan_reporting::{
use thiserror::Error;
use tracing::trace;

use super::{
preprocess::{PreprocessOutput, PreprocessorMetaData},
Composer, ShaderDefValue,
};
use super::{preprocess::PreprocessOutput, Composer, ShaderDefValue};
use crate::{compose::SPAN_SHIFT, redirect::RedirectError};

#[derive(Debug)]
Expand Down Expand Up @@ -42,18 +39,14 @@ impl ErrSource {
let raw_source = &composer.module_sets.get(name).unwrap().sanitized_source;
let Ok(PreprocessOutput {
preprocessed_source: source,
meta: PreprocessorMetaData { imports, .. },
..
}) = composer
.preprocessor
.preprocess(raw_source, defs, composer.validate)
else {
return Default::default();
};

let Ok(source) = composer.substitute_shader_string(&source, &imports) else {
return Default::default();
};

Cow::Owned(source)
}
ErrSource::Constructing { source, .. } => Cow::Borrowed(source),
Expand All @@ -77,6 +70,8 @@ pub struct ComposerError {

#[derive(Debug, Error)]
pub enum ComposerErrorInner {
#[error("{0}")]
ImportParseError(String, usize),
#[error("required import '{0}' not found")]
ImportNotFound(String, usize),
#[error("{0}")]
Expand Down Expand Up @@ -215,6 +210,10 @@ impl ComposerError {
vec![Label::primary((), *pos..*pos)],
vec![format!("missing import '{msg}'")],
),
ComposerErrorInner::ImportParseError(msg, pos) => (
vec![Label::primary((), *pos..*pos)],
vec![format!("invalid import spec: '{msg}'")],
),
ComposerErrorInner::WgslParseError(e) => (
e.labels()
.map(|(range, msg)| {
Expand Down
Loading