[virglrenderer-devel] [PATCH 3/3] vrend_shader: add arb_gpu_shader_fp64 support

Dave Airlie airlied at gmail.com
Fri Jun 1 01:41:00 UTC 2018


From: Dave Airlie <airlied at redhat.com>

This is a basic step towards GL4.0 and greater,
add support for the FP64 extension.

This requires ARB_gpu_shader5 on the host, to
implement ldexp using bitfieldInsert.

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 src/gallium/auxiliary/tgsi/tgsi_info.c     |   4 +
 src/gallium/auxiliary/tgsi/tgsi_parse.c    |   1 +
 src/gallium/auxiliary/tgsi/tgsi_sanity.c   |   3 +-
 src/gallium/auxiliary/tgsi/tgsi_text.c     |   8 ++
 src/gallium/include/pipe/p_shader_tokens.h |   3 +-
 src/vrend_renderer.c                       |   5 +
 src/vrend_shader.c                         | 163 ++++++++++++++++++++++++++---
 7 files changed, 172 insertions(+), 15 deletions(-)

diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.c b/src/gallium/auxiliary/tgsi/tgsi_info.c
index 3b40c3d..a02b5bf 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_info.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_info.c
@@ -262,6 +262,7 @@ static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] =
    { 1, 1, 0, 0, 0, 0, COMP, "DFLR", TGSI_OPCODE_DFLR },
    { 1, 1, 0, 0, 0, 0, COMP, "DROUND", TGSI_OPCODE_DROUND },
    { 1, 1, 0, 0, 0, 0, COMP, "DSSG", TGSI_OPCODE_DSSG },
+   { 1, 2, 0, 0, 0, 0, COMP, "DDIV", TGSI_OPCODE_DDIV }
 };
 
 const struct tgsi_opcode_info *
@@ -352,6 +353,7 @@ tgsi_opcode_infer_type( uint opcode )
    case TGSI_OPCODE_POPC:
    case TGSI_OPCODE_LSB:
    case TGSI_OPCODE_UMSB:
+   case TGSI_OPCODE_D2U:
       return TGSI_TYPE_UNSIGNED;
    case TGSI_OPCODE_ARL:
    case TGSI_OPCODE_ARR:
@@ -379,6 +381,7 @@ tgsi_opcode_infer_type( uint opcode )
    case TGSI_OPCODE_DSGE:
    case TGSI_OPCODE_DSLT:
    case TGSI_OPCODE_DSNE:
+   case TGSI_OPCODE_D2I:
       return TGSI_TYPE_SIGNED;
    case TGSI_OPCODE_DADD:
    case TGSI_OPCODE_DABS:
@@ -399,6 +402,7 @@ tgsi_opcode_infer_type( uint opcode )
    case TGSI_OPCODE_DFLR:
    case TGSI_OPCODE_DROUND:
    case TGSI_OPCODE_DSSG:
+   case TGSI_OPCODE_DDIV:
    case TGSI_OPCODE_F2D:
    case TGSI_OPCODE_I2D:
    case TGSI_OPCODE_U2D:
diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.c b/src/gallium/auxiliary/tgsi/tgsi_parse.c
index 8891153..fc1f016 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_parse.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_parse.c
@@ -154,6 +154,7 @@ tgsi_parse_token(
          break;
 
       case TGSI_IMM_UINT32:
+      case TGSI_IMM_FLOAT64:
          for (i = 0; i < imm_count; i++) {
             next_token(ctx, &imm->u[i].Uint);
          }
diff --git a/src/gallium/auxiliary/tgsi/tgsi_sanity.c b/src/gallium/auxiliary/tgsi/tgsi_sanity.c
index 6b7fe4f..90836f7 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_sanity.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_sanity.c
@@ -454,7 +454,8 @@ iter_immediate(
     */
    if (imm->Immediate.DataType != TGSI_IMM_FLOAT32 &&
        imm->Immediate.DataType != TGSI_IMM_UINT32 &&
-       imm->Immediate.DataType != TGSI_IMM_INT32) {
+       imm->Immediate.DataType != TGSI_IMM_INT32 &&
+       imm->Immediate.DataType != TGSI_IMM_FLOAT64) {
       report_error( ctx, "(%u): Invalid immediate data type", imm->Immediate.DataType );
       return TRUE;
    }
diff --git a/src/gallium/auxiliary/tgsi/tgsi_text.c b/src/gallium/auxiliary/tgsi/tgsi_text.c
index c1b1916..16ad03b 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_text.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_text.c
@@ -260,6 +260,14 @@ static boolean parse_double( const char **pcur, uint32_t *val0, uint32_t *val1)
       uint32_t uval[2];
    } v;
 
+   if (*cur == '0' && *(cur + 1) == 'x') {
+      *val0 = strtoul(cur, NULL, 16);
+      cur += 11;
+      *val1 = strtoul(cur, NULL, 16);
+      cur += 11;
+      *pcur = cur;
+      return TRUE;
+   }
    v.dval = strtod(cur, (char**)pcur);
    if (*pcur == cur)
       return FALSE;
diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h
index 0ff543e..10ec7a7 100644
--- a/src/gallium/include/pipe/p_shader_tokens.h
+++ b/src/gallium/include/pipe/p_shader_tokens.h
@@ -547,7 +547,8 @@ struct tgsi_property_data {
 #define TGSI_OPCODE_DFLR                220 /* nvc0 */
 #define TGSI_OPCODE_DROUND              221 /* nvc0 */
 #define TGSI_OPCODE_DSSG                222
-#define TGSI_OPCODE_LAST                223
+#define TGSI_OPCODE_DDIV                223
+#define TGSI_OPCODE_LAST                224
 
 /**
  * Opcode is the operation code to execute. A given operation defines the
diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
index df575b1..ec9cdfe 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -6944,6 +6944,7 @@ void vrend_renderer_fill_caps(uint32_t set, uint32_t version,
       caps->v1.bset.texture_query_lod = 1;
       caps->v1.bset.has_indirect_draw = 1;
       caps->v1.bset.has_sample_shading = 1;
+      caps->v1.bset.has_fp64 = 1;
    } else {
       if (epoxy_has_gl_extension("GL_ARB_draw_buffers_blend"))
          caps->v1.bset.indep_blend_func = 1;
@@ -6955,6 +6956,10 @@ void vrend_renderer_fill_caps(uint32_t set, uint32_t version,
          caps->v1.bset.has_indirect_draw = 1;
       if (epoxy_has_gl_extension("GL_ARB_sample_shading"))
          caps->v1.bset.has_sample_shading = 1;
+      /* need gpu shader 5 for bitfield insert */
+      if (epoxy_has_gl_extension("GL_ARB_gpu_shader_fp64") &&
+          epoxy_has_gl_extension("GL_ARB_gpu_shader5"))
+         caps->v1.bset.has_fp64 = 1;
    }
 
    if (gl_ver >= 42) {
diff --git a/src/vrend_shader.c b/src/vrend_shader.c
index 192da9a..3ad3289 100644
--- a/src/vrend_shader.c
+++ b/src/vrend_shader.c
@@ -55,6 +55,7 @@ extern int vrend_dump_shaders;
 #define SHADER_REQ_SAMPLE_SHADING     (1 << 11)
 #define SHADER_REQ_GPU_SHADER5        (1 << 12)
 #define SHADER_REQ_DERIVATIVE_CONTROL (1 << 13)
+#define SHADER_REQ_FP64               (1 << 14)
 
 struct vrend_shader_io {
    unsigned                name;
@@ -183,6 +184,7 @@ static const struct vrend_shader_table shader_req_table[] = {
     { SHADER_REQ_SAMPLE_SHADING, "GL_ARB_sample_shading" },
     { SHADER_REQ_GPU_SHADER5, "GL_ARB_gpu_shader5" },
     { SHADER_REQ_DERIVATIVE_CONTROL, "GL_ARB_derivative_control" },
+    { SHADER_REQ_FP64, "GL_ARB_gpu_shader_fp64" },
 };
 
 enum vrend_type_qualifier {
@@ -203,6 +205,8 @@ enum vrend_type_qualifier {
    UINT_BITS_TO_FLOAT = 14,
    FLOAT_BITS_TO_INT = 15,
    INT_BITS_TO_FLOAT = 16,
+   DOUBLE = 17,
+   DVEC2 = 18,
 };
 
 static const struct vrend_shader_table conversion_table[] =
@@ -224,6 +228,8 @@ static const struct vrend_shader_table conversion_table[] =
    {UINT_BITS_TO_FLOAT, "uintBitsToFloat"},
    {FLOAT_BITS_TO_INT, "floatBitsToInt"},
    {INT_BITS_TO_FLOAT, "intBitsToFloat"},
+   {DOUBLE, "double"},
+   {DVEC2, "dvec2"},
 };
 
 static inline const char *get_string(enum vrend_type_qualifier key)
@@ -932,9 +938,10 @@ iter_immediate(
    for (i = 0; i < 4; i++) {
       if (imm->Immediate.DataType == TGSI_IMM_FLOAT32) {
          ctx->imm[first].val[i].f = imm->u[i].Float;
-      } else if (imm->Immediate.DataType == TGSI_IMM_UINT32) {
+      } else if (imm->Immediate.DataType == TGSI_IMM_UINT32 ||
+                 imm->Immediate.DataType == TGSI_IMM_FLOAT64) {
          ctx->shader_req_bits |= SHADER_REQ_INTS;
-         ctx->imm[first].val[i].ui  = imm->u[i].Uint;
+         ctx->imm[first].val[i].ui = imm->u[i].Uint;
       } else if (imm->Immediate.DataType == TGSI_IMM_INT32) {
          ctx->shader_req_bits |= SHADER_REQ_INTS;
          ctx->imm[first].val[i].i = imm->u[i].Int;
@@ -1767,6 +1774,7 @@ struct dest_info {
   enum vrend_type_qualifier dtypeprefix;
   enum vrend_type_qualifier dstconv;
   enum vrend_type_qualifier udstconv;
+  enum vrend_type_qualifier idstconv;
   bool dst_override_no_wm[2];
 };
 
@@ -1775,6 +1783,7 @@ get_destination_info(struct dump_ctx *ctx,
                      const struct tgsi_full_instruction *inst,
                      struct dest_info *dinfo,
                      char dsts[3][255],
+                     char fp64_dsts[3][255],
                      char *writemask)
 {
    const struct tgsi_full_dst_register *dst_reg;
@@ -1783,6 +1792,11 @@ get_destination_info(struct dump_ctx *ctx,
    if (dtype == TGSI_TYPE_SIGNED || dtype == TGSI_TYPE_UNSIGNED)
       ctx->shader_req_bits |= SHADER_REQ_INTS;
 
+   if (dtype == TGSI_TYPE_DOUBLE) {
+      /* we need the uvec2 conversion for doubles */
+      ctx->shader_req_bits |= SHADER_REQ_INTS | SHADER_REQ_FP64;
+   }
+
    if (inst->Instruction.Opcode == TGSI_OPCODE_TXQ) {
       dinfo->dtypeprefix = INT_BITS_TO_FLOAT;
    } else {
@@ -1799,11 +1813,14 @@ get_destination_info(struct dump_ctx *ctx,
    }
 
    for (uint32_t i = 0; i < inst->Instruction.NumDstRegs; i++) {
+      char fp64_writemask[6] = {0};
       dst_reg = &inst->Dst[i];
       dinfo->dst_override_no_wm[i] = false;
       if (dst_reg->Register.WriteMask != TGSI_WRITEMASK_XYZW) {
-         int wm_idx = 0;
+         int wm_idx = 0, dbl_wm_idx = 0;
          writemask[wm_idx++] = '.';
+         fp64_writemask[dbl_wm_idx++] = '.';
+
          if (dst_reg->Register.WriteMask & 0x1)
             writemask[wm_idx++] = 'x';
          if (dst_reg->Register.WriteMask & 0x2)
@@ -1813,11 +1830,30 @@ get_destination_info(struct dump_ctx *ctx,
          if (dst_reg->Register.WriteMask & 0x8)
             writemask[wm_idx++] = 'w';
 
-         dinfo->dstconv = FLOAT + wm_idx - 2;
-         dinfo->udstconv = UINT + wm_idx - 2;
+         if (dtype == TGSI_TYPE_DOUBLE) {
+           if (dst_reg->Register.WriteMask & 0x3)
+             fp64_writemask[dbl_wm_idx++] = 'x';
+           if (dst_reg->Register.WriteMask & 0xc)
+             fp64_writemask[dbl_wm_idx++] = 'y';
+         }
+
+         if (dtype == TGSI_TYPE_DOUBLE) {
+            if (dbl_wm_idx == 2)
+               dinfo->dstconv = DOUBLE;
+            else
+               dinfo->dstconv = DVEC2;
+         } else {
+            dinfo->dstconv = FLOAT + wm_idx - 2;
+            dinfo->udstconv = UINT + wm_idx - 2;
+            dinfo->idstconv = INT + wm_idx - 2;
+         }
       } else {
-         dinfo->dstconv = VEC4;
+         if (dtype == TGSI_TYPE_DOUBLE)
+            dinfo->dstconv = DVEC2;
+         else
+            dinfo->dstconv = VEC4;
          dinfo->udstconv = UVEC4;
+         dinfo->idstconv = IVEC4;
       }
 
       if (dst_reg->Register.File == TGSI_FILE_OUTPUT) {
@@ -1871,6 +1907,13 @@ get_destination_info(struct dump_ctx *ctx,
       else if (dst_reg->Register.File == TGSI_FILE_ADDRESS) {
          snprintf(dsts[i], 255, "addr%d", dst_reg->Register.Index);
       }
+
+      if (dtype == TGSI_TYPE_DOUBLE) {
+         strcpy(fp64_dsts[i], dsts[i]);
+         snprintf(dsts[i], 255, "fp64_dst[%d]%s", i, fp64_writemask);
+         writemask[0] = 0;
+      }
+
    }
 
    return 0;
@@ -1887,7 +1930,8 @@ static int
 get_source_info(struct dump_ctx *ctx,
                 const struct tgsi_full_instruction *inst,
                 struct source_info *sinfo,
-                char srcs[3][255], char src_swizzle0[10])
+                char srcs[3][255], char src_swizzle0[10],
+                char fp64_srcs[3][255])
 {
    bool stprefix = false;
 
@@ -1896,8 +1940,15 @@ get_source_info(struct dump_ctx *ctx,
 
    if (stype == TGSI_TYPE_SIGNED || stype == TGSI_TYPE_UNSIGNED)
       ctx->shader_req_bits |= SHADER_REQ_INTS;
+   if (stype == TGSI_TYPE_DOUBLE)
+      ctx->shader_req_bits |= SHADER_REQ_INTS | SHADER_REQ_FP64;
 
    switch (stype) {
+   case TGSI_TYPE_DOUBLE:
+      stypeprefix = FLOAT_BITS_TO_UINT;
+      sinfo->svec4 = DVEC2;
+      stprefix = true;
+      break;
    case TGSI_TYPE_UNSIGNED:
       stypeprefix = FLOAT_BITS_TO_UINT;
       sinfo->svec4 = UVEC4;
@@ -1918,15 +1969,15 @@ get_source_info(struct dump_ctx *ctx,
       char prefix[6] = {0};
       char arrayname[16] = {0};
       int swz_idx = 0, pre_idx = 0;
-      boolean isabsolute = src->Register.Absolute;
+      boolean isfloatabsolute = src->Register.Absolute && stype != TGSI_TYPE_DOUBLE;
 
       sinfo->override_no_wm[i] = false;
-      if (isabsolute)
+      if (isfloatabsolute)
          swizzle[swz_idx++] = ')';
 
       if (src->Register.Negate)
          prefix[pre_idx++] = '-';
-      if (isabsolute)
+      if (isfloatabsolute)
          strcpy(&prefix[pre_idx++], "abs(");
 
       if (src->Register.Dimension) {
@@ -2089,6 +2140,12 @@ get_source_info(struct dump_ctx *ctx,
                   imm_stypeprefix = UINT_BITS_TO_FLOAT;
             } else if (stype == TGSI_TYPE_UNSIGNED || stype == TGSI_TYPE_SIGNED)
                imm_stypeprefix = TYPE_CONVERSION_NONE;
+         } else if (imd->type == TGSI_IMM_FLOAT64) {
+            vtype = UVEC4;
+            if (stype == TGSI_TYPE_DOUBLE)
+               imm_stypeprefix = TYPE_CONVERSION_NONE;
+            else
+               imm_stypeprefix = UINT_BITS_TO_FLOAT;
          }
 
          /* build up a vec4 of immediates */
@@ -2124,6 +2181,9 @@ get_source_info(struct dump_ctx *ctx,
             case TGSI_IMM_INT32:
                snprintf(temp, 25, "%d", imd->val[idx].i);
                break;
+            case TGSI_IMM_FLOAT64:
+               snprintf(temp, 48, "%uU", imd->val[idx].ui);
+               break;
             default:
                fprintf(stderr, "unhandled imm type: %x\n", imd->type);
                return false;
@@ -2132,7 +2192,7 @@ get_source_info(struct dump_ctx *ctx,
             if (j < 3)
                strcat(srcs[i], ",");
             else {
-               snprintf(temp, 4, "))%c", isabsolute ? ')' : 0);
+               snprintf(temp, 4, "))%c", isfloatabsolute ? ')' : 0);
                strncat(srcs[i], temp, 255);
             }
          }
@@ -2156,6 +2216,15 @@ get_source_info(struct dump_ctx *ctx,
                break;
             }
       }
+
+      if (stype == TGSI_TYPE_DOUBLE) {
+         boolean isabsolute = src->Register.Absolute;
+         char buf[512];
+         strcpy(fp64_srcs[i], srcs[i]);
+         snprintf(srcs[i], 255, "fp64_src[%d]", i);
+         snprintf(buf, 255, "%s.x = %spackDouble2x32(uvec2(%s%s))%s;\n", srcs[i], isabsolute ? "abs(" : "", fp64_srcs[i], swizzle, isabsolute ? ")" : "");
+         EMIT_BUF_WITH_RET(ctx, buf);
+      }
    }
 
    return 0;
@@ -2169,6 +2238,7 @@ iter_instruction(struct tgsi_iterate_context *iter,
    struct dest_info dinfo = { 0 };
    struct source_info sinfo = { 0 };
    char srcs[4][255], dsts[3][255], buf[512];
+   char fp64_srcs[4][255], fp64_dsts[3][255];
    uint instno = ctx->instno++;
    char writemask[6] = {0};
    char *sret;
@@ -2193,16 +2263,17 @@ iter_instruction(struct tgsi_iterate_context *iter,
          prepare_so_movs(ctx);
    }
 
-   ret = get_destination_info(ctx, inst, &dinfo, dsts, writemask);
+   ret = get_destination_info(ctx, inst, &dinfo, dsts, fp64_dsts, writemask);
    if (ret)
       return FALSE;
 
-   ret = get_source_info(ctx, inst, &sinfo, srcs, src_swizzle0);
+   ret = get_source_info(ctx, inst, &sinfo, srcs, src_swizzle0, fp64_srcs);
    if (ret)
       return FALSE;
 
    switch (inst->Instruction.Opcode) {
    case TGSI_OPCODE_SQRT:
+   case TGSI_OPCODE_DSQRT:
       snprintf(buf, 255, "%s = sqrt(vec4(%s))%s;\n", dsts[0], srcs[0], writemask);
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
@@ -2227,12 +2298,14 @@ iter_instruction(struct tgsi_iterate_context *iter,
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
    case TGSI_OPCODE_MAX:
+   case TGSI_OPCODE_DMAX:
    case TGSI_OPCODE_IMAX:
    case TGSI_OPCODE_UMAX:
       snprintf(buf, 255, "%s = %s(%s(max(%s, %s)));\n", dsts[0], get_string(dinfo.dstconv), get_string(dinfo.dtypeprefix), srcs[0], srcs[1]);
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
    case TGSI_OPCODE_MIN:
+   case TGSI_OPCODE_DMIN:
    case TGSI_OPCODE_IMIN:
    case TGSI_OPCODE_UMIN:
       snprintf(buf, 255, "%s = %s(%s(min(%s, %s)));\n", dsts[0], get_string(dinfo.dstconv), get_string(dinfo.dtypeprefix), srcs[0], srcs[1]);
@@ -2240,6 +2313,7 @@ iter_instruction(struct tgsi_iterate_context *iter,
       break;
    case TGSI_OPCODE_ABS:
    case TGSI_OPCODE_IABS:
+   case TGSI_OPCODE_DABS:
       emit_op1("abs");
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
@@ -2328,6 +2402,10 @@ iter_instruction(struct tgsi_iterate_context *iter,
       snprintf(buf, 255, "%s = %s(1.0/(%s));\n", dsts[0], get_string(dinfo.dstconv), srcs[0]);
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
+   case TGSI_OPCODE_DRCP:
+      snprintf(buf, 255, "%s = %s(1.0LF/(%s));\n", dsts[0], get_string(dinfo.dstconv), srcs[0]);
+      EMIT_BUF_WITH_RET(ctx, buf);
+      break;
    case TGSI_OPCODE_FLR:
       emit_op1("floor");
       EMIT_BUF_WITH_RET(ctx, buf);
@@ -2345,6 +2423,7 @@ iter_instruction(struct tgsi_iterate_context *iter,
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
    case TGSI_OPCODE_FRC:
+   case TGSI_OPCODE_DFRAC:
       emit_op1("fract");
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
@@ -2357,6 +2436,7 @@ iter_instruction(struct tgsi_iterate_context *iter,
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
    case TGSI_OPCODE_RSQ:
+   case TGSI_OPCODE_DRSQ:
       snprintf(buf, 255, "%s = %s(inversesqrt(%s.x));\n", dsts[0], get_string(dinfo.dstconv), srcs[0]);
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
@@ -2365,6 +2445,7 @@ iter_instruction(struct tgsi_iterate_context *iter,
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
    case TGSI_OPCODE_ADD:
+   case TGSI_OPCODE_DADD:
       emit_arit_op2("+");
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
@@ -2377,10 +2458,12 @@ iter_instruction(struct tgsi_iterate_context *iter,
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
    case TGSI_OPCODE_MUL:
+   case TGSI_OPCODE_DMUL:
       emit_arit_op2("*");
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
    case TGSI_OPCODE_DIV:
+   case TGSI_OPCODE_DDIV:
       emit_arit_op2("/");
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
@@ -2414,6 +2497,7 @@ iter_instruction(struct tgsi_iterate_context *iter,
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
    case TGSI_OPCODE_UMAD:
+   case TGSI_OPCODE_DMAD:
       snprintf(buf, 255, "%s = %s(%s((%s * %s + %s)%s));\n", dsts[0], get_string(dinfo.dstconv), get_string(dinfo.dtypeprefix), srcs[0], srcs[1], srcs[2], writemask);
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
@@ -2453,18 +2537,42 @@ iter_instruction(struct tgsi_iterate_context *iter,
       snprintf(buf, 255, "%s = %s(ivec4(%s)%s);\n", dsts[0], get_string(dinfo.dstconv), srcs[0], writemask);
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
+   case TGSI_OPCODE_I2D:
+      snprintf(buf, 255, "%s = %s(ivec4(%s));\n", dsts[0], get_string(dinfo.dstconv), srcs[0]);
+      EMIT_BUF_WITH_RET(ctx, buf);
+      break;
+   case TGSI_OPCODE_D2F:
+      snprintf(buf, 255, "%s = %s(%s);\n", dsts[0], get_string(dinfo.dstconv), srcs[0]);
+      EMIT_BUF_WITH_RET(ctx, buf);
+      break;
    case TGSI_OPCODE_U2F:
       snprintf(buf, 255, "%s = %s(uvec4(%s)%s);\n", dsts[0], get_string(dinfo.dstconv), srcs[0], writemask);
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
+   case TGSI_OPCODE_U2D:
+      snprintf(buf, 255, "%s = %s(uvec4(%s));\n", dsts[0], get_string(dinfo.dstconv), srcs[0]);
+      EMIT_BUF_WITH_RET(ctx, buf);
+      break;
    case TGSI_OPCODE_F2I:
       snprintf(buf, 255, "%s = %s(%s(ivec4(%s))%s);\n", dsts[0], get_string(dinfo.dstconv), get_string(dinfo.dtypeprefix), srcs[0], writemask);
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
+   case TGSI_OPCODE_D2I:
+      snprintf(buf, 255, "%s = %s(%s(%s(%s)));\n", dsts[0], get_string(dinfo.dstconv), get_string(dinfo.dtypeprefix), get_string(dinfo.idstconv), srcs[0]);
+      EMIT_BUF_WITH_RET(ctx, buf);
+      break;
    case TGSI_OPCODE_F2U:
       snprintf(buf, 255, "%s = %s(%s(uvec4(%s))%s);\n", dsts[0], get_string(dinfo.dstconv), get_string(dinfo.dtypeprefix), srcs[0], writemask);
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
+   case TGSI_OPCODE_D2U:
+      snprintf(buf, 255, "%s = %s(%s(%s(%s)));\n", dsts[0], get_string(dinfo.dstconv), get_string(dinfo.dtypeprefix), get_string(dinfo.udstconv), srcs[0]);
+      EMIT_BUF_WITH_RET(ctx, buf);
+      break;
+   case TGSI_OPCODE_F2D:
+      snprintf(buf, 255, "%s = %s(%s(%s));\n", dsts[0], get_string(dinfo.dstconv), get_string(dinfo.dtypeprefix), srcs[0]);
+      EMIT_BUF_WITH_RET(ctx, buf);
+      break;
    case TGSI_OPCODE_NOT:
       snprintf(buf, 255, "%s = %s(uintBitsToFloat(~(uvec4(%s))));\n", dsts[0], get_string(dinfo.dstconv), srcs[0]);
       EMIT_BUF_WITH_RET(ctx, buf);
@@ -2473,12 +2581,19 @@ iter_instruction(struct tgsi_iterate_context *iter,
       snprintf(buf, 255, "%s = %s(intBitsToFloat(-(ivec4(%s))));\n", dsts[0], get_string(dinfo.dstconv), srcs[0]);
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
+   case TGSI_OPCODE_DNEG:
+      snprintf(buf, 255, "%s = %s(-%s);\n", dsts[0], get_string(dinfo.dstconv), srcs[0]);
+      EMIT_BUF_WITH_RET(ctx, buf);
+      break;
    case TGSI_OPCODE_SEQ:
       emit_compare("equal");
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
    case TGSI_OPCODE_USEQ:
    case TGSI_OPCODE_FSEQ:
+   case TGSI_OPCODE_DSEQ:
+      if (inst->Instruction.Opcode == TGSI_OPCODE_DSEQ)
+         strcpy(writemask, ".x");
       emit_ucompare("equal");
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
@@ -2489,6 +2604,9 @@ iter_instruction(struct tgsi_iterate_context *iter,
    case TGSI_OPCODE_ISLT:
    case TGSI_OPCODE_USLT:
    case TGSI_OPCODE_FSLT:
+   case TGSI_OPCODE_DSLT:
+      if (inst->Instruction.Opcode == TGSI_OPCODE_DSLT)
+         strcpy(writemask, ".x");
       emit_ucompare("lessThan");
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
@@ -2498,6 +2616,9 @@ iter_instruction(struct tgsi_iterate_context *iter,
       break;
    case TGSI_OPCODE_USNE:
    case TGSI_OPCODE_FSNE:
+   case TGSI_OPCODE_DSNE:
+      if (inst->Instruction.Opcode == TGSI_OPCODE_DSNE)
+         strcpy(writemask, ".x");
       emit_ucompare("notEqual");
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
@@ -2508,6 +2629,9 @@ iter_instruction(struct tgsi_iterate_context *iter,
    case TGSI_OPCODE_ISGE:
    case TGSI_OPCODE_USGE:
    case TGSI_OPCODE_FSGE:
+   case TGSI_OPCODE_DSGE:
+      if (inst->Instruction.Opcode == TGSI_OPCODE_DSGE)
+          strcpy(writemask, ".x");
       emit_ucompare("greaterThanEqual");
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
@@ -2676,6 +2800,13 @@ iter_instruction(struct tgsi_iterate_context *iter,
       break;
    }
 
+   for (uint32_t i = 0; i < 1; i++) {
+      enum tgsi_opcode_type dtype = tgsi_opcode_infer_dst_type(inst->Instruction.Opcode);
+      if (dtype == TGSI_TYPE_DOUBLE) {
+         snprintf(buf, 255, "%s = uintBitsToFloat(unpackDouble2x32(%s));\n", fp64_dsts[0], dsts[0]);
+         EMIT_BUF_WITH_RET(ctx, buf);
+      }
+   }
    if (inst->Instruction.Saturate) {
       snprintf(buf, 255, "%s = clamp(%s, 0.0, 1.0);\n", dsts[0], dsts[0]);
       EMIT_BUF_WITH_RET(ctx, buf);
@@ -3048,6 +3179,12 @@ static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr)
       snprintf(buf, 255, "uvec4 umul_temp;\n");
       STRCAT_WITH_RET(glsl_hdr, buf);
       snprintf(buf, 255, "ivec4 imul_temp;\n");
+   }
+
+   if (ctx->shader_req_bits & SHADER_REQ_FP64) {
+      snprintf(buf, 255, "dvec2 fp64_dst[3];\n");
+      STRCAT_WITH_RET(glsl_hdr, buf);
+      snprintf(buf, 255, "dvec2 fp64_src[4];\n");
       STRCAT_WITH_RET(glsl_hdr, buf);
    }
 
-- 
2.14.3



More information about the virglrenderer-devel mailing list