From 1d35f77228ad540a551a8e09e062b764a6e31f5e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Tue, 4 Dec 2012 14:52:44 +0000 Subject: [PATCH] gallivm,llvmpipe,draw: Support multiple constant buffers. Support 16 (defined in LP_MAX_TGSI_CONST_BUFFERS) as opposed to 32 (as defined by PIPE_MAX_CONSTANT_BUFFERS) because that would make the jit context become unnecessarily large. v2: Bump limit from 4 to 16 to cover ARB_uniform_buffer_object needs, per Dave Airlie. Reviewed-by: Brian Paul --- src/gallium/auxiliary/draw/draw_llvm.c | 5 +- src/gallium/auxiliary/draw/draw_llvm.h | 9 +- .../draw/draw_pt_fetch_shade_pipeline_llvm.c | 16 ++-- src/gallium/auxiliary/gallivm/lp_bld_limits.h | 3 + .../auxiliary/gallivm/lp_bld_tgsi_soa.c | 19 +++- src/gallium/drivers/llvmpipe/lp_context.h | 2 +- src/gallium/drivers/llvmpipe/lp_jit.c | 3 +- src/gallium/drivers/llvmpipe/lp_jit.h | 5 +- src/gallium/drivers/llvmpipe/lp_setup.c | 90 +++++++++++-------- src/gallium/drivers/llvmpipe/lp_setup.h | 3 +- .../drivers/llvmpipe/lp_setup_context.h | 2 +- .../drivers/llvmpipe/lp_state_derived.c | 5 +- src/gallium/drivers/llvmpipe/lp_state_fs.c | 2 +- 13 files changed, 103 insertions(+), 61 deletions(-) diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index 6f0e1de7481..039db8fce49 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.c +++ b/src/gallium/auxiliary/draw/draw_llvm.c @@ -161,8 +161,9 @@ create_jit_context_type(struct gallivm_state *gallivm, LLVMTypeRef elem_types[5]; LLVMTypeRef context_type; - elem_types[0] = LLVMPointerType(float_type, 0); /* vs_constants */ - elem_types[1] = LLVMPointerType(float_type, 0); /* gs_constants */ + elem_types[0] = LLVMArrayType(LLVMPointerType(float_type, 0), /* vs_constants */ + LP_MAX_TGSI_CONST_BUFFERS); + elem_types[1] = elem_types[0]; /* gs_constants */ elem_types[2] = LLVMPointerType(LLVMArrayType(LLVMArrayType(float_type, 4), DRAW_TOTAL_CLIP_PLANES), 0); elem_types[3] = LLVMPointerType(float_type, 0); /* viewport */ diff --git a/src/gallium/auxiliary/draw/draw_llvm.h b/src/gallium/auxiliary/draw/draw_llvm.h index d7a630eb015..bd11886149d 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.h +++ b/src/gallium/auxiliary/draw/draw_llvm.h @@ -32,6 +32,7 @@ #include "draw/draw_vs.h" #include "gallivm/lp_bld_sample.h" +#include "gallivm/lp_bld_limits.h" #include "pipe/p_context.h" #include "util/u_simple_list.h" @@ -94,8 +95,8 @@ enum { */ struct draw_jit_context { - const float *vs_constants; - const float *gs_constants; + const float *vs_constants[LP_MAX_TGSI_CONST_BUFFERS]; + const float *gs_constants[LP_MAX_TGSI_CONST_BUFFERS]; float (*planes) [DRAW_TOTAL_CLIP_PLANES][4]; float *viewport; @@ -104,10 +105,10 @@ struct draw_jit_context #define draw_jit_context_vs_constants(_gallivm, _ptr) \ - lp_build_struct_get(_gallivm, _ptr, 0, "vs_constants") + lp_build_struct_get_ptr(_gallivm, _ptr, 0, "vs_constants") #define draw_jit_context_gs_constants(_gallivm, _ptr) \ - lp_build_struct_get(_gallivm, _ptr, 1, "gs_constants") + lp_build_struct_get_ptr(_gallivm, _ptr, 1, "gs_constants") #define draw_jit_context_planes(_gallivm, _ptr) \ lp_build_struct_get(_gallivm, _ptr, 2, "planes") 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 04b286f0f5b..507c1586947 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 @@ -81,6 +81,8 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle, const unsigned nr = MAX2( shader->base.info.num_inputs, shader->base.info.num_outputs + 1 ); + unsigned i; + fpme->input_prim = in_prim; fpme->opt = opt; @@ -138,7 +140,6 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle, } else { /* Need to create new variant */ - unsigned i; /* First check if we've created too many variants. If so, free * 25% of the LRU to avoid using too much memory. @@ -171,11 +172,14 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle, fpme->current_variant = variant; - /*XXX we only support one constant buffer */ - fpme->llvm->jit_context.vs_constants = - draw->pt.user.vs_constants[0]; - fpme->llvm->jit_context.gs_constants = - draw->pt.user.gs_constants[0]; + for (i = 0; i < Elements(fpme->llvm->jit_context.vs_constants); ++i) { + fpme->llvm->jit_context.vs_constants[i] = + draw->pt.user.vs_constants[i]; + } + for (i = 0; i < Elements(fpme->llvm->jit_context.gs_constants); ++i) { + fpme->llvm->jit_context.gs_constants[i] = + draw->pt.user.gs_constants[i]; + } fpme->llvm->jit_context.planes = (float (*) [DRAW_TOTAL_CLIP_PLANES][4]) draw->pt.user.planes[0]; fpme->llvm->jit_context.viewport = diff --git a/src/gallium/auxiliary/gallivm/lp_bld_limits.h b/src/gallium/auxiliary/gallivm/lp_bld_limits.h index 905070e7ae8..30bed1ba31f 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_limits.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_limits.h @@ -51,6 +51,9 @@ #define LP_MAX_TGSI_PREDS 16 +#define LP_MAX_TGSI_CONST_BUFFERS 16 + + /** * Maximum control flow nesting * diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c index cdc784cf0df..9caac21fd9b 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c @@ -63,6 +63,7 @@ #include "lp_bld_debug.h" #include "lp_bld_printf.h" #include "lp_bld_sample.h" +#include "lp_bld_struct.h" static void lp_exec_mask_init(struct lp_exec_mask *mask, struct lp_build_context *bld) @@ -588,10 +589,22 @@ emit_fetch_constant( struct lp_build_context *uint_bld = &bld_base->uint_bld; LLVMValueRef indirect_index = NULL; struct lp_build_context *bld_fetch = stype_to_fetch(bld_base, stype); - + unsigned dimension = 0; + LLVMValueRef dimension_index; + LLVMValueRef consts_ptr; + /* XXX: Handle fetching xyzw components as a vector */ assert(swizzle != ~0); + if (reg->Register.Dimension) { + assert(!reg->Dimension.Indirect); + dimension = reg->Dimension.Index; + assert(dimension < LP_MAX_TGSI_CONST_BUFFERS); + } + + dimension_index = lp_build_const_int32(gallivm, dimension); + consts_ptr = lp_build_array_get(gallivm, bld->consts_ptr, dimension_index); + if (reg->Register.Indirect) { indirect_index = get_indirect_index(bld, reg->Register.File, @@ -609,7 +622,7 @@ emit_fetch_constant( index_vec = lp_build_add(uint_bld, index_vec, swizzle_vec); /* Gather values from the constant buffer */ - return build_gather(bld_fetch, bld->consts_ptr, index_vec); + return build_gather(bld_fetch, consts_ptr, index_vec); } else { LLVMValueRef index; /* index into the const buffer */ @@ -617,7 +630,7 @@ emit_fetch_constant( index = lp_build_const_int32(gallivm, reg->Register.Index*4 + swizzle); - scalar_ptr = LLVMBuildGEP(builder, bld->consts_ptr, + scalar_ptr = LLVMBuildGEP(builder, consts_ptr, &index, 1, ""); if (stype != TGSI_TYPE_FLOAT && stype != TGSI_TYPE_UNTYPED) { diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h index 25cdff998c4..5afa4360aae 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.h +++ b/src/gallium/drivers/llvmpipe/lp_context.h @@ -72,7 +72,7 @@ struct llvmpipe_context { struct pipe_blend_color blend_color; struct pipe_stencil_ref stencil_ref; struct pipe_clip_state clip; - struct pipe_resource *constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS]; + struct pipe_resource *constants[PIPE_SHADER_TYPES][LP_MAX_TGSI_CONST_BUFFERS]; struct pipe_framebuffer_state framebuffer; struct pipe_poly_stipple poly_stipple; struct pipe_scissor_state scissor; diff --git a/src/gallium/drivers/llvmpipe/lp_jit.c b/src/gallium/drivers/llvmpipe/lp_jit.c index 2667aeb24e6..ea7c8054bfa 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.c +++ b/src/gallium/drivers/llvmpipe/lp_jit.c @@ -124,7 +124,8 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp) LLVMTypeRef elem_types[LP_JIT_CTX_COUNT]; LLVMTypeRef context_type; - elem_types[LP_JIT_CTX_CONSTANTS] = LLVMPointerType(LLVMFloatTypeInContext(lc), 0); + elem_types[LP_JIT_CTX_CONSTANTS] = + LLVMArrayType(LLVMPointerType(LLVMFloatTypeInContext(lc), 0), LP_MAX_TGSI_CONST_BUFFERS); elem_types[LP_JIT_CTX_ALPHA_REF] = LLVMFloatTypeInContext(lc); elem_types[LP_JIT_CTX_STENCIL_REF_FRONT] = elem_types[LP_JIT_CTX_STENCIL_REF_BACK] = LLVMInt32TypeInContext(lc); diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h b/src/gallium/drivers/llvmpipe/lp_jit.h index b4699074656..5dc5bc4c4bf 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.h +++ b/src/gallium/drivers/llvmpipe/lp_jit.h @@ -37,6 +37,7 @@ #include "gallivm/lp_bld_struct.h" +#include "gallivm/lp_bld_limits.h" #include "pipe/p_state.h" #include "lp_texture.h" @@ -97,7 +98,7 @@ enum { */ struct lp_jit_context { - const float *constants; + const float *constants[LP_MAX_TGSI_CONST_BUFFERS]; float alpha_ref_value; @@ -127,7 +128,7 @@ enum { #define lp_jit_context_constants(_gallivm, _ptr) \ - lp_build_struct_get(_gallivm, _ptr, LP_JIT_CTX_CONSTANTS, "constants") + lp_build_struct_get_ptr(_gallivm, _ptr, LP_JIT_CTX_CONSTANTS, "constants") #define lp_jit_context_alpha_ref_value(_gallivm, _ptr) \ lp_build_struct_get(_gallivm, _ptr, LP_JIT_CTX_ALPHA_REF, "alpha_ref_value") diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 0f497afac53..7d40d8cf661 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -120,11 +120,15 @@ first_point( struct lp_setup_context *setup, void lp_setup_reset( struct lp_setup_context *setup ) { + unsigned i; + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); /* Reset derived state */ - setup->constants.stored_size = 0; - setup->constants.stored_data = NULL; + for (i = 0; i < Elements(setup->constants); ++i) { + setup->constants[i].stored_size = 0; + setup->constants[i].stored_data = NULL; + } setup->fs.stored = NULL; setup->dirty = ~0; @@ -549,13 +553,21 @@ lp_setup_set_fs_variant( struct lp_setup_context *setup, void lp_setup_set_fs_constants(struct lp_setup_context *setup, - struct pipe_resource *buffer) + unsigned num, + struct pipe_resource **buffers) { - LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffer); + unsigned i; + + LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffers); - pipe_resource_reference(&setup->constants.current, buffer); + assert(num <= Elements(setup->constants)); - setup->dirty |= LP_SETUP_NEW_CONSTANTS; + for (i = 0; i < num; ++i) { + if (setup->constants[i].current != buffers[i]) { + pipe_resource_reference(&setup->constants[i].current, buffers[i]); + setup->dirty |= LP_SETUP_NEW_CONSTANTS; + } + } } @@ -820,6 +832,7 @@ try_update_scene_state( struct lp_setup_context *setup ) { boolean new_scene = (setup->fs.stored == NULL); struct lp_scene *scene = setup->scene; + unsigned i; assert(scene); @@ -858,42 +871,44 @@ try_update_scene_state( struct lp_setup_context *setup ) setup->dirty |= LP_SETUP_NEW_FS; } - if(setup->dirty & LP_SETUP_NEW_CONSTANTS) { - struct pipe_resource *buffer = setup->constants.current; + if (setup->dirty & LP_SETUP_NEW_CONSTANTS) { + for (i = 0; i < Elements(setup->constants); ++i) { + struct pipe_resource *buffer = setup->constants[i].current; - if(buffer) { - unsigned current_size = buffer->width0; - const void *current_data = llvmpipe_resource_data(buffer); + if (buffer) { + unsigned current_size = buffer->width0; + const void *current_data = llvmpipe_resource_data(buffer); - /* TODO: copy only the actually used constants? */ + /* TODO: copy only the actually used constants? */ - if(setup->constants.stored_size != current_size || - !setup->constants.stored_data || - memcmp(setup->constants.stored_data, - current_data, - current_size) != 0) { - void *stored; + if (setup->constants[i].stored_size != current_size || + !setup->constants[i].stored_data || + memcmp(setup->constants[i].stored_data, + current_data, + current_size) != 0) { + void *stored; - stored = lp_scene_alloc(scene, current_size); - if (!stored) { - assert(!new_scene); - return FALSE; - } + stored = lp_scene_alloc(scene, current_size); + if (!stored) { + assert(!new_scene); + return FALSE; + } - memcpy(stored, - current_data, - current_size); - setup->constants.stored_size = current_size; - setup->constants.stored_data = stored; + memcpy(stored, + current_data, + current_size); + setup->constants[i].stored_size = current_size; + setup->constants[i].stored_data = stored; + } + } + else { + setup->constants[i].stored_size = 0; + setup->constants[i].stored_data = NULL; } - } - else { - setup->constants.stored_size = 0; - setup->constants.stored_data = NULL; - } - setup->fs.current.jit_context.constants = setup->constants.stored_data; - setup->dirty |= LP_SETUP_NEW_FS; + setup->fs.current.jit_context.constants[i] = setup->constants[i].stored_data; + setup->dirty |= LP_SETUP_NEW_FS; + } } @@ -904,7 +919,6 @@ try_update_scene_state( struct lp_setup_context *setup ) sizeof setup->fs.current) != 0) { struct lp_rast_state *stored; - uint i; /* The fs state that's been stored in the scene is different from * the new, current state. So allocate a new lp_rast_state object @@ -1039,7 +1053,9 @@ lp_setup_destroy( struct lp_setup_context *setup ) pipe_resource_reference(&setup->fs.current_tex[i], NULL); } - pipe_resource_reference(&setup->constants.current, NULL); + for (i = 0; i < Elements(setup->constants); i++) { + pipe_resource_reference(&setup->constants[i].current, NULL); + } /* free the scenes in the 'empty' queue */ for (i = 0; i < Elements(setup->scenes); i++) { diff --git a/src/gallium/drivers/llvmpipe/lp_setup.h b/src/gallium/drivers/llvmpipe/lp_setup.h index c3dde804002..55fbd9be8b8 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.h +++ b/src/gallium/drivers/llvmpipe/lp_setup.h @@ -100,7 +100,8 @@ lp_setup_set_fs_variant( struct lp_setup_context *setup, void lp_setup_set_fs_constants(struct lp_setup_context *setup, - struct pipe_resource *buffer); + unsigned num, + struct pipe_resource **buffers); void diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h index f810700ef29..60809db50a2 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_context.h +++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h @@ -131,7 +131,7 @@ struct lp_setup_context struct pipe_resource *current; unsigned stored_size; const void *stored_data; - } constants; + } constants[LP_MAX_TGSI_CONST_BUFFERS]; struct { struct pipe_blend_color current; diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c index 3b826de80c9..aef222d20f6 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_derived.c +++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c @@ -174,8 +174,9 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe ) } if (llvmpipe->dirty & LP_NEW_CONSTANTS) - lp_setup_set_fs_constants(llvmpipe->setup, - llvmpipe->constants[PIPE_SHADER_FRAGMENT][0]); + lp_setup_set_fs_constants(llvmpipe->setup, + Elements(llvmpipe->constants[PIPE_SHADER_FRAGMENT]), + llvmpipe->constants[PIPE_SHADER_FRAGMENT]); if (llvmpipe->dirty & (LP_NEW_SAMPLER_VIEW)) lp_setup_set_fragment_sampler_views(llvmpipe->setup, diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index f89f9525eee..dced5d25a7f 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -2422,7 +2422,7 @@ llvmpipe_set_constant_buffer(struct pipe_context *pipe, data = constants ? llvmpipe_resource_data(constants) : NULL; assert(shader < PIPE_SHADER_TYPES); - assert(index < PIPE_MAX_CONSTANT_BUFFERS); + assert(index < Elements(llvmpipe->constants[shader])); if(llvmpipe->constants[shader][index] == constants) return; -- 2.30.2