aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium/auxiliary/gallivm
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2010-07-20 18:48:53 -0600
committerBrian Paul <[email protected]>2010-07-20 18:50:35 -0600
commit4363d4d0b945c4ca6c303fb337e1fac39e6e1ad6 (patch)
treef50ef4d47998f86d3a509760fbdd7aa6316c56e4 /src/gallium/auxiliary/gallivm
parentb0636f78aa63aed2a68e86e7770c2a91c80bbb80 (diff)
gallivm: fix indirect addressing of constant buffer
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...
Diffstat (limited to 'src/gallium/auxiliary/gallivm')
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c108
1 files changed, 83 insertions, 25 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
index dec7556138c..3515d268f84 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
@@ -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;