From: Dave Airlie Date: Tue, 19 May 2020 02:16:34 +0000 (+1000) Subject: gallivm: add indirect texture switch statement builder. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=28f906ad913f7dbd2fff2d4226191d9e1a15273d;p=mesa.git gallivm: add indirect texture switch statement builder. This adds the apis to add an indirect accessor for arrays of textures, using an LLVM switch statement and per-texture sampler functions. It also adds the indexer to the sampler parameters Reviewed-by: Roland Scheidegger Part-of: --- diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.h b/src/gallium/auxiliary/gallivm/lp_bld_sample.h index 954bce600ec..24fc06ffe72 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.h @@ -105,6 +105,7 @@ struct lp_sampler_params struct lp_type type; unsigned texture_index; unsigned sampler_index; + LLVMValueRef texture_index_offset; unsigned sample_key; LLVMValueRef context_ptr; LLVMValueRef thread_data_ptr; @@ -120,6 +121,7 @@ struct lp_sampler_size_query_params { struct lp_type int_type; unsigned texture_unit; + LLVMValueRef texture_unit_offset; unsigned target; LLVMValueRef context_ptr; boolean is_sviewinfo; @@ -442,6 +444,20 @@ struct lp_build_sample_context LLVMValueRef context_ptr; }; +/* + * Indirect texture access context + * + * This is used to store info across building + * and indirect texture switch statement. + */ +struct lp_build_sample_array_switch { + struct gallivm_state *gallivm; + struct lp_sampler_params params; + unsigned base, range; + LLVMValueRef switch_ref; + LLVMBasicBlockRef merge_ref; + LLVMValueRef phi; +}; /** @@ -693,6 +709,21 @@ lp_build_img_op_soa(const struct lp_static_texture_state *static_texture_state, struct gallivm_state *gallivm, const struct lp_img_params *params); +void +lp_build_sample_array_init_soa(struct lp_build_sample_array_switch *switch_info, + struct gallivm_state *gallivm, + const struct lp_sampler_params *params, + LLVMValueRef idx, + unsigned base, unsigned range); + +void +lp_build_sample_array_case_soa(struct lp_build_sample_array_switch *switch_info, + int idx, + const struct lp_static_texture_state *static_texture_state, + const struct lp_static_sampler_state *static_sampler_state, + struct lp_sampler_dynamic_state *dynamic_texture_state); + +void lp_build_sample_array_fini_soa(struct lp_build_sample_array_switch *switch_info); #ifdef __cplusplus } #endif diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c index 86c70bc3088..2422405fa30 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c @@ -4228,3 +4228,91 @@ lp_build_img_op_soa(const struct lp_static_texture_state *static_texture_state, params->img_op, params->op, params->indata, params->indata2, params->outdata); } } + +/* + * These functions are for indirect texture access suppoort. + * + * Indirect textures are implemented using a switch statement, that + * takes the texture index and jumps to the sampler functions for + * that texture unit. + */ + +/* + * Initialise an indexed sampler switch block. + * + * This sets up the switch_info state and adds the LLVM flow control pieces. + */ +void +lp_build_sample_array_init_soa(struct lp_build_sample_array_switch *switch_info, + struct gallivm_state *gallivm, + const struct lp_sampler_params *params, + LLVMValueRef idx, + unsigned base, unsigned range) +{ + switch_info->gallivm = gallivm; + switch_info->params = *params; + switch_info->base = base; + switch_info->range = range; + + /* for generating the switch functions we don't want the texture index offset */ + switch_info->params.texture_index_offset = 0; + + LLVMBasicBlockRef initial_block = LLVMGetInsertBlock(gallivm->builder); + switch_info->merge_ref = lp_build_insert_new_block(gallivm, "texmerge"); + + switch_info->switch_ref = LLVMBuildSwitch(gallivm->builder, idx, + switch_info->merge_ref, range - base); + + LLVMTypeRef val_type[4]; + val_type[0] = val_type[1] = val_type[2] = val_type[3] = + lp_build_vec_type(gallivm, params->type); + LLVMTypeRef ret_type = LLVMStructTypeInContext(gallivm->context, val_type, 4, 0); + + LLVMValueRef undef_val = LLVMGetUndef(ret_type); + + LLVMPositionBuilderAtEnd(gallivm->builder, switch_info->merge_ref); + + switch_info->phi = LLVMBuildPhi(gallivm->builder, ret_type, ""); + LLVMAddIncoming(switch_info->phi, &undef_val, &initial_block, 1); +} + +/* + * Add an individual entry to the indirect texture switch. + * + * This builds the sample function and links a case for it into the switch statement. + */ +void +lp_build_sample_array_case_soa(struct lp_build_sample_array_switch *switch_info, + int idx, + const struct lp_static_texture_state *static_texture_state, + const struct lp_static_sampler_state *static_sampler_state, + struct lp_sampler_dynamic_state *dynamic_texture_state) +{ + struct gallivm_state *gallivm = switch_info->gallivm; + LLVMBasicBlockRef this_block = lp_build_insert_new_block(gallivm, "texblock"); + LLVMValueRef tex_ret; + + LLVMAddCase(switch_info->switch_ref, LLVMConstInt(LLVMInt32TypeInContext(gallivm->context), idx, 0), this_block); + LLVMPositionBuilderAtEnd(gallivm->builder, this_block); + + lp_build_sample_soa_func(gallivm, static_texture_state, + static_sampler_state, dynamic_texture_state, &switch_info->params, idx, idx, + &tex_ret); + + LLVMAddIncoming(switch_info->phi, &tex_ret, &this_block, 1); + LLVMBuildBr(gallivm->builder, switch_info->merge_ref); +} + +/* + * Finish a switch statement. + * + * This handles extract the results from the switch. + */ +void lp_build_sample_array_fini_soa(struct lp_build_sample_array_switch *switch_info) +{ + struct gallivm_state *gallivm = switch_info->gallivm; + + LLVMPositionBuilderAtEnd(gallivm->builder, switch_info->merge_ref); + for (unsigned i = 0; i < 4; i++) + switch_info->params.texel[i] = LLVMBuildExtractValue(gallivm->builder, switch_info->phi, i, ""); +}