summaryrefslogtreecommitdiffstats
path: root/src/gallium/auxiliary
diff options
context:
space:
mode:
authorZack Rusin <[email protected]>2013-05-08 23:48:20 -0400
committerZack Rusin <[email protected]>2013-05-14 03:09:32 -0400
commit29853ab7b8656cee9b92a53bec43f6e9f1e49691 (patch)
tree6b4ac7f1accc0358717fe98d6e8b1c5b982baafb /src/gallium/auxiliary
parent386327c48f88b052449afa4f41b1090d3fdb5ce9 (diff)
draw: don't crash on vertex buffer overflow
We would crash when stride was bigger than the size of the buffer. The correct behavior is to just fetch zero's in this case. Unfortunatly with user_buffer's there's no way to validate the size because currently we're just not getting it. Adjust the draw interface to pass the size along the mapped buffer, which works perfectly for buffer backed vertex_buffers and, in future, it will allow us to plumb user_buffer sizes through the same interface. 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')
-rw-r--r--src/gallium/auxiliary/draw/draw_context.c6
-rw-r--r--src/gallium/auxiliary/draw/draw_context.h3
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.c99
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.h16
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h10
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c7
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch.c4
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_emit.c2
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c2
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c4
10 files changed, 122 insertions, 31 deletions
diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index 6caa62ab31b..4eb1919b871 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -364,9 +364,11 @@ draw_set_vertex_elements(struct draw_context *draw,
*/
void
draw_set_mapped_vertex_buffer(struct draw_context *draw,
- unsigned attr, const void *buffer)
+ unsigned attr, const void *buffer,
+ size_t size)
{
- draw->pt.user.vbuffer[attr] = buffer;
+ draw->pt.user.vbuffer[attr].map = buffer;
+ draw->pt.user.vbuffer[attr].size = size;
}
diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h
index 94fac880c68..c7a40a1b1a2 100644
--- a/src/gallium/auxiliary/draw/draw_context.h
+++ b/src/gallium/auxiliary/draw/draw_context.h
@@ -215,7 +215,8 @@ void draw_set_indexes(struct draw_context *draw,
const void *elements, unsigned elem_size);
void draw_set_mapped_vertex_buffer(struct draw_context *draw,
- unsigned attr, const void *buffer);
+ unsigned attr, const void *buffer,
+ size_t size);
void
draw_set_mapped_constant_buffer(struct draw_context *draw,
diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
index 8e2ab1e3006..24b7be31362 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_llvm.c
@@ -78,6 +78,44 @@ draw_gs_llvm_iface(const struct lp_build_tgsi_gs_iface *iface)
}
/**
+ * Create LLVM type for draw_vertex_buffer.
+ */
+static LLVMTypeRef
+create_jit_dvbuffer_type(struct gallivm_state *gallivm,
+ const char *struct_name)
+{
+ LLVMTargetDataRef target = gallivm->target;
+ LLVMTypeRef dvbuffer_type;
+ LLVMTypeRef elem_types[DRAW_JIT_DVBUFFER_NUM_FIELDS];
+ LLVMTypeRef int32_type = LLVMInt32TypeInContext(gallivm->context);
+
+ elem_types[DRAW_JIT_DVBUFFER_MAP] =
+ LLVMPointerType(LLVMIntTypeInContext(gallivm->context, 8), 0);
+ elem_types[DRAW_JIT_DVBUFFER_SIZE] = int32_type;
+
+ dvbuffer_type = LLVMStructTypeInContext(gallivm->context, elem_types,
+ Elements(elem_types), 0);
+
+#if HAVE_LLVM < 0x0300
+ LLVMAddTypeName(gallivm->module, struct_name, dvbuffer_type);
+
+ /* Make sure the target's struct layout cache doesn't return
+ * stale/invalid data.
+ */
+ LLVMInvalidateStructLayout(gallivm->target, dvbuffer_type);
+#endif
+
+ LP_CHECK_MEMBER_OFFSET(struct draw_vertex_buffer, map,
+ target, dvbuffer_type,
+ DRAW_JIT_DVBUFFER_MAP);
+ LP_CHECK_MEMBER_OFFSET(struct draw_vertex_buffer, size,
+ target, dvbuffer_type,
+ DRAW_JIT_DVBUFFER_SIZE);
+
+ return dvbuffer_type;
+}
+
+/**
* Create LLVM type for struct draw_jit_texture
*/
static LLVMTypeRef
@@ -328,7 +366,8 @@ create_gs_jit_input_type(struct gallivm_state *gallivm)
* Create LLVM type for struct pipe_vertex_buffer
*/
static LLVMTypeRef
-create_jit_vertex_buffer_type(struct gallivm_state *gallivm, const char *struct_name)
+create_jit_vertex_buffer_type(struct gallivm_state *gallivm,
+ const char *struct_name)
{
LLVMTargetDataRef target = gallivm->target;
LLVMTypeRef elem_types[4];
@@ -337,7 +376,7 @@ create_jit_vertex_buffer_type(struct gallivm_state *gallivm, const char *struct_
elem_types[0] =
elem_types[1] = LLVMInt32TypeInContext(gallivm->context);
elem_types[2] =
- elem_types[3] = LLVMPointerType(LLVMInt8TypeInContext(gallivm->context), 0); /* vs_constants */
+ elem_types[3] = LLVMPointerType(LLVMInt8TypeInContext(gallivm->context), 0);
vb_type = LLVMStructTypeInContext(gallivm->context, elem_types,
Elements(elem_types), 0);
@@ -422,7 +461,8 @@ static void
create_jit_types(struct draw_llvm_variant *variant)
{
struct gallivm_state *gallivm = variant->gallivm;
- LLVMTypeRef texture_type, sampler_type, context_type, buffer_type, vb_type;
+ LLVMTypeRef texture_type, sampler_type, context_type, buffer_type,
+ vb_type;
texture_type = create_jit_texture_type(gallivm, "texture");
sampler_type = create_jit_sampler_type(gallivm, "sampler");
@@ -431,9 +471,9 @@ create_jit_types(struct draw_llvm_variant *variant)
"draw_jit_context");
variant->context_ptr_type = LLVMPointerType(context_type, 0);
- buffer_type = LLVMPointerType(LLVMIntTypeInContext(gallivm->context, 8), 0);
+ buffer_type = create_jit_dvbuffer_type(gallivm, "draw_vertex_buffer");
variant->buffer_ptr_type = LLVMPointerType(buffer_type, 0);
-
+
vb_type = create_jit_vertex_buffer_type(gallivm, "pipe_vertex_buffer");
variant->vb_ptr_type = LLVMPointerType(vb_type, 0);
}
@@ -631,7 +671,6 @@ generate_vs(struct draw_llvm_variant *variant,
}
}
-
static void
generate_fetch(struct gallivm_state *gallivm,
LLVMValueRef vbuffers_ptr,
@@ -641,7 +680,8 @@ generate_fetch(struct gallivm_state *gallivm,
LLVMValueRef index,
LLVMValueRef instance_id)
{
- const struct util_format_description *format_desc = util_format_description(velem->src_format);
+ const struct util_format_description *format_desc =
+ util_format_description(velem->src_format);
LLVMValueRef zero = LLVMConstNull(LLVMInt32TypeInContext(gallivm->context));
LLVMBuilderRef builder = gallivm->builder;
LLVMValueRef indices =
@@ -651,7 +691,14 @@ generate_fetch(struct gallivm_state *gallivm,
&indices, 1, "");
LLVMValueRef vb_stride = draw_jit_vbuffer_stride(gallivm, vbuf);
LLVMValueRef vb_buffer_offset = draw_jit_vbuffer_offset(gallivm, vbuf);
+ LLVMValueRef map_ptr = draw_jit_dvbuffer_map(gallivm, vbuffer_ptr);
+ LLVMValueRef buffer_size = draw_jit_dvbuffer_size(gallivm, vbuffer_ptr);
LLVMValueRef stride;
+ LLVMValueRef buffer_overflowed;
+ LLVMValueRef temp_ptr =
+ lp_build_alloca(gallivm,
+ lp_build_vec_type(gallivm, lp_float32_vec4_type()), "");
+ struct lp_build_if_state if_ctx;
if (velem->instance_divisor) {
/* array index = instance_id / instance_divisor */
@@ -662,8 +709,6 @@ generate_fetch(struct gallivm_state *gallivm,
stride = LLVMBuildMul(builder, vb_stride, index, "");
- vbuffer_ptr = LLVMBuildLoad(builder, vbuffer_ptr, "vbuffer");
-
stride = LLVMBuildAdd(builder, stride,
vb_buffer_offset,
"");
@@ -671,14 +716,36 @@ generate_fetch(struct gallivm_state *gallivm,
lp_build_const_int32(gallivm, velem->src_offset),
"");
-/* lp_build_printf(gallivm, "vbuf index = %d, stride is %d\n", indices, stride);*/
- vbuffer_ptr = LLVMBuildGEP(builder, vbuffer_ptr, &stride, 1, "");
+ buffer_overflowed = LLVMBuildICmp(builder, LLVMIntUGE,
+ stride, buffer_size,
+ "buffer_overflowed");
+ /*
+ lp_build_printf(gallivm, "vbuf index = %d, stride is %d\n", indices, stride);
+ lp_build_print_value(gallivm, " buffer size = ", buffer_size);
+ lp_build_print_value(gallivm, " buffer overflowed = ", buffer_overflowed);
+ */
+
+ lp_build_if(&if_ctx, gallivm, buffer_overflowed);
+ {
+ LLVMValueRef val =
+ lp_build_const_vec(gallivm, lp_float32_vec4_type(), 0);
+ LLVMBuildStore(builder, val, temp_ptr);
+ }
+ lp_build_else(&if_ctx);
+ {
+ LLVMValueRef val;
+ map_ptr = LLVMBuildGEP(builder, map_ptr, &stride, 1, "");
+
+ val = lp_build_fetch_rgba_aos(gallivm,
+ format_desc,
+ lp_float32_vec4_type(),
+ map_ptr,
+ zero, zero, zero);
+ LLVMBuildStore(builder, val, temp_ptr);
+ }
+ lp_build_endif(&if_ctx);
- *res = lp_build_fetch_rgba_aos(gallivm,
- format_desc,
- lp_float32_vec4_type(),
- vbuffer_ptr,
- zero, zero, zero);
+ *res = LLVMBuildLoad(builder, temp_ptr, "aos");
}
static void
diff --git a/src/gallium/auxiliary/draw/draw_llvm.h b/src/gallium/auxiliary/draw/draw_llvm.h
index 5909fc10a2d..d517b290666 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.h
+++ b/src/gallium/auxiliary/draw/draw_llvm.h
@@ -173,6 +173,18 @@ enum {
#define draw_jit_vbuffer_offset(_gallivm, _ptr) \
lp_build_struct_get(_gallivm, _ptr, 1, "buffer_offset")
+enum {
+ DRAW_JIT_DVBUFFER_MAP = 0,
+ DRAW_JIT_DVBUFFER_SIZE,
+ DRAW_JIT_DVBUFFER_NUM_FIELDS /* number of fields above */
+};
+
+#define draw_jit_dvbuffer_map(_gallivm, _ptr) \
+ lp_build_struct_get(_gallivm, _ptr, DRAW_JIT_DVBUFFER_MAP, "map")
+
+#define draw_jit_dvbuffer_size(_gallivm, _ptr) \
+ lp_build_struct_get(_gallivm, _ptr, DRAW_JIT_DVBUFFER_SIZE, "size")
+
/**
* This structure is passed directly to the generated geometry shader.
@@ -246,7 +258,7 @@ enum {
typedef int
(*draw_jit_vert_func)(struct draw_jit_context *context,
struct vertex_header *io,
- const char *vbuffers[PIPE_MAX_ATTRIBS],
+ const struct draw_vertex_buffer vbuffers[PIPE_MAX_ATTRIBS],
unsigned start,
unsigned count,
unsigned stride,
@@ -257,7 +269,7 @@ typedef int
typedef int
(*draw_jit_vert_func_elts)(struct draw_jit_context *context,
struct vertex_header *io,
- const char *vbuffers[PIPE_MAX_ATTRIBS],
+ const struct draw_vertex_buffer vbuffers[PIPE_MAX_ATTRIBS],
const unsigned *fetch_elts,
unsigned fetch_count,
unsigned stride,
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index 25a8ae61498..84344c36773 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -67,6 +67,14 @@ struct draw_pt_front_end;
/**
+ * Represents the mapped vertex buffer.
+ */
+struct draw_vertex_buffer {
+ const void *map;
+ size_t size;
+};
+
+/**
* Basic vertex info.
* Carry some useful information around with the vertices in the prim pipe.
*/
@@ -183,7 +191,7 @@ struct draw_context
unsigned max_index;
/** vertex arrays */
- const void *vbuffer[PIPE_MAX_ATTRIBS];
+ struct draw_vertex_buffer vbuffer[PIPE_MAX_ATTRIBS];
/** constant buffers (for vertex/geometry shader) */
const void *vs_constants[PIPE_MAX_CONSTANT_BUFFERS];
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
index 602d076dce2..a797d65de8c 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -282,7 +282,7 @@ draw_print_arrays(struct draw_context *draw, uint prim, int start, uint count)
for (j = 0; j < draw->pt.nr_vertex_elements; j++) {
uint buf = draw->pt.vertex_element[j].vertex_buffer_index;
- ubyte *ptr = (ubyte *) draw->pt.user.vbuffer[buf];
+ ubyte *ptr = (ubyte *) draw->pt.user.vbuffer[buf].map;
if (draw->pt.vertex_element[j].instance_divisor) {
ii = draw->instance_id / draw->pt.vertex_element[j].instance_divisor;
@@ -524,11 +524,12 @@ draw_vbo(struct draw_context *draw,
}
debug_printf("Buffers:\n");
for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
- debug_printf(" %u: stride=%u offset=%u ptr=%p\n",
+ debug_printf(" %u: stride=%u offset=%u size=%d ptr=%p\n",
i,
draw->pt.vertex_buffer[i].stride,
draw->pt.vertex_buffer[i].buffer_offset,
- draw->pt.user.vbuffer[i]);
+ draw->pt.user.vbuffer[i].size,
+ draw->pt.user.vbuffer[i].map);
}
}
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch.c b/src/gallium/auxiliary/draw/draw_pt_fetch.c
index 9fab7b681fb..3740deab5a8 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch.c
@@ -159,7 +159,7 @@ draw_pt_fetch_run(struct pt_fetch *fetch,
for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
translate->set_buffer(translate,
i,
- ((char *)draw->pt.user.vbuffer[i] +
+ ((char *)draw->pt.user.vbuffer[i].map +
draw->pt.vertex_buffer[i].buffer_offset),
draw->pt.vertex_buffer[i].stride,
draw->pt.max_index);
@@ -186,7 +186,7 @@ draw_pt_fetch_run_linear(struct pt_fetch *fetch,
for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
translate->set_buffer(translate,
i,
- ((char *)draw->pt.user.vbuffer[i] +
+ ((char *)draw->pt.user.vbuffer[i].map +
draw->pt.vertex_buffer[i].buffer_offset),
draw->pt.vertex_buffer[i].stride,
draw->pt.max_index);
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
index f30db1386cc..dc6decba70e 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
@@ -169,7 +169,7 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
feme->translate->set_buffer(feme->translate,
i,
- ((char *)draw->pt.user.vbuffer[i] +
+ ((char *)draw->pt.user.vbuffer[i].map +
draw->pt.vertex_buffer[i].buffer_offset),
draw->pt.vertex_buffer[i].stride,
draw->pt.max_index);
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
index 870b23bbf58..d30cd412ef6 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
@@ -159,7 +159,7 @@ fse_prepare(struct draw_pt_middle_end *middle,
for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
fse->active->set_buffer( fse->active,
i,
- ((const ubyte *) draw->pt.user.vbuffer[i] +
+ ((const ubyte *) draw->pt.user.vbuffer[i].map +
draw->pt.vertex_buffer[i].buffer_offset),
draw->pt.vertex_buffer[i].stride,
draw->pt.max_index );
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 1924c7351b2..bc99c169deb 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
@@ -348,7 +348,7 @@ llvm_pipeline_generic( struct draw_pt_middle_end *middle,
if (fetch_info->linear)
clipped = fpme->current_variant->jit_func( &fpme->llvm->jit_context,
llvm_vert_info.verts,
- (const char **)draw->pt.user.vbuffer,
+ draw->pt.user.vbuffer,
fetch_info->start,
fetch_info->count,
fpme->vertex_size,
@@ -357,7 +357,7 @@ llvm_pipeline_generic( struct draw_pt_middle_end *middle,
else
clipped = fpme->current_variant->jit_func_elts( &fpme->llvm->jit_context,
llvm_vert_info.verts,
- (const char **)draw->pt.user.vbuffer,
+ draw->pt.user.vbuffer,
fetch_info->elts,
fetch_info->count,
fpme->vertex_size,