From e6f7fe33244fd4f537b3055c1b51037825c0a48e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 16 Jun 2020 12:50:41 +1000 Subject: [PATCH] gallivm/nir: add support for indirect image loading This adds support for indirect image loading, image stores can cause images with different formats to be stored to, so this operates like the texture code now. Reviewed-by: Roland Scheidegger Part-of: --- src/gallium/auxiliary/gallivm/lp_bld_sample.h | 23 ++++++ .../auxiliary/gallivm/lp_bld_sample_soa.c | 75 +++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.h b/src/gallium/auxiliary/gallivm/lp_bld_sample.h index 399c24df1d6..a91e9c2ddbc 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.h @@ -460,6 +460,14 @@ struct lp_build_sample_array_switch { LLVMValueRef phi; }; +struct lp_build_img_op_array_switch { + struct gallivm_state *gallivm; + struct lp_img_params params; + unsigned base, range; + LLVMValueRef switch_ref; + LLVMBasicBlockRef merge_ref; + LLVMValueRef phi[4]; +}; /** * We only support a few wrap modes in lp_build_sample_wrap_linear_int() at @@ -726,6 +734,21 @@ lp_build_sample_array_case_soa(struct lp_build_sample_array_switch *switch_info, struct lp_sampler_dynamic_state *dynamic_texture_state); void lp_build_sample_array_fini_soa(struct lp_build_sample_array_switch *switch_info); + +void +lp_build_image_op_switch_soa(struct lp_build_img_op_array_switch *switch_info, + struct gallivm_state *gallivm, + const struct lp_img_params *params, + LLVMValueRef idx, + unsigned base, unsigned range); + +void +lp_build_image_op_array_case(struct lp_build_img_op_array_switch *switch_info, + int idx, + const struct lp_static_texture_state *static_texture_state, + struct lp_sampler_dynamic_state *dynamic_state); + +void lp_build_image_op_array_fini_soa(struct lp_build_img_op_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 b6af6015d80..e0d751690ed 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c @@ -4325,3 +4325,78 @@ void lp_build_sample_array_fini_soa(struct lp_build_sample_array_switch *switch_ for (unsigned i = 0; i < 4; i++) switch_info->params.texel[i] = LLVMBuildExtractValue(gallivm->builder, switch_info->phi, i, ""); } + +void +lp_build_image_op_switch_soa(struct lp_build_img_op_array_switch *switch_info, + struct gallivm_state *gallivm, + const struct lp_img_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.image_index_offset = 0; + + LLVMBasicBlockRef initial_block = LLVMGetInsertBlock(gallivm->builder); + switch_info->merge_ref = lp_build_insert_new_block(gallivm, "imgmerge"); + + switch_info->switch_ref = LLVMBuildSwitch(gallivm->builder, idx, + switch_info->merge_ref, range - base); + + if (params->img_op != LP_IMG_STORE) { + LLVMTypeRef ret_type = lp_build_vec_type(gallivm, params->type); + LLVMValueRef undef_val = LLVMGetUndef(ret_type); + + LLVMPositionBuilderAtEnd(gallivm->builder, switch_info->merge_ref); + + for (unsigned i = 0; i < ((params->img_op == LP_IMG_LOAD) ? 4 : 1); i++) { + switch_info->phi[i] = LLVMBuildPhi(gallivm->builder, ret_type, ""); + LLVMAddIncoming(switch_info->phi[i], &undef_val, &initial_block, 1); + } + } +} + +void +lp_build_image_op_array_case(struct lp_build_img_op_array_switch *switch_info, + int idx, + const struct lp_static_texture_state *static_texture_state, + struct lp_sampler_dynamic_state *dynamic_state) +{ + struct gallivm_state *gallivm = switch_info->gallivm; + LLVMBasicBlockRef this_block = lp_build_insert_new_block(gallivm, "img"); + LLVMValueRef tex_ret[4]; + + LLVMAddCase(switch_info->switch_ref, lp_build_const_int32(gallivm, idx), this_block); + LLVMPositionBuilderAtEnd(gallivm->builder, this_block); + + switch_info->params.image_index = idx; + + lp_build_img_op_soa(static_texture_state, dynamic_state, switch_info->gallivm, &switch_info->params, tex_ret); + if (switch_info->params.img_op != LP_IMG_STORE) { + for (unsigned i = 0; i < ((switch_info->params.img_op == LP_IMG_LOAD) ? 4 : 1); i++) + tex_ret[i] = LLVMBuildBitCast(gallivm->builder, tex_ret[i], lp_build_vec_type(gallivm, switch_info->params.type), ""); + + this_block = LLVMGetInsertBlock(gallivm->builder); + for (unsigned i = 0; i < ((switch_info->params.img_op == LP_IMG_LOAD) ? 4 : 1); i++) { + LLVMAddIncoming(switch_info->phi[i], &tex_ret[i], &this_block, 1); + } + } + LLVMBuildBr(gallivm->builder, switch_info->merge_ref); +} + +void lp_build_image_op_array_fini_soa(struct lp_build_img_op_array_switch *switch_info) +{ + struct gallivm_state *gallivm = switch_info->gallivm; + + LLVMPositionBuilderAtEnd(gallivm->builder, switch_info->merge_ref); + + if (switch_info->params.img_op != LP_IMG_STORE) { + for (unsigned i = 0; i < ((switch_info->params.img_op == LP_IMG_LOAD) ? 4 : 1); i++) { + switch_info->params.outdata[i] = switch_info->phi[i]; + } + } +} -- 2.30.2