/// Construct a float `Scalar` with the given width. /// /// This is especially common when dealing with /// `TypeInner::Matrix`, where the scalar kind is implicit. pubconstfn float(width: crate::Bytes) -> Self { Self {
kind: crate::ScalarKind::Float,
width,
}
}
/// Get the size of this type. pubfn size(&self, _gctx: GlobalCtx) -> u32 { match *self { Self::Scalar(scalar) | Self::Atomic(scalar) => scalar.width as u32, Self::Vector { size, scalar } => size as u32 * scalar.width as u32, // matrices are treated as arrays of aligned columns Self::Matrix {
columns,
rows,
scalar,
} => Alignment::from(rows) * scalar.width as u32 * columns as u32, Self::Pointer { .. } | Self::ValuePointer { .. } => POINTER_SPAN, Self::Array {
base: _,
size,
stride,
} => { let count = match size { super::ArraySize::Constant(count) => count.get(), // any struct member or array element needing a size at pipeline-creation time // must have a creation-fixed footprint super::ArraySize::Pending(_) => 0, // A dynamically-sized array has to have at least one element super::ArraySize::Dynamic => 1,
};
count * stride
} Self::Struct { span, .. } => span, Self::Image { .. }
| Self::Sampler { .. }
| Self::AccelerationStructure
| Self::RayQuery
| Self::BindingArray { .. } => 0,
}
}
/// Return the canonical form of `self`, or `None` if it's already in /// canonical form. /// /// Certain types have multiple representations in `TypeInner`. This /// function converts all forms of equivalent types to a single /// representative of their class, so that simply applying `Eq` to the /// result indicates whether the types are equivalent, as far as Naga IR is /// concerned. pubfn canonical_form(
&self,
types: &crate::UniqueArena<crate::Type>,
) -> Option<crate::TypeInner> { usecrate::TypeInner as Ti; match *self {
Ti::Pointer { base, space } => match types[base].inner {
Ti::Scalar(scalar) => Some(Ti::ValuePointer {
size: None,
scalar,
space,
}),
Ti::Vector { size, scalar } => Some(Ti::ValuePointer {
size: Some(size),
scalar,
space,
}),
_ => None,
},
_ => None,
}
}
/// Compare `self` and `rhs` as types. /// /// This is mostly the same as `<TypeInner as Eq>::eq`, but it treats /// `ValuePointer` and `Pointer` types as equivalent. /// /// When you know that one side of the comparison is never a pointer, it's /// fine to not bother with canonicalization, and just compare `TypeInner` /// values with `==`. pubfn equivalent(
&self,
rhs: &crate::TypeInner,
types: &crate::UniqueArena<crate::Type>,
) -> bool { let left = self.canonical_form(types); let right = rhs.canonical_form(types);
left.as_ref().unwrap_or(self) == right.as_ref().unwrap_or(rhs)
}
implcrate::Expression { /// Returns true if the expression is considered emitted at the start of a function. pubconstfn needs_pre_emit(&self) -> bool { match *self { Self::Literal(_)
| Self::Constant(_)
| Self::Override(_)
| Self::ZeroValue(_)
| Self::FunctionArgument(_)
| Self::GlobalVariable(_)
| Self::LocalVariable(_) => true,
_ => false,
}
}
/// Return true if this expression is a dynamic array/vector/matrix index, /// for [`Access`]. /// /// This method returns true if this expression is a dynamically computed /// index, and as such can only be used to index matrices when they appear /// behind a pointer. See the documentation for [`Access`] for details. /// /// Note, this does not check the _type_ of the given expression. It's up to /// the caller to establish that the `Access` expression is well-typed /// through other means, like [`ResolveContext`]. /// /// [`Access`]: crate::Expression::Access /// [`ResolveContext`]: crate::proc::ResolveContext pubconstfn is_dynamic_index(&self) -> bool { match *self { Self::Literal(_) | Self::ZeroValue(_) | Self::Constant(_) => false,
_ => true,
}
}
}
implcrate::Function { /// Return the global variable being accessed by the expression `pointer`. /// /// Assuming that `pointer` is a series of `Access` and `AccessIndex` /// expressions that ultimately access some part of a `GlobalVariable`, /// return a handle for that global. /// /// If the expression does not ultimately access a global variable, return /// `None`. pubfn originating_global(
&self, mut pointer: crate::Handle<crate::Expression>,
) -> Option<crate::Handle<crate::GlobalVariable>> { loop {
pointer = matchself.expressions[pointer] { crate::Expression::Access { base, .. } => base, crate::Expression::AccessIndex { base, .. } => base, crate::Expression::GlobalVariable(handle) => return Some(handle), crate::Expression::LocalVariable(_) => return None, crate::Expression::FunctionArgument(_) => return None, // There are no other expressions that produce pointer values.
_ => unreachable!(),
}
}
}
}
impl GlobalCtx<'_> { /// Try to evaluate the expression in `self.global_expressions` using its `handle` and return it as a `u32`. #[allow(dead_code)] pub(super) fn eval_expr_to_u32(
&self,
handle: crate::Handle<crate::Expression>,
) -> Result<u32, U32EvalError> { self.eval_expr_to_u32_from(handle, self.global_expressions)
}
/// Try to evaluate the expression in the `arena` using its `handle` and return it as a `u32`. pub(super) fn eval_expr_to_u32_from(
&self,
handle: crate::Handle<crate::Expression>,
arena: &crate::Arena<crate::Expression>,
) -> Result<u32, U32EvalError> { matchself.eval_expr_to_literal_from(handle, arena) {
Some(crate::Literal::U32(value)) => Ok(value),
Some(crate::Literal::I32(value)) => {
value.try_into().map_err(|_| U32EvalError::Negative)
}
_ => Err(U32EvalError::NonConst),
}
}
/// Try to evaluate the expression in the `arena` using its `handle` and return it as a `bool`. #[allow(dead_code)] pub(super) fn eval_expr_to_bool_from(
&self,
handle: crate::Handle<crate::Expression>,
arena: &crate::Arena<crate::Expression>,
) -> Option<bool> { matchself.eval_expr_to_literal_from(handle, arena) {
Some(crate::Literal::Bool(value)) => Some(value),
_ => None,
}
}
/// Return an iterator over the individual components assembled by a /// `Compose` expression. /// /// Given `ty` and `components` from an `Expression::Compose`, return an /// iterator over the components of the resulting value. /// /// Normally, this would just be an iterator over `components`. However, /// `Compose` expressions can concatenate vectors, in which case the i'th /// value being composed is not generally the i'th element of `components`. /// This function consults `ty` to decide if this concatenation is occurring, /// and returns an iterator that produces the components of the result of /// the `Compose` expression in either case. pubfn flatten_compose<'arenas>(
ty: crate::Handle<crate::Type>,
components: &'arenas [crate::Handle<crate::Expression>],
expressions: &'arenas crate::Arena<crate::Expression>,
types: &'arenas crate::UniqueArena<crate::Type>,
) -> impl Iterator<Item = crate::Handle<crate::Expression>> + 'arenas { // Returning `impl Iterator` is a bit tricky. We may or may not // want to flatten the components, but we have to settle on a // single concrete type to return. This function returns a single // iterator chain that handles both the flattening and // non-flattening cases. let (size, is_vector) = ifletcrate::TypeInner::Vector { size, .. } = types[ty].inner {
(size as usize, true)
} else {
(components.len(), false)
};
// Expressions like `vec4(vec3(vec2(6, 7), 8), 9)` require us to // flatten up to two levels of `Compose` expressions. // // Expressions like `vec4(vec3(1.0), 1.0)` require us to flatten // `Splat` expressions. Fortunately, the operand of a `Splat` must // be a scalar, so we can stop there.
components
.iter()
.flat_map(move |component| flatten_compose(component, is_vector, expressions))
.flat_map(move |component| flatten_compose(component, is_vector, expressions))
.flat_map(move |component| flatten_splat(component, is_vector, expressions))
.take(size)
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.