diff options
Diffstat (limited to 'src/gallium/auxiliary/draw/draw_llvm.c')
-rw-r--r-- | src/gallium/auxiliary/draw/draw_llvm.c | 90 |
1 files changed, 64 insertions, 26 deletions
diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index 24b7be31362..017d7294100 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.c +++ b/src/gallium/auxiliary/draw/draw_llvm.c @@ -1455,14 +1455,16 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant, struct gallivm_state *gallivm = variant->gallivm; LLVMContextRef context = gallivm->context; LLVMTypeRef int32_type = LLVMInt32TypeInContext(context); - LLVMTypeRef arg_types[8]; + LLVMTypeRef arg_types[9]; + unsigned num_arg_types = + elts ? Elements(arg_types) : Elements(arg_types) - 1; LLVMTypeRef func_type; LLVMValueRef context_ptr; LLVMBasicBlockRef block; LLVMBuilderRef builder; struct lp_type vs_type; LLVMValueRef end, start; - LLVMValueRef count, fetch_elts, fetch_count; + LLVMValueRef count, fetch_elts, fetch_elt_max, fetch_count; LLVMValueRef stride, step, io_itr; LLVMValueRef io_ptr, vbuffers_ptr, vb_ptr; LLVMValueRef zero = lp_build_const_int32(gallivm, 0); @@ -1495,19 +1497,21 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant, memset(&system_values, 0, sizeof(system_values)); - arg_types[0] = get_context_ptr_type(variant); /* context */ - arg_types[1] = get_vertex_header_ptr_type(variant); /* vertex_header */ - arg_types[2] = get_buffer_ptr_type(variant); /* vbuffers */ - if (elts) - arg_types[3] = LLVMPointerType(int32_type, 0);/* fetch_elts * */ - else - arg_types[3] = int32_type; /* start */ - arg_types[4] = int32_type; /* fetch_count / count */ - arg_types[5] = int32_type; /* stride */ - arg_types[6] = get_vb_ptr_type(variant); /* pipe_vertex_buffer's */ - arg_types[7] = int32_type; /* instance_id */ + i = 0; + arg_types[i++] = get_context_ptr_type(variant); /* context */ + arg_types[i++] = get_vertex_header_ptr_type(variant); /* vertex_header */ + arg_types[i++] = get_buffer_ptr_type(variant); /* vbuffers */ + if (elts) { + arg_types[i++] = LLVMPointerType(int32_type, 0);/* fetch_elts */ + arg_types[i++] = int32_type; /* fetch_elt_max */ + } else + arg_types[i++] = int32_type; /* start */ + arg_types[i++] = int32_type; /* fetch_count / count */ + arg_types[i++] = int32_type; /* stride */ + arg_types[i++] = get_vb_ptr_type(variant); /* pipe_vertex_buffer's */ + arg_types[i++] = int32_type; /* instance_id */ - func_type = LLVMFunctionType(int32_type, arg_types, Elements(arg_types), 0); + func_type = LLVMFunctionType(int32_type, arg_types, num_arg_types, 0); variant_func = LLVMAddFunction(gallivm->module, elts ? "draw_llvm_shader_elts" : "draw_llvm_shader", @@ -1519,7 +1523,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant, variant->function = variant_func; LLVMSetFunctionCallConv(variant_func, LLVMCCallConv); - for (i = 0; i < Elements(arg_types); ++i) + for (i = 0; i < num_arg_types; ++i) if (LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind) LLVMAddAttribute(LLVMGetParam(variant_func, i), LLVMNoAliasAttribute); @@ -1527,9 +1531,9 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant, context_ptr = LLVMGetParam(variant_func, 0); io_ptr = LLVMGetParam(variant_func, 1); vbuffers_ptr = LLVMGetParam(variant_func, 2); - stride = LLVMGetParam(variant_func, 5); - vb_ptr = LLVMGetParam(variant_func, 6); - system_values.instance_id = LLVMGetParam(variant_func, 7); + stride = LLVMGetParam(variant_func, 5 + (elts ? 1 : 0)); + vb_ptr = LLVMGetParam(variant_func, 6 + (elts ? 1 : 0)); + system_values.instance_id = LLVMGetParam(variant_func, 7 + (elts ? 1 : 0)); lp_build_name(context_ptr, "context"); lp_build_name(io_ptr, "io"); @@ -1539,9 +1543,11 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant, lp_build_name(system_values.instance_id, "instance_id"); if (elts) { - fetch_elts = LLVMGetParam(variant_func, 3); - fetch_count = LLVMGetParam(variant_func, 4); + fetch_elts = LLVMGetParam(variant_func, 3); + fetch_elt_max = LLVMGetParam(variant_func, 4); + fetch_count = LLVMGetParam(variant_func, 5); lp_build_name(fetch_elts, "fetch_elts"); + lp_build_name(fetch_elt_max, "fetch_elt_max"); lp_build_name(fetch_count, "fetch_count"); start = count = NULL; } @@ -1621,16 +1627,48 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant, * a few of the 4 vertex fetches will be out of bounds */ true_index = lp_build_min(&bld, true_index, fetch_max); + system_values.vertex_id = LLVMBuildInsertElement( + gallivm->builder, + system_values.vertex_id, true_index, + lp_build_const_int32(gallivm, i), ""); + if (elts) { LLVMValueRef fetch_ptr; - fetch_ptr = LLVMBuildGEP(builder, fetch_elts, - &true_index, 1, ""); - true_index = LLVMBuildLoad(builder, fetch_ptr, "fetch_elt"); + LLVMValueRef index_overflowed; + LLVMValueRef index_ptr = + lp_build_alloca( + gallivm, + lp_build_vec_type(gallivm, lp_type_int(32)), ""); + struct lp_build_if_state if_ctx; + index_overflowed = LLVMBuildICmp(builder, LLVMIntUGE, + true_index, fetch_elt_max, + "index_overflowed"); + + lp_build_if(&if_ctx, gallivm, index_overflowed); + { + /* Generate maximum possible index so that + * generate_fetch can treat it just like + * any other overflow and return zeros. + * We don't have to worry about the restart + * primitive index because it has already been + * handled + */ + LLVMValueRef val = + lp_build_const_int32(gallivm, 0xffffffff); + LLVMBuildStore(builder, val, index_ptr); + } + lp_build_else(&if_ctx); + { + LLVMValueRef val; + fetch_ptr = LLVMBuildGEP(builder, fetch_elts, + &true_index, 1, ""); + val = LLVMBuildLoad(builder, fetch_ptr, ""); + LLVMBuildStore(builder, val, index_ptr); + } + lp_build_endif(&if_ctx); + true_index = LLVMBuildLoad(builder, index_ptr, "true_index"); } - system_values.vertex_id = LLVMBuildInsertElement(gallivm->builder, - system_values.vertex_id, true_index, - lp_build_const_int32(gallivm, i), ""); for (j = 0; j < draw->pt.nr_vertex_elements; ++j) { struct pipe_vertex_element *velem = &draw->pt.vertex_element[j]; LLVMValueRef vb_index = |