[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,
> ®->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