Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

How to compute the derivative of the fragment...

Discussion in 'Shaders' started by bloomingdedalus, Feb 15, 2015.

  1. bloomingdedalus

    bloomingdedalus

    Joined:
    Aug 13, 2012
    Posts:
    139
    What data in the fragment shader can I access that would allow me to know these values? The problem I'm having is that I'm sampling multiple UV maps per pass with different UV coordinates which is throwing off the internal way the derivatives are calculated. Is there a way to compute these derivatives for just the main set of UV coordinates and sample with the same derivatives in each other sample in the fragment pass?

    Without accessing the previous pixel's UV value, I really have no clue how I'm supposed to compute a derivative of anything...

    float4 tex2D(sampler2D samp, float2 s, float2 dx, float2 dy)
     
  2. bloomingdedalus

    bloomingdedalus

    Joined:
    Aug 13, 2012
    Posts:
    139
    Nevermind, I finally understood how ddx() and ddy() work... I was confused how passing them scaler quantities would give me derivatives of anything...
     
  3. JohKr

    JohKr

    Joined:
    Jun 9, 2023
    Posts:
    5
    Care to share your wisdom? I also wonder how it calculates derivatives with scalars.
     
  4. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,495
    Groups of pixels are rendered in lockstep in what are commonly referred to as "warps" or "wavefronts" of usually 32 or 16 pixels depending on hardware. So when the hardware gets to that instruction for those group of pixels, the value being fed into the ddx/ddy functions is now guaranteed computed for all of them, so a comparison to X/Y neighbor pixels in that warp can be done and then further instructions can use the result.

    Which side it samples the neighbor from will also change depending on hardware and if the pixel is on the edge of the group or not, in which case it will flip to sample the side that has a neighbor instead; this happens at a very low level. So the derivative functions are never getting information from outside their local cluster (warp) of pixels and shader throughput can remain fairly high since not every pixel of the shader kernel rendering on screen has to be in lockstep, only the ones in a given warp.

    This is also why if you have dynamic conditionals in your shader, if even 1 pixel in the warp ends up taking the longer conditional path, then the whole warp will run that path (but of course won't utilize the result downstream), slowing down the rendering of 32 pixels, not 1.
     
    Last edited: Aug 19, 2023
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,217
    Minor correction. All pixels within a warp / wavefront are not run in lockstep. Pixel quads, each 2x2 square of pixels, within a wave/warp are. It's within each of those pixel quads that the derivatives are calculated. Each pixel quad within a warp may be run in parallel, but depending on the hardware may not be in perfect lockstep. However code execution across all threads (pixels) within a wave/warp is shared, so anywhere the code paths between threads diverge the threads not using the same code path are masked.
     
    Invertex likes this.