gallivm: fix indirect addressing of constant buffer
authorBrian Paul <brianp@vmware.com>
Wed, 21 Jul 2010 00:48:53 +0000 (18:48 -0600)
committerBrian Paul <brianp@vmware.com>
Wed, 21 Jul 2010 00:50:35 +0000 (18:50 -0600)
The previous code assumed that all elements of the address register
were the same.  But it can vary from pixel to pixel or vertex to
vertex so we must use a gather operation when dynamically indexing
the constant buffer.

Still need to fix this for the temporary register file...

src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c

index dec7556138cc23a67795eb1ebba56edf8f705d28..3515d268f8406880de00ae7189c4dd060f952613 100644 (file)
@@ -49,6 +49,7 @@
 #include "lp_bld_type.h"
 #include "lp_bld_const.h"
 #include "lp_bld_arit.h"
+#include "lp_bld_gather.h"
 #include "lp_bld_logic.h"
 #include "lp_bld_swizzle.h"
 #include "lp_bld_flow.h"
@@ -423,6 +424,38 @@ get_temp_ptr(struct lp_build_tgsi_soa_context *bld,
    }
 }
 
+
+/**
+ * Gather vector.
+ * XXX the lp_build_gather() function should be capable of doing this
+ * with a little work.
+ */
+static LLVMValueRef
+build_gather(struct lp_build_tgsi_soa_context *bld,
+             LLVMValueRef base_ptr,
+             LLVMValueRef indexes)
+{
+   LLVMValueRef res = bld->base.undef;
+   unsigned i;
+
+   /*
+    * Loop over elements of index_vec, load scalar value, insert it into 'res'.
+    */
+   for (i = 0; i < bld->base.type.length; i++) {
+      LLVMValueRef ii = LLVMConstInt(LLVMInt32Type(), i, 0);
+      LLVMValueRef index = LLVMBuildExtractElement(bld->base.builder,
+                                                   indexes, ii, "");
+      LLVMValueRef scalar_ptr = LLVMBuildGEP(bld->base.builder, base_ptr,
+                                             &index, 1, "");
+      LLVMValueRef scalar = LLVMBuildLoad(bld->base.builder, scalar_ptr, "");
+
+      res = LLVMBuildInsertElement(bld->base.builder, res, scalar, ii, "");
+   }
+
+   return res;
+}
+
+
 /**
  * Register fetch.
  */
@@ -437,7 +470,7 @@ emit_fetch(
    const unsigned swizzle =
       tgsi_util_get_full_src_register_swizzle(reg, chan_index);
    LLVMValueRef res;
-   LLVMValueRef addr = NULL;
+   LLVMValueRef addr_vec = NULL;
 
    if (swizzle > 3) {
       assert(0 && "invalid swizzle in emit_fetch()");
@@ -447,35 +480,51 @@ emit_fetch(
    if (reg->Register.Indirect) {
       LLVMTypeRef int_vec_type = lp_build_int_vec_type(bld->base.type);
       unsigned swizzle = tgsi_util_get_src_register_swizzle( &reg->Indirect, chan_index );
-      addr = LLVMBuildLoad(bld->base.builder,
-                           bld->addr[reg->Indirect.Index][swizzle],
-                           "");
+
+      LLVMValueRef vec4 = lp_build_const_int_vec(bld->int_bld.type, 4); 
+
+      assert(bld->has_indirect_addressing);
+
+      addr_vec = LLVMBuildLoad(bld->base.builder,
+                               bld->addr[reg->Indirect.Index][swizzle],
+                               "load addr");
+
       /* for indexing we want integers */
-      addr = LLVMBuildFPToSI(bld->base.builder, addr,
-                             int_vec_type, "");
-      addr = LLVMBuildExtractElement(bld->base.builder,
-                                     addr, LLVMConstInt(LLVMInt32Type(), 0, 0),
-                                     "");
-      addr = lp_build_mul(&bld->base, addr, LLVMConstInt(LLVMInt32Type(), 4, 0));
+      addr_vec = LLVMBuildFPToSI(bld->base.builder, addr_vec,
+                                 int_vec_type, "");
+
+      /* addr_vec = addr_vec * 4 */
+      addr_vec = lp_build_mul(&bld->base, addr_vec, vec4);
    }
 
    switch (reg->Register.File) {
    case TGSI_FILE_CONSTANT:
       {
-         LLVMValueRef index = LLVMConstInt(LLVMInt32Type(),
-                                           reg->Register.Index*4 + swizzle, 0);
-         LLVMValueRef scalar, scalar_ptr;
-
          if (reg->Register.Indirect) {
-            /*lp_build_printf(bld->base.builder,
-              "\taddr = %d\n", addr);*/
-            index = lp_build_add(&bld->base, index, addr);
+            LLVMValueRef index_vec;  /* index into the const buffer */
+
+            /* index_vec = broadcast(reg->Register.Index * 4 + swizzle) */
+            index_vec = lp_build_const_int_vec(bld->int_bld.type,
+                                   reg->Register.Index * 4 + swizzle);
+
+            /* index_vec = index_vec + addr_vec */
+            index_vec = lp_build_add(&bld->base, index_vec, addr_vec);
+
+            /* Gather values from the constant buffer */
+            res = build_gather(bld, bld->consts_ptr, index_vec);
          }
-         scalar_ptr = LLVMBuildGEP(bld->base.builder, bld->consts_ptr,
-                                   &index, 1, "");
-         scalar = LLVMBuildLoad(bld->base.builder, scalar_ptr, "");
+         else {
+            LLVMValueRef index;  /* index into the const buffer */
+            LLVMValueRef scalar, scalar_ptr;
+
+            index = lp_build_const_int32(reg->Register.Index*4 + swizzle);
+
+            scalar_ptr = LLVMBuildGEP(bld->base.builder, bld->consts_ptr,
+                                      &index, 1, "");
+            scalar = LLVMBuildLoad(bld->base.builder, scalar_ptr, "");
 
-         res = lp_build_broadcast_scalar(&bld->base, scalar);
+            res = lp_build_broadcast_scalar(&bld->base, scalar);
+         }
       }
       break;
 
@@ -491,10 +540,19 @@ emit_fetch(
 
    case TGSI_FILE_TEMPORARY:
       {
-         LLVMValueRef temp_ptr = get_temp_ptr(bld, reg->Register.Index,
-                                              swizzle,
-                                              reg->Register.Indirect,
-                                              addr);
+         LLVMValueRef addr = NULL;
+         LLVMValueRef temp_ptr;
+
+         if (reg->Register.Indirect) {
+            LLVMValueRef zero = lp_build_const_int32(0);
+            addr = LLVMBuildExtractElement(bld->base.builder,
+                                           addr_vec, zero, "");
+         }
+
+         temp_ptr = get_temp_ptr(bld, reg->Register.Index,
+                                 swizzle,
+                                 reg->Register.Indirect,
+                                 addr);
          res = LLVMBuildLoad(bld->base.builder, temp_ptr, "");
          if(!res)
             return bld->base.undef;