Skip to content

Commit

Permalink
Add partial derivative builtins
Browse files Browse the repository at this point in the history
Revert derive_hash_xor_eq clippy suggestion
  • Loading branch information
evahop committed Mar 15, 2023
1 parent 7f829c6 commit 6867a2c
Show file tree
Hide file tree
Showing 20 changed files with 342 additions and 102 deletions.
38 changes: 29 additions & 9 deletions src/back/glsl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ impl Version {
fn supports_integer_functions(&self) -> bool {
*self >= Version::Desktop(400) || *self >= Version::new_gles(310)
}

fn supports_derivative_control(&self) -> bool {
*self >= Version::Desktop(450)
}
}

impl PartialOrd for Version {
Expand Down Expand Up @@ -2829,17 +2833,33 @@ impl<'a, W: Write> Writer<'a, W> {
}
// `Derivative` is a function call to a glsl provided function
Expression::Derivative { axis, expr } => {
use crate::DerivativeAxis as Da;

write!(
self.out,
"{}(",
use crate::{DerivativeAxis as Axis, DerivativeControl as Ctrl};
let fun_name = if self.options.version.supports_derivative_control() {
match axis {
Axis::X(ctrl) => match ctrl {
Ctrl::Coarse => "dFdxCoarse",
Ctrl::Fine => "dFdxFine",
_ => "dFdx",
},
Axis::Y(ctrl) => match ctrl {
Ctrl::Coarse => "dFdyCoarse",
Ctrl::Fine => "dFdyFine",
_ => "dFdy",
},
Axis::Width(ctrl) => match ctrl {
Ctrl::Coarse => "fwidthCoarse",
Ctrl::Fine => "fwidthFine",
_ => "fwidth",
},
}
} else {
match axis {
Da::X => "dFdx",
Da::Y => "dFdy",
Da::Width => "fwidth",
Axis::X(_) => "dFdx",
Axis::Y(_) => "dFdy",
_ => "fwidth",
}
)?;
};
write!(self.out, "{fun_name}(")?;
self.write_expr(expr, ctx)?;
write!(self.out, ")")?
}
Expand Down
17 changes: 12 additions & 5 deletions src/back/hlsl/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2802,12 +2802,19 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
write!(self.out, "({var_name}) - {offset}) / {stride})")?
}
Expression::Derivative { axis, expr } => {
use crate::DerivativeAxis as Da;

use crate::{DerivativeAxis as Axis, DerivativeControl as Ctrl};
let fun_str = match axis {
Da::X => "ddx",
Da::Y => "ddy",
Da::Width => "fwidth",
Axis::X(ctrl) => match ctrl {
Ctrl::Coarse => "ddx_coarse",
Ctrl::Fine => "ddx_fine",
_ => "ddx",
},
Axis::Y(ctrl) => match ctrl {
Ctrl::Coarse => "ddy_coarse",
Ctrl::Fine => "ddy_fine",
_ => "ddy",
},
_ => "fwidth",
};
write!(self.out, "{fun_str}(")?;
self.write_expr(module, expr, func_ctx)?;
Expand Down
7 changes: 4 additions & 3 deletions src/back/msl/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1580,10 +1580,11 @@ impl<W: Write> Writer<W> {
_ => return Err(Error::Validation),
},
crate::Expression::Derivative { axis, expr } => {
use crate::DerivativeAxis as Axis;
let op = match axis {
crate::DerivativeAxis::X => "dfdx",
crate::DerivativeAxis::Y => "dfdy",
crate::DerivativeAxis::Width => "fwidth",
Axis::X(_) => "dfdx",
Axis::Y(_) => "dfdy",
_ => "fwidth",
};
write!(self.out, "{NAMESPACE}::{op}")?;
self.put_call_parameters(iter::once(expr), context)?;
Expand Down
32 changes: 27 additions & 5 deletions src/back/spv/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1335,14 +1335,36 @@ impl<'w> BlockContext<'w> {
id
}
crate::Expression::Derivative { axis, expr } => {
use crate::DerivativeAxis as Da;

use crate::{DerivativeAxis as Axis, DerivativeControl as Ctrl};
match axis {
Axis::X(ctrl) | Axis::Y(ctrl) | Axis::Width(ctrl) => match ctrl {
Ctrl::Coarse | Ctrl::Fine => {
self.writer.require_any(
"DerivativeControl",
&[spirv::Capability::DerivativeControl],
)?;
}
_ => {}
},
}
let id = self.gen_id();
let expr_id = self.cached[expr];
let op = match axis {
Da::X => spirv::Op::DPdx,
Da::Y => spirv::Op::DPdy,
Da::Width => spirv::Op::Fwidth,
Axis::X(ctrl) => match ctrl {
Ctrl::Coarse => spirv::Op::DPdxCoarse,
Ctrl::Fine => spirv::Op::DPdxFine,
_ => spirv::Op::DPdx,
},
Axis::Y(ctrl) => match ctrl {
Ctrl::Coarse => spirv::Op::DPdyCoarse,
Ctrl::Fine => spirv::Op::DPdyFine,
_ => spirv::Op::DPdy,
},
Axis::Width(ctrl) => match ctrl {
Ctrl::Coarse => spirv::Op::FwidthCoarse,
Ctrl::Fine => spirv::Op::FwidthFine,
_ => spirv::Op::Fwidth,
},
};
block
.body
Expand Down
21 changes: 16 additions & 5 deletions src/back/wgsl/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1658,12 +1658,23 @@ impl<W: Write> Writer<W> {
write!(self.out, ")")?
}
Expression::Derivative { axis, expr } => {
use crate::DerivativeAxis as Da;

use crate::{DerivativeAxis as Axis, DerivativeControl as Ctrl};
let op = match axis {
Da::X => "dpdx",
Da::Y => "dpdy",
Da::Width => "fwidth",
Axis::X(ctrl) => match ctrl {
Ctrl::Coarse => "dpdxCoarse",
Ctrl::Fine => "dpdxFine",
_ => "dpdx",
},
Axis::Y(ctrl) => match ctrl {
Ctrl::Coarse => "dpdyCoarse",
Ctrl::Fine => "dpdyFine",
_ => "dpdy",
},
Axis::Width(ctrl) => match ctrl {
Ctrl::Coarse => "fwidthCoarse",
Ctrl::Fine => "fwidthFine",
_ => "fwidth",
},
};
write!(self.out, "{op}(")?;
self.write_expr(module, expr, func_ctx)?;
Expand Down
27 changes: 14 additions & 13 deletions src/front/glsl/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ use super::{
Error, ErrorKind, Frontend, Result,
};
use crate::{
BinaryOperator, Block, Constant, DerivativeAxis, Expression, Handle, ImageClass,
ImageDimension as Dim, ImageQuery, MathFunction, Module, RelationalFunction, SampleLevel,
ScalarKind as Sk, Span, Type, TypeInner, UnaryOperator, VectorSize,
BinaryOperator, Block, Constant, DerivativeAxis as Axis, DerivativeControl as Ctrl, Expression,
Handle, ImageClass, ImageDimension as Dim, ImageQuery, MathFunction, Module,
RelationalFunction, SampleLevel, ScalarKind as Sk, Span, Type, TypeInner, UnaryOperator,
VectorSize,
};

impl crate::ScalarKind {
Expand Down Expand Up @@ -571,15 +572,15 @@ fn inject_standard_builtins(
"degrees" => MacroCall::MathFunction(MathFunction::Degrees),
"floatBitsToInt" => MacroCall::BitCast(Sk::Sint),
"floatBitsToUint" => MacroCall::BitCast(Sk::Uint),
"dFdx" | "dFdxFine" | "dFdxCoarse" => {
MacroCall::Derivate(DerivativeAxis::X)
}
"dFdy" | "dFdyFine" | "dFdyCoarse" => {
MacroCall::Derivate(DerivativeAxis::Y)
}
"fwidth" | "fwidthFine" | "fwidthCoarse" => {
MacroCall::Derivate(DerivativeAxis::Width)
}
"dFdxCoarse" => MacroCall::Derivate(Axis::X(Ctrl::Coarse)),
"dFdyCoarse" => MacroCall::Derivate(Axis::Y(Ctrl::Coarse)),
"fwidthCoarse" => MacroCall::Derivate(Axis::Width(Ctrl::Coarse)),
"dFdxFine" => MacroCall::Derivate(Axis::X(Ctrl::Fine)),
"dFdyFine" => MacroCall::Derivate(Axis::Y(Ctrl::Fine)),
"fwidthFine" => MacroCall::Derivate(Axis::Width(Ctrl::Fine)),
"dFdx" => MacroCall::Derivate(Axis::X(Ctrl::None)),
"dFdy" => MacroCall::Derivate(Axis::Y(Ctrl::None)),
"fwidth" => MacroCall::Derivate(Axis::Width(Ctrl::None)),
_ => unreachable!(),
},
))
Expand Down Expand Up @@ -1661,7 +1662,7 @@ pub enum MacroCall {
MixBoolean,
Clamp(Option<VectorSize>),
BitCast(Sk),
Derivate(DerivativeAxis),
Derivate(Axis),
Barrier,
/// SmoothStep needs a separate variant because it might need it's inputs
/// to be splatted depending on the overload
Expand Down
3 changes: 0 additions & 3 deletions src/front/glsl/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,6 @@ impl Frontend {
Expression::Compose {
ty: vector_ty,
components: (0..rows as u32)
.into_iter()
.map(|r| match r == i {
true => value,
false => zero,
Expand Down Expand Up @@ -376,7 +375,6 @@ impl Frontend {
components.push(match ori_rows.cmp(&rows) {
Ordering::Less => {
let components = (0..rows as u32)
.into_iter()
.map(|r| {
if r < ori_rows as u32 {
ctx.add_expression(
Expand Down Expand Up @@ -415,7 +413,6 @@ impl Frontend {
inner: ConstantInner::Composite {
ty: vector_ty,
components: (0..rows as u32)
.into_iter()
.map(|r| match r == i {
true => one_constant,
false => zero_constant,
Expand Down
57 changes: 51 additions & 6 deletions src/front/spv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3337,14 +3337,59 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
});
body_idx = loop_body_idx;
}
Op::DPdx | Op::DPdxFine | Op::DPdxCoarse => {
parse_expr_op!(crate::DerivativeAxis::X, DERIVATIVE)?;
Op::DPdxCoarse => {
parse_expr_op!(
crate::DerivativeAxis::X(crate::DerivativeControl::Coarse),
DERIVATIVE
)?;
}
Op::DPdyCoarse => {
parse_expr_op!(
crate::DerivativeAxis::Y(crate::DerivativeControl::Coarse),
DERIVATIVE
)?;
}
Op::FwidthCoarse => {
parse_expr_op!(
crate::DerivativeAxis::Width(crate::DerivativeControl::Coarse),
DERIVATIVE
)?;
}
Op::DPdxFine => {
parse_expr_op!(
crate::DerivativeAxis::X(crate::DerivativeControl::Fine),
DERIVATIVE
)?;
}
Op::DPdy | Op::DPdyFine | Op::DPdyCoarse => {
parse_expr_op!(crate::DerivativeAxis::Y, DERIVATIVE)?;
Op::DPdyFine => {
parse_expr_op!(
crate::DerivativeAxis::Y(crate::DerivativeControl::Fine),
DERIVATIVE
)?;
}
Op::Fwidth | Op::FwidthFine | Op::FwidthCoarse => {
parse_expr_op!(crate::DerivativeAxis::Width, DERIVATIVE)?;
Op::FwidthFine => {
parse_expr_op!(
crate::DerivativeAxis::Width(crate::DerivativeControl::Fine),
DERIVATIVE
)?;
}
Op::DPdx => {
parse_expr_op!(
crate::DerivativeAxis::X(crate::DerivativeControl::None),
DERIVATIVE
)?;
}
Op::DPdy => {
parse_expr_op!(
crate::DerivativeAxis::Y(crate::DerivativeControl::None),
DERIVATIVE
)?;
}
Op::Fwidth => {
parse_expr_op!(
crate::DerivativeAxis::Width(crate::DerivativeControl::None),
DERIVATIVE
)?;
}
Op::ArrayLength => {
inst.expect(5)?;
Expand Down
13 changes: 10 additions & 3 deletions src/front/wgsl/parse/conv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,17 @@ pub fn get_scalar_type(word: &str) -> Option<(crate::ScalarKind, crate::Bytes)>
}

pub fn map_derivative_axis(word: &str) -> Option<crate::DerivativeAxis> {
use crate::{DerivativeAxis as Axis, DerivativeControl as Ctrl};
match word {
"dpdx" => Some(crate::DerivativeAxis::X),
"dpdy" => Some(crate::DerivativeAxis::Y),
"fwidth" => Some(crate::DerivativeAxis::Width),
"dpdxCoarse" => Some(Axis::X(Ctrl::Coarse)),
"dpdyCoarse" => Some(Axis::Y(Ctrl::Coarse)),
"fwidthCoarse" => Some(Axis::Width(Ctrl::Coarse)),
"dpdxFine" => Some(Axis::X(Ctrl::Fine)),
"dpdyFine" => Some(Axis::Y(Ctrl::Fine)),
"fwidthFine" => Some(Axis::Width(Ctrl::Fine)),
"dpdx" => Some(Axis::X(Ctrl::None)),
"dpdy" => Some(Axis::Y(Ctrl::None)),
"fwidth" => Some(Axis::Width(Ctrl::None)),
_ => None,
}
}
Expand Down
17 changes: 14 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -976,15 +976,26 @@ pub enum AtomicFunction {
Exchange { compare: Option<Handle<Expression>> },
}

/// Hint at which precision to compute a derivative.
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
pub enum DerivativeControl {
Coarse,
Fine,
None,
}

/// Axis on which to compute a derivative.
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
pub enum DerivativeAxis {
X,
Y,
Width,
X(DerivativeControl),
Y(DerivativeControl),
Width(DerivativeControl),
}

/// Built-in shader function for testing relation between values.
Expand Down
2 changes: 1 addition & 1 deletion src/proc/typifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ impl<'a> ResolveContext<'a> {
},
crate::Expression::AtomicResult { ty, .. } => TypeResolution::Handle(ty),
crate::Expression::Select { accept, .. } => past(accept)?.clone(),
crate::Expression::Derivative { axis: _, expr } => past(expr)?.clone(),
crate::Expression::Derivative { expr, .. } => past(expr)?.clone(),
crate::Expression::Relational { fun, argument } => match fun {
crate::RelationalFunction::All | crate::RelationalFunction::Any => {
TypeResolution::Value(Ti::Scalar {
Expand Down
2 changes: 1 addition & 1 deletion src/valid/analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1014,7 +1014,7 @@ fn uniform_control_flow() {
// checks the non-uniform control flow
let derivative_expr = expressions.append(
E::Derivative {
axis: crate::DerivativeAxis::X,
axis: crate::DerivativeAxis::X(crate::DerivativeControl::None),
expr: constant_expr,
},
Default::default(),
Expand Down
2 changes: 1 addition & 1 deletion src/valid/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,7 @@ impl super::Validator {
}
ShaderStages::all()
}
E::Derivative { axis: _, expr } => {
E::Derivative { expr, .. } => {
match resolver[expr] {
Ti::Scalar {
kind: Sk::Float, ..
Expand Down
5 changes: 1 addition & 4 deletions src/valid/handles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,10 +345,7 @@ impl super::Validator {
.check_dep(accept)?
.check_dep(reject)?;
}
crate::Expression::Derivative {
axis: _,
expr: argument,
} => {
crate::Expression::Derivative { expr: argument, .. } => {
handle.check_dep(argument)?;
}
crate::Expression::Relational { fun: _, argument } => {
Expand Down
Loading

0 comments on commit 6867a2c

Please sign in to comment.