radeonsi: disable aniso filtering for non-mipmap textures on SI-CI
authorMarek Olšák <marek.olsak@amd.com>
Thu, 7 Apr 2016 19:37:43 +0000 (21:37 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Tue, 12 Apr 2016 12:29:48 +0000 (14:29 +0200)
The closed driver does this, but it looks at base_level and last_level
and uses a conditional assignment, which LLVM can't generate on SGPRs.

That led me to invent this solution that abuses the image descriptor.

Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/gallium/drivers/radeonsi/si_shader.c
src/gallium/drivers/radeonsi/si_state.c

index 08da3e37550e4e583d936069cd08dfc1b43bc0ce..59c6f41f803fbd3540f8af8cb9545a7089d3eba7 100644 (file)
@@ -3339,6 +3339,35 @@ static LLVMValueRef get_sampler_desc(struct si_shader_context *ctx,
        return get_sampler_desc_custom(ctx, list, index, type);
 }
 
+/* Disable anisotropic filtering if BASE_LEVEL == LAST_LEVEL.
+ *
+ * SI-CI:
+ *   If BASE_LEVEL == LAST_LEVEL, the shader must disable anisotropic
+ *   filtering manually. The driver sets img7 to a mask clearing
+ *   MAX_ANISO_RATIO if BASE_LEVEL == LAST_LEVEL. The shader must do:
+ *     s_and_b32 samp0, samp0, img7
+ *
+ * VI:
+ *   The ANISO_OVERRIDE sampler field enables this fix in TA.
+ */
+static LLVMValueRef sici_fix_sampler_aniso(struct si_shader_context *ctx,
+                                          LLVMValueRef res, LLVMValueRef samp)
+{
+       LLVMBuilderRef builder = ctx->radeon_bld.gallivm.builder;
+       LLVMValueRef img7, samp0;
+
+       if (ctx->screen->b.chip_class >= VI)
+               return samp;
+
+       img7 = LLVMBuildExtractElement(builder, res,
+                                      LLVMConstInt(ctx->i32, 7, 0), "");
+       samp0 = LLVMBuildExtractElement(builder, samp,
+                                       LLVMConstInt(ctx->i32, 0, 0), "");
+       samp0 = LLVMBuildAnd(builder, samp0, img7, "");
+       return LLVMBuildInsertElement(builder, samp, samp0,
+                                     LLVMConstInt(ctx->i32, 0, 0), "");
+}
+
 static void tex_fetch_ptrs(
        struct lp_build_tgsi_context *bld_base,
        struct lp_build_emit_data *emit_data,
@@ -3370,6 +3399,7 @@ static void tex_fetch_ptrs(
                        *fmask_ptr = get_sampler_desc(ctx, ind_index, DESC_FMASK);
                } else {
                        *samp_ptr = get_sampler_desc(ctx, ind_index, DESC_SAMPLER);
+                       *samp_ptr = sici_fix_sampler_aniso(ctx, *res_ptr, *samp_ptr);
                        *fmask_ptr = NULL;
                }
        } else {
@@ -4701,9 +4731,13 @@ static void preload_samplers(struct si_shader_context *ctx)
                if (info->is_msaa_sampler[i])
                        ctx->fmasks[i] =
                                get_sampler_desc(ctx, offset, DESC_FMASK);
-               else
+               else {
                        ctx->sampler_states[i] =
                                get_sampler_desc(ctx, offset, DESC_SAMPLER);
+                       ctx->sampler_states[i] =
+                               sici_fix_sampler_aniso(ctx, ctx->sampler_views[i],
+                                                      ctx->sampler_states[i]);
+               }
        }
 }
 
index fe27ca5ac166db89b9b9de2fb99f1385002fdcde..d75565a5c24f01dbf12c2d1644868cbb1fc55558 100644 (file)
@@ -3136,6 +3136,16 @@ si_make_texture_descriptor(struct si_screen *screen,
        } else {
                state[6] = 0;
                state[7] = 0;
+
+               /* The last dword is unused by hw. The shader uses it to clear
+                * bits in the first dword of sampler state.
+                */
+               if (screen->b.chip_class <= CIK && res->nr_samples <= 1) {
+                       if (first_level == last_level)
+                               state[7] = C_008F30_MAX_ANISO_RATIO;
+                       else
+                               state[7] = 0xffffffff;
+               }
        }
 
        /* Initialize the sampler view for FMASK. */