[Mesa-dev] [PATCH 2/3] gallium: Add support for 32x32 muls with 64 bit results

Zack Rusin zackr at vmware.com
Tue Oct 8 12:22:23 PDT 2013


The code introduces two new 32bit integer multiplication opcodes which
can be used to produce correct 64 bit results. GLSL, OpenCL and D3D10+
require them. We use two seperate opcodes, because they match the
behavior of GLSL and OpenCL, are a lot easier to add than a single
opcode with multiple destinations and because there's not much (any)
difference wrt code-generation.

Signed-off-by: Zack Rusin <zackr at vmware.com>
---
 src/gallium/auxiliary/tgsi/tgsi_exec.c             | 34 ++++++++++++++++++++++
 src/gallium/auxiliary/tgsi/tgsi_info.c             |  6 ++++
 src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h       |  3 ++
 src/gallium/auxiliary/tgsi/tgsi_util.c             |  2 ++
 src/gallium/docs/source/tgsi.rst                   | 30 +++++++++++++++++++
 src/gallium/include/pipe/p_shader_tokens.h         |  5 +++-
 .../tests/graw/vertex-shader/vert-imul_hi.sh       | 13 +++++++++
 .../tests/graw/vertex-shader/vert-umul_hi.sh       | 11 +++++++
 8 files changed, 103 insertions(+), 1 deletion(-)
 create mode 100644 src/gallium/tests/graw/vertex-shader/vert-imul_hi.sh
 create mode 100644 src/gallium/tests/graw/vertex-shader/vert-umul_hi.sh

diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c
index 0750a50..6db1238 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c
@@ -3478,6 +3478,32 @@ micro_umul(union tgsi_exec_channel *dst,
 }
 
 static void
+micro_imul_hi(union tgsi_exec_channel *dst,
+              const union tgsi_exec_channel *src0,
+              const union tgsi_exec_channel *src1)
+{
+#define I64M(x, y) ((((int64_t)x) * ((int64_t)y)) >> 32)
+   dst->i[0] = I64M(src0->i[0], src1->i[0]);
+   dst->i[1] = I64M(src0->i[1], src1->i[1]);
+   dst->i[2] = I64M(src0->i[2], src1->i[2]);
+   dst->i[3] = I64M(src0->i[3], src1->i[3]);
+#undef I64M
+}
+
+static void
+micro_umul_hi(union tgsi_exec_channel *dst,
+              const union tgsi_exec_channel *src0,
+              const union tgsi_exec_channel *src1)
+{
+#define U64M(x, y) ((((uint64_t)x) * ((uint64_t)y)) >> 32)
+   dst->u[0] = U64M(src0->u[0], src1->u[0]);
+   dst->u[1] = U64M(src0->u[1], src1->u[1]);
+   dst->u[2] = U64M(src0->u[2], src1->u[2]);
+   dst->u[3] = U64M(src0->u[3], src1->u[3]);
+#undef U64M
+}
+
+static void
 micro_useq(union tgsi_exec_channel *dst,
            const union tgsi_exec_channel *src0,
            const union tgsi_exec_channel *src1)
