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

Document a bit more of the API #89

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and probably less useful externally:
the compose module allows construction of shaders from modules (which are themselves shaders).

it does this by treating shaders as modules, and
- preprocessing each module
- building each module independently to naga IR
- creating "header" files for each supported language, which are used to build dependent modules/shaders
- making final shaders by combining the shader IR with the IR for imported modules
Expand Down Expand Up @@ -155,7 +156,7 @@ the `#if` directive requires a def name, an operator, and a value for comparison
- the operator must be one of `==`, `!=`, `>=`, `>`, `<`, `<=`
- the value must be an integer literal if comparing to a `ShaderDefValue::Int` or `ShaderDefValue::Uint`, or `true` or `false` if comparing to a `ShaderDef::Bool`.

shader defs can also be used in the shader source with `#SHADER_DEF` or `#{SHADER_DEF}`, and will be substituted for their value.
shader defs can be used in the shader source with `#SHADER_DEF` or `#{SHADER_DEF}`, and will be substituted for their value. unlike `#define` in C, the shader defs will not aggressively replace all instances of the def name in the shader source. one has to explicitly refer to the def name in the source with the `#{SHADER_DEF}` directive.

the preprocessor branching directives (`ifdef`, `ifndef` and `if`) can be prefixed with `#else` to create more complex control flows:

Expand All @@ -176,6 +177,7 @@ shader defs can be created or overridden at the start of the top-level shader wi
#define USER_NUMBER 42
```
the created value will default to `true` if not specified.
unlike `#define` in C, the value of the def is evaluated once at the very start of shader compilation, and acts as a global constant for the rest of the compilation.

## error reporting

Expand Down
31 changes: 31 additions & 0 deletions src/compose/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ impl ShaderDefValue {
#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
pub struct OwnedShaderDefs(BTreeMap<String, ShaderDefValue>);

/// Modules are compiled differently based on the shader def values provided.
/// So a single source code can actually correspond to multiple modules.
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
struct ModuleKey(OwnedShaderDefs);

Expand Down Expand Up @@ -298,15 +300,26 @@ impl ComposableModuleDefinition {
}
}

/// #import foo::bar::{a, b, c} would be represented as
/// ```no_run
/// ImportDefinition {
/// import: "foo::bar",
/// items: vec!["a", "b", "c"]
/// }
/// ```
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct ImportDefinition {
/// Module name
pub import: String,
/// All the items that were imported from the module
pub items: Vec<String>,
}

#[derive(Debug, Clone)]
pub struct ImportDefWithOffset {
/// Module and items imported
definition: ImportDefinition,
/// Where in the source the import was declared
offset: usize,
}

Expand All @@ -316,6 +329,8 @@ pub struct ImportDefWithOffset {
#[derive(Debug)]
pub struct Composer {
pub validate: bool,
/// All modules, where each module can actually correspond to multiple modules that are built with different shader defs
/// We're caching them across multiple calls to `make_naga_module`
pub module_sets: HashMap<String, ComposableModuleDefinition>,
pub module_index: HashMap<usize, String>,
pub capabilities: naga::valid::Capabilities,
Expand Down Expand Up @@ -1354,20 +1369,34 @@ impl Composer {

#[derive(Default)]
pub struct ComposableModuleDescriptor<'a> {
/// Source code of the module
pub source: &'a str,
/// File path of the module, useful for error reporting
pub file_path: &'a str,
/// WGSL or GLSL
pub language: ShaderLanguage,
/// Overriding/setting the name for this module. Useful for modules that either
/// - do not specify #define_import_path
/// - have an inconvenient name
pub as_name: Option<String>,
/// Extra imports that are implicitly added.
pub additional_imports: &'a [ImportDefinition],
/// extra shader def values bound to this module
pub shader_defs: HashMap<String, ShaderDefValue>,
}

#[derive(Default)]
pub struct NagaModuleDescriptor<'a> {
/// Source of main module
pub source: &'a str,
/// File path of main module, useful for error reporting
pub file_path: &'a str,
/// Shader language, but split into separate stages (vertex/fragment)
pub shader_type: ShaderType,
/// #define values. Specified at the last moment to allow for runtime values.
/// Apply to all modules.
pub shader_defs: HashMap<String, ShaderDefValue>,
/// Extra imports that are implicitly added.
pub additional_imports: &'a [ImportDefinition],
}

Expand Down Expand Up @@ -1563,6 +1592,7 @@ impl Composer {

let sanitized_source = self.sanitize_and_set_auto_bindings(source);

// Get all possible imports
let PreprocessorMetaData {
name,
defines,
Expand Down Expand Up @@ -1638,6 +1668,7 @@ impl Composer {
modules: Default::default(),
};

// Get the concrete imports, given the shader defs
let PreprocessOutput {
preprocessed_source,
imports,
Expand Down
4 changes: 4 additions & 0 deletions src/compose/preprocess.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,13 @@ impl Default for Preprocessor {

#[derive(Debug)]
pub struct PreprocessorMetaData {
/// Name of the module (#define_import_path)
pub name: Option<String>,
/// The imports that were actually used (analyzes the source code during preprocesisng)
pub imports: Vec<ImportDefWithOffset>,
/// #define values in the module
pub defines: HashMap<String, ShaderDefValue>,
/// Defines that are referenced in the module. Either with #{name} or a variation of #ifdef name
pub effective_defs: HashSet<String>,
}

Expand Down
Loading