radv: handle GFX9 1D textures
authorDave Airlie <airlied@redhat.com>
Wed, 16 Aug 2017 05:20:29 +0000 (06:20 +0100)
committerDave Airlie <airlied@redhat.com>
Tue, 12 Sep 2017 22:40:41 +0000 (08:40 +1000)
As GFX9 can't handle 1D depth textures, radeonsi and
apparantly pro just update all 1D textures to 2D,
and work around it.

This ports the workarounds from radeonsi.

Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Cc: "17.2" <mesa-stable@lists.freedesktop.org>
Signed-off-by: Dave Airlie <airlied@redhat.com>
src/amd/common/ac_nir_to_llvm.c
src/amd/vulkan/radv_image.c

index 8f9f771acf8be2d9bed09e0160ccd76a790e6bdc..22e915dd0dd8238e9d2a02fdfe569a568f6f4aa2 100644 (file)
@@ -3264,13 +3264,13 @@ static LLVMValueRef get_image_coords(struct ac_nir_context *ctx,
 
        int count;
        enum glsl_sampler_dim dim = glsl_get_sampler_dim(type);
+       bool is_array = glsl_sampler_type_is_array(type);
        bool add_frag_pos = (dim == GLSL_SAMPLER_DIM_SUBPASS ||
                             dim == GLSL_SAMPLER_DIM_SUBPASS_MS);
        bool is_ms = (dim == GLSL_SAMPLER_DIM_MS ||
                      dim == GLSL_SAMPLER_DIM_SUBPASS_MS);
-
-       count = image_type_to_components_count(dim,
-                                              glsl_sampler_type_is_array(type));
+       bool gfx9_1d = ctx->abi->chip_class >= GFX9 && dim == GLSL_SAMPLER_DIM_1D;
+       count = image_type_to_components_count(dim, is_array);
 
        if (is_ms) {
                LLVMValueRef fmask_load_address[3];
@@ -3278,7 +3278,7 @@ static LLVMValueRef get_image_coords(struct ac_nir_context *ctx,
 
                fmask_load_address[0] = LLVMBuildExtractElement(ctx->ac.builder, src0, masks[0], "");
                fmask_load_address[1] = LLVMBuildExtractElement(ctx->ac.builder, src0, masks[1], "");
-               if (glsl_sampler_type_is_array(type))
+               if (is_array)
                        fmask_load_address[2] = LLVMBuildExtractElement(ctx->ac.builder, src0, masks[2], "");
                else
                        fmask_load_address[2] = NULL;
@@ -3297,7 +3297,7 @@ static LLVMValueRef get_image_coords(struct ac_nir_context *ctx,
                                                               sample_index,
                                                               get_sampler_desc(ctx, instr->variables[0], AC_DESC_FMASK, true, false));
        }
-       if (count == 1) {
+       if (count == 1 && !gfx9_1d) {
                if (instr->src[0].ssa->num_components)
                        res = LLVMBuildExtractElement(ctx->ac.builder, src0, masks[0], "");
                else
@@ -3307,9 +3307,8 @@ static LLVMValueRef get_image_coords(struct ac_nir_context *ctx,
                if (is_ms)
                        count--;
                for (chan = 0; chan < count; ++chan) {
-                       coords[chan] = LLVMBuildExtractElement(ctx->ac.builder, src0, masks[chan], "");
+                       coords[chan] = llvm_extract_elem(&ctx->ac, src0, chan);
                }
-
                if (add_frag_pos) {
                        for (chan = 0; chan < 2; ++chan)
                                coords[chan] = LLVMBuildAdd(ctx->ac.builder, coords[chan], LLVMBuildFPToUI(ctx->ac.builder, ctx->abi->frag_pos[chan],
@@ -3317,6 +3316,16 @@ static LLVMValueRef get_image_coords(struct ac_nir_context *ctx,
                        coords[2] = ac_to_integer(&ctx->ac, ctx->abi->inputs[radeon_llvm_reg_index_soa(VARYING_SLOT_LAYER, 0)]);
                        count++;
                }
+
+               if (gfx9_1d) {
+                       if (is_array) {
+                               coords[2] = coords[1];
+                               coords[1] = ctx->ac.i32_0;
+                       } else
+                               coords[1] = ctx->ac.i32_0;
+                       count++;
+               }
+
                if (is_ms) {
                        coords[count] = sample_index;
                        count++;
@@ -3561,14 +3570,22 @@ static LLVMValueRef visit_image_size(struct ac_nir_context *ctx,
 
        res = ac_build_image_opcode(&ctx->ac, &args);
 
+       LLVMValueRef two = LLVMConstInt(ctx->ac.i32, 2, false);
+
        if (glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_CUBE &&
            glsl_sampler_type_is_array(type)) {
-               LLVMValueRef two = LLVMConstInt(ctx->ac.i32, 2, false);
                LLVMValueRef six = LLVMConstInt(ctx->ac.i32, 6, false);
                LLVMValueRef z = LLVMBuildExtractElement(ctx->ac.builder, res, two, "");
                z = LLVMBuildSDiv(ctx->ac.builder, z, six, "");
                res = LLVMBuildInsertElement(ctx->ac.builder, res, z, two, "");
        }
+       if (glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_1D &&
+           glsl_sampler_type_is_array(type)) {
+               LLVMValueRef layers = LLVMBuildExtractElement(ctx->ac.builder, res, two, "");
+               res = LLVMBuildInsertElement(ctx->ac.builder, res, layers,
+                                               ctx->ac.i32_1, "");
+
+       }
        return res;
 }
 
@@ -4495,23 +4512,39 @@ static void visit_tex(struct ac_nir_context *ctx, nir_tex_instr *instr)
 
        /* pack derivatives */
        if (ddx || ddy) {
+               int num_src_deriv_channels, num_dest_deriv_channels;
                switch (instr->sampler_dim) {
                case GLSL_SAMPLER_DIM_3D:
                case GLSL_SAMPLER_DIM_CUBE:
                        num_deriv_comp = 3;
+                       num_src_deriv_channels = 3;
+                       num_dest_deriv_channels = 3;
                        break;
                case GLSL_SAMPLER_DIM_2D:
                default:
+                       num_src_deriv_channels = 2;
+                       num_dest_deriv_channels = 2;
                        num_deriv_comp = 2;
                        break;
                case GLSL_SAMPLER_DIM_1D:
-                       num_deriv_comp = 1;
+                       num_src_deriv_channels = 1;
+                       if (ctx->abi->chip_class >= GFX9) {
+                               num_dest_deriv_channels = 2;
+                               num_deriv_comp = 2;
+                       } else {
+                               num_dest_deriv_channels = 1;
+                               num_deriv_comp = 1;
+                       }
                        break;
                }
 
-               for (unsigned i = 0; i < num_deriv_comp; i++) {
+               for (unsigned i = 0; i < num_src_deriv_channels; i++) {
                        derivs[i] = ac_to_float(&ctx->ac, llvm_extract_elem(&ctx->ac, ddx, i));
-                       derivs[num_deriv_comp + i] = ac_to_float(&ctx->ac, llvm_extract_elem(&ctx->ac, ddy, i));
+                       derivs[num_dest_deriv_channels + i] = ac_to_float(&ctx->ac, llvm_extract_elem(&ctx->ac, ddy, i));
+               }
+               for (unsigned i = num_src_deriv_channels; i < num_dest_deriv_channels; i++) {
+                       derivs[i] = ctx->ac.f32_0;
+                       derivs[num_dest_deriv_channels + i] = ctx->ac.f32_0;
                }
        }
 
@@ -4552,6 +4585,23 @@ static void visit_tex(struct ac_nir_context *ctx, nir_tex_instr *instr)
                        }
                        address[count++] = coords[2];
                }
+
+               if (ctx->abi->chip_class >= GFX9) {
+                       LLVMValueRef filler;
+                       if (instr->op == nir_texop_txf)
+                               filler = ctx->ac.i32_0;
+                       else
+                               filler = LLVMConstReal(ctx->ac.f32, 0.5);
+
+                       if (instr->sampler_dim == GLSL_SAMPLER_DIM_1D) {
+                               if (instr->is_array) {
+                                       address[count] = address[count - 1];
+                                       address[count - 1] = filler;
+                                       count++;
+                               } else
+                                       address[count++] = filler;
+                       }
+               }
        }
 
        /* Pack LOD */
@@ -4648,6 +4698,14 @@ static void visit_tex(struct ac_nir_context *ctx, nir_tex_instr *instr)
                LLVMValueRef z = LLVMBuildExtractElement(ctx->ac.builder, result, two, "");
                z = LLVMBuildSDiv(ctx->ac.builder, z, six, "");
                result = LLVMBuildInsertElement(ctx->ac.builder, result, z, two, "");
+       } else if (ctx->abi->chip_class >= GFX9 &&
+                  instr->op == nir_texop_txs &&
+                  instr->sampler_dim == GLSL_SAMPLER_DIM_1D &&
+                  instr->is_array) {
+               LLVMValueRef two = LLVMConstInt(ctx->ac.i32, 2, false);
+               LLVMValueRef layers = LLVMBuildExtractElement(ctx->ac.builder, result, two, "");
+               result = LLVMBuildInsertElement(ctx->ac.builder, result, layers,
+                                               ctx->ac.i32_1, "");
        } else if (instr->dest.ssa.num_components != 4)
                result = trim_vector(&ctx->ac, result, instr->dest.ssa.num_components);
 
index 4d83ae564fcc45494ed10504311887a88fa80dcd..df288666bebc3812680d5c3d027c4d1dda190ce8 100644 (file)
@@ -281,10 +281,14 @@ si_set_mutable_tex_desc_fields(struct radv_device *device,
 }
 
 static unsigned radv_tex_dim(VkImageType image_type, VkImageViewType view_type,
-                            unsigned nr_layers, unsigned nr_samples, bool is_storage_image)
+                            unsigned nr_layers, unsigned nr_samples, bool is_storage_image, bool gfx9)
 {
        if (view_type == VK_IMAGE_VIEW_TYPE_CUBE || view_type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
                return is_storage_image ? V_008F1C_SQ_RSRC_IMG_2D_ARRAY : V_008F1C_SQ_RSRC_IMG_CUBE;
+
+       /* GFX9 allocates 1D textures as 2D. */
+       if (gfx9 && image_type == VK_IMAGE_TYPE_1D)
+               image_type = VK_IMAGE_TYPE_2D;
        switch (image_type) {
        case VK_IMAGE_TYPE_1D:
                return nr_layers > 1 ? V_008F1C_SQ_RSRC_IMG_1D_ARRAY : V_008F1C_SQ_RSRC_IMG_1D;
@@ -375,7 +379,7 @@ si_make_texture_descriptor(struct radv_device *device,
        }
 
        type = radv_tex_dim(image->type, view_type, image->info.array_size, image->info.samples,
-                           is_storage_image);
+                           is_storage_image, device->physical_device->rad_info.chip_class >= GFX9);
        if (type == V_008F1C_SQ_RSRC_IMG_1D_ARRAY) {
                height = 1;
                depth = image->info.array_size;
@@ -495,7 +499,7 @@ si_make_texture_descriptor(struct radv_device *device,
                        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(radv_tex_dim(image->type, view_type, 1, 0, false));
+                       S_008F1C_TYPE(radv_tex_dim(image->type, view_type, 1, 0, false, false));
                fmask_state[4] = 0;
                fmask_state[5] = S_008F24_BASE_ARRAY(first_layer);
                fmask_state[6] = 0;