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

Roland Scheidegger sroland at vmware.com
Thu Jan 16 09:34:30 PST 2014


Am 16.01.2014 03:09, 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 to let it make
> sure that the constant buffer indices are always within bounds.
> The behavior follows the d3d10 spec, which says the overflow
> should always return all zeros, and overflow is only defined
> as access beyond the size of the currently bound buffer. Accesses
> beyond the declared shader constant register size are not
> considered an overflow and expected to return garbage but consistent
> garbage (we follow the behavior which some wlk tests expect which
> is to return the actual values from the bound buffer).
> 
> 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    | 89 ++++++++++++++++++----
>  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         |  5 +-
>  9 files changed, 152 insertions(+), 43 deletions(-)
> 
> diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
> index 331039a..0bbb680 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, /* num_vs_constants */
> +                                 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, num_vs_constants,
> +                          target, context_type, DRAW_JIT_CTX_NUM_CONSTANTS);
>     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, /* num_constants */
> +                                 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, num_constants,
> +                          target, context_type, DRAW_GS_JIT_CTX_NUM_CONSTANTS);
>     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 num_consts_ptr =
> +      draw_jit_context_num_vs_constants(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,
> +                     num_consts_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, num_consts_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);
> +   num_consts_ptr =
> +      draw_gs_jit_context_num_constants(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,
> +                     num_consts_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..2e465b2 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 num_vs_constants[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_NUM_CONSTANTS        = 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_num_vs_constants(_gallivm, _ptr) \
> +   lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_JIT_CTX_NUM_CONSTANTS, "num_vs_constants")
> +
>  #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 num_constants[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_NUM_CONSTANTS = 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_num_constants(_gallivm, _ptr) \
> +   lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_GS_JIT_CTX_NUM_CONSTANTS, "num_constants")
> +
>  #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..5a6d059 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 =
> +         ceil(draw->pt.user.vs_constants_size[i] / (sizeof(float) * 4));
I don't know what the ceil is supposed to do but it doesn't look like it
could work since the division is all ints already.



