6

From the OpenGL documentation:

dFdxFine and dFdyFine calculate derivatives using local differencing based on on the value of p for the current fragment and its immediate neighbor(s).

dFdxCoarse and dFdyCoarse calculate derivatives using local differencing based on the value of p for the current fragment's neighbors, and will possibly, but not necessarily, include the value for the current fragment. That is, over a given area, the implementation can compute derivatives in fewer unique locations than would be allowed for the corresponding dFdxFine and dFdyFine functions.

Which is the difference between them? When should I care?

I understand that both calculates the derivative of the value respect the window coordinates, but I don't understand the method used to computed them.

I guess that they are both implemented in hardware, but could you post a dFdx pseudo-code implementation?

dv1729
  • 987
  • 1
  • 8
  • 25

1 Answers1

12

From the GLSL spec:

It is typical to consider a 2x2 square of fragments or samples, and compute independent dFdxFine per row and independent dFdyFine per column, while computing only a single dFdxCoarse and a single dFdyCoarse for the entire 2x2 square.

Basically the way the derivatives are computed is by numeric differentiation. For the sake of simplicity assume we are rendering into a single-sampled framebuffer, and assume we want to compute dFdx(a). Then typically a 2x2 square of neighboring fragments will be shaded simultaneously (i.e. within the same workgroup):

    a00  a10
    a01  a11

Conceptually all shader invocations will compute their value a, write it to the shared memory, and issue a barrier. Then after the barrier the derivatives can be approximated by:

dFdxFine(a) = (a10 - a00)/dx       at xy = 00, 10
dFdxFine(a) = (a11 - a01)/dx       at xy = 01, 11

For the coarse derivatives the specification explicitly permits to compute only one derivative for the whole 2x2 block of pixels. So a conforming implementation could just as well compute:

dFdxCoarse(a) = (a10 - a00)/dx     at xy = 00, 10, 01, 11

Whether there is a difference in performance between the two depends on the hardware. If they do return different results on your hardware though, then the 'coarse' version should be faster. Usually you should not care about these functions however. Simply use the dFdx and dFdy variants, which use the implementation default variant (either fine or coarse).

Yakov Galka
  • 70,775
  • 16
  • 139
  • 220
  • 1
    I would suggest using `Fine` unless there is a genuine performance issue, then switch to `Coarse` as a micro-optimization. – Nicol Bolas Sep 19 '16 at 21:38
  • That makes sense, but... After reading the GLSL spec i found this: "Thus, all second-order coarse derivatives, e.g., dFdxCoarse(dFdxCoarse(x)), may be 0, even for non-linear arguments. However, second-order fine derivatives, e.g., dFdxFine(dFdxFine(x)) will properly reflect the difference between the independent fine derivatives computed within the 2x2 square." However, in your example dFdxFine(dFdxFine(x)) is always 0, right? – dv1729 Sep 19 '16 at 23:07
  • 2
    @dv1729: "*dFdxFine(dFdxFine(x))*" You misread the specification. The inner function is dFd***y***Fine. – Nicol Bolas Sep 19 '16 at 23:19
  • 2
    Oh, You're right, there was a typo in the extension spec (https://www.opengl.org/registry/specs/ARB/derivative_control.txt). It is fixed on the GLSL lang 4.5 spec (https://www.opengl.org/registry/doc/GLSLangSpec.4.50.diff.pdf). Thanks! – dv1729 Sep 19 '16 at 23:28