nvc0/ir: flush denorms to zero in non-compute shaders
authorIlia Mirkin <imirkin@alum.mit.edu>
Tue, 28 Apr 2015 07:30:08 +0000 (03:30 -0400)
committerIlia Mirkin <imirkin@alum.mit.edu>
Wed, 29 Apr 2015 00:17:03 +0000 (20:17 -0400)
This will set the FTZ flag (flush denorms to zero) on all opcodes that
can take it.

This resolves issues in Unigine Heaven 4.0 where there were solid-filled
boxes popping up.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=89455
Cc: "10.4 10.5" <mesa-stable@lists.freedesktop.org>
Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.h

index 18e8e67bc87b1b0887b219c6bc6f05d7f21db1fb..b61f3c49bb90056ed968b5cf6dde9fdd199abb8b 100644 (file)
@@ -96,6 +96,26 @@ NVC0LegalizeSSA::handleRCPRSQ(Instruction *i)
    bld.mkOp2(OP_MERGE, TYPE_U64, def, dst[0], dst[1]);
 }
 
+void
+NVC0LegalizeSSA::handleFTZ(Instruction *i)
+{
+   // Only want to flush float inputs
+   if (i->sType != TYPE_F32)
+      return;
+
+   // If we're already flushing denorms (and NaN's) to zero, no need for this.
+   if (i->dnz)
+      return;
+
+   // Only certain classes of operations can flush
+   OpClass cls = prog->getTarget()->getOpClass(i->op);
+   if (cls != OPCLASS_ARITH && cls != OPCLASS_COMPARE &&
+       cls != OPCLASS_CONVERT)
+      return;
+
+   i->ftz = true;
+}
+
 bool
 NVC0LegalizeSSA::visit(Function *fn)
 {
@@ -109,8 +129,11 @@ NVC0LegalizeSSA::visit(BasicBlock *bb)
    Instruction *next;
    for (Instruction *i = bb->getEntry(); i; i = next) {
       next = i->next;
-      if (i->dType == TYPE_F32)
+      if (i->dType == TYPE_F32) {
+         if (prog->getType() != Program::TYPE_COMPUTE)
+            handleFTZ(i);
          continue;
+      }
       switch (i->op) {
       case OP_DIV:
       case OP_MOD:
index d8ff5cd3d96eef453c2e3cb839d8fc6d595dfd9c..260e101a1fbf33c46b18ecc916641743e3a0b2aa 100644 (file)
@@ -36,6 +36,7 @@ private:
    // we want to insert calls to the builtin library only after optimization
    void handleDIV(Instruction *); // integer division, modulus
    void handleRCPRSQ(Instruction *); // double precision float recip/rsqrt
+   void handleFTZ(Instruction *);
 
 private:
    BuildUtil bld;