diff options
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/radeonsi/si_shader_nir.c | 80 |
1 files changed, 50 insertions, 30 deletions
diff --git a/src/gallium/drivers/radeonsi/si_shader_nir.c b/src/gallium/drivers/radeonsi/si_shader_nir.c index 5d6280b80f7..87ca0161b45 100644 --- a/src/gallium/drivers/radeonsi/si_shader_nir.c +++ b/src/gallium/drivers/radeonsi/si_shader_nir.c @@ -897,50 +897,70 @@ si_nir_load_sampler_desc(struct ac_shader_abi *abi, bool write, bool bindless) { struct si_shader_context *ctx = si_shader_context_from_abi(abi); + const struct tgsi_shader_info *info = &ctx->shader->selector->info; LLVMBuilderRef builder = ctx->ac.builder; - LLVMValueRef list = LLVMGetParam(ctx->main_fn, ctx->param_samplers_and_images); - LLVMValueRef index; + unsigned const_index = base_index + constant_index; + bool dcc_off = write; + + /* TODO: images_store and images_atomic are not set */ + if (!dynamic_index && image && + (info->images_store | info->images_atomic) & (1 << const_index)) + dcc_off = true; assert(!descriptor_set); + assert(!image || desc_type == AC_DESC_IMAGE || desc_type == AC_DESC_BUFFER); - dynamic_index = dynamic_index ? dynamic_index : ctx->ac.i32_0; - index = LLVMBuildAdd(builder, dynamic_index, - LLVMConstInt(ctx->ac.i32, base_index + constant_index, false), - ""); + if (bindless) { + LLVMValueRef list = + LLVMGetParam(ctx->main_fn, ctx->param_bindless_samplers_and_images); - if (image) { - assert(desc_type == AC_DESC_IMAGE || desc_type == AC_DESC_BUFFER); - assert(base_index + constant_index < ctx->num_images); + /* dynamic_index is the bindless handle */ + if (image) { + return si_load_image_desc(ctx, list, dynamic_index, desc_type, + dcc_off, true); + } + + /* Since bindless handle arithmetic can contain an unsigned integer + * wraparound and si_load_sampler_desc assumes there isn't any, + * use GEP without "inbounds" (inside ac_build_pointer_add) + * to prevent incorrect code generation and hangs. + */ + dynamic_index = LLVMBuildMul(ctx->ac.builder, dynamic_index, + LLVMConstInt(ctx->i32, 2, 0), ""); + list = ac_build_pointer_add(&ctx->ac, list, dynamic_index); + return si_load_sampler_desc(ctx, list, ctx->i32_0, desc_type); + } + + unsigned num_slots = image ? ctx->num_images : ctx->num_samplers; + assert(const_index < num_slots); - if (dynamic_index) - index = si_llvm_bound_index(ctx, index, ctx->num_images); + LLVMValueRef list = LLVMGetParam(ctx->main_fn, ctx->param_samplers_and_images); + LLVMValueRef index = LLVMConstInt(ctx->ac.i32, const_index, false); + + if (dynamic_index) { + index = LLVMBuildAdd(builder, index, dynamic_index, ""); + + /* From the GL_ARB_shader_image_load_store extension spec: + * + * If a shader performs an image load, store, or atomic + * operation using an image variable declared as an array, + * and if the index used to select an individual element is + * negative or greater than or equal to the size of the + * array, the results of the operation are undefined but may + * not lead to termination. + */ + index = si_llvm_bound_index(ctx, index, num_slots); + } + if (image) { index = LLVMBuildSub(ctx->ac.builder, LLVMConstInt(ctx->i32, SI_NUM_IMAGES - 1, 0), index, ""); - - /* TODO: be smarter about when we use dcc_off */ - return si_load_image_desc(ctx, list, index, desc_type, write, bindless); + return si_load_image_desc(ctx, list, index, desc_type, dcc_off, false); } - assert(base_index + constant_index < ctx->num_samplers); - - if (dynamic_index) - index = si_llvm_bound_index(ctx, index, ctx->num_samplers); - index = LLVMBuildAdd(ctx->ac.builder, index, LLVMConstInt(ctx->i32, SI_NUM_IMAGES / 2, 0), ""); - - if (bindless) { - /* Since bindless handle arithmetic can contain an unsigned integer - * wraparound and si_load_sampler_desc assumes there isn't any, - * use GEP without "inbounds" (inside ac_build_pointer_add) - * to prevent incorrect code generation and hangs. - */ - index = LLVMBuildMul(ctx->ac.builder, index, LLVMConstInt(ctx->i32, 2, 0), ""); - list = ac_build_pointer_add(&ctx->ac, list, index); - index = ctx->i32_0; - } return si_load_sampler_desc(ctx, list, index, desc_type); } |