diff options
author | Zack Rusin <[email protected]> | 2013-05-08 23:48:20 -0400 |
---|---|---|
committer | Zack Rusin <[email protected]> | 2013-05-14 03:09:32 -0400 |
commit | 29853ab7b8656cee9b92a53bec43f6e9f1e49691 (patch) | |
tree | 6b4ac7f1accc0358717fe98d6e8b1c5b982baafb /src/gallium/auxiliary/draw/draw_llvm.c | |
parent | 386327c48f88b052449afa4f41b1090d3fdb5ce9 (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/draw/draw_llvm.c')
-rw-r--r-- | src/gallium/auxiliary/draw/draw_llvm.c | 99 |
1 files changed, 83 insertions, 16 deletions
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 |