[Mesa-dev] [PATCH 1/4] gallivm, llvmpipe, draw: Support multiple constant buffers.
Brian Paul
brianp at vmware.com
Thu Dec 6 10:02:50 PST 2012
On 12/06/2012 10:35 AM, jfonseca at vmware.com wrote:
> From: José Fonseca<jfonseca at vmware.com>
>
> Support 4 (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.
> ---
> 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 +
> src/gallium/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 +-
> src/gallium/drivers/llvmpipe/lp_setup_context.h | 2 +-
> src/gallium/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 6f0e1de..039db8f 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 d7a630e..bd11886 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 04b286f..507c158 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 905070e..9675d4f 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 4
> +
> +
> /**
> * 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 cdc784c..9caac21 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 25cdff9..5afa436 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 2667aeb..ea7c805 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 b469907..5dc5bc4 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 26fa46d..35a1139 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;
> + }
> + }
> }
>
>
> @@ -818,6 +830,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);
>
> @@ -856,42 +869,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< LP_MAX_TGSI_CONST_BUFFERS; ++i) {
Instead of LP_MAX_TGSI_CONST_BUFFERS I think you could use
Elements(setup->constants) as elsewhere.
> + 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;
> + }
> }
>
>
> @@ -902,7 +917,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
> @@ -1037,7 +1051,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 c3dde80..55fbd9b 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 f810700..60809db 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 3b826de..aef222d 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 f89f952..dced5d2 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;
Reviewed-by: Brian Paul <brianp at vmware.com>
More information about the mesa-dev
mailing list