radeonsi/gfx9: add a workaround for 1D depth textures
authorMarek Olšák <marek.olsak@amd.com>
Tue, 24 Jan 2017 20:39:42 +0000 (21:39 +0100)
committerMarek Olšák <marek.olsak@amd.com>
Thu, 30 Mar 2017 12:44:33 +0000 (14:44 +0200)
The same workaround is used by Vulkan.

Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/gallium/drivers/radeon/radeon_winsys.h
src/gallium/drivers/radeonsi/si_shader.c
src/gallium/drivers/radeonsi/si_state.c
src/gallium/winsys/amdgpu/drm/amdgpu_surface.c

index e25f60cb904f244dd82488c9d4b047698419dfef..5b032bfea7b822f138d86028991ce2991b25dbf1 100644 (file)
@@ -327,6 +327,13 @@ struct legacy_surf_layout {
     uint8_t                     stencil_tiling_index[RADEON_SURF_MAX_LEVELS];
 };
 
+/* Same as addrlib - AddrResourceType. */
+enum gfx9_resource_type {
+    RADEON_RESOURCE_1D = 0,
+    RADEON_RESOURCE_2D,
+    RADEON_RESOURCE_3D,
+};
+
 struct gfx9_surf_flags {
     uint16_t                    swizzle_mode; /* tile mode */
     uint16_t                    epitch; /* (pitch - 1) or (height - 1) */
@@ -346,6 +353,7 @@ struct gfx9_surf_layout {
     struct gfx9_surf_meta_flags htile; /* metadata of depth and stencil */
     struct gfx9_surf_meta_flags cmask; /* metadata of fmask */
 
+    enum gfx9_resource_type     resource_type; /* 1D, 2D or 3D */
     /* The size of the 2D plane containing all mipmap levels. */
     uint64_t                    surf_slice_size;
     uint16_t                    surf_pitch; /* in blocks */
index 20d6bd732b268c9faa00b3177b6a89582c4eebef..20686bd331c3fd40c632941d0f3af1998493e9df 100644 (file)
@@ -3297,6 +3297,7 @@ static LLVMValueRef image_fetch_coords(
                const struct tgsi_full_instruction *inst,
                unsigned src)
 {
+       struct si_shader_context *ctx = si_shader_context(bld_base);
        struct gallivm_state *gallivm = bld_base->base.gallivm;
        LLVMBuilderRef builder = gallivm->builder;
        unsigned target = inst->Memory.Texture;
@@ -3311,6 +3312,17 @@ 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) {
+               if (target == TGSI_TEXTURE_1D) {
+                       coords[1] = bld_base->uint_bld.zero;
+                       num_coords++;
+               } else if (target == TGSI_TEXTURE_1D_ARRAY) {
+                       coords[2] = coords[1];
+                       coords[1] = bld_base->uint_bld.zero;
+               }
+       }
+
        if (num_coords == 1)
                return coords[0];
 
@@ -4440,11 +4452,12 @@ static void tex_fetch_args(
 
        /* Pack user derivatives */
        if (opcode == TGSI_OPCODE_TXD) {
-               int param, num_src_deriv_channels;
+               int param, num_src_deriv_channels, num_dst_deriv_channels;
 
                switch (target) {
                case TGSI_TEXTURE_3D:
                        num_src_deriv_channels = 3;
+                       num_dst_deriv_channels = 3;
                        num_deriv_channels = 3;
                        break;
                case TGSI_TEXTURE_2D:
@@ -4454,6 +4467,7 @@ static void tex_fetch_args(
                case TGSI_TEXTURE_2D_ARRAY:
                case TGSI_TEXTURE_SHADOW2D_ARRAY:
                        num_src_deriv_channels = 2;
+                       num_dst_deriv_channels = 2;
                        num_deriv_channels = 2;
                        break;
                case TGSI_TEXTURE_CUBE:
@@ -4462,6 +4476,7 @@ static void tex_fetch_args(
                case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
                        /* Cube derivatives will be converted to 2D. */
                        num_src_deriv_channels = 3;
+                       num_dst_deriv_channels = 3;
                        num_deriv_channels = 2;
                        break;
                case TGSI_TEXTURE_1D:
@@ -4469,16 +4484,31 @@ static void tex_fetch_args(
                case TGSI_TEXTURE_1D_ARRAY:
                case TGSI_TEXTURE_SHADOW1D_ARRAY:
                        num_src_deriv_channels = 1;
-                       num_deriv_channels = 1;
+
+                       /* 1D textures are allocated and used as 2D on GFX9. */
+                       if (ctx->screen->b.chip_class >= GFX9) {
+                               num_dst_deriv_channels = 2;
+                               num_deriv_channels = 2;
+                       } else {
+                               num_dst_deriv_channels = 1;
+                               num_deriv_channels = 1;
+                       }
                        break;
                default:
                        unreachable("invalid target");
                }
 
-               for (param = 0; param < 2; param++)
+               for (param = 0; param < 2; param++) {
                        for (chan = 0; chan < num_src_deriv_channels; chan++)
-                               derivs[param * num_src_deriv_channels + chan] =
+                               derivs[param * num_dst_deriv_channels + chan] =
                                        lp_build_emit_fetch(bld_base, inst, param+1, chan);
+
+                       /* Fill in the rest with zeros. */
+                       for (chan = num_src_deriv_channels;
+                            chan < num_dst_deriv_channels; chan++)
+                               derivs[param * num_dst_deriv_channels + chan] =
+                                       bld_base->base.zero;
+               }
        }
 
        if (target == TGSI_TEXTURE_CUBE ||
@@ -4502,6 +4532,27 @@ static void tex_fetch_args(
        if (num_coords > 2)
                address[count++] = coords[2];
 
+       /* 1D textures are allocated and used as 2D on GFX9. */
+       if (ctx->screen->b.chip_class >= GFX9) {
+               LLVMValueRef filler;
+
+               /* Use 0.5, so that we don't sample the border color. */
+               if (opcode == TGSI_OPCODE_TXF)
+                       filler = bld_base->uint_bld.zero;
+               else
+                       filler = LLVMConstReal(ctx->f32, 0.5);
+
+               if (target == TGSI_TEXTURE_1D ||
+                   target == TGSI_TEXTURE_SHADOW1D) {
+                       address[count++] = filler;
+               } else if (target == TGSI_TEXTURE_1D_ARRAY ||
+                          target == TGSI_TEXTURE_SHADOW1D_ARRAY) {
+                       address[count] = coords[count - 1];
+                       address[count - 1] = filler;
+                       count++;
+               }
+       }
+
        /* Pack LOD or sample index */
        if (opcode == TGSI_OPCODE_TXL || opcode == TGSI_OPCODE_TXF)
                address[count++] = coords[3];
index 3e0708f92082f9e8eb578346c12c6955d6148d0d..5d1953fe6b0028a0c8ecb9601794300c2133d6f9 100644 (file)
@@ -1665,9 +1665,11 @@ static unsigned si_tex_compare(unsigned compare)
        }
 }
 
-static unsigned si_tex_dim(unsigned res_target, unsigned view_target,
-                          unsigned nr_samples)
+static unsigned si_tex_dim(struct si_screen *sscreen, struct r600_texture *rtex,
+                          unsigned view_target, unsigned nr_samples)
 {
+       unsigned res_target = rtex->resource.b.b.target;
+
        if (view_target == PIPE_TEXTURE_CUBE ||
            view_target == PIPE_TEXTURE_CUBE_ARRAY)
                res_target = view_target;
@@ -1676,6 +1678,17 @@ static unsigned si_tex_dim(unsigned res_target, unsigned view_target,
                 res_target == PIPE_TEXTURE_CUBE_ARRAY)
                res_target = PIPE_TEXTURE_2D_ARRAY;
 
+       /* GFX9 allocates 1D textures as 2D. */
+       if ((res_target == PIPE_TEXTURE_1D ||
+            res_target == PIPE_TEXTURE_1D_ARRAY) &&
+           sscreen->b.chip_class >= GFX9 &&
+           rtex->surface.u.gfx9.resource_type == RADEON_RESOURCE_2D) {
+               if (res_target == PIPE_TEXTURE_1D)
+                       res_target = PIPE_TEXTURE_2D;
+               else
+                       res_target = PIPE_TEXTURE_2D_ARRAY;
+       }
+
        switch (res_target) {
        default:
        case PIPE_TEXTURE_1D:
@@ -2210,24 +2223,10 @@ static void si_initialize_color_surface(struct si_context *sctx,
 
        if (sctx->b.chip_class >= GFX9) {
                unsigned mip0_depth = util_max_layer(&rtex->resource.b.b, 0);
-               unsigned type;
-
-               switch (rtex->resource.b.b.target) {
-               case PIPE_TEXTURE_1D:
-               case PIPE_TEXTURE_1D_ARRAY:
-                       type = V_028C74_1D;
-                       break;
-               default:
-                       type = V_028C74_2D;
-                       break;
-               case PIPE_TEXTURE_3D:
-                       type = V_028C74_3D;
-                       break;
-               }
 
                surf->cb_color_view |= S_028C6C_MIP_LEVEL(surf->base.u.tex.level);
                surf->cb_color_attrib |= S_028C74_MIP0_DEPTH(mip0_depth) |
-                                        S_028C74_RESOURCE_TYPE(type);
+                                        S_028C74_RESOURCE_TYPE(rtex->surface.u.gfx9.resource_type);
                surf->cb_color_attrib2 = S_028C68_MIP0_WIDTH(rtex->resource.b.b.width0 - 1) |
                                         S_028C68_MIP0_HEIGHT(rtex->resource.b.b.height0 - 1) |
                                         S_028C68_MAX_MIP(rtex->resource.b.b.last_level);
@@ -3108,7 +3107,7 @@ si_make_texture_descriptor(struct si_screen *screen,
 
                assert(res->target != PIPE_TEXTURE_3D || (first_level == 0 && last_level == 0));
        } else {
-               type = si_tex_dim(res->target, target, res->nr_samples);
+               type = si_tex_dim(screen, tex, target, res->nr_samples);
        }
 
        if (type == V_008F1C_SQ_RSRC_IMG_1D_ARRAY) {
@@ -3227,7 +3226,7 @@ si_make_texture_descriptor(struct si_screen *screen,
                                 S_008F1C_DST_SEL_Y(V_008F1C_SQ_SEL_X) |
                                 S_008F1C_DST_SEL_Z(V_008F1C_SQ_SEL_X) |
                                 S_008F1C_DST_SEL_W(V_008F1C_SQ_SEL_X) |
-                                S_008F1C_TYPE(si_tex_dim(res->target, target, 0));
+                                S_008F1C_TYPE(si_tex_dim(screen, tex, target, 0));
                fmask_state[4] = 0;
                fmask_state[5] = S_008F24_BASE_ARRAY(first_layer);
                fmask_state[6] = 0;
index 512d56bc03b183cb20e8163c636155850c009bb7..dd3a154c14b280c05ff7d0d80c3a1c9963c2af02 100644 (file)
@@ -847,15 +847,11 @@ static int gfx9_surface_init(struct radeon_winsys *rws,
    AddrSurfInfoIn.numFrags = AddrSurfInfoIn.numSamples;
 
    switch (tex->target) {
+   /* GFX9 doesn't support 1D depth textures, so allocate all 1D textures
+    * as 2D to avoid having shader variants for 1D vs 2D, so all shaders
+    * must sample 1D textures as 2D. */
    case PIPE_TEXTURE_1D:
    case PIPE_TEXTURE_1D_ARRAY:
-      AddrSurfInfoIn.resourceType = ADDR_RSRC_TEX_1D;
-      AddrSurfInfoIn.width = tex->width0;
-      AddrSurfInfoIn.height = 1;
-      AddrSurfInfoIn.numSlices = tex->array_size;
-      AddrSurfInfoIn.swizzleMode = ADDR_SW_LINEAR; /* the only allowed mode */
-      break;
-
    case PIPE_TEXTURE_2D:
    case PIPE_TEXTURE_2D_ARRAY:
    case PIPE_TEXTURE_RECT:
@@ -901,6 +897,8 @@ static int gfx9_surface_init(struct radeon_winsys *rws,
       assert(0);
    }
 
+   surf->u.gfx9.resource_type = AddrSurfInfoIn.resourceType;
+
    surf->surf_size = 0;
    surf->dcc_size = 0;
    surf->htile_size = 0;