dPdx and dPdy from OpenGL 2.0 spec

Both of these fragment shader functions (dPdx§ and dPdy§) are defined in the spec as derivative in x and y (respectively) using local differencing for the input argument p.

My question is: What is p?

Having just the functions dx() and dy() makes sense to me. What good is passing in some variable p? It can’t mean ‘with respect to p’ because p ultimately just a constant, and the derivative of a constant is 0.

Originally posted by Nakoruru:
[b]Both of these fragment shader functions (dPdx(p) and dPdy(p)) are defined in the spec as derivative in x and y (respectively) using local differencing for the input argument p.

My question is: What is p?
B]

It’s an expression, and you’re right, if the expression is uniform, it’s derivative will be zero.

But more commonly, (and more usefully) the expression will have a varying component to it. The simplest expression is a direct interpolated value coming into the fragment unit from the rasterizer. This can be used to estimate filter widths for anti-aliasing procedural textures. (There’s even a built in function fwidth that is based on dpDx and dpDy.)

In the OpenGL 2.0 Shading Language Whitepaper, look at the anti-aliased checkerboard and anti-aliased simple brick shader examples for common usage.

-mr. bill

Well, the argument may be an expression, but expressions are evaluated before they are passed to functions. The argument is not an expression, its a genType, which is a float or, vecX

If you pass an expression, it will be resolved to a single value and then passed (unless there is more going on, but this is explained as being a function, not a special contruct that evaluates your expression. And wouldn’t that be a bit complicated for a fragment shader?).

At first I thought that p might be an enumeration, and that you could perhaps pass ‘MultiTexCoord0’ or ‘Color’ and get the dx and dy. But that is not what appears to be going on.

It seems to be far from clear and I would love someone who knows for sure to explain what is going on.

Sounds a bit like the Renderman Shading Language derivative functions. P in renderman sl is typically used to refer to a 3d geometric point. You’d use those functions to find the derivative of a particular variable (or of u or v as surface params) at a particular point on a surface. But I dunno if it’s the same for the openGL sl… pure speculation.

Combining what you said about uniform vs varying with the comment in the language specification (dunno if there is more detail in the whitepaper) I get the feeling that my confusion stems from the fact that this is not so much a function, as a special operator. It simply did not make any sense to take the derivative of a scalar or vector value.

I guess that the that this ‘function’ takes needs to be ‘passed’ the label (name) of a varying variable (ugh, that sounds redundant ^_^)

It ‘returns’ the rasterizers current dx or dy for the register its stored in.

Does this sound right? If this is true then they have totally failed to properly explain what is going on. If not then what is going on?

I originally ask ‘what is p’. If I pass in 2.3 what will I get? If I pass TexCoord0 + Color * BackColor what do I get? Are these valid? The spec says they are but doesn’t explain what I get. Placing a varying variable name will resolve to a scalar or vecX as well (like 2.3) unless this function is somehow special. It seems like you would need a unary operator like & in C++ in order to refer to some other aspect of the variable other than its value.

Maybe this just needs to be called an operator instead of a function.

I’m going to stop giving you all rope to hang me with now…

Originally posted by Nakoruru:
I get the feeling that my confusion stems from the fact that this is not so much a function, as a special operator. It simply did not make any sense to take the derivative of a scalar or vector value.

Not so much a function as a special fragment only function. Does that help? You can think of dPdx as a special function that is not a derivative of a single scalar or vector, but rather the delta(s) between the scalar or vector and one of its neighbors dx away.

The Renderman Companion and Advanced Renderman talk about this a bit. A couple of good published details about implementations of dPdx and dPdy can be found with “BMRT: A Global Illumination Implementation of the RenderMan Standard” [Gritz, Hahn] and “Implementing RenderMan - Practice, Problems and Enhancements” [Slusallek, Pflaum, Seidel].

-mr. bill

I assume the following:

If I pass in 2.3 what will I get?

Zero.

