i965: Add support for saturating immediates.
authorMatt Turner <mattst88@gmail.com>
Sun, 21 Dec 2014 14:56:54 +0000 (06:56 -0800)
committerMatt Turner <mattst88@gmail.com>
Mon, 29 Dec 2014 18:08:18 +0000 (10:08 -0800)
I don't feel great about assert(!"unimplemented: ...") but these
cases do only seem possible under some currently impossible circumstances.

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
src/mesa/drivers/dri/i965/brw_fs.cpp
src/mesa/drivers/dri/i965/brw_shader.cpp
src/mesa/drivers/dri/i965/brw_shader.h
src/mesa/drivers/dri/i965/brw_vec4.cpp

index 2837fc0477d76e01223e4c1ce1b1064f5c66393a..78c068f0e3f55f55370c8c4295ff91dd99d1f7c0 100644 (file)
@@ -2292,6 +2292,22 @@ fs_visitor::opt_algebraic()
 
    foreach_block_and_inst(block, fs_inst, inst, cfg) {
       switch (inst->opcode) {
+      case BRW_OPCODE_MOV:
+         if (inst->src[0].file != IMM)
+            break;
+
+         if (inst->saturate) {
+            if (inst->dst.type != inst->src[0].type)
+               assert(!"unimplemented: saturate mixed types");
+
+            if (brw_saturate_immediate(inst->dst.type,
+                                       &inst->src[0].fixed_hw_reg)) {
+               inst->saturate = false;
+               progress = true;
+            }
+         }
+         break;
+
       case BRW_OPCODE_MUL:
         if (inst->src[1].file != IMM)
            continue;
index 1e5227c6c88f4af4270be6cfc0797852853bdb22..e38dfd6635dbe1942d261a3fb7d5a9e122ed69dd 100644 (file)
@@ -575,6 +575,53 @@ brw_instruction_name(enum opcode op)
    unreachable("not reached");
 }
 
+bool
+brw_saturate_immediate(enum brw_reg_type type, struct brw_reg *reg)
+{
+   union {
+      unsigned ud;
+      int d;
+      float f;
+   } imm = { reg->dw1.ud }, sat_imm;
+
+   switch (type) {
+   case BRW_REGISTER_TYPE_UD:
+   case BRW_REGISTER_TYPE_D:
+   case BRW_REGISTER_TYPE_UQ:
+   case BRW_REGISTER_TYPE_Q:
+      /* Nothing to do. */
+      return false;
+   case BRW_REGISTER_TYPE_UW:
+      sat_imm.ud = CLAMP(imm.ud, 0, USHRT_MAX);
+      break;
+   case BRW_REGISTER_TYPE_W:
+      sat_imm.d = CLAMP(imm.d, SHRT_MIN, SHRT_MAX);
+      break;
+   case BRW_REGISTER_TYPE_F:
+      sat_imm.f = CLAMP(imm.f, 0.0f, 1.0f);
+      break;
+   case BRW_REGISTER_TYPE_UB:
+      sat_imm.ud = CLAMP(imm.ud, 0, UCHAR_MAX);
+      break;
+   case BRW_REGISTER_TYPE_B:
+      sat_imm.d = CLAMP(imm.d, CHAR_MIN, CHAR_MAX);
+      break;
+   case BRW_REGISTER_TYPE_V:
+   case BRW_REGISTER_TYPE_UV:
+   case BRW_REGISTER_TYPE_VF:
+      assert(!"unimplemented: saturate vector immediate");
+   case BRW_REGISTER_TYPE_DF:
+   case BRW_REGISTER_TYPE_HF:
+      assert(!"unimplemented: saturate DF/HF immediate");
+   }
+
+   if (imm.ud != sat_imm.ud) {
+      reg->dw1.ud = sat_imm.ud;
+      return true;
+   }
+   return false;
+}
+
 backend_visitor::backend_visitor(struct brw_context *brw,
                                  struct gl_shader_program *shader_prog,
                                  struct gl_program *prog,
index 05434a7f76e08f83ca74105eee1c2b1894826d01..233e224c22add2ccffc7568949fdbbec9e03c21c 100644 (file)
@@ -192,6 +192,7 @@ enum brw_reg_type brw_type_for_base_type(const struct glsl_type *type);
 enum brw_conditional_mod brw_conditional_for_comparison(unsigned int op);
 uint32_t brw_math_function(enum opcode op);
 const char *brw_instruction_name(enum opcode op);
+bool brw_saturate_immediate(enum brw_reg_type type, struct brw_reg *reg);
 
 #ifdef __cplusplus
 extern "C" {
index b303eb68699e328d5dbcab1d23abff5683e6dc16..36de76ae4044a3536d8b0b598334de0290fb41ea 100644 (file)
@@ -572,6 +572,22 @@ vec4_visitor::opt_algebraic()
 
    foreach_block_and_inst(block, vec4_instruction, inst, cfg) {
       switch (inst->opcode) {
+      case BRW_OPCODE_MOV:
+         if (inst->src[0].file != IMM)
+            break;
+
+         if (inst->saturate) {
+            if (inst->dst.type != inst->src[0].type)
+               assert(!"unimplemented: saturate mixed types");
+
+            if (brw_saturate_immediate(inst->dst.type,
+                                       &inst->src[0].fixed_hw_reg)) {
+               inst->saturate = false;
+               progress = true;
+            }
+         }
+         break;
+
       case VEC4_OPCODE_UNPACK_UNIFORM:
          if (inst->src[0].file != UNIFORM) {
             inst->opcode = BRW_OPCODE_MOV;