<h2>Background</h2>
<p>In order to support <a href="https://en.wikipedia.org/wiki/Mipmap" rel="nofollow noreferrer">mipmapping</a>, the texture sampling system needs to know what scale the texture is being displayed at. In order to determine that scale automatically, the <em>derivatives</em> (or “gradient”) of the texture coordinates are used. The way GPUs calculate derivatives is by comparing the results of the calculations performed in one fragment to adjacent fragments.</p>
<p>The reason you can't put <code>textureSample</code> inside of <code>if</code> is because it is possible that the <code>if</code> takes different branches on different pixels, and so the derivative won't exist. “Uniform control flow” means “all fragments are guaranteed to execute this code”.</p>
<h2>Possible solutions</h2>
<ul>
<li><p>If <code>r_texture</code> has no mipmaps, or if <code>r_sampler</code> is configured to prevent using them, then you don't need to select a mipmap level. Use <code>textureSampleLevel(r_texture, r_sampler, in.tex_coords, 0.0)</code> — the additional argument is the mipmap level, and 0 means the full-resolution texture, which is all you want in this case.</p>
</li>
<li><p>If you do wish to use mipmaps, then you can compute the relevant derivatives outside of the <code>if</code>, and use them inside:</p>
<pre><code>let ddx = dpdx(in.tex_coords);
let ddy = dpdy(in.tex_coords);
if in.use_texture {
    let sample = textureSampleGrad(r_texture, r_sampler, in.tex_coords, ddx, ddy);
    return sample * in.color;
} else {
    return in.color;
}
</code></pre>
<p>This is basically doing what <code>textureSample</code> would do implicitly, but moving just the parts that can't be in the <code>if</code> outside.</p>
</li>
</ul>
<h2>Language notes</h2>
<p>The code in this answer is <a href="https://www.w3.org/TR/WGSL/" rel="nofollow noreferrer">WGSL</a>. Equivalent functions in GLSL:</p>
<div class="s-table-container">
<table class="s-table">
<thead>
<tr>
<th>WGSL</th>
<th>GLSL</th>
</tr>
</thead>
<tbody>
<tr>
<td>textureSample()</td>
<td>texture()</td>
</tr>
<tr>
<td>textureSampleGrad()</td>
<td>textureGrad()</td>
</tr>
<tr>
<td>dpdx()</td>
<td>dFdx()</td>
</tr>
<tr>
<td>dpdy()</td>
<td>dFdy()</td>
</tr>
</tbody>
</table>
</div>
<p>Also, <a href="https://www.khronos.org/opengl/wiki/Sampler_(GLSL)#Non-uniform_flow_control" rel="nofollow noreferrer">here's another introduction to the same concepts from the Khronos OpenGL wiki (which uses GLSL)</a>.</p>

CC BY-SA 4.0
2023-09-26T18:21:16.997Z
Thanks, that was very insightful. FWIW, I found that the mipmap level in `textureSampleLevel()` needs to be specified as a float.
junglie85
CC BY-SA 4.0
2023-09-23T22:27:22.807Z
2023-09-26T20:19:27.710Z
2023-09-26T20:19:27.710Z
Kevin Reid
<p>How can I avoid having to declare the sampler outside of the if statement in this shader code sample?</p>
<pre><code>let sample = textureSample(r_texture, r_sampler, in.tex_coords);
if in.use_texture {
    return sample * in.color;
} else {
    return in.color;
}
</code></pre>
<p>This came up as an answer to another of my <a href="https://computergraphics.stackexchange.com/questions/13682/conditionally-sample-from-texture-in-shader/13683#13683">questions</a>, and it was suggested that the sampler needed to be declared here due to uniform control flow, but that it could be avoided.</p>
<p>How to avoid it?</p>

CC BY-SA 4.0
2023-09-25T20:10:27.807Z
This more of avoiding calling the textureSample function outside an if statement then declaring it.
pmw1234
<shader><fragment-shader>
How to avoid declaring sampler outside of statement?
junglie85
# How to avoid declaring sampler outside of statement?

(Asked by: username_0 on 2023-09-23)

How can I avoid having to declare the sampler outside of the if statement in this shader code sample?

```
let sample = textureSample(r_texture, r_sampler, in.tex_coords);
if in.use_texture {
    return sample * in.color;
} else {
    return in.color;
}

```

This came up as an answer to another of my [questions](https://computergraphics.stackexchange.com/questions/13682/conditionally-sample-from-texture-in-shader/13683#13683), and it was suggested that the sampler needed to be declared here due to uniform control flow, but that it could be avoided.

How to avoid it?

**Tags:** shader, fragment-shader

> **Comments:**
> **username_1**: This more of avoiding calling the textureSample function outside an if statement then declaring it.  

---

## 1 answers

### Answer by username_2 on 2023-09-23. Score: 4 | Accepted answer

## Background

In order to support [mipmapping](https://en.wikipedia.org/wiki/Mipmap), the texture sampling system needs to know what scale the texture is being displayed at. In order to determine that scale automatically, the *derivatives* (or “gradient”) of the texture coordinates are used. The way GPUs calculate derivatives is by comparing the results of the calculations performed in one fragment to adjacent fragments.

The reason you can't put `textureSample` inside of `if` is because it is possible that the `if` takes different branches on different pixels, and so the derivative won't exist. “Uniform control flow” means “all fragments are guaranteed to execute this code”.

## Possible solutions

* If `r_texture` has no mipmaps, or if `r_sampler` is configured to prevent using them, then you don't need to select a mipmap level. Use `textureSampleLevel(r_texture, r_sampler, in.tex_coords, 0.0)` — the additional argument is the mipmap level, and 0 means the full-resolution texture, which is all you want in this case.
* If you do wish to use mipmaps, then you can compute the relevant derivatives outside of the `if`, and use them inside:

  ```
  let ddx = dpdx(in.tex_coords);
  let ddy = dpdy(in.tex_coords);
  if in.use_texture {
      let sample = textureSampleGrad(r_texture, r_sampler, in.tex_coords, ddx, ddy);
      return sample * in.color;
  } else {
      return in.color;
  }

  ```

  This is basically doing what `textureSample` would do implicitly, but moving just the parts that can't be in the `if` outside.

## Language notes

The code in this answer is [WGSL](https://www.w3.org/TR/WGSL/). Equivalent functions in GLSL:

| WGSL | GLSL |
| --- | --- |
| textureSample() | texture() |
| textureSampleGrad() | textureGrad() |
| dpdx() | dFdx() |
| dpdy() | dFdy() |

Also, [here's another introduction to the same concepts from the Khronos OpenGL wiki (which uses GLSL)](https://www.khronos.org/opengl/wiki/Sampler_(GLSL)#Non-uniform_flow_control).

> **Comments:**
> **username_0**: Thanks, that was very insightful. FWIW, I found that the mipmap level in `textureSampleLevel()` needs to be specified as a float.  

---

