gallivm/gs: fix indirect addressing in geometry shaders
authorZack Rusin <zackr@vmware.com>
Wed, 17 Apr 2013 19:15:12 +0000 (12:15 -0700)
committerZack Rusin <zackr@vmware.com>
Wed, 17 Apr 2013 22:28:54 +0000 (15:28 -0700)
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@vmware.com>
Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
Reviewed-by: Roland Scheidegger <sroland@vmware.com>
src/gallium/auxiliary/draw/draw_llvm.c
src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c

index 33fe40d5e7f5d7663dd58b73b2f2778c3fe4b9a6..8e3ea8897d0297a93c83bc73763969ad7daa30c1 100644 (file)
@@ -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;
 }
index 0fbb8aabbb02f81119db4d36ba3174f30858e33d..78a1f0ea4eeefa069b1655726fe2208cf67cd664 100644 (file)
@@ -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);
index 28eb57b4b51397b2a435d992e606a03dcb1deef7..ea7dec727d2f7189dda33b9e191d9d1c738b96db 100644 (file)
@@ -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);