[Mesa-dev] [PATCH] llvmpipe: fix possible constant buffer overflow

Roland Scheidegger sroland at vmware.com
Wed Dec 18 17:02:35 PST 2013


Am 19.12.2013 01:16, schrieb Zack Rusin:
> It's possible to bind a smaller buffer as a constant buffer, than
> what the shader actually uses/requires. This could cause nasty
> crashes. This patch adds the architecture to pass the maximum
> allowable constant buffer index to the jit so let it make
> sure that the constant buffer indices are always within bounds.
> Currently only used for indirect addressing.
> 
> Signed-off-by: Zack Rusin <zackr at vmware.com>
> ---
>  src/gallium/auxiliary/draw/draw_llvm.c             | 42 +++++++++++++++-------
>  src/gallium/auxiliary/draw/draw_llvm.h             | 32 +++++++++++------
>  .../draw/draw_pt_fetch_shade_pipeline_llvm.c       |  6 ++++
>  src/gallium/auxiliary/gallivm/lp_bld_tgsi.h        |  2 ++
>  src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c    | 14 +++++++-
>  src/gallium/drivers/llvmpipe/lp_jit.c              |  7 +++-
>  src/gallium/drivers/llvmpipe/lp_jit.h              |  5 +++
>  src/gallium/drivers/llvmpipe/lp_setup.c            |  7 +++-
>  src/gallium/drivers/llvmpipe/lp_state_fs.c         |  6 ++--
>  9 files changed, 92 insertions(+), 29 deletions(-)
> 
> diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
> index 71cc45f..e5a3842 100644
> --- a/src/gallium/auxiliary/draw/draw_llvm.c
> +++ b/src/gallium/auxiliary/draw/draw_llvm.c
> @@ -242,17 +242,20 @@ create_jit_context_type(struct gallivm_state *gallivm,
>  {
>     LLVMTargetDataRef target = gallivm->target;
>     LLVMTypeRef float_type = LLVMFloatTypeInContext(gallivm->context);
> +   LLVMTypeRef int_type = LLVMInt32TypeInContext(gallivm->context);
>     LLVMTypeRef elem_types[DRAW_JIT_CTX_NUM_FIELDS];
>     LLVMTypeRef context_type;
>  
>     elem_types[0] = LLVMArrayType(LLVMPointerType(float_type, 0), /* vs_constants */
>                                   LP_MAX_TGSI_CONST_BUFFERS);
> -   elem_types[1] = LLVMPointerType(LLVMArrayType(LLVMArrayType(float_type, 4),
> +   elem_types[1] = LLVMArrayType(int_type, /* vs_constants_max_index */
> +                                 LP_MAX_TGSI_CONST_BUFFERS);
> +   elem_types[2] = LLVMPointerType(LLVMArrayType(LLVMArrayType(float_type, 4),
>                                                   DRAW_TOTAL_CLIP_PLANES), 0);
> -   elem_types[2] = LLVMPointerType(float_type, 0); /* viewport */
> -   elem_types[3] = LLVMArrayType(texture_type,
> +   elem_types[3] = LLVMPointerType(float_type, 0); /* viewport */
> +   elem_types[4] = LLVMArrayType(texture_type,
>                                   PIPE_MAX_SHADER_SAMPLER_VIEWS); /* textures */
> -   elem_types[4] = LLVMArrayType(sampler_type,
> +   elem_types[5] = LLVMArrayType(sampler_type,
>                                   PIPE_MAX_SAMPLERS); /* samplers */
>     context_type = LLVMStructTypeInContext(gallivm->context, elem_types,
>                                            Elements(elem_types), 0);
> @@ -264,6 +267,8 @@ create_jit_context_type(struct gallivm_state *gallivm,
>  
>     LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, vs_constants,
>                            target, context_type, DRAW_JIT_CTX_CONSTANTS);
> +   LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, vs_constants_max_index,
> +                          target, context_type, DRAW_JIT_CTX_CONSTANTS_MAX_INDEX);
>     LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, planes,
>                            target, context_type, DRAW_JIT_CTX_PLANES);
>     LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, viewport,
> @@ -298,20 +303,22 @@ create_gs_jit_context_type(struct gallivm_state *gallivm,
>  
>     elem_types[0] = LLVMArrayType(LLVMPointerType(float_type, 0), /* constants */
>                                   LP_MAX_TGSI_CONST_BUFFERS);
> -   elem_types[1] = LLVMPointerType(LLVMArrayType(LLVMArrayType(float_type, 4),
> +   elem_types[1] = LLVMArrayType(int_type, /* constants_max_index */
> +                                 LP_MAX_TGSI_CONST_BUFFERS);
> +   elem_types[2] = LLVMPointerType(LLVMArrayType(LLVMArrayType(float_type, 4),
>                                                   DRAW_TOTAL_CLIP_PLANES), 0);
> -   elem_types[2] = LLVMPointerType(float_type, 0); /* viewport */
> +   elem_types[3] = LLVMPointerType(float_type, 0); /* viewport */
>  
> -   elem_types[3] = LLVMArrayType(texture_type,
> +   elem_types[4] = LLVMArrayType(texture_type,
>                                   PIPE_MAX_SHADER_SAMPLER_VIEWS); /* textures */
> -   elem_types[4] = LLVMArrayType(sampler_type,
> +   elem_types[5] = LLVMArrayType(sampler_type,
>                                   PIPE_MAX_SAMPLERS); /* samplers */
>     
> -   elem_types[5] = LLVMPointerType(LLVMPointerType(int_type, 0), 0);
> -   elem_types[6] = LLVMPointerType(LLVMVectorType(int_type,
> -                                                  vector_length), 0);
> +   elem_types[6] = LLVMPointerType(LLVMPointerType(int_type, 0), 0);
>     elem_types[7] = LLVMPointerType(LLVMVectorType(int_type,
>                                                    vector_length), 0);
> +   elem_types[8] = LLVMPointerType(LLVMVectorType(int_type,
> +                                                  vector_length), 0);
>  
>     context_type = LLVMStructTypeInContext(gallivm->context, elem_types,
>                                            Elements(elem_types), 0);
> @@ -323,6 +330,8 @@ create_gs_jit_context_type(struct gallivm_state *gallivm,
>  
>     LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, constants,
>                            target, context_type, DRAW_GS_JIT_CTX_CONSTANTS);
> +   LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, constants_max_index,
> +                          target, context_type, DRAW_GS_JIT_CTX_CONSTANTS_MAX_INDEX);
>     LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, planes,
>                            target, context_type, DRAW_GS_JIT_CTX_PLANES);
>     LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, viewport,
> @@ -617,7 +626,10 @@ generate_vs(struct draw_llvm_variant *variant,
>  {
>     struct draw_llvm *llvm = variant->llvm;
>     const struct tgsi_token *tokens = llvm->draw->vs.vertex_shader->state.tokens;
> -   LLVMValueRef consts_ptr = draw_jit_context_vs_constants(variant->gallivm, context_ptr);
> +   LLVMValueRef consts_ptr =
> +      draw_jit_context_vs_constants(variant->gallivm, context_ptr);
> +   LLVMValueRef consts_max_index_ptr =
> +      draw_jit_context_vs_constants_max_index(variant->gallivm, context_ptr);
>     struct lp_build_sampler_soa *sampler = 0;
>  
>     if (gallivm_debug & (GALLIVM_DEBUG_TGSI | GALLIVM_DEBUG_IR)) {
> @@ -633,6 +645,7 @@ generate_vs(struct draw_llvm_variant *variant,
>                       vs_type,
>                       NULL /*struct lp_build_mask_context *mask*/,
>                       consts_ptr,
> +                     consts_max_index_ptr,
>                       system_values,
>                       inputs,
>                       outputs,
> @@ -2089,7 +2102,7 @@ draw_gs_llvm_generate(struct draw_llvm *llvm,
>     unsigned i;
>     struct draw_gs_llvm_iface gs_iface;
>     const struct tgsi_token *tokens = variant->shader->base.state.tokens;
> -   LLVMValueRef consts_ptr;
> +   LLVMValueRef consts_ptr, consts_max_index_ptr;
>     LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][TGSI_NUM_CHANNELS];
>     struct lp_build_mask_context mask;
>     const struct tgsi_shader_info *gs_info = &variant->shader->base.info;
> @@ -2163,6 +2176,8 @@ draw_gs_llvm_generate(struct draw_llvm *llvm,
>     gs_type.length = vector_length;
>  
>     consts_ptr = draw_gs_jit_context_constants(variant->gallivm, context_ptr);
> +   consts_max_index_ptr =
> +      draw_gs_jit_context_constants_max_index(variant->gallivm, context_ptr);
>  
>     /* code generated texture sampling */
>     sampler = draw_llvm_sampler_soa_create(variant->key.samplers,
> @@ -2185,6 +2200,7 @@ draw_gs_llvm_generate(struct draw_llvm *llvm,
>                       gs_type,
>                       &mask,
>                       consts_ptr,
> +                     consts_max_index_ptr,
>                       &system_values,
>                       NULL,
>                       outputs,
> diff --git a/src/gallium/auxiliary/draw/draw_llvm.h b/src/gallium/auxiliary/draw/draw_llvm.h
> index 1d238a2..5005ba6 100644
> --- a/src/gallium/auxiliary/draw/draw_llvm.h
> +++ b/src/gallium/auxiliary/draw/draw_llvm.h
> @@ -123,6 +123,7 @@ enum {
>  struct draw_jit_context
>  {
>     const float *vs_constants[LP_MAX_TGSI_CONST_BUFFERS];
> +   int vs_constants_max_index[LP_MAX_TGSI_CONST_BUFFERS];
>     float (*planes) [DRAW_TOTAL_CLIP_PLANES][4];
>     float *viewport;
>  
> @@ -131,17 +132,21 @@ struct draw_jit_context
>  };
>  
>  enum {
> -   DRAW_JIT_CTX_CONSTANTS   = 0,
> -   DRAW_JIT_CTX_PLANES      = 1,
> -   DRAW_JIT_CTX_VIEWPORT    = 2,
> -   DRAW_JIT_CTX_TEXTURES    = 3,
> -   DRAW_JIT_CTX_SAMPLERS    = 4,
> +   DRAW_JIT_CTX_CONSTANTS            = 0,
> +   DRAW_JIT_CTX_CONSTANTS_MAX_INDEX  = 1,
> +   DRAW_JIT_CTX_PLANES               = 2,
> +   DRAW_JIT_CTX_VIEWPORT             = 3,
> +   DRAW_JIT_CTX_TEXTURES             = 4,
> +   DRAW_JIT_CTX_SAMPLERS             = 5,
>     DRAW_JIT_CTX_NUM_FIELDS
>  };
>  
>  #define draw_jit_context_vs_constants(_gallivm, _ptr) \
>     lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_JIT_CTX_CONSTANTS, "vs_constants")
>  
> +#define draw_jit_context_vs_constants_max_index(_gallivm, _ptr) \
> +   lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_JIT_CTX_CONSTANTS_MAX_INDEX, "vs_constants_max_index")
> +
>  #define draw_jit_context_planes(_gallivm, _ptr) \
>     lp_build_struct_get(_gallivm, _ptr, DRAW_JIT_CTX_PLANES, "planes")
>  
> @@ -200,6 +205,7 @@ enum {
>  struct draw_gs_jit_context
>  {
>     const float *constants[LP_MAX_TGSI_CONST_BUFFERS];
> +   int constants_max_index[LP_MAX_TGSI_CONST_BUFFERS];
>     float (*planes) [DRAW_TOTAL_CLIP_PLANES][4];
>     float *viewport;
>  
> @@ -215,23 +221,27 @@ struct draw_gs_jit_context
>  
>  enum {
>     DRAW_GS_JIT_CTX_CONSTANTS = 0,
> -   DRAW_GS_JIT_CTX_PLANES = 1,
> -   DRAW_GS_JIT_CTX_VIEWPORT = 2,
> +   DRAW_GS_JIT_CTX_CONSTANTS_MAX_INDEX = 1,
> +   DRAW_GS_JIT_CTX_PLANES = 2,
> +   DRAW_GS_JIT_CTX_VIEWPORT = 3,
>     /* Textures and samples are reserved for DRAW_JIT_CTX_TEXTURES
>      * and DRAW_JIT_CTX_SAMPLERS, because they both need
>      * to be at exactly the same locations as they are in the
>      * VS ctx structure for sampling to work. */
>     DRAW_GS_JIT_CTX_TEXTURES = DRAW_JIT_CTX_TEXTURES,
>     DRAW_GS_JIT_CTX_SAMPLERS = DRAW_JIT_CTX_SAMPLERS,
> -   DRAW_GS_JIT_CTX_PRIM_LENGTHS = 5,
> -   DRAW_GS_JIT_CTX_EMITTED_VERTICES = 6,
> -   DRAW_GS_JIT_CTX_EMITTED_PRIMS = 7,
> -   DRAW_GS_JIT_CTX_NUM_FIELDS = 8
> +   DRAW_GS_JIT_CTX_PRIM_LENGTHS = 6,
> +   DRAW_GS_JIT_CTX_EMITTED_VERTICES = 7,
> +   DRAW_GS_JIT_CTX_EMITTED_PRIMS = 8,
> +   DRAW_GS_JIT_CTX_NUM_FIELDS = 9
>  };
>  
>  #define draw_gs_jit_context_constants(_gallivm, _ptr) \
>     lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_GS_JIT_CTX_CONSTANTS, "constants")
>  
> +#define draw_gs_jit_context_constants_max_index(_gallivm, _ptr) \
> +   lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_GS_JIT_CTX_CONSTANTS_MAX_INDEX, "constants_max_index")
> +
>  #define draw_gs_jit_context_planes(_gallivm, _ptr) \
>     lp_build_struct_get(_gallivm, _ptr, DRAW_GS_JIT_CTX_PLANES, "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 9f17241..cf20a03 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
> @@ -262,10 +262,16 @@ llvm_middle_end_bind_parameters(struct draw_pt_middle_end *middle)
>     unsigned i;
>  
>     for (i = 0; i < Elements(fpme->llvm->jit_context.vs_constants); ++i) {
> +      int num_consts = draw->pt.user.vs_constants_size[i] / sizeof(float);
>        fpme->llvm->jit_context.vs_constants[i] = draw->pt.user.vs_constants[i];
> +      fpme->llvm->jit_context.vs_constants_max_index[i] =
> +         num_consts ? num_consts - 1 : 0;
>     }
>     for (i = 0; i < Elements(fpme->llvm->gs_jit_context.constants); ++i) {
> +      int num_consts = draw->pt.user.gs_constants_size[i] / sizeof(float);
>        fpme->llvm->gs_jit_context.constants[i] = draw->pt.user.gs_constants[i];
> +      fpme->llvm->gs_jit_context.constants_max_index[i] =
> +         num_consts ? num_consts - 1 : 0;
>     }
>  
>     fpme->llvm->jit_context.planes =
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> index 881cd5b..4f988b8 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
> @@ -225,6 +225,7 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
>                    struct lp_type type,
>                    struct lp_build_mask_context *mask,
>                    LLVMValueRef consts_ptr,
> +                  LLVMValueRef const_sizes_ptr,
>                    const struct lp_bld_tgsi_system_values *system_values,
>                    const LLVMValueRef (*inputs)[4],
>                    LLVMValueRef (*outputs)[4],
> @@ -433,6 +434,7 @@ struct lp_build_tgsi_soa_context
>     LLVMValueRef max_output_vertices_vec;
>  
>     LLVMValueRef consts_ptr;
> +   LLVMValueRef const_sizes_ptr;
>     const LLVMValueRef (*inputs)[TGSI_NUM_CHANNELS];
>     LLVMValueRef (*outputs)[TGSI_NUM_CHANNELS];
>  
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> index 6d8dc8c..fdbba21 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> @@ -996,6 +996,7 @@ emit_fetch_constant(
>     unsigned dimension = 0;
>     LLVMValueRef dimension_index;
>     LLVMValueRef consts_ptr;
> +   LLVMValueRef max_const_buf_index;
>     LLVMValueRef res;
>  
>     /* XXX: Handle fetching xyzw components as a vector */
> @@ -1008,7 +1009,10 @@ emit_fetch_constant(
>     }
>  
>     dimension_index = lp_build_const_int32(gallivm, dimension);
> -   consts_ptr = lp_build_array_get(gallivm, bld->consts_ptr, dimension_index);
> +   consts_ptr =
> +      lp_build_array_get(gallivm, bld->consts_ptr, dimension_index);
> +   max_const_buf_index =
> +      lp_build_array_get(gallivm, bld->const_sizes_ptr, dimension_index);
>  
>     if (reg->Register.Indirect) {
>        LLVMValueRef indirect_index;
> @@ -1021,6 +1025,11 @@ emit_fetch_constant(
>                                            reg->Register.Index,
>                                            &reg->Indirect);
>  
> +      max_const_buf_index = lp_build_broadcast_scalar(uint_bld,
> +                                                      max_const_buf_index);
> +      indirect_index = lp_build_min(uint_bld, indirect_index,
> +                                    max_const_buf_index);
> +
>        /* index_vec = indirect_index * 4 + swizzle */
>        index_vec = lp_build_shl_imm(uint_bld, indirect_index, 2);
>        index_vec = lp_build_add(uint_bld, index_vec, swizzle_vec);
> @@ -1044,6 +1053,7 @@ emit_fetch_constant(
>        struct lp_build_context *bld_fetch = stype_to_fetch(bld_base, stype);
>        res = LLVMBuildBitCast(builder, res, bld_fetch->vec_type, "");
>     }
> +
>     return res;
>  }
>  
> @@ -3352,6 +3362,7 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
>                    struct lp_type type,
>                    struct lp_build_mask_context *mask,
>                    LLVMValueRef consts_ptr,
> +                  LLVMValueRef const_sizes_ptr,
>                    const struct lp_bld_tgsi_system_values *system_values,
>                    const LLVMValueRef (*inputs)[TGSI_NUM_CHANNELS],
>                    LLVMValueRef (*outputs)[TGSI_NUM_CHANNELS],
> @@ -3379,6 +3390,7 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
>     bld.inputs = inputs;
>     bld.outputs = outputs;
>     bld.consts_ptr = consts_ptr;
> +   bld.const_sizes_ptr = const_sizes_ptr;
>     bld.sampler = sampler;
>     bld.bld_base.info = info;
>     bld.indirect_files = info->indirect_files;
> diff --git a/src/gallium/drivers/llvmpipe/lp_jit.c b/src/gallium/drivers/llvmpipe/lp_jit.c
> index fa36fd3..7dbab10 100644
> --- a/src/gallium/drivers/llvmpipe/lp_jit.c
> +++ b/src/gallium/drivers/llvmpipe/lp_jit.c
> @@ -166,7 +166,9 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp)
>        LLVMTypeRef context_type;
>  
>        elem_types[LP_JIT_CTX_CONSTANTS] =
> -            LLVMArrayType(LLVMPointerType(LLVMFloatTypeInContext(lc), 0), LP_MAX_TGSI_CONST_BUFFERS);
> +         LLVMArrayType(LLVMPointerType(LLVMFloatTypeInContext(lc), 0), LP_MAX_TGSI_CONST_BUFFERS);
> +      elem_types[LP_JIT_CTX_CONSTANTS_MAX_INDEX] =
> +            LLVMArrayType(LLVMInt32TypeInContext(lc), 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);
> @@ -190,6 +192,9 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp)
>        LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, constants,
>                               gallivm->target, context_type,
>                               LP_JIT_CTX_CONSTANTS);
> +      LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, constants_max_index,
> +                             gallivm->target, context_type,
> +                             LP_JIT_CTX_CONSTANTS_MAX_INDEX);
>        LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, alpha_ref_value,
>                               gallivm->target, context_type,
>                               LP_JIT_CTX_ALPHA_REF);
> diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h b/src/gallium/drivers/llvmpipe/lp_jit.h
> index 8eefa7c..b10ee51 100644
> --- a/src/gallium/drivers/llvmpipe/lp_jit.h
> +++ b/src/gallium/drivers/llvmpipe/lp_jit.h
> @@ -121,6 +121,7 @@ enum {
>  struct lp_jit_context
>  {
>     const float *constants[LP_MAX_TGSI_CONST_BUFFERS];
> +   int constants_max_index[LP_MAX_TGSI_CONST_BUFFERS];
>  
>     float alpha_ref_value;
>  
> @@ -142,6 +143,7 @@ struct lp_jit_context
>   */
>  enum {
>     LP_JIT_CTX_CONSTANTS = 0,
> +   LP_JIT_CTX_CONSTANTS_MAX_INDEX,
>     LP_JIT_CTX_ALPHA_REF,
>     LP_JIT_CTX_STENCIL_REF_FRONT,
>     LP_JIT_CTX_STENCIL_REF_BACK,
> @@ -157,6 +159,9 @@ enum {
>  #define lp_jit_context_constants(_gallivm, _ptr) \
>     lp_build_struct_get_ptr(_gallivm, _ptr, LP_JIT_CTX_CONSTANTS, "constants")
>  
> +#define lp_jit_context_constants_max_index(_gallivm, _ptr) \
> +   lp_build_struct_get_ptr(_gallivm, _ptr, LP_JIT_CTX_CONSTANTS_MAX_INDEX, "constants_max_index")
> +
>  #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 2fad469..b238104 100644
> --- a/src/gallium/drivers/llvmpipe/lp_setup.c
> +++ b/src/gallium/drivers/llvmpipe/lp_setup.c
> @@ -987,6 +987,7 @@ try_update_scene_state( struct lp_setup_context *setup )
>           struct pipe_resource *buffer = setup->constants[i].current.buffer;
>           const unsigned current_size = setup->constants[i].current.buffer_size;
>           const ubyte *current_data = NULL;
> +         int num_constants;
>  
>           if (buffer) {
>              /* resource buffer */
> @@ -1027,7 +1028,11 @@ try_update_scene_state( struct lp_setup_context *setup )
>              setup->constants[i].stored_data = NULL;
>           }
>  
> -         setup->fs.current.jit_context.constants[i] = setup->constants[i].stored_data;
> +         setup->fs.current.jit_context.constants[i] =
> +            setup->constants[i].stored_data;
> +         num_constants = setup->constants[i].stored_size / sizeof(float);
> +         setup->fs.current.jit_context.constants_max_index[i] =
> +            num_constants ? num_constants - 1 : 0; 
>           setup->dirty |= LP_SETUP_NEW_FS;
>        }
>     }
> diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
> index 2118c1a..4ccc909 100644
> --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
> +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
> @@ -262,7 +262,7 @@ generate_fs_loop(struct gallivm_state *gallivm,
>     const struct tgsi_token *tokens = shader->base.tokens;
>     LLVMTypeRef vec_type;
>     LLVMValueRef mask_ptr, mask_val;
> -   LLVMValueRef consts_ptr;
> +   LLVMValueRef consts_ptr, consts_max_index_ptr;
>     LLVMValueRef z;
>     LLVMValueRef z_value, s_value;
>     LLVMValueRef z_fb, s_fb;
> @@ -334,6 +334,8 @@ generate_fs_loop(struct gallivm_state *gallivm,
>     vec_type = lp_build_vec_type(gallivm, type);
>  
>     consts_ptr = lp_jit_context_constants(gallivm, context_ptr);
> +   consts_max_index_ptr =
> +      lp_jit_context_constants_max_index(gallivm, context_ptr);
>  
>     lp_build_for_loop_begin(&loop_state, gallivm,
>                             lp_build_const_int32(gallivm, 0),
> @@ -412,7 +414,7 @@ generate_fs_loop(struct gallivm_state *gallivm,
>  
>     /* Build the actual shader */
>     lp_build_tgsi_soa(gallivm, tokens, type, &mask,
> -                     consts_ptr, &system_values,
> +                     consts_ptr, consts_max_index_ptr, &system_values,
>                       interp->inputs,
>                       outputs, sampler, &shader->info.base, NULL);
>  
> 

so much plumbing...
I wonder if it would make sense to instead of plumbing one more var
through everything if the constant ptr array would be replaced with at
struct?
So instead of
struct draw_jit_context
{
   const float *vs_constants[LP_MAX_TGSI_CONST_BUFFERS];
   int vs_constants_max_index[LP_MAX_TGSI_CONST_BUFFERS];
   float (*planes) [DRAW_TOTAL_CLIP_PLANES][4];
   float *viewport;
}

you'd have
struct {
   const float *vs_constants[LP_MAX_TGSI_CONST_BUFFERS];
   int vs_constants_max_index[LP_MAX_TGSI_CONST_BUFFERS];
} const_s;

struct draw_jit_context
{
   struct const_s constants;
   float (*planes) [DRAW_TOTAL_CLIP_PLANES][4];
   float *viewport;
}

But maybe that's more trouble than what it's worth, so your change looks
good to me.

Roland


More information about the mesa-dev mailing list