1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use crate::float::Float;

#[cfg(target_arch = "spirv")]
macro_rules! deriv_fn {
    ($p:ident, $inst:ident) => {
        unsafe {
            let mut o = Default::default();
            ::core::arch::asm!(
                "%input = OpLoad _ {0}",
                concat!("%result = ", stringify!($inst), " _ %input"),
                "OpStore {1} %result",
                in(reg) &$p,
                in(reg) &mut o,
            );
            o
        }
    };
}

/// Returns the partial derivative of `component` with respect to the window's X
/// coordinate. Returns the same result as either [`ddx_fine`] or
/// [`ddx_coarse`], selection of which one is dependent on external factors.
#[crate::macros::vectorized]
#[crate::macros::gpu_only]
pub fn ddx<F: Float>(component: F) -> F {
    deriv_fn!(component, OpDPdx)
}

/// Returns the partial derivative of `component` with respect to the window's X
/// coordinate. Uses local differencing based on the value of `component` for
/// the current fragment and its immediate neighbor(s).
#[crate::macros::vectorized]
#[crate::macros::gpu_only]
pub fn ddx_fine<F: Float>(component: F) -> F {
    deriv_fn!(component, OpDPdxFine)
}

/// Returns the partial derivative of `component` with respect to the window's X
/// coordinate. Uses local differencing based on the value of `component` for
/// the current fragment’s neighbors, and possibly, but not necessarily,
/// includes the value of `component` for the current fragment. That is, over a
/// given area, the implementation can compute X derivatives in fewer unique
/// locations than would be allowed by [`ddx_fine`].
#[crate::macros::vectorized]
#[crate::macros::gpu_only]
pub fn ddx_coarse<F: Float>(component: F) -> F {
    deriv_fn!(component, OpDPdxCoarse)
}

/// Returns the partial derivative of `component` with respect to the window's Y
/// coordinate. Returns the same result as either [`ddy_fine`] or
/// [`ddy_coarse`], selection of which one is dependent on external factors.
#[crate::macros::vectorized]
#[crate::macros::gpu_only]
pub fn ddy<F: Float>(component: F) -> F {
    deriv_fn!(component, OpDPdy)
}

/// Returns the partial derivative of `component` with respect to the window's Y
/// coordinate. Uses local differencing based on the value of `component` for
/// the current fragment and its immediate neighbor(s).
#[crate::macros::vectorized]
#[crate::macros::gpu_only]
pub fn ddy_fine<F: Float>(component: F) -> F {
    deriv_fn!(component, OpDPdyFine)
}

/// Returns the partial derivative of `component` with respect to the window's Y
/// coordinate. Uses local differencing based on the value of `component` for
/// the current fragment’s neighbors, and possibly, but not necessarily,
/// includes the value of `component` for the current fragment. That is, over a
/// given area, the implementation can compute Y derivatives in fewer unique
/// locations than would be allowed by [`ddy_fine`].
#[crate::macros::vectorized]
#[crate::macros::gpu_only]
pub fn ddy_coarse<F: Float>(component: F) -> F {
    deriv_fn!(component, OpDPdyCoarse)
}

/// Returns the sum of the absolute values of [`ddx`] and [`ddy`] as a single
/// operation.
#[crate::macros::vectorized]
#[crate::macros::gpu_only]
pub fn fwidth<F: Float>(component: F) -> F {
    deriv_fn!(component, OpFwidth)
}

/// Returns the sum of the absolute values of [`ddx_fine`] and [`ddy_fine`] as a
/// single operation.
#[crate::macros::vectorized]
#[crate::macros::gpu_only]
pub fn fwidth_fine<F: Float>(component: F) -> F {
    deriv_fn!(component, OpFwidthFine)
}

/// Returns the sum of the absolute values of [`ddx_coarse`] and [`ddy_coarse`]
/// as a single operation.
#[crate::macros::vectorized]
#[crate::macros::gpu_only]
pub fn fwidth_coarse<F: Float>(component: F) -> F {
    deriv_fn!(component, OpFwidthCoarse)
}