@@ -4277,6 +4303,14 @@ exec_instruction(
       exec_vector_binary(mach, inst, micro_umul, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
       break;
 
+   case TGSI_OPCODE_IMUL_HI:
+      exec_vector_binary(mach, inst, micro_imul_hi, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
+      break;
+
+   case TGSI_OPCODE_UMUL_HI:
+      exec_vector_binary(mach, inst, micro_umul_hi, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
+      break;
+
    case TGSI_OPCODE_USEQ:
       exec_vector_binary(mach, inst, micro_useq, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
       break;
diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.c b/src/gallium/auxiliary/tgsi/tgsi_info.c
index 7a5d18f..0beef44 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_info.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_info.c
@@ -219,6 +219,8 @@ static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] =
    { 1, 3, 1, 0, 0, 0, OTHR, "TEX2", TGSI_OPCODE_TEX2 },
    { 1, 3, 1, 0, 0, 0, OTHR, "TXB2", TGSI_OPCODE_TXB2 },
    { 1, 3, 1, 0, 0, 0, OTHR, "TXL2", TGSI_OPCODE_TXL2 },
+   { 1, 2, 0, 0, 0, 0, COMP, "IMUL_HI", TGSI_OPCODE_IMUL_HI },
+   { 1, 2, 0, 0, 0, 0, COMP, "UMUL_HI", TGSI_OPCODE_UMUL_HI },
 };
 
 const struct tgsi_opcode_info *
@@ -297,6 +299,7 @@ tgsi_opcode_infer_type( uint opcode )
    case TGSI_OPCODE_USLT:
    case TGSI_OPCODE_USNE:
    case TGSI_OPCODE_SVIEWINFO:
+   case TGSI_OPCODE_UMUL_HI:
       return TGSI_TYPE_UNSIGNED;
    case TGSI_OPCODE_ARL:
    case TGSI_OPCODE_ARR:
@@ -317,6 +320,7 @@ tgsi_opcode_infer_type( uint opcode )
    case TGSI_OPCODE_UARL:
    case TGSI_OPCODE_IABS:
    case TGSI_OPCODE_ISSG:
+   case TGSI_OPCODE_IMUL_HI:
       return TGSI_TYPE_SIGNED;
    default:
       return TGSI_TYPE_FLOAT;
@@ -339,7 +343,9 @@ tgsi_opcode_infer_src_type( uint opcode )
    case TGSI_OPCODE_CASE:
    case TGSI_OPCODE_SAMPLE_I:
    case TGSI_OPCODE_SAMPLE_I_MS:
+   case TGSI_OPCODE_UMUL_HI:
       return TGSI_TYPE_UNSIGNED;
+   case TGSI_OPCODE_IMUL_HI:
    case TGSI_OPCODE_I2F:
       return TGSI_TYPE_SIGNED;
    case TGSI_OPCODE_ARL:
diff --git a/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
index b8144a8..1ef78dd 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
@@ -204,6 +204,9 @@ OP12(SAMPLE_INFO)
 
 OP13(UCMP)
 
+OP12(IMUL_HI)
+OP12(UMUL_HI)
+
 #undef OP00
 #undef OP01
 #undef OP10
diff --git a/src/gallium/auxiliary/tgsi/tgsi_util.c b/src/gallium/auxiliary/tgsi/tgsi_util.c
index b3bc8f2..73a0667 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_util.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_util.c
@@ -243,6 +243,8 @@ tgsi_util_get_inst_usage_mask(const struct tgsi_full_instruction *inst,
    case TGSI_OPCODE_USHR:
    case TGSI_OPCODE_USLT:
    case TGSI_OPCODE_USNE:
+   case TGSI_OPCODE_IMUL_HI:
+   case TGSI_OPCODE_UMUL_HI:
       /* Channel-wise operations */
       read_mask = write_mask;
       break;
diff --git a/src/gallium/docs/source/tgsi.rst b/src/gallium/docs/source/tgsi.rst
index 41f2798..8e54ec3 100644
--- a/src/gallium/docs/source/tgsi.rst
+++ b/src/gallium/docs/source/tgsi.rst
@@ -1103,6 +1103,36 @@ Support for these opcodes indicated by PIPE_SHADER_CAP_INTEGERS (all of them?)
   dst.w = src0.w \times src1.w
 
 
+.. opcode:: IMUL_HI - Signed Integer Multiply High Bits
+
+   The high 32bits of the multiplication of 2 signed integers are returned.
+
+.. math::
+
+  dst.x = src0.x \times src1.x >> 32
+
+  dst.y = src0.y \times src1.y >> 32
+
+  dst.z = src0.z \times src1.z >> 32
+
+  dst.w = src0.w \times src1.w >> 32
+
+
+.. opcode:: UMUL_HI - Unsigned Integer Multiply High Bits
+
+   The high 32bits of the multiplication of 2 unsigned integers are returned.
+
+.. math::
+
+  dst.x = src0.x \times src1.x >> 32
+
+  dst.y = src0.y \times src1.y >> 32
+
+  dst.z = src0.z \times src1.z >> 32
+
+  dst.w = src0.w \times src1.w >> 32
+
+
 .. opcode:: IDIV - Signed Integer Division
 
    TBD: behavior for division by zero.
diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h
index 1beec05..8010902 100644
--- a/src/gallium/include/pipe/p_shader_tokens.h
+++ b/src/gallium/include/pipe/p_shader_tokens.h
@@ -450,7 +450,10 @@ struct tgsi_property_data {
 #define TGSI_OPCODE_TXB2                178
 #define TGSI_OPCODE_TXL2                179
 
-#define TGSI_OPCODE_LAST                180
+#define TGSI_OPCODE_IMUL_HI             180
+#define TGSI_OPCODE_UMUL_HI             181
+
+#define TGSI_OPCODE_LAST                182
 
 #define TGSI_SAT_NONE            0  /* do not saturate */
 #define TGSI_SAT_ZERO_ONE        1  /* clamp to [0,1] */
diff --git a/src/gallium/tests/graw/vertex-shader/vert-imul_hi.sh b/src/gallium/tests/graw/vertex-shader/vert-imul_hi.sh
new file mode 100644
index 0000000..60e2d80
--- /dev/null
+++ b/src/gallium/tests/graw/vertex-shader/vert-imul_hi.sh
@@ -0,0 +1,13 @@
+VERT
+DCL IN[0]
+DCL IN[1]
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+DCL TEMP[0]
+DCL TEMP[1]
+IMM[0] INT32 {-2147483648, 2, 0, -1}
+MOV OUT[0], IN[0]
+IMUL_HI TEMP[0], IMM[0].xzzx, IMM[0].yzzy
+UMUL TEMP[0], TEMP[0], IMM[0].wwww
+I2F OUT[1], TEMP[0]
+END
diff --git a/src/gallium/tests/graw/vertex-shader/vert-umul_hi.sh b/src/gallium/tests/graw/vertex-shader/vert-umul_hi.sh
new file mode 100644
index 0000000..4aa79fe
--- /dev/null
+++ b/src/gallium/tests/graw/vertex-shader/vert-umul_hi.sh
@@ -0,0 +1,11 @@
+VERT
+DCL IN[0]
+DCL IN[1]
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+DCL TEMP[0]
+IMM[0] INT32 {4, 1073741824, 0, 1}
+MOV OUT[0], IN[0]
+UMUL_HI TEMP[0], IMM[0].xzzx, IMM[0].yzzy
+I2F OUT[1], TEMP[0]
+END
-- 
1.8.1.2


More information about the mesa-dev mailing list