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);
}