[Mesa-dev] [PATCH] gallivm: Compile flag to debug TGSI execution through printfs.

jfonseca at vmware.com jfonseca at vmware.com
Wed Nov 13 09:37:44 PST 2013


From: José Fonseca <jfonseca at vmware.com>

It is similar to tgsi_exec.c's DEBUG_EXECUTION compile flag.

I had prototyped this for a while while debugging an issue, but finally
cleaned this up and added a few more bells and whistles.

Here is a sample output.

CONST[0]:
  X: 0.006250 0.006250 0.006250 0.006250
  Y: -0.007143 -0.007143 -0.007143 -0.007143
  Z: -1.000000 -1.000000 -1.000000 -1.000000
  W: 1.000000 1.000000 1.000000 1.000000
IN[0]:
  X: 143.500000 175.500000 175.500000 143.500000
  Y: 123.500000 123.500000 155.500000 155.500000
  Z: 0.000000 0.000000 0.000000 0.000000
  W: 1.000000 1.000000 1.000000 1.000000
>   1: RCP TEMP[0].w, IN[0].wwww
    TEMP[0].w =  1 1 1 1
>   2: MAD TEMP[0].xy, IN[0], CONST[0], CONST[0].zwzw
    TEMP[0].x =  -0.103124976 0.0968750715 0.0968750715 -0.103124976
    TEMP[0].y =  0.117857158 0.117857158 -0.110714316 -0.110714316
>   3: MUL OUT[0].xy, TEMP[0], TEMP[0].wwww
    OUT[0].x =  -0.103124976 0.0968750715 0.0968750715 -0.103124976
    OUT[0].y =  0.117857158 0.117857158 -0.110714316 -0.110714316
>   4: MUL OUT[0].z, IN[0].zzzz, TEMP[0].wwww
    OUT[0].z =  0 0 0 0
>   5: MOV OUT[0].w, TEMP[0]
    OUT[0].w =  1 1 1 1
---
 src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c | 158 +++++++++++++++++++-----
 src/gallium/auxiliary/tgsi/tgsi_dump.c          |  23 ++++
 src/gallium/auxiliary/tgsi/tgsi_dump.h          |   7 ++
 3 files changed, 159 insertions(+), 29 deletions(-)

diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
index 5f81066..917826d 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
@@ -47,6 +47,7 @@
 #include "tgsi/tgsi_parse.h"
 #include "tgsi/tgsi_util.h"
 #include "tgsi/tgsi_scan.h"
+#include "tgsi/tgsi_strings.h"
 #include "lp_bld_tgsi_action.h"
 #include "lp_bld_type.h"
 #include "lp_bld_const.h"
@@ -67,6 +68,17 @@
 
 #define DUMP_GS_EMITS 0
 
+/*
+ * If non-zero, the generated LLVM IR will print intermediate results on every TGSI
+ * instruction.
+ *
+ * TODO:
+ * - take execution masks in consideration
+ * - debug control-flow instructions
+ */
+#define DEBUG_EXECUTION 0
+
+
 static void lp_exec_mask_init(struct lp_exec_mask *mask, struct lp_build_context *bld)
 {
    LLVMTypeRef int_type = LLVMInt32TypeInContext(bld->gallivm->context);
@@ -664,6 +676,43 @@ static void lp_exec_mask_endsub(struct lp_exec_mask *mask, int *pc)
 }
 
 
