summaryrefslogtreecommitdiffstats
path: root/src/gallium/auxiliary/draw
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/auxiliary/draw')
-rw-r--r--src/gallium/auxiliary/draw/draw_context.c7
-rw-r--r--src/gallium/auxiliary/draw/draw_context.h3
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.c90
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.h1
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h11
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c9
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c1
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_vsplit_tmp.h42
8 files changed, 110 insertions, 54 deletions
diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index 4eb1919b871..78190388ef1 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -627,7 +627,8 @@ void draw_set_render( struct draw_context *draw,
*/
void
draw_set_indexes(struct draw_context *draw,
- const void *elements, unsigned elem_size)
+ const void *elements, unsigned elem_size,
+ unsigned elem_buffer_space)
{
assert(elem_size == 0 ||
elem_size == 1 ||
@@ -635,6 +636,10 @@ draw_set_indexes(struct draw_context *draw,
elem_size == 4);
draw->pt.user.elts = elements;
draw->pt.user.eltSizeIB = elem_size;
+ if (elem_size)
+ draw->pt.user.eltMax = elem_buffer_space / elem_size;
+ else
+ draw->pt.user.eltMax = 0;
}
diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h
index c7a40a1b1a2..47bad0d73d4 100644
--- a/src/gallium/auxiliary/draw/draw_context.h
+++ b/src/gallium/auxiliary/draw/draw_context.h
@@ -212,7 +212,8 @@ void draw_set_vertex_elements(struct draw_context *draw,
const struct pipe_vertex_element *elements);
void draw_set_indexes(struct draw_context *draw,
- const void *elements, unsigned elem_size);
+ const void *elements, unsigned elem_size,
+ unsigned available_space);
void draw_set_mapped_vertex_buffer(struct draw_context *draw,
unsigned attr, const void *buffer,
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 =
diff --git a/src/gallium/auxiliary/draw/draw_llvm.h b/src/gallium/auxiliary/draw/draw_llvm.h
index d517b290666..347fde2b55f 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.h
+++ b/src/gallium/auxiliary/draw/draw_llvm.h
@@ -271,6 +271,7 @@ typedef int
struct vertex_header *io,
const struct draw_vertex_buffer vbuffers[PIPE_MAX_ATTRIBS],
const unsigned *fetch_elts,
+ unsigned fetch_max_elt,
unsigned fetch_count,
unsigned stride,
struct pipe_vertex_buffer *vertex_buffers,
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index 84344c36773..44698db93d0 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -186,7 +186,8 @@ struct draw_context
/** bytes per index (0, 1, 2 or 4) */
unsigned eltSizeIB;
unsigned eltSize;
- int eltBias;
+ unsigned eltMax;
+ int eltBias;
unsigned min_index;
unsigned max_index;
@@ -460,4 +461,12 @@ draw_get_rasterizer_no_cull( struct draw_context *draw,
boolean flatshade );
+/**
+ * Return index i from the index buffer.
+ * If the index buffer would overflow we return the
+ * index of the first element in the vb.
+ */
+#define DRAW_GET_IDX(elts, i) \
+ ((i) >= draw->pt.user.eltMax) ? 0 : elts[i]
+
#endif /* DRAW_PRIVATE_H */
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
index a797d65de8c..14dde67b24c 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -339,7 +339,7 @@ draw_print_arrays(struct draw_context *draw, uint prim, int start, uint count)
#define PRIM_RESTART_LOOP(elements) \
do { \
for (i = start; i < end; i++) { \
- if (elements[i] == info->restart_index) { \
+ if (i < elt_max && elements[i] == info->restart_index) { \
if (cur_count > 0) { \
/* draw elts up to prev pos */ \
draw_pt_arrays(draw, prim, cur_start, cur_count); \
@@ -371,6 +371,7 @@ draw_pt_arrays_restart(struct draw_context *draw,
const unsigned start = info->start;
const unsigned count = info->count;
const unsigned end = start + count;
+ const unsigned elt_max = draw->pt.user.eltMax;
unsigned i, cur_start, cur_count;
assert(info->primitive_restart);
@@ -496,7 +497,7 @@ draw_vbo(struct draw_context *draw,
assert(info->instance_count > 0);
if (info->indexed)
assert(draw->pt.user.elts);
-
+
count = info->count;
draw->pt.user.eltBias = info->index_bias;
@@ -506,7 +507,7 @@ draw_vbo(struct draw_context *draw,
if (0)
debug_printf("draw_vbo(mode=%u start=%u count=%u):\n",
- info->mode, info->start, info->count);
+ info->mode, info->start, count);
if (0)
tgsi_dump(draw->vs.vertex_shader->state.tokens, 0);
@@ -534,7 +535,7 @@ draw_vbo(struct draw_context *draw,
}
if (0)
- draw_print_arrays(draw, info->mode, info->start, MIN2(info->count, 20));
+ draw_print_arrays(draw, info->mode, info->start, MIN2(count, 20));
index_limit = util_draw_max_index(draw->pt.vertex_buffer,
draw->pt.vertex_element,
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
index fa8baf38889..f734311e73c 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
@@ -359,6 +359,7 @@ llvm_pipeline_generic( struct draw_pt_middle_end *middle,
llvm_vert_info.verts,
draw->pt.user.vbuffer,
fetch_info->elts,
+ draw->pt.user.eltMax,
fetch_info->count,
fpme->vertex_size,
draw->pt.vertex_buffer,
diff --git a/src/gallium/auxiliary/draw/draw_pt_vsplit_tmp.h b/src/gallium/auxiliary/draw/draw_pt_vsplit_tmp.h
index 2e94705609f..2d8957e91e7 100644
--- a/src/gallium/auxiliary/draw/draw_pt_vsplit_tmp.h
+++ b/src/gallium/auxiliary/draw/draw_pt_vsplit_tmp.h
@@ -45,16 +45,16 @@ CONCAT(vsplit_primitive_, ELT_TYPE)(struct vsplit_frontend *vsplit,
unsigned fetch_start, fetch_count;
const ushort *draw_elts = NULL;
unsigned i;
-
- ib += istart;
+ const unsigned start = istart;
+ const unsigned end = istart + icount;
/* use the ib directly */
if (min_index == 0 && sizeof(ib[0]) == sizeof(draw_elts[0])) {
if (icount > vsplit->max_vertices)
return FALSE;
- for (i = 0; i < icount; i++) {
- ELT_TYPE idx = ib[i];
+ for (i = start; i < end; i++) {
+ ELT_TYPE idx = DRAW_GET_IDX(ib, i);
if (idx < min_index || idx > max_index) {
debug_printf("warning: index out of range\n");
}
@@ -85,23 +85,23 @@ CONCAT(vsplit_primitive_, ELT_TYPE)(struct vsplit_frontend *vsplit,
if (!draw_elts) {
if (min_index == 0) {
- for (i = 0; i < icount; i++) {
- ELT_TYPE idx = ib[i];
+ for (i = start; i < end; i++) {
+ ELT_TYPE idx = DRAW_GET_IDX(ib, i);
if (idx < min_index || idx > max_index) {
debug_printf("warning: index out of range\n");
}
- vsplit->draw_elts[i] = (ushort) idx;
+ vsplit->draw_elts[i - start] = (ushort) idx;
}
}
else {
- for (i = 0; i < icount; i++) {
- ELT_TYPE idx = ib[i];
+ for (i = start; i < end; i++) {
+ ELT_TYPE idx = DRAW_GET_IDX(ib, i);
if (idx < min_index || idx > max_index) {
debug_printf("warning: index out of range\n");
}
- vsplit->draw_elts[i] = (ushort) (idx - min_index);
+ vsplit->draw_elts[i - start] = (ushort) (idx - min_index);
}
}
@@ -138,41 +138,41 @@ CONCAT(vsplit_segment_cache_, ELT_TYPE)(struct vsplit_frontend *vsplit,
spoken = !!spoken;
if (ibias == 0) {
if (spoken)
- ADD_CACHE(vsplit, ib[ispoken]);
+ ADD_CACHE(vsplit, DRAW_GET_IDX(ib, ispoken));
for (i = spoken; i < icount; i++)
- ADD_CACHE(vsplit, ib[istart + i]);
+ ADD_CACHE(vsplit, DRAW_GET_IDX(ib, istart + i));
if (close)
- ADD_CACHE(vsplit, ib[iclose]);
+ ADD_CACHE(vsplit, DRAW_GET_IDX(ib, iclose));
}
else if (ibias > 0) {
if (spoken)
- ADD_CACHE(vsplit, (uint) ib[ispoken] + ibias);
+ ADD_CACHE(vsplit, (uint) DRAW_GET_IDX(ib, ispoken) + ibias);
for (i = spoken; i < icount; i++)
- ADD_CACHE(vsplit, (uint) ib[istart + i] + ibias);
+ ADD_CACHE(vsplit, (uint) DRAW_GET_IDX(ib, istart + i) + ibias);
if (close)
- ADD_CACHE(vsplit, (uint) ib[iclose] + ibias);
+ ADD_CACHE(vsplit, (uint) DRAW_GET_IDX(ib, iclose) + ibias);
}
else {
if (spoken) {
if ((int) ib[ispoken] < -ibias)
return;
- ADD_CACHE(vsplit, ib[ispoken] + ibias);
+ ADD_CACHE(vsplit, DRAW_GET_IDX(ib, ispoken) + ibias);
}
for (i = spoken; i < icount; i++) {
- if ((int) ib[istart + i] < -ibias)
+ if ((int) DRAW_GET_IDX(ib, istart + i) < -ibias)
return;
- ADD_CACHE(vsplit, ib[istart + i] + ibias);
+ ADD_CACHE(vsplit, DRAW_GET_IDX(ib, istart + i) + ibias);
}
if (close) {
- if ((int) ib[iclose] < -ibias)
+ if ((int) DRAW_GET_IDX(ib, iclose) < -ibias)
return;
- ADD_CACHE(vsplit, ib[iclose] + ibias);
+ ADD_CACHE(vsplit, DRAW_GET_IDX(ib, iclose) + ibias);
}
}