gallivm: add support for TGSI instructions with two outputs
authorNicolai Hähnle <nicolai.haehnle@amd.com>
Sat, 16 Sep 2017 10:50:42 +0000 (12:50 +0200)
committerNicolai Hähnle <nicolai.haehnle@amd.com>
Fri, 29 Sep 2017 10:07:57 +0000 (12:07 +0200)
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
src/gallium/auxiliary/gallivm/lp_bld_tgsi.c
src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.h
src/gallium/auxiliary/tgsi/tgsi_exec.h

index 66f752989abeb3078d2f3a620c419b9e24080ee5..b33976bb647eb53bfa4f080f7ca7f1ded238318e 100644 (file)
@@ -264,11 +264,17 @@ lp_build_tgsi_inst_llvm(
 
    memset(&emit_data, 0, sizeof(emit_data));
 
-   assert(info->num_dst <= 1);
+   assert(info->num_dst <= 2);
    if (info->num_dst) {
       TGSI_FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
          emit_data.output[chan_index] = bld_base->base.undef;
       }
+
+      if (info->num_dst >= 2) {
+         TGSI_FOR_EACH_DST1_ENABLED_CHANNEL( inst, chan_index ) {
+            emit_data.output1[chan_index] = bld_base->base.undef;
+         }
+      }
    }
 
    emit_data.inst = inst;
@@ -309,11 +315,21 @@ lp_build_tgsi_inst_llvm(
          TGSI_FOR_EACH_DST0_ENABLED_CHANNEL(inst, chan_index) {
             emit_data.output[chan_index] = val;
          }
+
+         if (info->num_dst >= 2) {
+            val = emit_data.output1[0];
+            memset(emit_data.output1, 0, sizeof(emit_data.output1));
+            TGSI_FOR_EACH_DST1_ENABLED_CHANNEL(inst, chan_index) {
+               emit_data.output1[chan_index] = val;
+            }
+         }
       }
    }
 
    if (info->num_dst > 0 && info->opcode != TGSI_OPCODE_STORE) {
       bld_base->emit_store(bld_base, inst, info, 0, emit_data.output);
+      if (info->num_dst >= 2)
+         bld_base->emit_store(bld_base, inst, info, 1, emit_data.output1);
    }
    return TRUE;
 }
index 463d44eb45087cf6d890ce2a5ce89c9390ae60b1..c92517fee286770984508066acb5470ed024e052 100644 (file)
@@ -81,6 +81,11 @@ struct lp_build_emit_data {
     */
    LLVMValueRef output[4];
 
+   /**
+    * Secondary output for instruction that have a second destination register.
+    */
+   LLVMValueRef output1[4];
+
    /**
     * The current instruction that is being 'executed'.
     */
index bcf4a32a8acb0b04b75f9da8bb6f79ee1f0cb77b..d28d99793b8b9a7e18c1b954af2f835ca7aa2f5a 100644 (file)
@@ -58,6 +58,15 @@ extern "C" {
    TGSI_FOR_EACH_CHANNEL( CHAN )\
       TGSI_IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN )
 
+#define TGSI_IS_DST1_CHANNEL_ENABLED( INST, CHAN )\
+   ((INST)->Dst[1].Register.WriteMask & (1 << (CHAN)))
+
+#define TGSI_IF_IS_DST1_CHANNEL_ENABLED( INST, CHAN )\
+   if (TGSI_IS_DST1_CHANNEL_ENABLED( INST, CHAN ))
+
+#define TGSI_FOR_EACH_DST1_ENABLED_CHANNEL( INST, CHAN )\
+   TGSI_FOR_EACH_CHANNEL( CHAN )\
+      TGSI_IF_IS_DST1_CHANNEL_ENABLED( INST, CHAN )
 
 /**
   * Registers may be treated as float, signed int or unsigned int.