summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZack Rusin <[email protected]>2013-04-17 12:15:12 -0700
committerZack Rusin <[email protected]>2013-04-17 15:28:54 -0700
commitcb58c79efb1402cd89504856033b6322d0096233 (patch)
treed78c1e274341b5f3a7ca23d3cc6d3f78c11950a7
parent02039066a8bd4e9cdce7f7d4c90606b54018d74e (diff)
gallivm/gs: fix indirect addressing in geometry shaders
We were always treating the vertex index as a scalar but when the shader is using indirect addressing it will be a vector of indices for each channel. This was causing some nasty crashes insides LLVM. Signed-off-by: Zack Rusin <[email protected]> Reviewed-by: Jose Fonseca <[email protected]> Reviewed-by: Roland Scheidegger <[email protected]>
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.c34
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_tgsi.h1
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c1
3 files changed, 30 insertions, 6 deletions
diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
index 33fe40d5e7f..8e3ea8897d0 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_llvm.c
@@ -1253,6 +1253,7 @@ clipmask_booli32(struct gallivm_state *gallivm,
static LLVMValueRef
draw_gs_llvm_fetch_input(const struct lp_build_tgsi_gs_iface *gs_iface,
struct lp_build_tgsi_context * bld_base,
+ boolean is_indirect,
LLVMValueRef vertex_index,
LLVMValueRef attrib_index,
LLVMValueRef swizzle_index)
@@ -1262,13 +1263,34 @@ draw_gs_llvm_fetch_input(const struct lp_build_tgsi_gs_iface *gs_iface,
LLVMBuilderRef builder = gallivm->builder;
LLVMValueRef indices[3];
LLVMValueRef res;
+ struct lp_type type = bld_base->base.type;
+
+ if (is_indirect) {
+ int i;
+ res = bld_base->base.zero;
+ for (i = 0; i < type.length; ++i) {
+ LLVMValueRef idx = lp_build_const_int32(gallivm, i);
+ LLVMValueRef vert_chan_index = LLVMBuildExtractElement(builder,
+ vertex_index, idx, "");
+ LLVMValueRef channel_vec, value;
+ indices[0] = vert_chan_index;
+ indices[1] = attrib_index;
+ indices[2] = swizzle_index;
+
+ channel_vec = LLVMBuildGEP(builder, gs->input, indices, 3, "");
+ channel_vec = LLVMBuildLoad(builder, channel_vec, "");
+ value = LLVMBuildExtractElement(builder, channel_vec, idx, "");
+
+ res = LLVMBuildInsertElement(builder, res, value, idx, "");
+ }
+ } else {
+ indices[0] = vertex_index;
+ indices[1] = attrib_index;
+ indices[2] = swizzle_index;
- indices[0] = vertex_index;
- indices[1] = attrib_index;
- indices[2] = swizzle_index;
-
- res = LLVMBuildGEP(builder, gs->input, indices, 3, "");
- res = LLVMBuildLoad(builder, res, "");
+ res = LLVMBuildGEP(builder, gs->input, indices, 3, "");
+ res = LLVMBuildLoad(builder, res, "");
+ }
return res;
}
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
index 0fbb8aabbb0..78a1f0ea4ee 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
@@ -368,6 +368,7 @@ struct lp_build_tgsi_gs_iface
{
LLVMValueRef (*fetch_input)(const struct lp_build_tgsi_gs_iface *gs_iface,
struct lp_build_tgsi_context * bld_base,
+ boolean is_indirect,
LLVMValueRef vertex_index,
LLVMValueRef attrib_index,
LLVMValueRef swizzle_index);
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
index 28eb57b4b51..ea7dec727d2 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
@@ -829,6 +829,7 @@ emit_fetch_gs_input(
}
res = bld->gs_iface->fetch_input(bld->gs_iface, bld_base,
+ reg->Dimension.Indirect,
vertex_index, attrib_index,
swizzle_index);