mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
123 lines
4.4 KiB
Rust
123 lines
4.4 KiB
Rust
//! Functions which export shader modules into binary and text formats.
|
|
|
|
#[cfg(feature = "dot-out")]
|
|
pub mod dot;
|
|
#[cfg(feature = "glsl-out")]
|
|
pub mod glsl;
|
|
#[cfg(feature = "hlsl-out")]
|
|
pub mod hlsl;
|
|
#[cfg(feature = "msl-out")]
|
|
pub mod msl;
|
|
#[cfg(feature = "spv-out")]
|
|
pub mod spv;
|
|
#[cfg(feature = "wgsl-out")]
|
|
pub mod wgsl;
|
|
|
|
/// How should code generated by Naga do indexing bounds checks?
|
|
///
|
|
/// When a vector, matrix, or array index is out of bounds—either negative, or
|
|
/// greater than or equal to the number of elements in the type—WGSL requires
|
|
/// that some other index of the implementation's choice that is in bounds is
|
|
/// used instead. (There are no types with zero elements.)
|
|
///
|
|
/// Different users of Naga will prefer different defaults:
|
|
///
|
|
/// - When used as part of a WebGPU implementation, the WGSL specification
|
|
/// requires the `Restrict` behavior.
|
|
///
|
|
/// - When used by the `wgpu` crate for native development, `wgpu` selects
|
|
/// `ReadZeroSkipWrite` as its default.
|
|
///
|
|
/// - Naga's own default is `UndefinedBehavior`, so that shader translations
|
|
/// are as faithful to the original as possible.
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub enum IndexBoundsCheckPolicy {
|
|
/// Replace out-of-bounds indexes with some arbitrary in-bounds index.
|
|
///
|
|
/// (This does not necessarily mean clamping. For example, interpreting the
|
|
/// index as unsigned and taking the minimum with the largest valid index
|
|
/// would also be a valid implementation. That would map negative indices to
|
|
/// the last element, not the first.)
|
|
Restrict,
|
|
|
|
/// Out-of-bounds reads return zero, and writes have no effect.
|
|
ReadZeroSkipWrite,
|
|
|
|
/// Out-of-bounds indexes are undefined behavior. Generate the fastest code
|
|
/// possible. This is the default for Naga, as a translator, but consumers
|
|
/// should consider defaulting to a safer behavior.
|
|
UndefinedBehavior,
|
|
}
|
|
|
|
/// The default `IndexBoundsCheckPolicy` is `UndefinedBehavior`.
|
|
impl Default for IndexBoundsCheckPolicy {
|
|
fn default() -> Self {
|
|
IndexBoundsCheckPolicy::UndefinedBehavior
|
|
}
|
|
}
|
|
|
|
impl crate::Expression {
|
|
/// Returns the ref count, upon reaching which this expression
|
|
/// should be considered for baking.
|
|
///
|
|
/// Note: we have to cache any expressions that depend on the control flow,
|
|
/// or otherwise they may be moved into a non-uniform contol flow, accidentally.
|
|
#[allow(dead_code)]
|
|
fn bake_ref_count(&self) -> usize {
|
|
match *self {
|
|
// accesses are never cached, only loads are
|
|
crate::Expression::Access { .. } | crate::Expression::AccessIndex { .. } => !0,
|
|
// sampling may use the control flow, and image ops look better by themselves
|
|
crate::Expression::ImageSample { .. } | crate::Expression::ImageLoad { .. } => 1,
|
|
// derivatives use the control flow
|
|
crate::Expression::Derivative { .. } => 1,
|
|
// TODO: We need a better fix for named `Load` expressions
|
|
// More info - https://github.com/gfx-rs/naga/pull/914
|
|
// And https://github.com/gfx-rs/naga/issues/910
|
|
crate::Expression::Load { .. } => 1,
|
|
// cache expressions that are referenced multiple times
|
|
_ => 2,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Helper function that returns the string corresponding to the [`BinaryOperator`](crate::BinaryOperator)
|
|
/// # Notes
|
|
/// Used by `glsl-out`, `msl-out`, `wgsl-out`, `hlsl-out`.
|
|
#[allow(dead_code)]
|
|
fn binary_operation_str(op: crate::BinaryOperator) -> &'static str {
|
|
use crate::BinaryOperator as Bo;
|
|
match op {
|
|
Bo::Add => "+",
|
|
Bo::Subtract => "-",
|
|
Bo::Multiply => "*",
|
|
Bo::Divide => "/",
|
|
Bo::Modulo => "%",
|
|
Bo::Equal => "==",
|
|
Bo::NotEqual => "!=",
|
|
Bo::Less => "<",
|
|
Bo::LessEqual => "<=",
|
|
Bo::Greater => ">",
|
|
Bo::GreaterEqual => ">=",
|
|
Bo::And => "&",
|
|
Bo::ExclusiveOr => "^",
|
|
Bo::InclusiveOr => "|",
|
|
Bo::LogicalAnd => "&&",
|
|
Bo::LogicalOr => "||",
|
|
Bo::ShiftLeft => "<<",
|
|
Bo::ShiftRight => ">>",
|
|
}
|
|
}
|
|
|
|
/// Helper function that returns the string corresponding to the [`VectorSize`](crate::VectorSize)
|
|
/// # Notes
|
|
/// Used by `msl-out`, `wgsl-out`, `hlsl-out`.
|
|
#[allow(dead_code)]
|
|
fn vector_size_str(size: crate::VectorSize) -> &'static str {
|
|
match size {
|
|
crate::VectorSize::Bi => "2",
|
|
crate::VectorSize::Tri => "3",
|
|
crate::VectorSize::Quad => "4",
|
|
}
|
|
}
|