radeonsi/gfx9: add a workaround for viewing a slice of 3D as a 2D image
authorMarek Olšák <marek.olsak@amd.com>
Sun, 23 Apr 2017 22:01:06 +0000 (00:01 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Wed, 26 Apr 2017 11:08:05 +0000 (13:08 +0200)
Cc: 17.1 <mesa-stable@lists.freedesktop.org>
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/gallium/drivers/radeonsi/si_shader.c

index c5c994d60726ae8d0d1fb0434ed661d5b6263822..bbb1c13cf26318ef2f9440b216f4df6872ef5c29 100644 (file)
@@ -3400,7 +3400,7 @@ image_fetch_rsrc(
 static LLVMValueRef image_fetch_coords(
                struct lp_build_tgsi_context *bld_base,
                const struct tgsi_full_instruction *inst,
-               unsigned src)
+               unsigned src, LLVMValueRef desc)
 {
        struct si_shader_context *ctx = si_shader_context(bld_base);
        struct gallivm_state *gallivm = &ctx->gallivm;
@@ -3417,8 +3417,8 @@ static LLVMValueRef image_fetch_coords(
                coords[chan] = tmp;
        }
 
-       /* 1D textures are allocated and used as 2D on GFX9. */
        if (ctx->screen->b.chip_class >= GFX9) {
+               /* 1D textures are allocated and used as 2D on GFX9. */
                if (target == TGSI_TEXTURE_1D) {
                        coords[1] = ctx->i32_0;
                        num_coords++;
@@ -3426,6 +3426,21 @@ static LLVMValueRef image_fetch_coords(
                        coords[2] = coords[1];
                        coords[1] = ctx->i32_0;
                        num_coords++;
+               } else if (target == TGSI_TEXTURE_2D) {
+                       /* The hw can't bind a slice of a 3D image as a 2D
+                        * image, because it ignores BASE_ARRAY if the target
+                        * is 3D. The workaround is to read BASE_ARRAY and set
+                        * it as the 3rd address operand for all 2D images.
+                        */
+                       LLVMValueRef first_layer, const5, mask;
+
+                       const5 = LLVMConstInt(ctx->i32, 5, 0);
+                       mask = LLVMConstInt(ctx->i32, S_008F24_BASE_ARRAY(~0), 0);
+                       first_layer = LLVMBuildExtractElement(builder, desc, const5, "");
+                       first_layer = LLVMBuildAnd(builder, first_layer, mask, "");
+
+                       coords[2] = first_layer;
+                       num_coords++;
                }
        }
 
@@ -3540,7 +3555,7 @@ static void load_fetch_args(
                LLVMValueRef coords;
 
                image_fetch_rsrc(bld_base, &inst->Src[0], false, target, &rsrc);
-               coords = image_fetch_coords(bld_base, inst, 1);
+               coords = image_fetch_coords(bld_base, inst, 1, rsrc);
 
                if (target == TGSI_TEXTURE_BUFFER) {
                        buffer_append_args(ctx, emit_data, rsrc, coords,
@@ -3815,16 +3830,15 @@ static void store_fetch_args(
                 */
                bool force_glc = ctx->screen->b.chip_class == SI;
 
-               coords = image_fetch_coords(bld_base, inst, 0);
+               image_fetch_rsrc(bld_base, &memory, true, target, &rsrc);
+               coords = image_fetch_coords(bld_base, inst, 0, rsrc);
 
                if (target == TGSI_TEXTURE_BUFFER) {
-                       image_fetch_rsrc(bld_base, &memory, true, target, &rsrc);
                        buffer_append_args(ctx, emit_data, rsrc, coords,
                                           ctx->i32_0, false, force_glc);
                } else {
                        emit_data->args[1] = coords;
-                       image_fetch_rsrc(bld_base, &memory, true, target,
-                                        &emit_data->args[2]);
+                       emit_data->args[2] = rsrc;
                        emit_data->args[3] = LLVMConstInt(ctx->i32, 15, 0); /* dmask */
                        emit_data->arg_count = 4;
 
@@ -4028,7 +4042,7 @@ static void atomic_fetch_args(
                LLVMValueRef coords;
 
                image_fetch_rsrc(bld_base, &inst->Src[0], true, target, &rsrc);
-               coords = image_fetch_coords(bld_base, inst, 1);
+               coords = image_fetch_coords(bld_base, inst, 1, rsrc);
 
                if (target == TGSI_TEXTURE_BUFFER) {
                        buffer_append_args(ctx, emit_data, rsrc, coords,