Explanation of dFdx
Asked Answered
D

1

73

I am trying to understand the dFdx() and dFdy() functions in GLSL.

I understand the following:

  1. The derivative is the rate of change
  2. The partial derivative of a function with two parameters is when you differentiate the function while keeping one of the parameters constant.
  3. dFdx() and dFdy() find the rate that a value changes between the current fragment and a neighboring fragment.

I don't understand what the rate of change is referring to. Is it the rate of change of fragment coordinates?

Could it possibly be that you can find the rate of change of an arbitrary variable between two invocations of the fragment shader? Are the shader invocations "reading" variables from neighboring invocations? For a (simplistic) example:

// invocation for fragment 1
float x = 1.0;
float d = dFdx(x);

// invocation for fragment next to fragment 1 along the x axis.
float x = 2.0;
float d = dFdx(x);

Would d be -1.0 and 1.0 respectively?

Dineric answered 3/5, 2013 at 18:28 Comment(1)
There's a good discussion of it here.Globefish
S
154

To understand how these instructions work, it helps to understand the basic execution architecture of GPUs and how fragment programs map to that architecture.

GPUs run a bunch of threads in 'lock-step' over the same program, which each thread having its own set of registers. So it fetches an instruction, then executes that instruction N times, once for each running thread. To deal with conditional branches and such, they also have an 'active mask' for the currently running group of threads. Threads that are not active in the mask don't actually run (so their registers don't change). Whenever there is a conditional branch or join (branch target) the thread mask is changed appropriately.

Now when a fragment program is run, the fragments to be run are arranged into "quads" -- 2x2 squares of 4 pixels that always run together in a thread group. Each thread in the group knows its own pixel coordinate, and can easily find the coordinate of the adjacent pixel in the quad by flipping the lowest bit of the x (or y) coord.

When the GPU executes a DDX or DDY instruction, what happens is that it peeks at the registers for the thread for the adjacent pixel and does a subtract with the value from the current pixel -- subtracting the value for the higher coordinate (lowest bit 1) from the lower (lowest bit 0).

This has implications if you use dFdx or dFdy in a conditional branch -- if one of the threads in a quad is active while the other is not, the GPU will still look at the register of the inactive thread, which might have any old value in it, so the result could be anything.

Suctorial answered 3/5, 2013 at 23:5 Comment(4)
Trying to read up on this a lot and I will also join and thank you @ChrisDodd. This was incredibly helpful and insightful.Gaulin
Your explanation is excellent- where can I find the documentation describing this behavior?Graph
Thanks for this. Doesn't the quad mechanism imply that each horizontal pair of pixels will have a single value for dFdx ? i guess i could just test that. answer: yes. shadertoy.com/view/llGyzyLoudish
i've found that on some devices such as my iPhone 6, the "quads" seem to be "pairs" - ie, they're 2x1 instead of 2x2. does anyone know how to determine these values definitively inside a shader ? i've looked for a constant but haven't found one.Loudish

© 2022 - 2024 — McMap. All rights reserved.