diff options
author | Zack Rusin <[email protected]> | 2013-12-18 19:16:07 -0500 |
---|---|---|
committer | Zack Rusin <[email protected]> | 2014-01-16 16:33:57 -0500 |
commit | 93b953d139112bea1c9c64a3de462cbb52c544fd (patch) | |
tree | ffb9b2c3867a9b396c361645aab66f3786cb5d37 | |
parent | dd687fb8d090f08d09ac5e350a92f38ded837788 (diff) |
llvmpipe: do constant buffer bounds checking in shaders
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 <[email protected]>
Reviewed-by: Jose Fonseca <[email protected]>
Reviewed-by: Brian Paul <[email protected]>
Reviewed-by: Roland Scheidegger <[email protected]>
-rw-r--r-- | src/gallium/auxiliary/draw/draw_llvm.c | 42 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_llvm.h | 32 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c | 6 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_tgsi.h | 2 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c | 111 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_jit.c | 7 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_jit.h | 5 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup.c | 7 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_state_fs.c | 5 |
9 files changed, 174 insertions, 43 deletions
diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index 331039aad6e..0bbb6804984 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 1d238a2a9c2..2e465b2239c 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 9f172418544..846e1d58052 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) * 4); 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 = + draw->pt.user.gs_constants_size[i] / (sizeof(float) * 4); 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 881cd5ba829..4f988b8fa4d 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 6d8dc8c6f19..d9b21f831ca 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,54 @@ 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; + + /* + * overflow_mask is a boolean vector telling us which channels + * in the vector overflowed. We use the overflow behavior for + * constant buffers which is defined as: + * Out of bounds access to constant buffer returns 0 in all + * componenets. Out of bounds behavior is always with respect + * to the size of the buffer bound at that slot. + */ + 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, ""); - res = LLVMBuildInsertElement(builder, res, 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, ""); + } + } + + if (overflow_mask) { + res = LLVMBuildLoad(builder, temp_ptr, "gather_val"); } return res; @@ -912,12 +963,23 @@ 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]); + /* + * emit_fetch_constant handles constant buffer overflow so this code + * is pointless for them. + * Furthermore the D3D10 spec in section 6.5 says: + * If the constant buffer bound to a slot is larger than the size + * declared in the shader for that slot, implementations are allowed + * to return incorrect data (not necessarily 0) for indices that are + * larger than the declared size but smaller than the buffer size. + */ + 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 +1058,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 +1071,40 @@ 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); + /* All fetches are from the same constant buffer, so + * we need to propagate the size to a vector to do a + * vector comparison */ + num_consts = lp_build_broadcast_scalar(uint_bld, num_consts); + /* Construct a boolean vector telling us which channels + * overflow the bound constant buffer */ + 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 +1122,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 +1164,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, NULL); } else { res = bld->immediates[reg->Register.Index][swizzle]; @@ -1132,7 +1211,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, NULL); } else { if (bld->indirect_files & (1 << TGSI_FILE_INPUT)) { LLVMValueRef lindex = lp_build_const_int32(gallivm, @@ -1242,7 +1321,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, NULL); } else { LLVMValueRef temp_ptr; @@ -3352,6 +3431,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 +3459,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 fa36fd3512e..075bd148e88 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 8eefa7c8479..1325a8cc482 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 7f2223129aa..58811b0edd3 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 = + setup->constants[i].stored_size / (sizeof(float) * 4); + 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 eedafa36838..31ed8478e9b 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); |