X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fllvmpipe%2Flp_tex_sample.c;h=d0e6d99082cd22d0d595fdbc324b8bf4701babeb;hp=ed4282937f88859aea7ffe416395e1c6a67a86ee;hb=30c5cbbcd206aa55f8dad4cdc96407642d0e98a8;hpb=0f68236a2487dbeb0396b996debcda595b0b54a1 diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample.c b/src/gallium/drivers/llvmpipe/lp_tex_sample.c index ed4282937f8..d0e6d99082c 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" @@ -64,8 +65,6 @@ struct llvmpipe_sampler_dynamic_state struct lp_sampler_dynamic_state base; const struct lp_sampler_static_state *static_state; - - LLVMValueRef context_ptr; }; @@ -77,6 +76,24 @@ struct lp_llvm_sampler_soa struct lp_build_sampler_soa base; struct llvmpipe_sampler_dynamic_state dynamic_state; + unsigned nr_samplers; +}; + +struct llvmpipe_image_dynamic_state +{ + struct lp_sampler_dynamic_state base; + + const struct lp_image_static_state *static_state; +}; + +/** + * This is the bridge between our sampler and the TGSI translator. + */ +struct lp_llvm_image_soa +{ + struct lp_build_image_soa base; + + struct llvmpipe_image_dynamic_state dynamic_state; }; @@ -91,37 +108,36 @@ struct lp_llvm_sampler_soa static LLVMValueRef lp_llvm_texture_member(const struct lp_sampler_dynamic_state *base, struct gallivm_state *gallivm, - unsigned unit, + LLVMValueRef context_ptr, + unsigned texture_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); + assert(texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS); /* context[0] */ indices[0] = lp_build_const_int32(gallivm, 0); /* context[0].textures */ indices[1] = lp_build_const_int32(gallivm, LP_JIT_CTX_TEXTURES); /* context[0].textures[unit] */ - indices[2] = lp_build_const_int32(gallivm, unit); + indices[2] = lp_build_const_int32(gallivm, texture_unit); /* context[0].textures[unit].member */ indices[3] = lp_build_const_int32(gallivm, member_index); - ptr = LLVMBuildGEP(builder, state->context_ptr, indices, Elements(indices), ""); + ptr = LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), ""); if (emit_load) res = LLVMBuildLoad(builder, ptr, ""); else res = ptr; - lp_build_name(res, "context.texture%u.%s", unit, member_name); + lp_build_name(res, "context.texture%u.%s", texture_unit, member_name); return res; } @@ -140,23 +156,180 @@ lp_llvm_texture_member(const struct lp_sampler_dynamic_state *base, static LLVMValueRef \ lp_llvm_texture_##_name( const struct lp_sampler_dynamic_state *base, \ struct gallivm_state *gallivm, \ - unsigned unit) \ + LLVMValueRef context_ptr, \ + unsigned texture_unit) \ { \ - return lp_llvm_texture_member(base, gallivm, unit, _index, #_name, _emit_load ); \ + return lp_llvm_texture_member(base, gallivm, context_ptr, \ + texture_unit, _index, #_name, _emit_load ); \ } LP_LLVM_TEXTURE_MEMBER(width, LP_JIT_TEXTURE_WIDTH, TRUE) LP_LLVM_TEXTURE_MEMBER(height, LP_JIT_TEXTURE_HEIGHT, TRUE) LP_LLVM_TEXTURE_MEMBER(depth, LP_JIT_TEXTURE_DEPTH, TRUE) +LP_LLVM_TEXTURE_MEMBER(first_level, LP_JIT_TEXTURE_FIRST_LEVEL, TRUE) LP_LLVM_TEXTURE_MEMBER(last_level, LP_JIT_TEXTURE_LAST_LEVEL, TRUE) +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(data_ptr, LP_JIT_TEXTURE_DATA, 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) +LP_LLVM_TEXTURE_MEMBER(mip_offsets, LP_JIT_TEXTURE_MIP_OFFSETS, FALSE) +LP_LLVM_TEXTURE_MEMBER(num_samples, LP_JIT_TEXTURE_NUM_SAMPLES, TRUE) +LP_LLVM_TEXTURE_MEMBER(sample_stride, LP_JIT_TEXTURE_SAMPLE_STRIDE, TRUE) + + +/** + * 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, + LLVMValueRef context_ptr, + unsigned sampler_unit, + unsigned member_index, + const char *member_name, + boolean emit_load) +{ + LLVMBuilderRef builder = gallivm->builder; + LLVMValueRef indices[4]; + LLVMValueRef ptr; + LLVMValueRef res; + + assert(sampler_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, sampler_unit); + /* context[0].samplers[unit].member */ + indices[3] = lp_build_const_int32(gallivm, member_index); + + ptr = LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), ""); + + if (emit_load) + res = LLVMBuildLoad(builder, ptr, ""); + else + res = ptr; + + lp_build_name(res, "context.sampler%u.%s", sampler_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, \ + LLVMValueRef context_ptr, \ + unsigned sampler_unit) \ + { \ + return lp_llvm_sampler_member(base, gallivm, context_ptr, \ + sampler_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) + + +/** + * Fetch the specified member of the lp_jit_image 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_image_member(const struct lp_sampler_dynamic_state *base, + struct gallivm_state *gallivm, + LLVMValueRef context_ptr, + unsigned image_unit, + unsigned member_index, + const char *member_name, + boolean emit_load) +{ + LLVMBuilderRef builder = gallivm->builder; + LLVMValueRef indices[4]; + LLVMValueRef ptr; + LLVMValueRef res; + + assert(image_unit < PIPE_MAX_SHADER_IMAGES); + + /* context[0] */ + indices[0] = lp_build_const_int32(gallivm, 0); + /* context[0].images */ + indices[1] = lp_build_const_int32(gallivm, LP_JIT_CTX_IMAGES); + /* context[0].images[unit] */ + indices[2] = lp_build_const_int32(gallivm, image_unit); + /* context[0].images[unit].member */ + indices[3] = lp_build_const_int32(gallivm, member_index); + + ptr = LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), ""); + + if (emit_load) + res = LLVMBuildLoad(builder, ptr, ""); + else + res = ptr; + + lp_build_name(res, "context.image%u.%s", image_unit, member_name); + + return res; +} + + +/** + * Helper macro to instantiate the functions that generate the code to + * fetch the members of lp_jit_image to fulfill the sampler code + * generator requests. + * + * This complexity is the price we have to pay to keep the image + * sampler code generator a reusable module without dependencies to + * llvmpipe internals. + */ +#define LP_LLVM_IMAGE_MEMBER(_name, _index, _emit_load) \ + static LLVMValueRef \ + lp_llvm_image_##_name( const struct lp_sampler_dynamic_state *base, \ + struct gallivm_state *gallivm, \ + LLVMValueRef context_ptr, \ + unsigned image_unit) \ + { \ + return lp_llvm_image_member(base, gallivm, context_ptr, \ + image_unit, _index, #_name, _emit_load ); \ + } + + +LP_LLVM_IMAGE_MEMBER(width, LP_JIT_IMAGE_WIDTH, TRUE) +LP_LLVM_IMAGE_MEMBER(height, LP_JIT_IMAGE_HEIGHT, TRUE) +LP_LLVM_IMAGE_MEMBER(depth, LP_JIT_IMAGE_DEPTH, TRUE) +LP_LLVM_IMAGE_MEMBER(base_ptr, LP_JIT_IMAGE_BASE, TRUE) +LP_LLVM_IMAGE_MEMBER(row_stride, LP_JIT_IMAGE_ROW_STRIDE, TRUE) +LP_LLVM_IMAGE_MEMBER(img_stride, LP_JIT_IMAGE_IMG_STRIDE, TRUE) +LP_LLVM_IMAGE_MEMBER(num_samples, LP_JIT_IMAGE_NUM_SAMPLES, TRUE) +LP_LLVM_IMAGE_MEMBER(sample_stride, LP_JIT_IMAGE_SAMPLE_STRIDE, TRUE) + +#if LP_USE_TEXTURE_CACHE +static LLVMValueRef +lp_llvm_texture_cache_ptr(const struct lp_sampler_dynamic_state *base, + struct gallivm_state *gallivm, + LLVMValueRef thread_data_ptr, + unsigned unit) +{ + /* We use the same cache for all units */ + (void)unit; + + return lp_jit_thread_data_cache(gallivm, thread_data_ptr); +} +#endif static void @@ -173,64 +346,146 @@ lp_llvm_sampler_soa_destroy(struct lp_build_sampler_soa *sampler) static void lp_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base, struct gallivm_state *gallivm, - struct lp_type type, - unsigned unit, - unsigned num_coords, - const LLVMValueRef *coords, - const LLVMValueRef *ddx, - const LLVMValueRef *ddy, - LLVMValueRef lod_bias, /* optional */ - LLVMValueRef explicit_lod, /* optional */ - LLVMValueRef *texel) + const struct lp_sampler_params *params) { struct lp_llvm_sampler_soa *sampler = (struct lp_llvm_sampler_soa *)base; + unsigned texture_index = params->texture_index; + unsigned sampler_index = params->sampler_index; - 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, texel); + lp_build_sample_nop(gallivm, params->type, params->coords, params->texel); return; } - lp_build_sample_soa(gallivm, - &sampler->dynamic_state.static_state[unit], + lp_build_sample_soa(&sampler->dynamic_state.static_state[texture_index].texture_state, + &sampler->dynamic_state.static_state[sampler_index].sampler_state, &sampler->dynamic_state.base, - type, - unit, - num_coords, coords, - ddx, ddy, - lod_bias, explicit_lod, - texel); + gallivm, params); +} + +/** + * Fetch the texture size. + */ +static void +lp_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base, + struct gallivm_state *gallivm, + const struct lp_sampler_size_query_params *params) +{ + struct lp_llvm_sampler_soa *sampler = (struct lp_llvm_sampler_soa *)base; + + assert(params->texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS); + + lp_build_size_query_soa(gallivm, + &sampler->dynamic_state.static_state[params->texture_unit].texture_state, + &sampler->dynamic_state.base, + params); } struct lp_build_sampler_soa * lp_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state, - LLVMValueRef context_ptr) + unsigned nr_samplers) { struct lp_llvm_sampler_soa *sampler; sampler = CALLOC_STRUCT(lp_llvm_sampler_soa); - if(!sampler) + if (!sampler) return NULL; sampler->base.destroy = lp_llvm_sampler_soa_destroy; - sampler->base.emit_fetch_texel = lp_llvm_sampler_soa_emit_fetch_texel; + sampler->base.emit_tex_sample = lp_llvm_sampler_soa_emit_fetch_texel; + sampler->base.emit_size_query = lp_llvm_sampler_soa_emit_size_query; sampler->dynamic_state.base.width = lp_llvm_texture_width; sampler->dynamic_state.base.height = lp_llvm_texture_height; sampler->dynamic_state.base.depth = lp_llvm_texture_depth; + sampler->dynamic_state.base.first_level = lp_llvm_texture_first_level; sampler->dynamic_state.base.last_level = lp_llvm_texture_last_level; + sampler->dynamic_state.base.base_ptr = lp_llvm_texture_base_ptr; 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.data_ptr = lp_llvm_texture_data_ptr; - 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.mip_offsets = lp_llvm_texture_mip_offsets; + sampler->dynamic_state.base.num_samples = lp_llvm_texture_num_samples; + sampler->dynamic_state.base.sample_stride = lp_llvm_texture_sample_stride; + 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; + +#if LP_USE_TEXTURE_CACHE + sampler->dynamic_state.base.cache_ptr = lp_llvm_texture_cache_ptr; +#endif sampler->dynamic_state.static_state = static_state; - sampler->dynamic_state.context_ptr = context_ptr; + sampler->nr_samplers = nr_samplers; return &sampler->base; } +static void +lp_llvm_image_soa_destroy(struct lp_build_image_soa *image) +{ + FREE(image); +} + +static void +lp_llvm_image_soa_emit_op(const struct lp_build_image_soa *base, + struct gallivm_state *gallivm, + const struct lp_img_params *params) +{ + struct lp_llvm_image_soa *image = (struct lp_llvm_image_soa *)base; + unsigned image_index = params->image_index; + assert(image_index < PIPE_MAX_SHADER_IMAGES); + + lp_build_img_op_soa(&image->dynamic_state.static_state[image_index].image_state, + &image->dynamic_state.base, + gallivm, params); +} + +/** + * Fetch the texture size. + */ +static void +lp_llvm_image_soa_emit_size_query(const struct lp_build_image_soa *base, + struct gallivm_state *gallivm, + const struct lp_sampler_size_query_params *params) +{ + struct lp_llvm_image_soa *image = (struct lp_llvm_image_soa *)base; + + assert(params->texture_unit < PIPE_MAX_SHADER_IMAGES); + + lp_build_size_query_soa(gallivm, + &image->dynamic_state.static_state[params->texture_unit].image_state, + &image->dynamic_state.base, + params); +} + +struct lp_build_image_soa * +lp_llvm_image_soa_create(const struct lp_image_static_state *static_state) +{ + struct lp_llvm_image_soa *image; + + image = CALLOC_STRUCT(lp_llvm_image_soa); + if (!image) + return NULL; + + image->base.destroy = lp_llvm_image_soa_destroy; + image->base.emit_op = lp_llvm_image_soa_emit_op; + image->base.emit_size_query = lp_llvm_image_soa_emit_size_query; + + image->dynamic_state.base.width = lp_llvm_image_width; + image->dynamic_state.base.height = lp_llvm_image_height; + + image->dynamic_state.base.depth = lp_llvm_image_depth; + image->dynamic_state.base.base_ptr = lp_llvm_image_base_ptr; + image->dynamic_state.base.row_stride = lp_llvm_image_row_stride; + image->dynamic_state.base.img_stride = lp_llvm_image_img_stride; + image->dynamic_state.base.num_samples = lp_llvm_image_num_samples; + image->dynamic_state.base.sample_stride = lp_llvm_image_sample_stride; + + image->dynamic_state.static_state = static_state; + + return &image->base; +}