diff options
author | Kenneth Graunke <[email protected]> | 2016-10-27 20:12:56 -0700 |
---|---|---|
committer | Kenneth Graunke <[email protected]> | 2016-10-28 10:40:53 -0700 |
commit | e6aeeace6953a7007d98082e3f44bff40a44106d (patch) | |
tree | 40f29b754dec9b0a455394da7f4bff3fa5eeef31 /src | |
parent | c538846e313c43858fb118db012b592513c0ed29 (diff) |
glsl: Improve accuracy of alpha scaling in advanced blend lowering.
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: [email protected]
Cc: [email protected]
Bugzilla: https://cvs.khronos.org/bugzilla/show_bug.cgi?id=16042
Signed-off-by: Kenneth Graunke <[email protected]>
Reviewed-by: Eduardo Lima Mitev <[email protected]>
Reviewed-by: Francisco Jerez <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/glsl/lower_blend_equation_advanced.cpp | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/src/compiler/glsl/lower_blend_equation_advanced.cpp b/src/compiler/glsl/lower_blend_equation_advanced.cpp index 1d033924159..f8210e3aaa5 100644 --- a/src/compiler/glsl/lower_blend_equation_advanced.cpp +++ b/src/compiler/glsl/lower_blend_equation_advanced.cpp @@ -308,12 +308,18 @@ calc_blend_result(ir_factory f, f.emit(assign(dst_alpha, swizzle_w(fb))); f.emit(if_tree(equal(dst_alpha, imm1(0)), assign(dst_rgb, imm3(0)), - assign(dst_rgb, div(swizzle_xyz(fb), dst_alpha)))); + assign(dst_rgb, csel(equal(swizzle_xyz(fb), + swizzle(fb, SWIZZLE_WWWW, 3)), + imm3(1), + div(swizzle_xyz(fb), dst_alpha))))); f.emit(assign(src_alpha, swizzle_w(src))); f.emit(if_tree(equal(src_alpha, imm1(0)), assign(src_rgb, imm3(0)), - assign(src_rgb, div(swizzle_xyz(src), src_alpha)))); + assign(src_rgb, csel(equal(swizzle_xyz(src), + swizzle(src, SWIZZLE_WWWW, 3)), + imm3(1), + div(swizzle_xyz(src), src_alpha))))); ir_variable *factor = f.make_temp(glsl_type::vec3_type, "__blend_factor"); |