swr: Handle indirect indices in GS
authorGeorge Kyriazis <george.kyriazis@intel.com>
Wed, 20 Dec 2017 19:56:45 +0000 (13:56 -0600)
committerGeorge Kyriazis <george.kyriazis@intel.com>
Wed, 10 Jan 2018 20:02:17 +0000 (14:02 -0600)
BuilderSWR::swr_gs_llvm_fetch_input() (and consequently
 swr_gs_llvm_fetch_input()), did not handle the case where
is_vindex_indirect or is_aindex_direct is set.

Implement it, using the code in draw_llvm.c as a guideline.

Fixes the following piglit tests:
dynamic_input_array_index (crash)
gs-input-array-vec4-index-rd
vs-output-array-vec4-index-wr-before-gs

Reviewed-by: Bruce Cherniak <bruce.cherniak@intel.com>
src/gallium/drivers/swr/swr_shader.cpp

index 599dc43698af9c780557a643cd9c889ede1ca49a..257a6aae307cc437d4731f083f222a6f7dd839c1 100644 (file)
@@ -339,22 +339,53 @@ BuilderSWR::swr_gs_llvm_fetch_input(const struct lp_build_tgsi_gs_iface *gs_ifac
                            LLVMValueRef swizzle_index)
 {
     swr_gs_llvm_iface *iface = (swr_gs_llvm_iface*)gs_iface;
+    Value *vert_index = unwrap(vertex_index);
+    Value *attr_index = unwrap(attrib_index);
 
     IRB()->SetInsertPoint(unwrap(LLVMGetInsertBlock(gallivm->builder)));
 
-    assert(is_vindex_indirect == false && is_aindex_indirect == false);
+    if (is_vindex_indirect || is_aindex_indirect) {
+       int i;
+       Value *res = unwrap(bld_base->base.zero);
+       struct lp_type type = bld_base->base.type;
 
-    Value *attrib =
-       LOAD(GEP(iface->pVtxAttribMap, {C(0), unwrap(attrib_index)}));
+       for (i = 0; i < type.length; i++) {
+          Value *vert_chan_index = vert_index;
+          Value *attr_chan_index = attr_index;
 
-    Value *pVertex = LOAD(iface->pGsCtx, {0, SWR_GS_CONTEXT_pVerts});
-    Value *pInputVertStride = LOAD(iface->pGsCtx, {0, SWR_GS_CONTEXT_inputVertStride});
+          if (is_vindex_indirect) {
+             vert_chan_index = VEXTRACT(vert_index, C(i));
+          }
+          if (is_aindex_indirect) {
+             attr_chan_index = VEXTRACT(attr_index, C(i));
+          }
+
+          Value *attrib =
+             LOAD(GEP(iface->pVtxAttribMap, {C(0), attr_chan_index}));
+
+          Value *pVertex = LOAD(iface->pGsCtx, {0, SWR_GS_CONTEXT_pVerts});
+          Value *pInputVertStride = LOAD(iface->pGsCtx, {0, SWR_GS_CONTEXT_inputVertStride});
+
+          Value *pVector = ADD(MUL(vert_chan_index, pInputVertStride), attrib);
+          Value *pInput = LOAD(GEP(pVertex, {pVector, unwrap(swizzle_index)}));
 
-    Value *pVector = ADD(MUL(unwrap(vertex_index), pInputVertStride), attrib);
+          Value *value = VEXTRACT(pInput, C(i));
+          res = VINSERT(res, value, C(i));
+       }
+
+       return wrap(res);
+    } else {
+       Value *attrib = LOAD(GEP(iface->pVtxAttribMap, {C(0), attr_index}));
+
+       Value *pVertex = LOAD(iface->pGsCtx, {0, SWR_GS_CONTEXT_pVerts});
+       Value *pInputVertStride = LOAD(iface->pGsCtx, {0, SWR_GS_CONTEXT_inputVertStride});
 
-    Value *pInput = LOAD(GEP(pVertex, {pVector, unwrap(swizzle_index)}));
+       Value *pVector = ADD(MUL(vert_index, pInputVertStride), attrib);
 
-    return wrap(pInput);
+       Value *pInput = LOAD(GEP(pVertex, {pVector, unwrap(swizzle_index)}));
+
+       return wrap(pInput);
+    }
 }
 
 // GS output stream layout