>        fpme->llvm->jit_context.vs_constants[i] = draw->pt.user.vs_constants[i];
> +      fpme->llvm->jit_context.num_vs_constants[i] = num_consts;
>     }
>     for (i = 0; i < Elements(fpme->llvm->gs_jit_context.constants); ++i) {
> +      int num_consts =
> +         ceil(draw->pt.user.gs_constants_size[i] / (sizeof(float) * 4));
Same as above.


>        fpme->llvm->gs_jit_context.constants[i] = draw->pt.user.gs_constants[i];
> +      fpme->llvm->gs_jit_context.num_constants[i] = num_consts;
>     }
>  
>     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..0bf781b 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
> @@ -789,11 +789,19 @@ gather_outputs(struct lp_build_tgsi_soa_context * bld)
>  static LLVMValueRef
>  build_gather(struct lp_build_context *bld,
>               LLVMValueRef base_ptr,
> -             LLVMValueRef indexes)
> +             LLVMValueRef indexes,
> +             LLVMValueRef *overflow_mask)
>  {
>     LLVMBuilderRef builder = bld->gallivm->builder;
>     LLVMValueRef res = bld->undef;
>     unsigned i;
> +   LLVMValueRef temp_ptr;
> +
> +   if (overflow_mask) {
> +      temp_ptr = lp_build_alloca(
> +         bld->gallivm,
> +         lp_build_vec_type(bld->gallivm, bld->type), "");
> +   }
>  
>     /*
>      * Loop over elements of index_vec, load scalar value, insert it into 'res'.
> @@ -802,11 +810,46 @@ build_gather(struct lp_build_context *bld,
>        LLVMValueRef ii = lp_build_const_int32(bld->gallivm, i);
>        LLVMValueRef index = LLVMBuildExtractElement(builder,
>                                                     indexes, ii, "");
> -      LLVMValueRef scalar_ptr = LLVMBuildGEP(builder, base_ptr,
> -                                             &index, 1, "gather_ptr");
> -      LLVMValueRef scalar = LLVMBuildLoad(builder, scalar_ptr, "");
> +      LLVMValueRef scalar_ptr, scalar;
> +      LLVMValueRef overflow;
> +      struct lp_build_if_state if_ctx;
> +
> +      if (overflow_mask) {
> +         overflow = LLVMBuildExtractElement(builder, *overflow_mask,
> +                                            ii, "");
> +         lp_build_if(&if_ctx, bld->gallivm, overflow);
> +         {
> +            LLVMValueRef val = LLVMBuildLoad(builder, temp_ptr, "");
> +            val = LLVMBuildInsertElement(
> +               builder, val,
> +               LLVMConstNull(LLVMFloatTypeInContext(bld->gallivm->context)),
> +               ii, "");
> +            LLVMBuildStore(builder, val, temp_ptr);
> +         }
> +         lp_build_else(&if_ctx);
> +         {
> +            LLVMValueRef val = LLVMBuildLoad(builder, temp_ptr, "");
> +
> +            scalar_ptr = LLVMBuildGEP(builder, base_ptr,
> +                                      &index, 1, "gather_ptr");
> +            scalar = LLVMBuildLoad(builder, scalar_ptr, "");
> +
> +            val = LLVMBuildInsertElement(builder, val, scalar, ii, "");
> +
> +            LLVMBuildStore(builder, val, temp_ptr);
> +         }
> +         lp_build_endif(&if_ctx);
> +      } else {
> +         scalar_ptr = LLVMBuildGEP(builder, base_ptr,
> +                                   &index, 1, "gather_ptr");
> +         scalar = LLVMBuildLoad(builder, scalar_ptr, "");
> +
> +         res = LLVMBuildInsertElement(builder, res, scalar, ii, "");
> +      }
> +   }
>  
> -      res = LLVMBuildInsertElement(builder, res, scalar, ii, "");
> +   if (overflow_mask) {
> +      res = LLVMBuildLoad(builder, temp_ptr, "gather_val");
>     }
>  
>     return res;
> @@ -912,12 +955,14 @@ get_indirect_index(struct lp_build_tgsi_soa_context *bld,
>  
>     index = lp_build_add(uint_bld, base, rel);
>  
> -   max_index = lp_build_const_int_vec(bld->bld_base.base.gallivm,
> -                                      uint_bld->type,
> -                                      bld->bld_base.info->file_max[reg_file]);
> +   if (reg_file != TGSI_FILE_CONSTANT) {
> +      max_index = lp_build_const_int_vec(bld->bld_base.base.gallivm,
> +                                         uint_bld->type,
> +                                         bld->bld_base.info->file_max[reg_file]);
>  
> -   assert(!uint_bld->type.sign);
> -   index = lp_build_min(uint_bld, index, max_index);
> +      assert(!uint_bld->type.sign);
> +      index = lp_build_min(uint_bld, index, max_index);
> +   }
>  
>     return index;
>  }
> @@ -996,6 +1041,7 @@ emit_fetch_constant(
>     unsigned dimension = 0;
>     LLVMValueRef dimension_index;
>     LLVMValueRef consts_ptr;
> +   LLVMValueRef num_consts;
>     LLVMValueRef res;
>  
>     /* XXX: Handle fetching xyzw components as a vector */
> @@ -1008,25 +1054,35 @@ 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);
> +   num_consts =
> +      lp_build_array_get(gallivm, bld->const_sizes_ptr, dimension_index);
>  
>     if (reg->Register.Indirect) {
>        LLVMValueRef indirect_index;
>        LLVMValueRef swizzle_vec =
>           lp_build_const_int_vec(gallivm, uint_bld->type, swizzle);
>        LLVMValueRef index_vec;  /* index into the const buffer */
> +      LLVMValueRef overflow_mask;
>  
>        indirect_index = get_indirect_index(bld,
>                                            reg->Register.File,
>                                            reg->Register.Index,
>                                            &reg->Indirect);
>  
> +      num_consts = lp_build_broadcast_scalar(uint_bld, num_consts);
> +      overflow_mask = LLVMBuildICmp(builder, LLVMIntUGE,
> +                                    indirect_index,
> +                                    num_consts, "");
> +
>        /* 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);
>  
>        /* Gather values from the constant buffer */
> -      res = build_gather(&bld_base->base, consts_ptr, index_vec);
> +      res = build_gather(&bld_base->base, consts_ptr, index_vec,
> +                         &overflow_mask);
>     }
>     else {
>        LLVMValueRef index;  /* index into the const buffer */
> @@ -1044,6 +1100,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;
>  }
>  
> @@ -1085,7 +1142,7 @@ emit_fetch_immediate(
>        imms_array = LLVMBuildBitCast(builder, bld->imms_array, fptr_type, "");
>  
>        /* Gather values from the immediate register array */
> -      res = build_gather(&bld_base->base, imms_array, index_vec);
> +      res = build_gather(&bld_base->base, imms_array, index_vec, 0);
>     }
>     else {
>        res = bld->immediates[reg->Register.Index][swizzle];
> @@ -1132,7 +1189,7 @@ emit_fetch_input(
>        inputs_array = LLVMBuildBitCast(builder, bld->inputs_array, fptr_type, "");
>  
>        /* Gather values from the input register array */
> -      res = build_gather(&bld_base->base, inputs_array, index_vec);
> +      res = build_gather(&bld_base->base, inputs_array, index_vec, 0);
>     } else {
>        if (bld->indirect_files & (1 << TGSI_FILE_INPUT)) {
>           LLVMValueRef lindex = lp_build_const_int32(gallivm,
> @@ -1242,7 +1299,7 @@ emit_fetch_temporary(
>        temps_array = LLVMBuildBitCast(builder, bld->temps_array, fptr_type, "");
>  
>        /* Gather values from the temporary register array */
> -      res = build_gather(&bld_base->base, temps_array, index_vec);
> +      res = build_gather(&bld_base->base, temps_array, index_vec, 0);
>     }
>     else {
>        LLVMValueRef temp_ptr;
> @@ -3352,6 +3409,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 +3437,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..075bd14 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_NUM_CONSTANTS] =
> +            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, num_constants,
> +                             gallivm->target, context_type,
> +                             LP_JIT_CTX_NUM_CONSTANTS);
>        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..1325a8c 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 num_constants[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_NUM_CONSTANTS,
>     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_num_constants(_gallivm, _ptr) \
> +   lp_build_struct_get_ptr(_gallivm, _ptr, LP_JIT_CTX_NUM_CONSTANTS, "num_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 7f22231..3d33003 100644
> --- a/src/gallium/drivers/llvmpipe/lp_setup.c
> +++ b/src/gallium/drivers/llvmpipe/lp_setup.c
> @@ -984,6 +984,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 */
> @@ -1024,7 +1025,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 =
> +            ceil(setup->constants[i].stored_size / (sizeof(float) * 4));
Same as above.


> +         setup->fs.current.jit_context.num_constants[i] = num_constants;
>           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 eedafa3..31ed847 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, num_consts_ptr;
>     LLVMValueRef z;
>     LLVMValueRef z_value, s_value;
>     LLVMValueRef z_fb, s_fb;
> @@ -336,6 +336,7 @@ generate_fs_loop(struct gallivm_state *gallivm,
>     vec_type = lp_build_vec_type(gallivm, type);
>  
>     consts_ptr = lp_jit_context_constants(gallivm, context_ptr);
> +   num_consts_ptr = lp_jit_context_num_constants(gallivm, context_ptr);
>  
>     lp_build_for_loop_begin(&loop_state, gallivm,
>                             lp_build_const_int32(gallivm, 0),
> @@ -414,7 +415,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, num_consts_ptr, &system_values,
>                       interp->inputs,
>                       outputs, sampler, &shader->info.base, NULL);
>  
> 

Otherwise looks good to me. Do you have a reference handy for the d3d10
requirement that buffer overflows must return 0 and could throw that in
there as a comment somewhere along the overflow_mask handling? (Even if
this isn't mentioned in the specs a comment would be nice in any case
why this is required.)

Roland


More information about the mesa-dev mailing list