mrbill and folker have been doing a sterling job of trying to explain the workings of dpdx and its family .
As the original author of the Shading Language White paper I must apologise if the explanation of this ‘function’ was not to Nakoruru’s satisfaction and we will add some language to clarify things.
Derivatives can be derived in two ways - analytically or numerically. In the analytic case you need an expression while in the numerical case you just need to be able to find the value of the ‘thing’ you want to differentiate local to the point of interest.
Analytic differentiation is clearly not workable as any of the elements of the expression may not be differentiable - a lookup table (bump mapping, for example) would fall into this category.
For numeric differentiation if you make the assumption that the fragments are being evaluated on a SIMD array and you have access to your neighbour’s values then the magic of the dPdx call is to ask their x neighbour’s for their value of the ‘thing’ and subtract yours from it. The dx value is one, by definition, so the result is simple to provide.
At the evaluation of dPdx the ‘thing’ is just a number so how it was derived is immaterial. The function does accept an expression (as all functions do for their input arguments) and the expression is evaluated to a value. The expression can be anything, even the framebuffer colour value, and the only uncertainty arises if the expression is evaluated as part of a conditional (because the neighbour’s values may not be defined).
Should it be a function or operator? There are a limited number of suitable characters in the 7 bit ASCII set and as soon as you start to reuse to ones defined by C the expressions can end up looking very confusing. Using a named function makes the operation more readable and allows the user to redefine it if they want to - operator overloading is not a supported language feature so if done through an operator user couldn’t redefine the meaning.
We make a point in the white paper of saying that the built in functions are provided for convenience and to access hardware specific features. The convenience functions can easily be emulated by the user but the hardware ones may be impossible or just very difficult.
dPdx is in the impossible category to do a general solution, but it is possible to do a specific solution if you know what the analytic solution is or you can manually calculate the local differences. For you to calculate the local differences you will have to know the complete expression tree, maybe starting 5 subroutine levels back for example, so you can substitute x+1 into it. The expression tree may also use data you don’t have access to, such as the framebuffer colour value of your neighbour.