[Mesa-dev] [PATCH] gallivm/gs: fix indirect addressing in geometry shaders

Zack Rusin zackr at vmware.com
Wed Apr 17 12:17:02 PDT 2013


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 <zackr at vmware.com>
---
 src/gallium/auxiliary/draw/draw_llvm.c          |   34 +++++++++++++++++++----
 src/gallium/auxiliary/gallivm/lp_bld_tgsi.h     |    1 +
 src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c |    1 +
 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 33fe40d..8e3ea88 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 0fbb8aa..78a1f0e 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 28eb57b..ea7dec7 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);
 
-- 
1.7.10.4



More information about the mesa-dev mailing list