Shadow samplers vs. regular samplers

I’m bumping this because I have the same question. I don’t understand why shadow sampler can’t be used for other single component textures.
I’m rendering my depth maps manually and I can’t use it with the shadow sampler

It’s probably the same reason that the R32 and DEPTH_COMPONENT32 formats are not interchangeable. Depth components aren’t just single-channel formats even when they don’t have stencil attached.

To add to what Alfonse said, I think it’s primarily because it requires both:

  • Depth format texture
  • Depth comparisons enabled

on the GL side. (Disclaimer: I’m not a driver developer.)

Yes, it requires a depth texture, but you can read from those directly without depth compare using a standard sampler (e.g. sampler2D instead of sampler2DShadow).

However, the depth comparison operation requiring these special sampler types is sometimes backed by special purpose hardware on the GPU (e.g. for performing fast PCF filtering) that probably needs to be enabled, or at least selected, and very likely only works for depth texture formats. And whether it is or not, you can easily envision some GL drivers producing different underlying shader code depending on whether a texture() lookup in the shader should reflect the result of:

  1. a direct depth texture lookup, or
  2. a depth lookup with depth comparison (with or without PCF)

As some evidence of this, one of the guys I’ve worked with struggled for the longest time to get to the bottom of a GL driver crash that was caused by mismatching:

  1. The GL depth compare state,
  2. The GLSL shader referencing a shadow or a non-shadow sampler, and
  3. The GL texture format.

Apparently in some drivers, these must be synced properly to avoid invalid memory accesses down in the driver and/or on the GPU. Crashing in the GL driver is just fine here though because it’s invalid per-spec. But from his perspective, it sure would have been nice if the driver had checked for this and thrown a GL error.

Re “different shader code”, depth compare yes/no is almost certainly something that would trigger a runtime shader-recompile if they’d used the same sampler type in the GL language for this and completely leaned on the current app-side GL depth compare state and GL bound texture type (checking for sync, of course). So perhaps they added these samplers to preclude that this being yet-another-reason why the driver would recompile the shader program behind-your-back at draw time.

For more detail, consult this section in the OpenGL wiki:

It should also be noted that functions like texture use overloading based on the sampler type in order to know what parameters to take. Shadow samplers require an additional value: the comparison value. So the GLSL code must know that you’re doing a shadow sampler access.

Note that even SPIR-V (somewhat) requires that you put the depth comparison in the OpTypeImage type. It has a way to say “maybe, maybe not”. However, the sampling opcode you use does say whether you’re using depth comparisons. So it’s still hard-coded into the shader logic.

1 Like

For future reference, here’s some history, very much related to what we’re discussing:

ARB_fragment_program_shadow: