diff options
author | Roland Scheidegger <[email protected]> | 2014-11-24 23:32:12 +0100 |
---|---|---|
committer | Roland Scheidegger <[email protected]> | 2014-11-25 00:29:29 +0100 |
commit | 8148a06b8fdb734f7f9a11ce787ee6505939fdaa (patch) | |
tree | 2f456399b759f6556a6871072f00f88cd7f36988 /src/gallium | |
parent | 93d30ff5d628770fcff5a931401fe76fbd8242df (diff) |
llvmpipe: fix lp_test_arit denorm handling
llvmpipe disables denorms on purpose (on x86/sse only), because denorms are
generally neither required nor desired for graphic apis (and in case of d3d10,
they are forbidden).
However, this caused some arithmetic tests using denorms to fail on some
systems, because the reference did not generate the same results anymore.
(It did not fail on all systems - behavior of these math functions is sort
of undefined when called with non-standard floating point mode, hence the
result differing depending on implementation and in particular the sse
capabilities.)
So, for the reference, simply flush all (input/output) denorms manually
to zero in this case.
This fixes https://bugs.freedesktop.org/show_bug.cgi?id=67672.
Reviewed-by: Jose Fonseca <[email protected]>
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_test_arit.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_test_arit.c b/src/gallium/drivers/llvmpipe/lp_test_arit.c index 3fc64ce691d..290c523f049 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_arit.c +++ b/src/gallium/drivers/llvmpipe/lp_test_arit.c @@ -33,6 +33,7 @@ #include "util/u_pointer.h" #include "util/u_memory.h" #include "util/u_math.h" +#include "util/u_cpu_detect.h" #include "gallivm/lp_bld.h" #include "gallivm/lp_bld_debug.h" @@ -333,6 +334,38 @@ build_unary_test_func(struct gallivm_state *gallivm, /* + * Flush denorms to zero. + */ +static float +flush_denorm_to_zero(float val) +{ + /* + * If we have a denorm manually set it to (+-)0. + * This is because the reference may or may not do the right thing + * otherwise because we want the result according to treating all + * denormals as zero (FTZ/DAZ). Not using fpclassify because + * a) some compilers are stuck at c89 (msvc) + * b) not sure it reliably works with non-standard ftz/daz mode + * And, right now we only disable denorms with jited code on x86/sse + * (albeit this should be classified as a bug) so to get results which + * match we must only flush them to zero here in that case too. + */ + union fi fi_val; + + fi_val.f = val; + +#if defined(PIPE_ARCH_SSE) + if (util_cpu_caps.has_sse) { + if ((fi_val.ui & 0x7f800000) == 0) { + fi_val.ui &= 0xff800000; + } + } +#endif + + return fi_val.f; +} + +/* * Test one LLVM unary arithmetic builder function. */ static boolean @@ -374,10 +407,13 @@ test_unary(unsigned verbose, FILE *fp, const struct unary_test_t *test) test_func_jit(out, in); for (i = 0; i < num_vals; ++i) { - float ref = test->ref(in[i]); + float testval, ref; double error, precision; bool pass; + testval = flush_denorm_to_zero(in[i]); + ref = flush_denorm_to_zero(test->ref(testval)); + if (util_inf_sign(ref) && util_inf_sign(out[i]) == util_inf_sign(ref)) { error = 0; } else { |