When blending with GL_COLORBURN_KHR and these colors:
dst = <0.372549027, 0.372549027, 0.372549027, 0.372549027>
src = <0.09375, 0.046875, 0.0, 0.375>
the normalized dst value became 0.99999994 (due to precision problems
in the floating point divide of rgb by alpha). This caused the color
burn equation to fail the dst >= 1.0 comparison. The blue channel would
then fall through to the dst < 1.0 && src >= 0 comparison, which was
true, since src.b == 0. This produced a factor of 0.0 instead of 1.0.
This is an inherent numerical instability in the color burn and dodge
equations - depending on the precision of alpha scaling, the value can
be either 0.0 or 1.0. Technically, GLSL floating point division doesn't
even guarantee that 0.372549027 / 0.372549027 = 1.0. So arguably, the
CTS should allow either value. I've filed a bug at Khronos for further
discussion (linked below).
In the meantime, this patch improves the precision of alpha scaling by
replacing the division with (rgb == alpha ? 1.0 : rgb / alpha). We may
not need this long term, but for now, it fixes the following CTS tests:
ES31-CTS.blend_equation_advanced.blend_specific.GL_COLORBURN_KHR
ES31-CTS.blend_equation_advanced.blend_all.GL_COLORBURN_KHR_all_qualifier
Cc: currojerez@riseup.net
Cc: mesa-stable@lists.freedesktop.org
Bugzilla: https://cvs.khronos.org/bugzilla/show_bug.cgi?id=16042
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Eduardo Lima Mitev <elima@igalia.com>
Reviewed-by: Francisco Jerez <currojerez@riseup.net>
Caught by Coverity. Likely fixes real issues if an output component
is not present.
CID: 1372278
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
Many GPUs cannot handle GL_KHR_blend_equation_advanced natively, and
need to emulate it in the pixel shader. This lowering pass implements
all the necessary math for advanced blending. It fetches the existing
framebuffer value using the MESA_shader_framebuffer_fetch built-in
variables, and the previous commit's state var uniform to select
which equation to use.
This is done at the GLSL IR level to make it easy for all drivers to
implement the GL_KHR_blend_equation_advanced extension and share code.
Drivers need to hook up MESA_shader_framebuffer_fetch functionality:
1. Hook up the fb_fetch_output variable
2. Implement BlendBarrier()
Then to get KHR_blend_equation_advanced, they simply need to:
3. Disable hardware blending based on ctx->Color._AdvancedBlendEnabled
4. Call this lowering pass.
Very little driver specific code should be required.
v2: Handle multiple output variables per render target (which may exist
due to ARB_enhanced_layouts), and array variables (even with one
render target, we might have out vec4 color[1]), and non-vec4
variables (it's easier than finding spec text to justify not
handling it). Thanks to Francisco Jerez for the feedback.
v3: Lower main returns so that we have a single exit point where we
can add our blending epilogue (caught by Francisco Jerez).
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Francisco Jerez <currojerez@riseup.net>