diff options
author | Roland Scheidegger <[email protected]> | 2013-01-28 06:50:36 -0800 |
---|---|---|
committer | Roland Scheidegger <[email protected]> | 2013-01-28 06:50:36 -0800 |
commit | c789b981b244333cfc903bcd1e2fefc010500013 (patch) | |
tree | 0f0c5375916677240e11a1046af81bb2d5443030 /src/gallium/drivers/llvmpipe | |
parent | 87592cff57feef29565150b9203e220b50623f30 (diff) |
gallivm: split sampler and texture state
Split the sampler interface to use separate sampler and texture (sampler_view)
state. This is needed to support dx10-style sampling instructions.
This is not quite complete since both draw/llvmpipe don't really track
textures/samplers independently yet, as well as the gallivm code not quite
using the right sampler or texture index respectively (but it should work
for the sampling codes used by opengl).
We are however losing some optimizations in the process, apply_max_lod will
no longer work, and we potentially could end up with more (unnecessary)
recompiles (if switching textures with/without mipmaps only so it shouldn't
be too bad).
v2: don't use different callback structs for sampler/sampler view functions
(which just complicates things), fix up sampling code to actually use the
right texture or sampler index, and similar for llvmpipe/draw actually
distinguish between samplers and sampler views.
v3: fix more of PIPE_MAX_SAMPLER / PIPE_MAX_SHADER_SAMPLER_VIEWS mismatches
(both in draw and llvmpipe), based on feedback from José get rid of unneeded
static sampler derived state.(which also fixes the only 2 piglit regressions
due to a forgotten assignment), fix comments based on Brian's feedback.
v4: remove some accidental unrelated whitespace changes
Reviewed-by: José Fonseca <[email protected]>
Reviewed-by: Brian Paul <[email protected]>
Diffstat (limited to 'src/gallium/drivers/llvmpipe')
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_context.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_jit.c | 54 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_jit.h | 24 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup.c | 16 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup_context.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_state_fs.c | 84 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_state_fs.h | 17 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_state_sampler.c | 6 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_tex_sample.c | 102 |
9 files changed, 225 insertions, 84 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h index b11a3d838e3..9ccb67bdd1f 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.h +++ b/src/gallium/drivers/llvmpipe/lp_context.h @@ -76,12 +76,12 @@ struct llvmpipe_context { struct pipe_framebuffer_state framebuffer; struct pipe_poly_stipple poly_stipple; struct pipe_scissor_state scissor; - struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS]; struct pipe_viewport_state viewport; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; struct pipe_index_buffer index_buffer; - struct pipe_resource *mapped_vs_tex[PIPE_MAX_SAMPLERS]; + struct pipe_resource *mapped_vs_tex[PIPE_MAX_SHADER_SAMPLER_VIEWS]; unsigned num_samplers[PIPE_SHADER_TYPES]; unsigned num_sampler_views[PIPE_SHADER_TYPES]; diff --git a/src/gallium/drivers/llvmpipe/lp_jit.c b/src/gallium/drivers/llvmpipe/lp_jit.c index ea7c8054bfa..d0a791671e6 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.c +++ b/src/gallium/drivers/llvmpipe/lp_jit.c @@ -45,7 +45,7 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp) { struct gallivm_state *gallivm = lp->gallivm; LLVMContextRef lc = gallivm->context; - LLVMTypeRef texture_type; + LLVMTypeRef texture_type, sampler_type; /* struct lp_jit_texture */ { @@ -61,11 +61,6 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp) elem_types[LP_JIT_TEXTURE_IMG_STRIDE] = elem_types[LP_JIT_TEXTURE_MIP_OFFSETS] = LLVMArrayType(LLVMInt32TypeInContext(lc), LP_MAX_TEXTURE_LEVELS); - elem_types[LP_JIT_TEXTURE_MIN_LOD] = - elem_types[LP_JIT_TEXTURE_MAX_LOD] = - elem_types[LP_JIT_TEXTURE_LOD_BIAS] = LLVMFloatTypeInContext(lc); - elem_types[LP_JIT_TEXTURE_BORDER_COLOR] = - LLVMArrayType(LLVMFloatTypeInContext(lc), 4); texture_type = LLVMStructTypeInContext(lc, elem_types, Elements(elem_types), 0); @@ -102,21 +97,41 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp) LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, mip_offsets, gallivm->target, texture_type, LP_JIT_TEXTURE_MIP_OFFSETS); - LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, min_lod, + LP_CHECK_STRUCT_SIZE(struct lp_jit_texture, + gallivm->target, texture_type); + } + + { + /* struct lp_jit_sampler */ + LLVMTypeRef elem_types[LP_JIT_SAMPLER_NUM_FIELDS]; + elem_types[LP_JIT_SAMPLER_MIN_LOD] = + elem_types[LP_JIT_SAMPLER_MAX_LOD] = + elem_types[LP_JIT_SAMPLER_LOD_BIAS] = LLVMFloatTypeInContext(lc); + elem_types[LP_JIT_SAMPLER_BORDER_COLOR] = + LLVMArrayType(LLVMFloatTypeInContext(lc), 4); + + sampler_type = LLVMStructTypeInContext(lc, elem_types, + Elements(elem_types), 0); +#if HAVE_LLVM < 0x0300 + LLVMAddTypeName(gallivm->module, "texture", texture_type); + + LLVMInvalidateStructLayout(gallivm->target, texture_type); +#endif + + LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, min_lod, gallivm->target, texture_type, - LP_JIT_TEXTURE_MIN_LOD); - LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, max_lod, + LP_JIT_SAMPLER_MIN_LOD); + LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, max_lod, gallivm->target, texture_type, - LP_JIT_TEXTURE_MAX_LOD); - LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, lod_bias, + LP_JIT_SAMPLER_MAX_LOD); + LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, lod_bias, gallivm->target, texture_type, - LP_JIT_TEXTURE_LOD_BIAS); - LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, border_color, + LP_JIT_SAMPLER_LOD_BIAS); + LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, border_color, gallivm->target, texture_type, - LP_JIT_TEXTURE_BORDER_COLOR); - - LP_CHECK_STRUCT_SIZE(struct lp_jit_texture, - gallivm->target, texture_type); + LP_JIT_SAMPLER_BORDER_COLOR); + LP_CHECK_STRUCT_SIZE(struct lp_jit_sampler, + gallivm->target, sampler_type); } /* struct lp_jit_context */ @@ -132,6 +147,8 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp) elem_types[LP_JIT_CTX_U8_BLEND_COLOR] = LLVMPointerType(LLVMInt8TypeInContext(lc), 0); elem_types[LP_JIT_CTX_F_BLEND_COLOR] = LLVMPointerType(LLVMFloatTypeInContext(lc), 0); elem_types[LP_JIT_CTX_TEXTURES] = LLVMArrayType(texture_type, + PIPE_MAX_SHADER_SAMPLER_VIEWS); + elem_types[LP_JIT_CTX_SAMPLERS] = LLVMArrayType(sampler_type, PIPE_MAX_SAMPLERS); context_type = LLVMStructTypeInContext(lc, elem_types, @@ -164,6 +181,9 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp) LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, textures, gallivm->target, context_type, LP_JIT_CTX_TEXTURES); + LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, samplers, + gallivm->target, context_type, + LP_JIT_CTX_SAMPLERS); LP_CHECK_STRUCT_SIZE(struct lp_jit_context, gallivm->target, context_type); diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h b/src/gallium/drivers/llvmpipe/lp_jit.h index 5dc5bc4c4bf..3057c0dc2b0 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.h +++ b/src/gallium/drivers/llvmpipe/lp_jit.h @@ -58,7 +58,11 @@ struct lp_jit_texture uint32_t row_stride[LP_MAX_TEXTURE_LEVELS]; uint32_t img_stride[LP_MAX_TEXTURE_LEVELS]; uint32_t mip_offsets[LP_MAX_TEXTURE_LEVELS]; - /* sampler state, actually */ +}; + + +struct lp_jit_sampler +{ float min_lod; float max_lod; float lod_bias; @@ -76,14 +80,18 @@ enum { LP_JIT_TEXTURE_ROW_STRIDE, LP_JIT_TEXTURE_IMG_STRIDE, LP_JIT_TEXTURE_MIP_OFFSETS, - LP_JIT_TEXTURE_MIN_LOD, - LP_JIT_TEXTURE_MAX_LOD, - LP_JIT_TEXTURE_LOD_BIAS, - LP_JIT_TEXTURE_BORDER_COLOR, LP_JIT_TEXTURE_NUM_FIELDS /* number of fields above */ }; +enum { + LP_JIT_SAMPLER_MIN_LOD, + LP_JIT_SAMPLER_MAX_LOD, + LP_JIT_SAMPLER_LOD_BIAS, + LP_JIT_SAMPLER_BORDER_COLOR, + LP_JIT_SAMPLER_NUM_FIELDS /* number of fields above */ +}; + /** * This structure is passed directly to the generated fragment shader. @@ -107,7 +115,8 @@ struct lp_jit_context uint8_t *u8_blend_color; float *f_blend_color; - struct lp_jit_texture textures[PIPE_MAX_SAMPLERS]; + struct lp_jit_texture textures[PIPE_MAX_SHADER_SAMPLER_VIEWS]; + struct lp_jit_sampler samplers[PIPE_MAX_SAMPLERS]; }; @@ -123,6 +132,7 @@ enum { LP_JIT_CTX_U8_BLEND_COLOR, LP_JIT_CTX_F_BLEND_COLOR, LP_JIT_CTX_TEXTURES, + LP_JIT_CTX_SAMPLERS, LP_JIT_CTX_COUNT }; @@ -148,6 +158,8 @@ enum { #define lp_jit_context_textures(_gallivm, _ptr) \ lp_build_struct_get_ptr(_gallivm, _ptr, LP_JIT_CTX_TEXTURES, "textures") +#define lp_jit_context_samplers(_gallivm, _ptr) \ + lp_build_struct_get_ptr(_gallivm, _ptr, LP_JIT_CTX_SAMPLERS, "samplers") /** diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index ffa0fe6eaa3..b0bc4a8132f 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -668,9 +668,9 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); - assert(num <= PIPE_MAX_SAMPLERS); + assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS); - for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { + for (i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) { struct pipe_sampler_view *view = i < num ? views[i] : NULL; if (view) { @@ -780,13 +780,13 @@ lp_setup_set_fragment_sampler_state(struct lp_setup_context *setup, const struct pipe_sampler_state *sampler = i < num ? samplers[i] : NULL; if (sampler) { - struct lp_jit_texture *jit_tex; - jit_tex = &setup->fs.current.jit_context.textures[i]; + struct lp_jit_sampler *jit_sam; + jit_sam = &setup->fs.current.jit_context.samplers[i]; - jit_tex->min_lod = sampler->min_lod; - jit_tex->max_lod = sampler->max_lod; - jit_tex->lod_bias = sampler->lod_bias; - COPY_4V(jit_tex->border_color, sampler->border_color.f); + jit_sam->min_lod = sampler->min_lod; + jit_sam->max_lod = sampler->max_lod; + jit_sam->lod_bias = sampler->lod_bias; + COPY_4V(jit_sam->border_color, sampler->border_color.f); } } diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h index 4d20dd38461..0e2de648a91 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_context.h +++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h @@ -123,7 +123,7 @@ struct lp_setup_context struct { const struct lp_rast_state *stored; /**< what's in the scene */ struct lp_rast_state current; /**< currently set state */ - struct pipe_resource *current_tex[PIPE_MAX_SAMPLERS]; + struct pipe_resource *current_tex[PIPE_MAX_SHADER_SAMPLER_VIEWS]; } fs; /** fragment shader constants */ diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index cf936d029b5..09f37e0cead 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -1904,7 +1904,7 @@ generate_fragment(struct llvmpipe_context *lp, LLVMPositionBuilderAtEnd(builder, block); /* code generated texture sampling */ - sampler = lp_llvm_sampler_soa_create(key->sampler, context_ptr); + sampler = lp_llvm_sampler_soa_create(key->state, context_ptr); zs_format_desc = util_format_description(key->zsbuf_format); @@ -2113,32 +2113,39 @@ dump_fs_variant_key(const struct lp_fragment_shader_variant_key *key) } debug_printf("blend.colormask = 0x%x\n", key->blend.rt[0].colormask); for (i = 0; i < key->nr_samplers; ++i) { + const struct lp_static_sampler_state *sampler = &key->state[i].sampler_state; debug_printf("sampler[%u] = \n", i); - debug_printf(" .format = %s\n", - util_format_name(key->sampler[i].format)); - debug_printf(" .target = %s\n", - util_dump_tex_target(key->sampler[i].target, TRUE)); - debug_printf(" .pot = %u %u %u\n", - key->sampler[i].pot_width, - key->sampler[i].pot_height, - key->sampler[i].pot_depth); debug_printf(" .wrap = %s %s %s\n", - util_dump_tex_wrap(key->sampler[i].wrap_s, TRUE), - util_dump_tex_wrap(key->sampler[i].wrap_t, TRUE), - util_dump_tex_wrap(key->sampler[i].wrap_r, TRUE)); + util_dump_tex_wrap(sampler->wrap_s, TRUE), + util_dump_tex_wrap(sampler->wrap_t, TRUE), + util_dump_tex_wrap(sampler->wrap_r, TRUE)); debug_printf(" .min_img_filter = %s\n", - util_dump_tex_filter(key->sampler[i].min_img_filter, TRUE)); + util_dump_tex_filter(sampler->min_img_filter, TRUE)); debug_printf(" .min_mip_filter = %s\n", - util_dump_tex_mipfilter(key->sampler[i].min_mip_filter, TRUE)); + util_dump_tex_mipfilter(sampler->min_mip_filter, TRUE)); debug_printf(" .mag_img_filter = %s\n", - util_dump_tex_filter(key->sampler[i].mag_img_filter, TRUE)); - if (key->sampler[i].compare_mode != PIPE_TEX_COMPARE_NONE) - debug_printf(" .compare_func = %s\n", util_dump_func(key->sampler[i].compare_func, TRUE)); - debug_printf(" .normalized_coords = %u\n", key->sampler[i].normalized_coords); - debug_printf(" .min_max_lod_equal = %u\n", key->sampler[i].min_max_lod_equal); - debug_printf(" .lod_bias_non_zero = %u\n", key->sampler[i].lod_bias_non_zero); - debug_printf(" .apply_min_lod = %u\n", key->sampler[i].apply_min_lod); - debug_printf(" .apply_max_lod = %u\n", key->sampler[i].apply_max_lod); + util_dump_tex_filter(sampler->mag_img_filter, TRUE)); + if (sampler->compare_mode != PIPE_TEX_COMPARE_NONE) + debug_printf(" .compare_func = %s\n", util_dump_func(sampler->compare_func, TRUE)); + debug_printf(" .normalized_coords = %u\n", sampler->normalized_coords); + debug_printf(" .min_max_lod_equal = %u\n", sampler->min_max_lod_equal); + debug_printf(" .lod_bias_non_zero = %u\n", sampler->lod_bias_non_zero); + debug_printf(" .apply_min_lod = %u\n", sampler->apply_min_lod); + debug_printf(" .apply_max_lod = %u\n", sampler->apply_max_lod); + } + for (i = 0; i < key->nr_sampler_views; ++i) { + const struct lp_static_texture_state *texture = &key->state[i].texture_state; + debug_printf("texture[%u] = \n", i); + debug_printf(" .format = %s\n", + util_format_name(texture->format)); + debug_printf(" .target = %s\n", + util_dump_tex_target(texture->target, TRUE)); + debug_printf(" .level_zero_only = %u\n", + texture->level_zero_only); + debug_printf(" .pot = %u %u %u\n", + texture->pot_width, + texture->pot_height, + texture->pot_depth); } } @@ -2251,6 +2258,7 @@ llvmpipe_create_fs_state(struct pipe_context *pipe, struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); struct lp_fragment_shader *shader; int nr_samplers; + int nr_sampler_views; int i; shader = CALLOC_STRUCT(lp_fragment_shader); @@ -2274,9 +2282,10 @@ llvmpipe_create_fs_state(struct pipe_context *pipe, } nr_samplers = shader->info.base.file_max[TGSI_FILE_SAMPLER] + 1; + nr_sampler_views = shader->info.base.file_max[TGSI_FILE_SAMPLER_VIEW] + 1; shader->variant_key_size = Offset(struct lp_fragment_shader_variant_key, - sampler[nr_samplers]); + state[MAX2(nr_samplers, nr_sampler_views)]); for (i = 0; i < shader->info.base.num_inputs; i++) { shader->inputs[i].usage_mask = shader->info.base.input_usage_mask[i]; @@ -2605,9 +2614,32 @@ make_variant_key(struct llvmpipe_context *lp, for(i = 0; i < key->nr_samplers; ++i) { if(shader->info.base.file_mask[TGSI_FILE_SAMPLER] & (1 << i)) { - lp_sampler_static_state(&key->sampler[i], - lp->sampler_views[PIPE_SHADER_FRAGMENT][i], - lp->samplers[PIPE_SHADER_FRAGMENT][i]); + lp_sampler_static_sampler_state(&key->state[i].sampler_state, + lp->samplers[PIPE_SHADER_FRAGMENT][i]); + } + } + + /* + * XXX If TGSI_FILE_SAMPLER_VIEW exists assume all texture opcodes + * are dx10-style? Can't really have mixed opcodes, at least not + * if we want to skip the holes here (without rescanning tgsi). + */ + if (shader->info.base.file_max[TGSI_FILE_SAMPLER_VIEW] != -1) { + key->nr_sampler_views = shader->info.base.file_max[TGSI_FILE_SAMPLER_VIEW] + 1; + for(i = 0; i < key->nr_sampler_views; ++i) { + if(shader->info.base.file_mask[TGSI_FILE_SAMPLER_VIEW] & (1 << i)) { + lp_sampler_static_texture_state(&key->state[i].texture_state, + lp->sampler_views[PIPE_SHADER_FRAGMENT][i]); + } + } + } + else { + key->nr_sampler_views = key->nr_samplers; + for(i = 0; i < key->nr_sampler_views; ++i) { + if(shader->info.base.file_mask[TGSI_FILE_SAMPLER] & (1 << i)) { + lp_sampler_static_texture_state(&key->state[i].texture_state, + lp->sampler_views[PIPE_SHADER_FRAGMENT][i]); + } } } } diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.h b/src/gallium/drivers/llvmpipe/lp_state_fs.h index 306f5f9669a..c8dc1c33cfe 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.h +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.h @@ -47,6 +47,18 @@ struct lp_fragment_shader; #define RAST_EDGE_TEST 1 +struct lp_sampler_static_state +{ + /* + * These attributes are effectively interleaved for more sane key handling. + * However, there might be lots of null space if the amount of samplers and + * textures isn't the same. + */ + struct lp_static_sampler_state sampler_state; + struct lp_static_texture_state texture_state; +}; + + struct lp_fragment_shader_variant_key { struct pipe_depth_state depth; @@ -59,14 +71,15 @@ struct lp_fragment_shader_variant_key } alpha; unsigned nr_cbufs:8; - unsigned nr_samplers:8; /* actually derivable from just the shader */ + unsigned nr_samplers:8; /* actually derivable from just the shader */ + unsigned nr_sampler_views:8; /* actually derivable from just the shader */ unsigned flatshade:1; unsigned occlusion_count:1; enum pipe_format zsbuf_format; enum pipe_format cbuf_format[PIPE_MAX_COLOR_BUFS]; - struct lp_sampler_static_state sampler[PIPE_MAX_SAMPLERS]; + struct lp_sampler_static_state state[PIPE_MAX_SHADER_SAMPLER_VIEWS]; }; diff --git a/src/gallium/drivers/llvmpipe/lp_state_sampler.c b/src/gallium/drivers/llvmpipe/lp_state_sampler.c index e7429cc35a1..9736ca94905 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_sampler.c +++ b/src/gallium/drivers/llvmpipe/lp_state_sampler.c @@ -143,7 +143,7 @@ llvmpipe_set_sampler_views(struct pipe_context *pipe, struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); uint i; - assert(num <= PIPE_MAX_SAMPLERS); + assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS); assert(shader < PIPE_SHADER_TYPES); assert(start + num <= Elements(llvmpipe->sampler_views[shader])); @@ -258,11 +258,11 @@ llvmpipe_prepare_vertex_sampling(struct llvmpipe_context *lp, uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS]; const void *addr; - assert(num <= PIPE_MAX_SAMPLERS); + assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS); if (!num) return; - for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { + for (i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) { struct pipe_sampler_view *view = i < num ? views[i] : NULL; if (view) { diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample.c b/src/gallium/drivers/llvmpipe/lp_tex_sample.c index 0bd5c4aa050..25125a0768b 100644 --- a/src/gallium/drivers/llvmpipe/lp_tex_sample.c +++ b/src/gallium/drivers/llvmpipe/lp_tex_sample.c @@ -49,6 +49,7 @@ #include "gallivm/lp_bld_tgsi.h" #include "lp_jit.h" #include "lp_tex_sample.h" +#include "lp_state_fs.h" #include "lp_debug.h" @@ -103,7 +104,7 @@ lp_llvm_texture_member(const struct lp_sampler_dynamic_state *base, LLVMValueRef ptr; LLVMValueRef res; - assert(unit < PIPE_MAX_SAMPLERS); + assert(unit < PIPE_MAX_SHADER_SAMPLER_VIEWS); /* context[0] */ indices[0] = lp_build_const_int32(gallivm, 0); @@ -155,10 +156,69 @@ LP_LLVM_TEXTURE_MEMBER(base_ptr, LP_JIT_TEXTURE_BASE, TRUE) LP_LLVM_TEXTURE_MEMBER(row_stride, LP_JIT_TEXTURE_ROW_STRIDE, FALSE) LP_LLVM_TEXTURE_MEMBER(img_stride, LP_JIT_TEXTURE_IMG_STRIDE, FALSE) LP_LLVM_TEXTURE_MEMBER(mip_offsets, LP_JIT_TEXTURE_MIP_OFFSETS, FALSE) -LP_LLVM_TEXTURE_MEMBER(min_lod, LP_JIT_TEXTURE_MIN_LOD, TRUE) -LP_LLVM_TEXTURE_MEMBER(max_lod, LP_JIT_TEXTURE_MAX_LOD, TRUE) -LP_LLVM_TEXTURE_MEMBER(lod_bias, LP_JIT_TEXTURE_LOD_BIAS, TRUE) -LP_LLVM_TEXTURE_MEMBER(border_color, LP_JIT_TEXTURE_BORDER_COLOR, FALSE) + + +/** + * Fetch the specified member of the lp_jit_sampler structure. + * \param emit_load if TRUE, emit the LLVM load instruction to actually + * fetch the field's value. Otherwise, just emit the + * GEP code to address the field. + * + * @sa http://llvm.org/docs/GetElementPtr.html + */ +static LLVMValueRef +lp_llvm_sampler_member(const struct lp_sampler_dynamic_state *base, + struct gallivm_state *gallivm, + unsigned unit, + unsigned member_index, + const char *member_name, + boolean emit_load) +{ + struct llvmpipe_sampler_dynamic_state *state = + (struct llvmpipe_sampler_dynamic_state *)base; + LLVMBuilderRef builder = gallivm->builder; + LLVMValueRef indices[4]; + LLVMValueRef ptr; + LLVMValueRef res; + + assert(unit < PIPE_MAX_SAMPLERS); + + /* context[0] */ + indices[0] = lp_build_const_int32(gallivm, 0); + /* context[0].samplers */ + indices[1] = lp_build_const_int32(gallivm, LP_JIT_CTX_SAMPLERS); + /* context[0].samplers[unit] */ + indices[2] = lp_build_const_int32(gallivm, unit); + /* context[0].samplers[unit].member */ + indices[3] = lp_build_const_int32(gallivm, member_index); + + ptr = LLVMBuildGEP(builder, state->context_ptr, indices, Elements(indices), ""); + + if (emit_load) + res = LLVMBuildLoad(builder, ptr, ""); + else + res = ptr; + + lp_build_name(res, "context.sampler%u.%s", unit, member_name); + + return res; +} + + +#define LP_LLVM_SAMPLER_MEMBER(_name, _index, _emit_load) \ + static LLVMValueRef \ + lp_llvm_sampler_##_name( const struct lp_sampler_dynamic_state *base, \ + struct gallivm_state *gallivm, \ + unsigned unit) \ + { \ + return lp_llvm_sampler_member(base, gallivm, unit, _index, #_name, _emit_load ); \ + } + + +LP_LLVM_SAMPLER_MEMBER(min_lod, LP_JIT_SAMPLER_MIN_LOD, TRUE) +LP_LLVM_SAMPLER_MEMBER(max_lod, LP_JIT_SAMPLER_MAX_LOD, TRUE) +LP_LLVM_SAMPLER_MEMBER(lod_bias, LP_JIT_SAMPLER_LOD_BIAS, TRUE) +LP_LLVM_SAMPLER_MEMBER(border_color, LP_JIT_SAMPLER_BORDER_COLOR, FALSE) static void @@ -177,7 +237,8 @@ lp_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base, struct gallivm_state *gallivm, struct lp_type type, boolean is_fetch, - unsigned unit, + unsigned texture_index, + unsigned sampler_index, const LLVMValueRef *coords, const LLVMValueRef *offsets, const struct lp_derivatives *derivs, @@ -187,7 +248,8 @@ lp_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base, { struct lp_llvm_sampler_soa *sampler = (struct lp_llvm_sampler_soa *)base; - assert(unit < PIPE_MAX_SAMPLERS); + assert(sampler_index < PIPE_MAX_SAMPLERS); + assert(texture_index < PIPE_MAX_SHADER_SAMPLER_VIEWS); if (LP_PERF & PERF_NO_TEX) { lp_build_sample_nop(gallivm, type, coords, texel); @@ -195,11 +257,13 @@ lp_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base, } lp_build_sample_soa(gallivm, - &sampler->dynamic_state.static_state[unit], + &sampler->dynamic_state.static_state[texture_index].texture_state, + &sampler->dynamic_state.static_state[sampler_index].sampler_state, &sampler->dynamic_state.base, type, is_fetch, - unit, + texture_index, + sampler_index, coords, offsets, derivs, @@ -221,14 +285,14 @@ lp_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base, struct lp_llvm_sampler_soa *sampler = (struct lp_llvm_sampler_soa *)base; assert(unit < PIPE_MAX_SAMPLERS); - + lp_build_size_query_soa(gallivm, - &sampler->dynamic_state.static_state[unit], - &sampler->dynamic_state.base, + &sampler->dynamic_state.static_state[unit].texture_state, + &sampler->dynamic_state.base, type, - unit, - explicit_lod, - sizes_out); + unit, + explicit_lod, + sizes_out); } @@ -254,10 +318,10 @@ lp_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state, sampler->dynamic_state.base.row_stride = lp_llvm_texture_row_stride; sampler->dynamic_state.base.img_stride = lp_llvm_texture_img_stride; sampler->dynamic_state.base.mip_offsets = lp_llvm_texture_mip_offsets; - sampler->dynamic_state.base.min_lod = lp_llvm_texture_min_lod; - sampler->dynamic_state.base.max_lod = lp_llvm_texture_max_lod; - sampler->dynamic_state.base.lod_bias = lp_llvm_texture_lod_bias; - sampler->dynamic_state.base.border_color = lp_llvm_texture_border_color; + sampler->dynamic_state.base.min_lod = lp_llvm_sampler_min_lod; + sampler->dynamic_state.base.max_lod = lp_llvm_sampler_max_lod; + sampler->dynamic_state.base.lod_bias = lp_llvm_sampler_lod_bias; + sampler->dynamic_state.base.border_color = lp_llvm_sampler_border_color; sampler->dynamic_state.static_state = static_state; sampler->dynamic_state.context_ptr = context_ptr; |