If I pass TexCoord0 + Color * BackColor what do I get?

Using usual derivation rules:

dPdx(TexCoord0 + Color * BackColor)
= dPdx(TexCoord0) + dPdx(Color) * BackColor + Color * dPdx(BackColor)

The meaning of dPdx(TexCoord0) is clear, it is TexCoord0 derived by the x coordinate. If Color is the vertex color passed from the vertex shader, then the meaning of dPdx(Color) is also clear in the same way. What is Backcolor?

Looking at the glslangspecv1.0.pdf specification, it includes the following note about the dPdx etc. functions:

These two functions are commonly used to estimate the
filter width used to anti-alias procedural textures.We
are assuming that the expression is being evaluated in
parallel on a SIMD array so that at any given point in
time the value of the function is known at the grid
points represented by the SIMD array. Local
differencing between SIMD array elements can
therefore be used to derive dPdx, dPdy, etc.

Conceptually (mathematically), a fragment shader does not operatate on normal values
(scalars, vectors etc.), but they operate on functions depending on x and y, and the fragment shader value value is evaluated only at end by fixing x and y for each fragment. Note that most values you work with in fragment shaders are calculated by interpolating vertex values, so they naturally are functions of x and y.
(What about frame buffer values? Probably dPdx is undefined for frame buffer values.)

Instead of this abstract picture, you may simply consider dPdx(p) as normal functions but wich have access to the values of p at neighboring pixels as simplified explanation.

First, I understand what the function returns and how it works. I guess now I am just complaining that its not property classified in the spec.

It can’t be thought of as a function because it cannot be implemented by any facility in the language unlike all the other functions. This is because it takes as the type of its argument a register and not a value (unless you can explain to me what dPdx(3.14) means). It returns something associated with that register, in this case the dx or dy of the interpolators.

This makes it more closely related to the & operator in C++ (which returns the address associated with a lable instead of its value). Of course, the & operator could be written as get_addr(myvar), but that would not make it any less an operator.

It would fail on get_addr(3.14) just like I suspect that dPdx(3.14) will fail. I just saying that the spec says it takes a genTyp, while I really think it takes is an lvalue with a storage type of varying.

Since there is no way to express dPdx in the language because of its specialness, you would not even be able to write a proper replacement for it, so it should also not be listed as a function you can override (just like you can’t override constructors which are also not functions).

At least, that is how I understand it. I am pretty much just stating what I believe until someone from 3dLabs clears things up. I just noticed that they have a new Bulletin board, maybe this would be a good thing to post.

Originally posted by Nakoruru:
[b]First, I understand what the function returns and how it works. I guess now I am just complaining that its not property classified in the spec.

It can’t be thought of as a function because it cannot be implemented by any facility in the language unlike all the other functions. This is because it takes as the type of its argument a register and not a value (unless you can explain to me what dPdx(3.14) means). It returns something associated with that register, in this case the dx or dy of the interpolators.

This makes it more closely related to the & operator in C++ (which returns the address associated with a lable instead of its value). Of course, the & operator could be written as get_addr(myvar), but that would not make it any less an operator.

It would fail on get_addr(3.14) just like I suspect that dPdx(3.14) will fail. I just saying that the spec says it takes a genTyp, while I really think it takes is an lvalue with a storage type of varying.

Since there is no way to express dPdx in the language because of its specialness, you would not even be able to write a proper replacement for it, so it should also not be listed as a function you can override (just like you can’t override constructors which are also not functions).

At least, that is how I understand it. I am pretty much just stating what I believe until someone from 3dLabs clears things up. I just noticed that they have a new Bulletin board, maybe this would be a good thing to post.

[/b]

In a simplified picture, a program is executed for each fragment, operating on values. But strictly speaking this is not true. In fact, the shader languages operates on functions. Thus, dPdx are also functions in the same way as all other functions, they are no special operators. So everything makes sense and is well-defined (except some exceptions, e.g. dPdx applied to a frame buffer value).

