[Mesa-dev] [PATCH 0/3] tgsi, radeonsi: add CANON opcode for float canonicalization

Nicolai Hähnle nhaehnle at gmail.com
Mon Sep 18 09:44:28 UTC 2017


Hi all,

This series fixes an issue we have on GCN due to the arguably inconsistent
handling of denormal floating point values. We disable denormals for 32-bit
floating point numbers, because enabling them would cost a lot of
performance. By and large, GCN floating point instructions flush denormals
to zero. An annoying exception are v_min_f32 and v_max_f32, whose behavior
can be described as:

  cc = compare(flushed(src0), flushed(src1))
  dst = cc ? src0 : src1;

When both sources are denormals (or 0.0), the comparison will consider the
numbers equal. The instruction will return one of them *without* flushing
to zero, which means that we might end up with the wrong one (depending on
how the operands are ordered).

The way this series fixes the issue is to explicitly cause flush-to-zero
behavior whenever the application may be able to observe a difference, which
is when floats are bit-cast to integers or stored in memory (SSBOs and
32f images, since those images can be bitcast r32i/ui).

Since the backend cannot reliably detect bitcasts, we add a new CANON opcode
which is modeled after LLVM's llvm.canonicalize.* intrinsic. If the driver
requests it, CANON is emitted before bitcasts and stores, which means most
shaders are unaffected (the alternative would be to emit it for bitcasts
*from* integers and for loads, which has a much wider impact).

For GCN, LLVM turns the canonicalize into a multiplication by 1.0. We may
want to teach LLVM about cases where the additional instruction is
unnecessary.

Please review!
Thanks,
Nicolai
--
 src/gallium/auxiliary/gallivm/lp_bld_limits.h     |  1 +
 src/gallium/auxiliary/tgsi/tgsi_exec.h            |  1 +
 src/gallium/auxiliary/tgsi/tgsi_info_opcodes.h    |  2 +-
 src/gallium/docs/source/screen.rst                |  2 ++
 src/gallium/docs/source/tgsi.rst                  | 18 ++++++++++++++++++
 src/gallium/drivers/etnaviv/etnaviv_screen.c      |  1 +
 src/gallium/drivers/freedreno/freedreno_screen.c  |  1 +
 src/gallium/drivers/nouveau/nv30/nv30_screen.c    |  2 ++
 src/gallium/drivers/nouveau/nv50/nv50_screen.c    |  1 +
 src/gallium/drivers/nouveau/nvc0/nvc0_screen.c    |  1 +
 src/gallium/drivers/r300/r300_screen.c            |  2 ++
 src/gallium/drivers/r600/r600_pipe.c              |  1 +
 src/gallium/drivers/radeonsi/si_pipe.c            |  1 +
 src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c |  2 ++
 src/gallium/drivers/svga/svga_screen.c            |  3 +++
 src/gallium/drivers/vc4/vc4_screen.c              |  1 +
 src/gallium/drivers/virgl/virgl_screen.c          |  1 +
 src/gallium/include/pipe/p_defines.h              |  1 +
 src/gallium/include/pipe/p_shader_tokens.h        |  2 +-
 src/mesa/state_tracker/st_glsl_to_tgsi.cpp        | 31 +++++++++++++++++++++++++++++--
 20 files changed, 71 insertions(+), 4 deletions(-)



More information about the mesa-dev mailing list