summaryrefslogtreecommitdiffstats
path: root/src/gallium/auxiliary/draw/draw_llvm.c
diff options
context:
space:
mode:
authorZack Rusin <[email protected]>2013-05-13 23:07:14 -0400
committerZack Rusin <[email protected]>2013-05-14 03:10:56 -0400
commit5104ed3dbf18d47736fc67a8e3e317ea18360fa8 (patch)
treed161f1e6f09b3ab6846b064105b8cfc014b203cc /src/gallium/auxiliary/draw/draw_llvm.c
parentd5250da8189d0fb9741049cdbfc50e84aab44ecb (diff)
draw: try to prevent overflows on index buffers
Pass in the size of the index buffer, when available, and use it to handle out of bounds conditions. The behavior in the case of an overflow needs to be the same as with other overflows in the vertex processing pipeline meaning that a vertex should still be generated but all attributes in it set to zero. Signed-off-by: Zack Rusin <[email protected]> Reviewed-by: José Fonseca <[email protected]> Reviewed-by: Roland Scheidegger <[email protected]>
Diffstat (limited to 'src/gallium/auxiliary/draw/draw_llvm.c')
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.c90
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 =