st/glsl_to_tgsi: fix DFRACEXP with only one destination
authorNicolai Hähnle <nicolai.haehnle@amd.com>
Fri, 6 Oct 2017 18:27:40 +0000 (20:27 +0200)
committerNicolai Hähnle <nicolai.haehnle@amd.com>
Wed, 11 Oct 2017 21:17:06 +0000 (23:17 +0200)
Replace the undefined destination by a new temporary register.

Cleanup merge_two_dsts while we're at it.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
src/mesa/state_tracker/st_glsl_to_tgsi.cpp

index 6a66317a21925e51fd9781dc56692ef5d3e1f1f0..7b81e18000afb9df42bbc5d78e8ef54c01555164 100644 (file)
@@ -5206,7 +5206,8 @@ glsl_to_tgsi_visitor::merge_two_dsts(void)
    /* We never delete inst, but we may delete its successor. */
    foreach_in_list(glsl_to_tgsi_instruction, inst, &this->instructions) {
       glsl_to_tgsi_instruction *inst2;
-      bool merged;
+      unsigned defined;
+
       if (num_inst_dst_regs(inst) != 2)
          continue;
 
@@ -5214,10 +5215,19 @@ glsl_to_tgsi_visitor::merge_two_dsts(void)
           inst->dst[1].file != PROGRAM_UNDEFINED)
          continue;
 
+      assert(inst->dst[0].file != PROGRAM_UNDEFINED ||
+             inst->dst[1].file != PROGRAM_UNDEFINED);
+
+      if (inst->dst[0].file == PROGRAM_UNDEFINED)
+         defined = 1;
+      else
+         defined = 0;
+
       inst2 = (glsl_to_tgsi_instruction *) inst->next;
       do {
-
-         if (inst->src[0].file == inst2->src[0].file &&
+         if (inst->op == inst2->op &&
+             inst2->dst[defined].file == PROGRAM_UNDEFINED &&
+             inst->src[0].file == inst2->src[0].file &&
              inst->src[0].index == inst2->src[0].index &&
              inst->src[0].type == inst2->src[0].type &&
              inst->src[0].swizzle == inst2->src[0].swizzle)
@@ -5225,21 +5235,19 @@ glsl_to_tgsi_visitor::merge_two_dsts(void)
          inst2 = (glsl_to_tgsi_instruction *) inst2->next;
       } while (inst2);
 
-      if (!inst2)
+      if (!inst2) {
+         /* Undefined destinations are not allowed, substitute with an unused
+          * temporary register.
+          */
+         st_src_reg tmp = get_temp(glsl_type::vec4_type);
+         inst->dst[defined ^ 1] = st_dst_reg(tmp);
+         inst->dst[defined ^ 1].writemask = 0;
          continue;
-      merged = false;
-      if (inst->dst[0].file == PROGRAM_UNDEFINED) {
-         merged = true;
-         inst->dst[0] = inst2->dst[0];
-      } else if (inst->dst[1].file == PROGRAM_UNDEFINED) {
-         inst->dst[1] = inst2->dst[1];
-         merged = true;
       }
 
-      if (merged) {
-         inst2->remove();
-         delete inst2;
-      }
+      inst->dst[defined ^ 1] = inst2->dst[defined ^ 1];
+      inst2->remove();
+      delete inst2;
    }
 }