[Mesa-dev] [PATCH] i965/fs: Don't emit saturates to do UNORM color clamping.
Roland Scheidegger
sroland at vmware.com
Wed Mar 19 09:36:27 PDT 2014
Am 19.03.2014 10:44, schrieb Kenneth Graunke:
> Traditionally, we've implemented fragment color clamping by emitting
> "mov.sat" in the fragment shader's final color write code, clamping
> the output to [0, 1] prior to blending. (When clamping is off, we
> use a regular "mov".) This means we have to recompile based on the
> GL_CLAMP_FRAGMENT_COLOR state, and because GL_FIXED_ONLY is an option,
> we need to consider the render target format.
>
> Modern applications frequently use both UNORM buffers and FLOAT buffers
> with color clamping disabled. (FLOAT with clamping explicitly enabled
> and SNORM buffers appear to be less common.) With all UNORM buffers,
> ctx->Color._ClampFragmentColor is true, while it's false in the typical
> unclamped FLOAT case.
>
> In other words, the two most common cases disagree about whether we
> should emit saturates. This meant basically all modern applications
> needed fragment shader recompiles.
Are you sure? mesa does not seem to enable color clamps if there's all
unorm buffers.
void
_mesa_update_clamp_fragment_color(struct gl_context *ctx)
{
struct gl_framebuffer *fb = ctx->DrawBuffer;
/* Don't clamp if:
* - there is no colorbuffer
* - all colorbuffers are unsigned normalized, so clamping has no effect
* - there is an integer colorbuffer
*/
if (!fb || !fb->_HasSNormOrFloatColorBuffer || fb->_IntegerColor)
ctx->Color._ClampFragmentColor = GL_FALSE;
else
ctx->Color._ClampFragmentColor = _mesa_get_clamp_fragment_color(ctx);
}
>
> It turns out that the saturates are superfluous for UNORM buffers. We
> always configure BLEND_STATE to enable pre-blend color clamping, using
> the render target format's range. This means the color calculator will
> already clamp all UNORM buffers to [0, 1].
>
> By dropping the saturates for the UNORM case, key->clamp_fragment_color
> can simply be false in the two most common cases, giving us a clear
> value to guess in the precompile.
>
> Unfortunately, it doesn't look like we can rely on the color calculator
> to implement fragment color clamping for non-UNORM formats:
>
> For SNORM, the color calculator clamps to [-1, 1] while OpenGL requires
> [0, 1] for some reason. (Technically, the ARB_color_buffer_float spec
> does specify [-1, 1], but every other specification contradicts that.)
> Requesting BRW_RENDERTARGET_CLAMPRANGE_UNORM is not allowed.
>
> Although we are allowed to request [0, 1] pre-blend clamping for FLOAT
> formats, we are also required to enable post-blend clamping, and it uses
> the same range. I believe this is incorrect for OpenGL rules---at the
> very least, no values appear to satisfy Piglit's
> arb_color_buffer_float-render test.
I agree color clamping is a mess. It doesn't help that GL has TWO clamps
- one for shader outputs (this is what will clamp to 0/1 apparently even
for signed normalized buffers when enabled), plus the always active
pre-blend clamp (this one will more meaningfully clamp to -1/1 for
signed normalized, though only mentioned correctly in 4.2+ - apparently
this is what your hw will do). At least the former clamp is legacy only...
I'm not really convinced the _ClampFragmentColor bit is actually fully
correct neither, I think the evaluation if clamping is needed or not
would need to be done per color buffer.
Roland
>
> Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
> ---
> src/mesa/drivers/dri/i965/brw_fs.cpp | 2 --
> src/mesa/drivers/dri/i965/brw_wm.c | 3 ++-
> 2 files changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
> index 1b32d63..bd44952 100644
> --- a/src/mesa/drivers/dri/i965/brw_fs.cpp
> +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
> @@ -3616,8 +3616,6 @@ brw_fs_precompile(struct gl_context *ctx, struct gl_shader_program *prog)
> BRW_FS_VARYING_INPUT_MASK) > 16)
> key.input_slots_valid = fp->Base.InputsRead | VARYING_BIT_POS;
>
> - key.clamp_fragment_color = ctx->API == API_OPENGL_COMPAT;
> -
> unsigned sampler_count = _mesa_fls(fp->Base.SamplersUsed);
> for (unsigned i = 0; i < sampler_count; i++) {
> if (fp->Base.ShadowSamplers & (1 << i)) {
> diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c
> index 0d0d6ec..baf001f 100644
> --- a/src/mesa/drivers/dri/i965/brw_wm.c
> +++ b/src/mesa/drivers/dri/i965/brw_wm.c
> @@ -488,7 +488,8 @@ static void brw_wm_populate_key( struct brw_context *brw,
> key->flat_shade = (ctx->Light.ShadeModel == GL_FLAT);
>
> /* _NEW_FRAG_CLAMP | _NEW_BUFFERS */
> - key->clamp_fragment_color = ctx->Color._ClampFragmentColor;
> + key->clamp_fragment_color = ctx->Color._ClampFragmentColor &&
> + ctx->DrawBuffer->_HasSNormOrFloatColorBuffer;
>
> /* _NEW_TEXTURE */
> brw_populate_sampler_prog_key_data(ctx, prog, brw->wm.base.sampler_count,
>
More information about the mesa-dev
mailing list