Especially note that dPdx etc. can be expressed in the language itself. They don’t play a special role. Of course, they are build-in functions and cannot be implemented as user-defined functions, but this holds for most build-in functions.

BTW, my background is physics, there it is exactly the same: A electromagnetic field vector is not a simple value, but a function of each point in space. For most operations like addition, you can consider a vector as single value in space without problems. But special operations like gradient only make sense if you know that the vector in fact is a function. But everything is always well-defined.

Some additional notes:

Originally posted by Nakoruru:
It would fail on get_addr(3.14) just like I suspect that dPdx(3.14) will fail.

It may fail for a particular compiler. But the correct implementation simply would give zero.

I just saying that the spec says it takes a genTyp, while I really think it takes is an lvalue with a storage type of varying.

I disagree. You can pass everything. The spec is correct. Expressions depending on the frame buffer values may be a valid expression, but the actual value may be undefined. But any r-value expression depending on varying variables, constants etc. are no problem at all and well-defined.

Since there is no way to express dPdx in the language because of its specialness, you would not even be able to write a proper replacement for it, so it should also not be listed as a function you can override (just like you can’t override constructors which are also not functions).

You can express these functions in the language. You can override it, you can also write a user-defined and user-implemented wrapper function for it, whatevey you want.

Of course, not every compiler might support it. But conceptually this is all no problem.

I do not think you understand exactly how programming languages work, or you would have caught yourself (or at least looked at the spec for SL).

To do what you describe, dPdx would have to take an EXPRESSION as its argument (which is not what the spec says). Being a function it takes a VALUE, that is what the spec says.

To show you what I mean, what do you think happens when I write this in C:

sqrt(2+2);

Does the function sqrt get some representation of the expression ‘2+2’ or does it get the evaluated expression ‘4’

You should now see my problem. dPdx cannot take the derivative of an expression it never sees. If it was like you said it would be very special indeed, because the grammar of SL would have to contain some mechanism for passing an expression to a function, and then taking the derivative of it. But it doesn’t, so what you propose cannot happen. I cannot just pass in an arbitraury expression, because that expression will get evaluated, and the value will get passed to the dPdx.

But, dPdx cannot do what it says it does with a value, it has to know the register it came from so it can figure out what that registers iterator delta is.

If it did what you said would definitely not be a function, but a special grammatical contruct. I do not think that is true at all.

Everyone should understand that I know what dPdx does, I am just arguing that its not explained adequately and that it is different enough from the other functions that it should be put in a different class altogether.

Originally posted by Nakoruru:
[b]I do not think you understand exactly how programming languages work, or you would have caught yourself (or at least looked at the spec for SL).

To do what you describe, dPdx would have to take an EXPRESSION as its argument (which is not what the spec says). Being a function it takes a VALUE, that is what the spec says.

To show you what I mean, what do you think happens when I write this in C:

sqrt(2+2);

Does the function sqrt get some representation of the expression ‘2+2’ or does it get the evaluated expression ‘4’

You should now see my problem. dPdx cannot take the derivative of an expression it never sees. If it was like you said it would be very special indeed, because the grammar of SL would have to contain some mechanism for passing an expression to a function, and then taking the derivative of it. But it doesn’t, so what you propose cannot happen. I cannot just pass in an arbitraury expression, because that expression will get evaluated, and the value will get passed to the dPdx.

But, dPdx cannot do what it says it does with a value, it has to know the register it came from so it can figure out what that registers iterator delta is.

If it did what you said would definitely not be a function, but a special grammatical contruct. I do not think that is true at all.

Everyone should understand that I know what dPdx does, I am just arguing that its not explained adequately and that it is different enough from the other functions that it should be put in a different class altogether.[/b]

It is like in function theory (e.g. gradient, divergence etc.) in mathematics and physics:

