spirv_std/arch/derivative.rs
1use crate::float::Float;
2
3#[cfg(target_arch = "spirv")]
4macro_rules! deriv_fn {
5 ($p:ident, $inst:ident) => {
6 unsafe {
7 let mut o = Default::default();
8 ::core::arch::asm!(
9 "%input = OpLoad _ {0}",
10 concat!("%result = ", stringify!($inst), " _ %input"),
11 "OpStore {1} %result",
12 in(reg) &$p,
13 in(reg) &mut o,
14 );
15 o
16 }
17 };
18}
19
20/// Returns the partial derivative of `component` with respect to the window's X
21/// coordinate. Returns the same result as either [`ddx_fine`] or
22/// [`ddx_coarse`], selection of which one is dependent on external factors.
23#[crate::macros::vectorized]
24#[crate::macros::gpu_only]
25pub fn ddx<F: Float>(component: F) -> F {
26 deriv_fn!(component, OpDPdx)
27}
28
29/// Returns the partial derivative of `component` with respect to the window's X
30/// coordinate. Uses local differencing based on the value of `component` for
31/// the current fragment and its immediate neighbor(s).
32#[crate::macros::vectorized]
33#[crate::macros::gpu_only]
34pub fn ddx_fine<F: Float>(component: F) -> F {
35 deriv_fn!(component, OpDPdxFine)
36}
37
38/// Returns the partial derivative of `component` with respect to the window's X
39/// coordinate. Uses local differencing based on the value of `component` for
40/// the current fragment’s neighbors, and possibly, but not necessarily,
41/// includes the value of `component` for the current fragment. That is, over a
42/// given area, the implementation can compute X derivatives in fewer unique
43/// locations than would be allowed by [`ddx_fine`].
44#[crate::macros::vectorized]
45#[crate::macros::gpu_only]
46pub fn ddx_coarse<F: Float>(component: F) -> F {
47 deriv_fn!(component, OpDPdxCoarse)
48}
49
50/// Returns the partial derivative of `component` with respect to the window's Y
51/// coordinate. Returns the same result as either [`ddy_fine`] or
52/// [`ddy_coarse`], selection of which one is dependent on external factors.
53#[crate::macros::vectorized]
54#[crate::macros::gpu_only]
55pub fn ddy<F: Float>(component: F) -> F {
56 deriv_fn!(component, OpDPdy)
57}
58
59/// Returns the partial derivative of `component` with respect to the window's Y
60/// coordinate. Uses local differencing based on the value of `component` for
61/// the current fragment and its immediate neighbor(s).
62#[crate::macros::vectorized]
63#[crate::macros::gpu_only]
64pub fn ddy_fine<F: Float>(component: F) -> F {
65 deriv_fn!(component, OpDPdyFine)
66}
67
68/// Returns the partial derivative of `component` with respect to the window's Y
69/// coordinate. Uses local differencing based on the value of `component` for
70/// the current fragment’s neighbors, and possibly, but not necessarily,
71/// includes the value of `component` for the current fragment. That is, over a
72/// given area, the implementation can compute Y derivatives in fewer unique
73/// locations than would be allowed by [`ddy_fine`].
74#[crate::macros::vectorized]
75#[crate::macros::gpu_only]
76pub fn ddy_coarse<F: Float>(component: F) -> F {
77 deriv_fn!(component, OpDPdyCoarse)
78}
79
80/// Returns the sum of the absolute values of [`ddx`] and [`ddy`] as a single
81/// operation.
82#[crate::macros::vectorized]
83#[crate::macros::gpu_only]
84pub fn fwidth<F: Float>(component: F) -> F {
85 deriv_fn!(component, OpFwidth)
86}
87
88/// Returns the sum of the absolute values of [`ddx_fine`] and [`ddy_fine`] as a
89/// single operation.
90#[crate::macros::vectorized]
91#[crate::macros::gpu_only]
92pub fn fwidth_fine<F: Float>(component: F) -> F {
93 deriv_fn!(component, OpFwidthFine)
94}
95
96/// Returns the sum of the absolute values of [`ddx_coarse`] and [`ddy_coarse`]
97/// as a single operation.
98#[crate::macros::vectorized]
99#[crate::macros::gpu_only]
100pub fn fwidth_coarse<F: Float>(component: F) -> F {
101 deriv_fn!(component, OpFwidthCoarse)
102}