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 <sroland@vmware.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3778>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user