On 19.01.2017 17:50, Ilia Mirkin wrote:
NVIDIA can't do division either (double or otherwise - but double is
even worse since the rcp is only half there). It has some fancy
functions which get things like division, sqrt, etc.

What does that mean, precisely? It might make sense to have a cap-bit after all, and then if somebody can be bothered to do it, have the front-end generate TGSI for the kind of Newton-Raphson code that LLVM implements for GCN.

Nicolai


2017-01-19 11:39 GMT-05:00 Roland Scheidegger <[email protected]>:
Double-capable Evergreen/NI can't do ddiv? Interesting. I wonder how
it's made d3d11 double conformant...

Roland

Am 19.01.2017 um 14:59 schrieb Nicolai Hähnle:
From: Nicolai Hähnle <[email protected]>

---
 src/gallium/drivers/r600/r600_shader.c | 59 ++++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/src/gallium/drivers/r600/r600_shader.c 
b/src/gallium/drivers/r600/r600_shader.c
index 5c4bc91..eaabb04 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -4384,20 +4384,77 @@ static int cayman_mul_double_instr(struct 
r600_shader_ctx *ctx)
                      alu.last = 1;
              r = r600_bytecode_add_alu(ctx->bc, &alu);
              if (r)
                      return r;
      }

      return 0;
 }

 /*
+ * Emit RECIP_64 + MUL_64 to implement division.
+ */
+static int cayman_ddiv_instr(struct r600_shader_ctx *ctx)
+{
+     struct tgsi_full_instruction *inst = 
&ctx->parse.FullToken.FullInstruction;
+     int r;
+     struct r600_bytecode_alu alu;
+     int t1 = ctx->temp_reg;
+     int k;
+
+     /* Only support one double at a time. This is the same constraint as
+      * in DMUL lowering. */
+     assert(inst->Dst[0].Register.WriteMask == TGSI_WRITEMASK_XY ||
+            inst->Dst[0].Register.WriteMask == TGSI_WRITEMASK_ZW);
+
+     k = inst->Dst[0].Register.WriteMask == TGSI_WRITEMASK_XY ? 0 : 1;
+
+     r = cayman_emit_unary_double_raw(ctx->bc, ALU_OP2_RECIP_64, t1, 
&ctx->src[1], false);
+     if (r)
+             return r;
+
+     for (int i = 0; i < 4; i++) {
+             memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+             alu.op = ALU_OP2_MUL_64;
+
+             r600_bytecode_src(&alu.src[0], &ctx->src[0], k * 2 + ((i == 3) ? 
0 : 1));
+
+             alu.src[1].sel = t1;
+             alu.src[1].chan = (i == 3) ? 0 : 1;
+
+             alu.dst.sel = t1;
+             alu.dst.chan = i;
+             alu.dst.write = 1;
+             if (i == 3)
+                     alu.last = 1;
+             r = r600_bytecode_add_alu(ctx->bc, &alu);
+             if (r)
+                     return r;
+     }
+
+     for (int i = 0; i < 2; i++) {
+             memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+             alu.op = ALU_OP1_MOV;
+             alu.src[0].sel = t1;
+             alu.src[0].chan = i;
+             tgsi_dst(ctx, &inst->Dst[0], k * 2 + i, &alu.dst);
+             alu.dst.write = 1;
+             if (i == 1)
+                     alu.last = 1;
+             r = r600_bytecode_add_alu(ctx->bc, &alu);
+             if (r)
+                     return r;
+     }
+     return 0;
+}
+
+/*
  * r600 - trunc to -PI..PI range
  * r700 - normalize by dividing by 2PI
  * see fdo bug 27901
  */
 static int tgsi_setup_trig(struct r600_shader_ctx *ctx)
 {
      int r;
      struct r600_bytecode_alu alu;

      memset(&alu, 0, sizeof(struct r600_bytecode_alu));
@@ -9393,20 +9450,21 @@ static const struct r600_shader_tgsi_instruction 
eg_shader_tgsi_instruction[] =
      [TGSI_OPCODE_UMSB]      = { ALU_OP1_FFBH_UINT, tgsi_msb},
      [TGSI_OPCODE_INTERP_CENTROID]   = { ALU_OP0_NOP, tgsi_interp_egcm},
      [TGSI_OPCODE_INTERP_SAMPLE]     = { ALU_OP0_NOP, tgsi_interp_egcm},
      [TGSI_OPCODE_INTERP_OFFSET]     = { ALU_OP0_NOP, tgsi_interp_egcm},
      [TGSI_OPCODE_F2D]       = { ALU_OP1_FLT32_TO_FLT64, tgsi_op2_64},
      [TGSI_OPCODE_D2F]       = { ALU_OP1_FLT64_TO_FLT32, 
tgsi_op2_64_single_dest},
      [TGSI_OPCODE_DABS]      = { ALU_OP1_MOV, tgsi_op2_64},
      [TGSI_OPCODE_DNEG]      = { ALU_OP2_ADD_64, tgsi_dneg},
      [TGSI_OPCODE_DADD]      = { ALU_OP2_ADD_64, tgsi_op2_64},
      [TGSI_OPCODE_DMUL]      = { ALU_OP2_MUL_64, cayman_mul_double_instr},
+     [TGSI_OPCODE_DDIV]      = { 0, cayman_ddiv_instr },
      [TGSI_OPCODE_DMAX]      = { ALU_OP2_MAX_64, tgsi_op2_64},
      [TGSI_OPCODE_DMIN]      = { ALU_OP2_MIN_64, tgsi_op2_64},
      [TGSI_OPCODE_DSLT]      = { ALU_OP2_SETGT_64, tgsi_op2_64_single_dest_s},
      [TGSI_OPCODE_DSGE]      = { ALU_OP2_SETGE_64, tgsi_op2_64_single_dest},
      [TGSI_OPCODE_DSEQ]      = { ALU_OP2_SETE_64, tgsi_op2_64_single_dest},
      [TGSI_OPCODE_DSNE]      = { ALU_OP2_SETNE_64, tgsi_op2_64_single_dest},
      [TGSI_OPCODE_DRCP]      = { ALU_OP2_RECIP_64, cayman_emit_double_instr},
      [TGSI_OPCODE_DSQRT]     = { ALU_OP2_SQRT_64, cayman_emit_double_instr},
      [TGSI_OPCODE_DMAD]      = { ALU_OP3_FMA_64, tgsi_op3_64},
      [TGSI_OPCODE_DFMA]      = { ALU_OP3_FMA_64, tgsi_op3_64},
@@ -9615,20 +9673,21 @@ static const struct r600_shader_tgsi_instruction 
cm_shader_tgsi_instruction[] =
      [TGSI_OPCODE_UMSB]      = { ALU_OP1_FFBH_UINT, tgsi_msb},
      [TGSI_OPCODE_INTERP_CENTROID]   = { ALU_OP0_NOP, tgsi_interp_egcm},
      [TGSI_OPCODE_INTERP_SAMPLE]     = { ALU_OP0_NOP, tgsi_interp_egcm},
      [TGSI_OPCODE_INTERP_OFFSET]     = { ALU_OP0_NOP, tgsi_interp_egcm},
      [TGSI_OPCODE_F2D]       = { ALU_OP1_FLT32_TO_FLT64, tgsi_op2_64},
      [TGSI_OPCODE_D2F]       = { ALU_OP1_FLT64_TO_FLT32, 
tgsi_op2_64_single_dest},
      [TGSI_OPCODE_DABS]      = { ALU_OP1_MOV, tgsi_op2_64},
      [TGSI_OPCODE_DNEG]      = { ALU_OP2_ADD_64, tgsi_dneg},
      [TGSI_OPCODE_DADD]      = { ALU_OP2_ADD_64, tgsi_op2_64},
      [TGSI_OPCODE_DMUL]      = { ALU_OP2_MUL_64, cayman_mul_double_instr},
+     [TGSI_OPCODE_DDIV]      = { 0, cayman_ddiv_instr },
      [TGSI_OPCODE_DMAX]      = { ALU_OP2_MAX_64, tgsi_op2_64},
      [TGSI_OPCODE_DMIN]      = { ALU_OP2_MIN_64, tgsi_op2_64},
      [TGSI_OPCODE_DSLT]      = { ALU_OP2_SETGT_64, tgsi_op2_64_single_dest_s},
      [TGSI_OPCODE_DSGE]      = { ALU_OP2_SETGE_64, tgsi_op2_64_single_dest},
      [TGSI_OPCODE_DSEQ]      = { ALU_OP2_SETE_64, tgsi_op2_64_single_dest},
      [TGSI_OPCODE_DSNE]      = { ALU_OP2_SETNE_64, tgsi_op2_64_single_dest},
      [TGSI_OPCODE_DRCP]      = { ALU_OP2_RECIP_64, cayman_emit_double_instr},
      [TGSI_OPCODE_DSQRT]     = { ALU_OP2_SQRT_64, cayman_emit_double_instr},
      [TGSI_OPCODE_DMAD]      = { ALU_OP3_FMA_64, tgsi_op3_64},
      [TGSI_OPCODE_DFMA]      = { ALU_OP3_FMA_64, tgsi_op3_64},


_______________________________________________
mesa-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

_______________________________________________
mesa-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to