gallivm: implement correct indirect addressing of temp registers
authorBrian Paul <brianp@vmware.com>
Wed, 21 Jul 2010 15:10:49 +0000 (09:10 -0600)
committerBrian Paul <brianp@vmware.com>
Wed, 21 Jul 2010 16:16:32 +0000 (10:16 -0600)
As with indexing the const buffer, the ADDR reg may have totally
different values for each element.  Need to use a gather operation.

src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c

index 4e640f5903c948068b73f044df4424aff6077c51..0e45d748f42708a059b936df281c555399dc3f81 100644 (file)
@@ -549,22 +549,40 @@ emit_fetch(
       break;
 
    case TGSI_FILE_TEMPORARY:
-      {
-         LLVMValueRef addr = NULL;
-         LLVMValueRef temp_ptr;
+      if (reg->Register.Indirect) {
+         LLVMValueRef vec_len =
+            lp_build_const_int_vec(bld->int_bld.type, bld->base.type.length);
+         LLVMValueRef index_vec;  /* index into the const buffer */
+         LLVMValueRef temps_array;
+         LLVMTypeRef float4_ptr_type;
 
-         if (reg->Register.Indirect) {
-            LLVMValueRef zero = lp_build_const_int32(0);
-            addr = LLVMBuildExtractElement(bld->base.builder,
-                                           addr_vec, zero, "");
-         }
+         assert(bld->has_indirect_addressing);
+
+         /* 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 += addr_vec */
+         index_vec = lp_build_add(&bld->int_bld, index_vec, addr_vec);
+
+         /* index_vec *= vector_length */
+         index_vec = lp_build_mul(&bld->int_bld, index_vec, vec_len);
+
+         /* cast temps_array pointer to float* */
+         float4_ptr_type = LLVMPointerType(LLVMFloatType(), 0);
+         temps_array = LLVMBuildBitCast(bld->int_bld.builder, bld->temps_array,
+                                        float4_ptr_type, "");
+
+         /* Gather values from the temporary register array */
+         res = build_gather(bld, temps_array, index_vec);
+      }
+      else {
+         LLVMValueRef temp_ptr;
          temp_ptr = get_temp_ptr(bld, reg->Register.Index,
                                  swizzle,
-                                 reg->Register.Indirect,
-                                 addr);
+                                 FALSE, NULL);
          res = LLVMBuildLoad(bld->base.builder, temp_ptr, "");
-         if(!res)
+         if (!res)
             return bld->base.undef;
       }
       break;