[DX10] HLSL: gradient based operation error

Started by
4 comments, last by n3Xus 14 years, 11 months ago
Hello, I'm writing a pixel shader for lighting, and if the light distance attentuation is zero I want to skip all the calculation and just return a black color. The problem is that I get this error: warning X4121: gradient based operation must be moved outside of flow control to prevent divergence. Performance may be improved by using a non-gradient operation. This pixel shader uses more textures to compute lighting (pos and normals are from texture beacause of deferred rendering). I've used the [flatten] attribute on the if statement but as far I as understand the documentation this will also execute all lighting code. Any ideas how I can overcome this?
Advertisement
Can you post the shader so that we can help you with a work around.
Got the exact same problem here... at the end I just dropped the "if" and do the calculations even if the light is too far. Is it better to have a warning or to skip complex code?

When you do a regular texture sampling operation (Texture2D.Sample), gradients are calculated using the partial derivatives of the texture coordinates in screen space. These derivatives determine which mipmap level to use. When you're using dynamic branching, your shader can't automatically calculate derivatives for texture coordinates inside a dynamic branch. This is because adjacent pixels in a quad might not take the same branch.

You have two easy solutions:

-Explicitly calculate the derivatives outside the branch, and pass them in to Texture2D.SampleGrad.

-Just use Texture2D.SampleLevel and explicitly specify the mipmap level. Since you're sampling G-Buffer textures, your probably don't have mipmaps which means this would be your best option.

First, sorry to hijack the OP thread but I guess it's better if I ask here cause it's related.

Every pages I read about this warning, people talks about Sampling. In my case, the warning appear at this line (taken from GPU Gems 3, AndyTx code):

float2 GetFilterSize(float2 dx, float2 dy, float2 TexSize){    return 2 * (abs(dx) + abs(dy)) * TexSize;}


dx and dy are the already calculated derivative values of the uvs using ddx() and ddy(). Texture reading is done using .Load (no sample) after. Both ddx() and .Load() can be in a "if" branch without warning, but not the simple math function above. Why?
Texture2D.SampleLevel does the trick, thanks MJP

This topic is closed to new replies.

Advertisement