sqrt(4) is exactly the same as sqrt(2+2),
because 2+2 is evaluated to 4 before sqrt is called. The point is, in case of the shader language, the basic elements are not numbers, but functions all the time.
This means, dPdx(a + b) also means
that a and b are first added, and then dPdx is called for the result. But a and b are functions of x and y, so the functions are added, and the resulting function is passed to dPdx. Also note that constants like 3.14 are only special cases of functions, namely functions which give the same value 3.14 for all x and y.

So dPdx takes an value as argument,
but the value is not only a number, but a function of x and y. dPdx does not take the derivation of an expression but of an value(of course, how the compiler works is a different issue).

It is the same as in linear algebra, for example:
grad(3.13) = 0
grad(x) = x / length(x)
grad(x * x) = 2 * x
Also in grad(x * x), the gradient never
sees the operation "", but only the resulting function = value f(x) = xx .

If you are used to fields in physics, you are also familiar with such kind of formalism. :wink:

I agree, the specs are too compact and don’t explain all that. It may be easier to simply say that dPdx are special functions. But it is not necessary to treat dPdx as special functions if you know the underlaying formalism.

For example, it is perfectly valid and well-defined to define

float myFunction(float a)
{
return dPdx(a * a);
}

float myOtherFunction()
{
return myFunction(gl_MultiTexCoord0);
}

Also here, a is a value which implicitely is a function of x and y (as every quantity in the fragment program).

That you want to apply dPdx to general expressions can be very useful in practise.

Show me where in the grammar of the SL that dPdx takes an expression.

You must realize that I am speaking in terms of actual language productions. So when I say ‘expression’ and ‘lvalue’ I mean the literal definitions of them in the spec, not vague general notions, so you cannot say that the function takes a function as a value because that is not what the spec says. The spec says its a function like any other, and that means that the expression in the parenthesis has been lost before it gets to the part of the compiler that handles function calls. Its no longer a function, but a bit of code that puts the right value into a place that the function call expects it to me. If it was otherwise, it would be in the BNF of the language, because what you are saying requires a different bit of grammer, but its not, so you are absolutely wrong about this.

What you say sounds good, and it may even be possible, but its not that the language does, not by a long shot.

I will look in the grammar, just to make sure, but I guarantee you it isn’t there.

Originally posted by Nakoruru:
[b]I do not think you understand exactly how programming languages work, or you would have caught yourself (or at least looked at the spec for SL).

To do what you describe, dPdx would have to take an EXPRESSION as its argument (which is not what the spec says). Being a function it takes a VALUE, that is what the spec says.[/b]

Actually, the spec says that arguments to functions are passed by reference.

But especially look at page 37 of “The OpenGL Shading Language V1.0, 12-June-2002” [Baldwin, Rost, Kessenich]

See http://www.3dlabs.com/support/developer/ogl2/specs/glslangspecv1.0.pdf

There are functions in the shader langauge that can not be emulated by the user. Textures are one. dPdx, dPdy are others.

Again, take a close look at “The Renderman Companion.” [Upstill] My copy is worn and yellowed. On page 314.

"A word about magic

Some of the functions above might some problematic to implement. Just how, for example, do Du() and Dv() know the derivative of, not just varying variables, but expressions as well?

The existence of these functions is a benefit of SPECIAL-PURPOSE [emphasis mine] programming language design.

These kind of functions work well enough that it is not worth discussing their internals. However, there are small but significant inherent dangers associated with some of the functions to follow. These pitfalls will be highlighted as they arise."

So, bar=dPdx(3.14) IS zero. Not might be zero. IS zero. bar=dPdx(texcoord0) is absolutely defined. So too is your example bar=dPdx(TexCoord0 + Color * BackColor); or even foo=TexCoord0 + Color * BackColor; bar=dPdx(foo);

But there ARE cases where dPdx might be undefined. Here’s one from “Advanced Renderman” [Apodaca, Gritz] (Thank you for printing it on acid free paper!)

“In addition, using varying variables in the condition of a loop or conditional is asking for trouble, because this can… produce incorrect results if derivatives are calculated in the body of the loop or conditional…”

So let the magic happen. The shading language is a SPECIAL-PURPOSE programming language. Perhaps we have to make it absolutely clear when it might deviate from false expectations.

But, you could also be right. If you could point to specific passage in the spec that you believe is in error, and propose alternate language that you believe is correct, then please do.

-mr. bill

Originally posted by Nakoruru:
Show me where in the grammar of the SL that dPdx takes an expression.

dPdx takes a VALUE, not an expression. But this value is a function of x and y, as every value in a shader program.

[b]
You must realize that I am speaking in terms of actual language productions. So when I say ‘expression’ and ‘lvalue’ I mean the literal definitions of them in the spec, not vague general notions, so you cannot say that the function takes a function as a value because that is not what the spec. The spec says its a function like any other, and that means that the expression in the parenthesis has been lost before it gets to the part of the compiler that handles function calls. Its no longer a function, but a bit of code that puts the right value into a place that the function call expects it to me. If it was otherwise, it would be in the BNF of the language, because what you are saying requires a different bit of grammer, but its not, so you are absolutely wrong about this.

What you say sounds good, and it may even be possible, but its not that the language does, not by a long shot.[/b]

I meant something different: The argument of dPdx is not only a function meaning an expression. I mean that EVERY value in every shader program strictly speaking is a function of x and y. Really EVERY value, also all arguments of user defined functions etc. etc. etc. In the same way as fields in physics are always functions of the location, even if you never write it explicitely.

For example, note that in

float myFunction(float a)
{
return dPdx(a * a);
}

float myOtherFunction()
{
return myFunction(gl_MultiTexCoord0);
}

the function myFunction is a user-defined function. Every value, including a, is depending on x and y. And the above myOtherFunction is equivalent to

float myOtherFunction()
{
return dPdx(gl_MultiTexCoord0 * gl_MultiTexCoord0);
}

Agreed, the above formalism is not explicitely mentioned in the specs. But on the other hand, this formalism is standard in mathematics (and phyics). Especially, it is standard to work with functions in the same way as with numbers and vectors. So “value” may be everything, and a value may depend on x and y, and so a value may be a function.

And the spec also does NOT say that values are NOT depending on x and y (functions on x and y). In contrary, it is obvious that all (most) values depend on x and y, so there is no problem as considering all values always as functions of x and y.

I am absolutely sure that everything is perfectly well-defined, both formally and the meaning.

Originally posted by mrbill:
But, you could also be right. If you could point to specific passage in the spec that you believe is in error, and propose alternate language that you believe is correct, then please do.

Suggestion:
Mention somewhere in the specs that all values in fragment programs are depending on x and y (including varying variables, expressions using varying variables, function results etc. etc), and so all values can be considered as functions of x and y.

Quoting how renderman works? sigh

I almost give up.

First of all, who cares if things are passed by reference or by value? Its ultimately a single object of a single type (a float or a vecX) and there is NO FACILITY IN THE SL for passing in expressions. If there was, that just proves my point that dPdx is a special grammarical feature of the language that needs to be further explained.

What can and cannot be passed to dPdx needs to be explained further.

I am almost completely sure that it does not take the derivative of expressions, if it is, then the spec (the SL spec, NOT RENDERMAN) is completely silent on this and it needs to not be explained (magic or not),

I believe that it simply reads a delta from the iterators associated with the lvalue (assignable expression) you pass it. meaning its limited to lvalues, not arbitruary expressions.

For instances, how would it get the symantic information nessecary to property resolve dPdx(sin(x))? I mean, how does it know that I have not redefined sin to be something completely different?

It doesn’t seem right to me to say that everything in the fragment shader is a function of x and y. What if I create a variable float foo, and then take dPdx(foo)? foo is not a function of x and y, its just something I created and can have any value at all with no relationship at all to x or y