+static LLVMValueRef
+get_file_ptr(struct lp_build_tgsi_soa_context *bld,
+             unsigned file,
+             unsigned index,
+             unsigned chan)
+{
+   LLVMBuilderRef builder = bld->bld_base.base.gallivm->builder;
+   LLVMValueRef (*array_of_vars)[TGSI_NUM_CHANNELS];
+   LLVMValueRef var_of_array;
+
+   switch (file) {
+   case TGSI_FILE_TEMPORARY:
+      array_of_vars = bld->temps;
+      var_of_array = bld->temps_array;
+      break;
+   case TGSI_FILE_OUTPUT:
+      array_of_vars = bld->outputs;
+      var_of_array = bld->outputs_array;
+      break;
+   default:
+      assert(0);
+      return NULL;
+   }
+
+   assert(chan < 4);
+
+   if (bld->indirect_files & (1 << file)) {
+      LLVMValueRef lindex = lp_build_const_int32(bld->bld_base.base.gallivm, index * 4 + chan);
+      return LLVMBuildGEP(builder, var_of_array, &lindex, 1, "");
+   }
+   else {
+      assert(index <= bld->bld_base.info->file_max[file]);
+      return array_of_vars[index][chan];
+   }
+}
+
+
 /**
  * Return pointer to a temporary register channel (src or dest).
  * Note that indirect addressing cannot be handled here.
@@ -675,15 +724,7 @@ lp_get_temp_ptr_soa(struct lp_build_tgsi_soa_context *bld,
              unsigned index,
              unsigned chan)
 {
-   LLVMBuilderRef builder = bld->bld_base.base.gallivm->builder;
-   assert(chan < 4);
-   if (bld->indirect_files & (1 << TGSI_FILE_TEMPORARY)) {
-      LLVMValueRef lindex = lp_build_const_int32(bld->bld_base.base.gallivm, index * 4 + chan);
-      return LLVMBuildGEP(builder, bld->temps_array, &lindex, 1, "");
-   }
-   else {
-      return bld->temps[index][chan];
-   }
+   return get_file_ptr(bld, TGSI_FILE_TEMPORARY, index, chan);
 }
 
 /**
@@ -697,16 +738,7 @@ lp_get_output_ptr(struct lp_build_tgsi_soa_context *bld,
                unsigned index,
                unsigned chan)
 {
-   LLVMBuilderRef builder = bld->bld_base.base.gallivm->builder;
-   assert(chan < 4);
-   if (bld->indirect_files & (1 << TGSI_FILE_OUTPUT)) {
-      LLVMValueRef lindex = lp_build_const_int32(bld->bld_base.base.gallivm,
-                                                 index * 4 + chan);
-      return LLVMBuildGEP(builder, bld->outputs_array, &lindex, 1, "");
-   }
-   else {
-      return bld->outputs[index][chan];
-   }
+   return get_file_ptr(bld, TGSI_FILE_OUTPUT, index, chan);
 }
 
 /*
@@ -1415,6 +1447,21 @@ emit_store_chan(
                              bld_base->info->file_max[reg->Register.File]);
    }
 
+   if (DEBUG_EXECUTION) {
+      /*
+       * Dump the value.
+       */
+
+      char buf[512];
+
+      util_snprintf(buf, sizeof buf, "    %s[%u].%c = ",
+                    tgsi_file_name(reg->Register.File),
+                    reg->Register.Index, "xyzw"[chan_index]);
+
+      lp_build_print_value(gallivm, buf, value);
+   }
+
+
    switch( reg->Register.File ) {
    case TGSI_FILE_OUTPUT:
       /* Outputs are always stored as floats */
@@ -1505,6 +1552,18 @@ emit_store(
    unsigned chan_index;
    struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
 
+   if (DEBUG_EXECUTION) {
+      /*
+       * Dump the TGSI instruction.
+       */
+
+      char buf[512];
+      buf[0] = '>';
+      buf[1] = ' ';
+      tgsi_dump_instruction_str(inst, bld_base->pc, &buf[2], sizeof buf - 2);
+      lp_build_printf(bld_base->base.gallivm, buf);
+   }
+
    if(info->num_dst) {
       LLVMValueRef pred[TGSI_NUM_CHANNELS];
 
@@ -2253,28 +2312,61 @@ emit_kill(struct lp_build_tgsi_soa_context *bld,
  * to stdout.
  */
 static void
-emit_dump_temps(struct lp_build_tgsi_soa_context *bld)
+emit_dump_file(struct lp_build_tgsi_soa_context *bld,
+               unsigned file)
 {
    struct gallivm_state *gallivm = bld->bld_base.base.gallivm;
    LLVMBuilderRef builder = gallivm->builder;
-   LLVMValueRef temp_ptr;
+   LLVMValueRef reg_ptr;
    LLVMValueRef i0 = lp_build_const_int32(gallivm, 0);
    LLVMValueRef i1 = lp_build_const_int32(gallivm, 1);
    LLVMValueRef i2 = lp_build_const_int32(gallivm, 2);
    LLVMValueRef i3 = lp_build_const_int32(gallivm, 3);
-   int index;
-   int n = bld->bld_base.info->file_max[TGSI_FILE_TEMPORARY];
+   unsigned index;
+   unsigned n = bld->bld_base.info->file_max[file];
+
+   n = MIN2(n, 16);
 
-   for (index = 0; index < n; index++) {
+   for (index = 0; index <= n; index++) {
       LLVMValueRef idx = lp_build_const_int32(gallivm, index);
       LLVMValueRef v[4][4], res;
       int chan;
 
-      lp_build_printf(gallivm, "TEMP[%d]:\n", idx);
+      lp_build_printf(gallivm, "%s[%d]:\n",
+                      lp_build_const_string(gallivm, tgsi_file_name(file)),
+                      idx);
 
       for (chan = 0; chan < 4; chan++) {
-         temp_ptr = lp_get_temp_ptr_soa(bld, index, chan);
-         res = LLVMBuildLoad(builder, temp_ptr, "");
+         if (file == TGSI_FILE_CONSTANT) {
+            struct tgsi_full_src_register reg;
+            memset(&reg, 0, sizeof reg);
+            reg.Register.File = file;
+            reg.Register.Index = index;
+            reg.Register.SwizzleX = 0;
+            reg.Register.SwizzleY = 1;
+            reg.Register.SwizzleZ = 2;
+            reg.Register.SwizzleW = 3;
+
+            res = bld->bld_base.emit_fetch_funcs[file](&bld->bld_base, &reg, TGSI_TYPE_FLOAT, chan);
+            if (!res) {
+               continue;
+            }
+         } else if (file == TGSI_FILE_INPUT) {
+            res = bld->inputs[index][chan];
+            if (!res) {
+               continue;
+            }
+         } else if (file == TGSI_FILE_TEMPORARY) {
+            reg_ptr = lp_get_temp_ptr_soa(bld, index, chan);
+            assert(reg_ptr);
+            res = LLVMBuildLoad(builder, reg_ptr, "");
+         } else if (file == TGSI_FILE_OUTPUT) {
+            reg_ptr = lp_get_output_ptr(bld, index, chan);
+            res = LLVMBuildLoad(builder, reg_ptr, "");
+            assert(reg_ptr);
+         } else {
+            assert(0);
+         }
          v[chan][0] = LLVMBuildExtractElement(builder, res, i0, "");
          v[chan][1] = LLVMBuildExtractElement(builder, res, i1, "");
          v[chan][2] = LLVMBuildExtractElement(builder, res, i2, "");
@@ -3174,6 +3266,11 @@ static void emit_prologue(struct lp_build_tgsi_context * bld_base)
       LLVMBuildStore(gallivm->builder, uint_bld->zero,
                      bld->total_emitted_vertices_vec_ptr);
    }
+
+   if (DEBUG_EXECUTION) {
+      emit_dump_file(bld, TGSI_FILE_CONSTANT);
+      emit_dump_file(bld, TGSI_FILE_INPUT);
+   }
 }
 
 static void emit_epilogue(struct lp_build_tgsi_context * bld_base)
@@ -3181,9 +3278,12 @@ static void emit_epilogue(struct lp_build_tgsi_context * bld_base)
    struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
    LLVMBuilderRef builder = bld_base->base.gallivm->builder;
 
-   if (0) {
+   if (DEBUG_EXECUTION) {
       /* for debugging */
-      emit_dump_temps(bld);
+      if (0) {
+         emit_dump_file(bld, TGSI_FILE_TEMPORARY);
+      }
+      emit_dump_file(bld, TGSI_FILE_OUTPUT);
    }
 
    /* If we have indirect addressing in outputs we need to copy our alloca array
diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.c b/src/gallium/auxiliary/tgsi/tgsi_dump.c
index 7f6a3d8..77bca62 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_dump.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_dump.c
@@ -721,3 +721,26 @@ tgsi_dump_str(
 
    tgsi_iterate_shader( tokens, &ctx.base.iter );
 }
+
+void
+tgsi_dump_instruction_str(
+   const struct tgsi_full_instruction *inst,
+   uint instno,
+   char *str,
+   size_t size)
+{
+   struct str_dump_ctx ctx;
+
+   ctx.base.instno = instno;
+   ctx.base.immno = instno;
+   ctx.base.indent = 0;
+   ctx.base.dump_printf = &str_dump_ctx_printf;
+   ctx.base.indentation = 0;
+
+   ctx.str = str;
+   ctx.str[0] = 0;
+   ctx.ptr = str;
+   ctx.left = (int)size;
+
+   iter_instruction( &ctx.base.iter, (struct tgsi_full_instruction *)inst );
+}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.h b/src/gallium/auxiliary/tgsi/tgsi_dump.h
index adaef9d..9820bb1 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_dump.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_dump.h
@@ -58,6 +58,13 @@ tgsi_dump_immediate(
    const struct tgsi_full_immediate *imm );
 
 void
+tgsi_dump_instruction_str(
+   const struct tgsi_full_instruction *inst,
+   uint instno,
+   char *str,
+   size_t size);
+
+void
 tgsi_dump_instruction(
    const struct tgsi_full_instruction *inst,
    uint instno );
-- 
1.8.3.2



More information about the mesa-dev mailing list