Skip to content

Commit

Permalink
[naga] Teach the constant evaluator vector/vector operators.
Browse files Browse the repository at this point in the history
Allow constant evaluation of binary operators whose left and right
operands are both vectors.
  • Loading branch information
jimblandy committed Dec 11, 2023
1 parent d2a64e4 commit 101c0ae
Show file tree
Hide file tree
Showing 7 changed files with 448 additions and 359 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ This feature allowed you to call `global_id` on any wgpu opaque handle to get a

#### Naga

- Naga's WGSL front and back ends now have experimental support for 64-bit floating-point literals: `1.0lf` denotes an `f64` value. There has been experimental support for an `f64` type for a while, but until now there was no syntax for writing literals with that type. As before, Naga module validation rejects `f64` values unless `naga::valid::Capabilities::FLOAT64` is requested. By @jimblandy in [#4747](https://github.com/gfx-rs/wgpu/pull/4747).
- Naga'sn WGSL front and back ends now have experimental support for 64-bit floating-point literals: `1.0lf` denotes an `f64` value. There has been experimental support for an `f64` type for a while, but until now there was no syntax for writing literals with that type. As before, Naga module validation rejects `f64` values unless `naga::valid::Capabilities::FLOAT64` is requested. By @jimblandy in [#4747](https://github.com/gfx-rs/wgpu/pull/4747).
- Naga constant evaluation can now process binary operators whose operands are both vectors. By @jimblandy in [#4861](https://github.com/gfx-rs/wgpu/pull/4861).

### Changes

Expand Down
95 changes: 95 additions & 0 deletions naga/src/proc/constant_evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1361,12 +1361,107 @@ impl<'a> ConstantEvaluator<'a> {
}
Expression::Compose { ty, components }
}
(
&Expression::Compose {
components: ref left_components,
ty: left_ty,
},
&Expression::Compose {
components: ref right_components,
ty: right_ty,
},
) => {
// We have to make a copy of the component lists, because the
// call to `binary_op_vector` needs `&mut self`, but `self` owns
// the component lists.
let left_flattened = crate::proc::flatten_compose(
left_ty,
left_components,
self.expressions,
self.types,
);
let right_flattened = crate::proc::flatten_compose(
right_ty,
right_components,
self.expressions,
self.types,
);

// `flatten_compose` doesn't return an `ExactSizeIterator`, so
// make a reasonable guess of the capacity we'll need.
let mut flattened = Vec::with_capacity(left_components.len());
flattened.extend(left_flattened.zip(right_flattened));

match (&self.types[left_ty].inner, &self.types[right_ty].inner) {
(
&TypeInner::Vector {
size: left_size, ..
},
&TypeInner::Vector {
size: right_size, ..
},
) if left_size == right_size => {
self.binary_op_vector(op, left_size, &flattened, left_ty, span)?
}
_ => return Err(ConstantEvaluatorError::InvalidBinaryOpArgs),
}
}
_ => return Err(ConstantEvaluatorError::InvalidBinaryOpArgs),
};

self.register_evaluated_expr(expr, span)
}

fn binary_op_vector(
&mut self,
op: BinaryOperator,
size: crate::VectorSize,
components: &[(Handle<Expression>, Handle<Expression>)],
left_ty: Handle<Type>,
span: Span,
) -> Result<Expression, ConstantEvaluatorError> {
let ty = match op {
// Relational operators produce vectors of booleans.
BinaryOperator::Equal
| BinaryOperator::NotEqual
| BinaryOperator::Less
| BinaryOperator::LessEqual
| BinaryOperator::Greater
| BinaryOperator::GreaterEqual => self.types.insert(
Type {
name: None,
inner: TypeInner::Vector {
size,
scalar: crate::Scalar::BOOL,
},
},
span,
),

// Other operators produce the same type as their left
// operand.
BinaryOperator::Add
| BinaryOperator::Subtract
| BinaryOperator::Multiply
| BinaryOperator::Divide
| BinaryOperator::Modulo
| BinaryOperator::And
| BinaryOperator::ExclusiveOr
| BinaryOperator::InclusiveOr
| BinaryOperator::LogicalAnd
| BinaryOperator::LogicalOr
| BinaryOperator::ShiftLeft
| BinaryOperator::ShiftRight => left_ty,
};

let components = components
.iter()
.map(|&(left, right)| self.binary_op(op, left, right, span))
.collect::<Result<Vec<_>, _>>()?;

Ok(Expression::Compose { ty, components })
}

/// Deep copy `expr` from `expressions` into `self.expressions`.
///
/// Return the root of the new copy.
Expand Down
4 changes: 2 additions & 2 deletions naga/tests/out/glsl/operators.main.Compute.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ vec4 builtins() {
}

vec4 splat() {
vec2 a_2 = (((vec2(2.0) + vec2(3.0)) - vec2(4.0)) / vec2(8.0));
ivec4 b = (ivec4(5) % ivec4(2));
vec2 a_2 = vec2(0.125, 0.125);
ivec4 b = ivec4(1, 1, 1, 1);
return (a_2.xyxy + vec4(b));
}

Expand Down
4 changes: 2 additions & 2 deletions naga/tests/out/hlsl/operators.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ float4 builtins()

float4 splat()
{
float2 a_2 = ((((2.0).xx + (3.0).xx) - (4.0).xx) / (8.0).xx);
int4 b = ((5).xxxx % (2).xxxx);
float2 a_2 = float2(0.125, 0.125);
int4 b = int4(1, 1, 1, 1);
return (a_2.xyxy + float4(b));
}

Expand Down
4 changes: 2 additions & 2 deletions naga/tests/out/msl/operators.msl
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ metal::float4 builtins(

metal::float4 splat(
) {
metal::float2 a_2 = ((metal::float2(2.0) + metal::float2(3.0)) - metal::float2(4.0)) / metal::float2(8.0);
metal::int4 b = metal::int4(5) % metal::int4(2);
metal::float2 a_2 = metal::float2(0.125, 0.125);
metal::int4 b = metal::int4(1, 1, 1, 1);
return a_2.xyxy + static_cast<metal::float4>(b);
}

Expand Down
Loading

0 comments on commit 101c0ae

Please sign in to comment.