I think that dPdx is only a way to get at the internal iterator values. Its a good point that texture also cannot be implemented by the language as well, so that is a good argument that you can also call dPdx a function, but it needs more explaining. That is all I wanted, not a long speculation that goes of into fantasy land about how the hardware is going to take derivatives for me.

I’m getting angry, so I’m going to give up here, and wait for someone to reply to my post over at 3Dlabs.

hum no one sais it takes expressions…
it takes values/references and does a numerical differenciation on it.

sort of

float dx(texcoords c,texture_id tex) {
return sample(c,tex) - sample(c+(1,0,0),tex);
}

that takes values, but treats them as a function…

i don’t really understand how these two funcs work, but its nothing magic. and they are simple functions you can code yourself in gl2.

Originally posted by Nakoruru:
For instances, how would it get the symantic information nessecary to property resolve dPdx(sin(x))? I mean, how does it know that I have not redefined sin to be something completely different?

In function formalism (e.g. in physics), you can define every normal function like sin, lg etc. also to functions in the obvious way by defining for example sin of a function f is defined as (sin(f))(x) := sin(f(x)). This is standard and used all the time, I was used to work in such way all the time.

Originally posted by Nakoruru:
It doesn’t seem right to me to say that everything in the fragment shader is a function of x and y. What if I create a variable float foo, and then take dPdx(foo)? foo is not a function of x and y, its just something I created and can have any value at all with no relationship at all to x or y

A value not depending on x and y is a special case of a function of x and y.

[b]

I think that dPdx is only a way to get at the internal iterator values. Its a good point that texture also cannot be implemented by the language as well, so that is a good argument that you can also call dPdx a function, but it needs more explaining. That is all I wanted, not a long speculation that goes of into fantasy land about how the hardware is going to take derivatives for me.
[/b]

An actual compiler implementation indeed may calculate the derivation by considering the expression and reducing it to dPdx(gl_MultiTexCoord0) etc… But I suppose most compilers (at least at the beginning) won’t support it.

I think there are two aspects:

a) What do we want?

Do we want that dPdx can be applied to any value? My suggestion: Yes. This is very important.

For example, suppose you write a user-defined helper function for distorting texture coordinates, maybe

vec2 myDistort(vec2 t)
{
return vec2(t.x + sin(t.x), t.y + cos(t.y));
}

Then suppose your main function uses such modified texture coordinates:

color = myDistort(texture2(0, glMultiTexCoord0))

Now if you want for example apply antialiasing to your texturing, you need to calculate dPdx from your modified texture coordinates, hence

dPdx(myDistort(texture2(0, glMultiTexCoord0)))

So I think it is very useful and very natural to calculate dPdx from arbitrary values, including results of user-defined functions. (Whether every compilers really supports this is a different iusse, but it would be very useful.)

The second question is:

b) Ok, we want it, but is it possible to define the meaning in an unique, well-defined way?
Answer: Yes. You “simply” realize that anyway all values depend on x and y, so formally everything depends on x and y.

But of course, if one knows how dPdx works, he does not necessarily have to know how exactly it is defined formally and have to go into details we are currently discussing about. But it may be good to know that it can be defined formally precise.

[b]

I’m getting angry, so I’m going to give up here, and wait for someone to reply to my post over at 3Dlabs.
[/b]

:wink:
Don’t take it too serious… :wink:

Originally posted by davepermen:
[b]hum no one sais it takes expressions…
it takes values/references and does a numerical differenciation on it.

sort of

float dx(texcoords c,texture_id tex) {
return sample(c,tex) - sample(c+(1,0,0),tex);
}

that takes values, but treats them as a function…

i don’t really understand how these two funcs work, but its nothing magic. and they are simple functions you can code yourself in gl2.[/b]

That’s not correct: You cannot code them by yourself since they calculate the gradient with respect to screen coordinates x and y. For example, how do you want to implement dPdx(gl_MultiTexCoord0) ? This is a build-in functionality. dPdx does not apply only to texture lookup, it also applies for example to texture coordinates itself.