Skip to content

Commit

Permalink
[naga] Add some documentation for the uniformity analysis.
Browse files Browse the repository at this point in the history
This is Naga's classic, over-conservative, non-standard-compliant
uniformity analysis. But it's still good to know what the heck it's
doing.
  • Loading branch information
jimblandy authored and teoxoy committed Mar 28, 2024
1 parent b34219c commit c613fbb
Showing 1 changed file with 58 additions and 11 deletions.
69 changes: 58 additions & 11 deletions naga/src/valid/analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,35 @@ pub struct SamplingKey {
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
/// Information about an expression in a function body.
pub struct ExpressionInfo {
/// Whether this expression is uniform, and why.
///
/// If this expression's value is not uniform, this is the handle
/// of the expression from which this one's non-uniformity
/// originates. Otherwise, this is `None`.
pub uniformity: Uniformity,

/// The number of statements and other expressions using this
/// expression's value.
pub ref_count: usize,

/// The global variable into which this expression produces a pointer.
///
/// This is `None` unless this expression is either a
/// [`GlobalVariable`], or an [`Access`] or [`AccessIndex`] that
/// ultimately refers to some part of a global.
///
/// [`Load`] expressions applied to pointer-typed arguments could
/// refer to globals, but we leave this as `None` for them.
///
/// [`GlobalVariable`]: crate::Expression::GlobalVariable
/// [`Access`]: crate::Expression::Access
/// [`AccessIndex`]: crate::Expression::AccessIndex
/// [`Load`]: crate::Expression::Load
assignable_global: Option<Handle<crate::GlobalVariable>>,

/// The type of this expression.
pub ty: TypeResolution,
}

Expand Down Expand Up @@ -311,14 +336,20 @@ pub enum UniformityDisruptor {
}

impl FunctionInfo {
/// Adds a value-type reference to an expression.
/// Record a use of `expr` of the sort given by `global_use`.
///
/// Bump `expr`'s reference count, and return its uniformity.
///
/// If `expr` is a pointer to a global variable, or some part of
/// a global variable, add `global_use` to that global's set of
/// uses.
#[must_use]
fn add_ref_impl(
&mut self,
handle: Handle<crate::Expression>,
expr: Handle<crate::Expression>,
global_use: GlobalUse,
) -> NonUniformResult {
let info = &mut self.expressions[handle.index()];
let info = &mut self.expressions[expr.index()];
info.ref_count += 1;
// mark the used global as read
if let Some(global) = info.assignable_global {
Expand All @@ -327,22 +358,38 @@ impl FunctionInfo {
info.uniformity.non_uniform_result
}

/// Adds a value-type reference to an expression.
/// Record a use of `expr` for its value.
///
/// This is used for almost all expression references. Anything
/// that writes to the value `expr` points to, or otherwise wants
/// contribute flags other than `GlobalUse::READ`, should use
/// `add_ref_impl` directly.
#[must_use]
fn add_ref(&mut self, handle: Handle<crate::Expression>) -> NonUniformResult {
self.add_ref_impl(handle, GlobalUse::READ)
fn add_ref(&mut self, expr: Handle<crate::Expression>) -> NonUniformResult {
self.add_ref_impl(expr, GlobalUse::READ)
}

/// Adds a potentially assignable reference to an expression.
/// These are destinations for `Store` and `ImageStore` statements,
/// which can transit through `Access` and `AccessIndex`.
/// Record a use of `expr`, and indicate which global variable it
/// refers to, if any.
///
/// Bump `expr`'s reference count, and return its uniformity.
///
/// If `expr` is a pointer to a global variable, or some part
/// thereof, store that global in `*assignable_global`. Leave the
/// global's uses unchanged.
///
/// This is used to determine the [`assignable_global`] for
/// [`Access`] and [`AccessIndex`] expressions that ultimately
/// refer to a global variable. Those expressions don't contribute
/// any usage to the global themselves; that depends on how other
/// expressions use them.
#[must_use]
fn add_assignable_ref(
&mut self,
handle: Handle<crate::Expression>,
expr: Handle<crate::Expression>,
assignable_global: &mut Option<Handle<crate::GlobalVariable>>,
) -> NonUniformResult {
let info = &mut self.expressions[handle.index()];
let info = &mut self.expressions[expr.index()];
info.ref_count += 1;
// propagate the assignable global up the chain, till it either hits
// a value-type expression, or the assignment statement.
Expand Down

0 comments on commit c613fbb

Please sign in to comment.