[Mesa-dev] [Mesa-stable] [PATCH 2/2] radeonsi: hard-code pixel center for interpolateAtSample without multisample buffers

Marek Olšák maraeo at gmail.com
Tue Sep 12 23:44:51 UTC 2017


For the series:

Reviewed-by: Marek Olšák <marek.olsak at amd.com>

Marek

On Mon, Sep 11, 2017 at 5:11 PM, Nicolai Hähnle <nhaehnle at gmail.com> wrote:
> From: Nicolai Hähnle <nicolai.haehnle at amd.com>
>
> The GLSL rules for interpolateAtSample are unfortunate:
>
>    "Returns the value of the input interpolant variable at
>     the location of sample number sample. If
>     multisample buffers are not available, the input
>     variable will be evaluated at the center of the pixel.
>     If sample sample does not exist, the position used to
>     interpolate the input variable is undefined."
>
> This fix will fallback to monolithic shader compilation when
> interpolateAtSample is used without multisampling.
>
> One alternative would be to always upload 16 sample positions,
> filling the buffer up with repetition when the actual number of
> samples is less, and then ANDing the sample ID with 0xf. However,
> that punishes all well-behaving users of interpolateAtSample,
> when in reality, only conformance tests should be affected by
> the issue.
>
> Fixes
> dEQP-GLES31.functional.shaders.multisample_interpolation.interpolate_at_sample.non_multisample_buffer.*
> ---
>  src/gallium/drivers/radeonsi/si_shader.c        | 28 ++++++++++++++++++++++++-
>  src/gallium/drivers/radeonsi/si_shader.h        |  3 +++
>  src/gallium/drivers/radeonsi/si_state_shaders.c |  3 +++
>  3 files changed, 33 insertions(+), 1 deletion(-)
>
> diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
> index 85de2e407b4..d0af60856b0 100644
> --- a/src/gallium/drivers/radeonsi/si_shader.c
> +++ b/src/gallium/drivers/radeonsi/si_shader.c
> @@ -3665,21 +3665,47 @@ static void interp_fetch_args(
>                 LLVMValueRef sample_id;
>                 LLVMValueRef halfval = LLVMConstReal(ctx->f32, 0.5f);
>
>                 /* fetch sample ID, then fetch its sample position,
>                  * and place into first two channels.
>                  */
>                 sample_id = lp_build_emit_fetch(bld_base,
>                                                 emit_data->inst, 1, TGSI_CHAN_X);
>                 sample_id = LLVMBuildBitCast(gallivm->builder, sample_id,
>                                              ctx->i32, "");
> -               sample_position = load_sample_position(ctx, sample_id);
> +
> +               /* Section 8.13.2 (Interpolation Functions) of the OpenGL Shading
> +                * Language 4.50 spec says about interpolateAtSample:
> +                *
> +                *    "Returns the value of the input interpolant variable at
> +                *     the location of sample number sample. If multisample
> +                *     buffers are not available, the input variable will be
> +                *     evaluated at the center of the pixel. If sample sample
> +                *     does not exist, the position used to interpolate the
> +                *     input variable is undefined."
> +                *
> +                * This means that sample_id values outside of the valid are
> +                * in fact valid input, and the usual mechanism for loading the
> +                * sample position doesn't work.
> +                */
> +               if (ctx->shader->key.mono.u.ps.interpolate_at_sample_force_center) {
> +                       LLVMValueRef center[4] = {
> +                               LLVMConstReal(ctx->f32, 0.5),
> +                               LLVMConstReal(ctx->f32, 0.5),
> +                               ctx->ac.f32_0,
> +                               ctx->ac.f32_0,
> +                       };
> +
> +                       sample_position = lp_build_gather_values(gallivm, center, 4);
> +               } else {
> +                       sample_position = load_sample_position(ctx, sample_id);
> +               }
>
>                 emit_data->args[0] = LLVMBuildExtractElement(gallivm->builder,
>                                                              sample_position,
>                                                              ctx->i32_0, "");
>
>                 emit_data->args[0] = LLVMBuildFSub(gallivm->builder, emit_data->args[0], halfval, "");
>                 emit_data->args[1] = LLVMBuildExtractElement(gallivm->builder,
>                                                              sample_position,
>                                                              ctx->i32_1, "");
>                 emit_data->args[1] = LLVMBuildFSub(gallivm->builder, emit_data->args[1], halfval, "");
> diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h
> index be17cf462be..22bb56b0ece 100644
> --- a/src/gallium/drivers/radeonsi/si_shader.h
> +++ b/src/gallium/drivers/radeonsi/si_shader.h
> @@ -508,20 +508,23 @@ struct si_shader_key {
>
>         /* Flags for monolithic compilation only. */
>         struct {
>                 /* One byte for every input: SI_FIX_FETCH_* enums. */
>                 uint8_t         vs_fix_fetch[SI_MAX_ATTRIBS];
>
>                 union {
>                         uint64_t        ff_tcs_inputs_to_copy; /* for fixed-func TCS */
>                         /* When PS needs PrimID and GS is disabled. */
>                         unsigned        vs_export_prim_id:1;
> +                       struct {
> +                               unsigned interpolate_at_sample_force_center:1;
> +                       } ps;
>                 } u;
>         } mono;
>
>         /* Optimization flags for asynchronous compilation only. */
>         struct {
>                 /* For HW VS (it can be VS, TES, GS) */
>                 uint64_t        kill_outputs; /* "get_unique_index" bits */
>                 unsigned        clip_disable:1;
>
>                 /* For shaders where monolithic variants have better code.
> diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c
> index 6b63e69d91c..cbef8d8a646 100644
> --- a/src/gallium/drivers/radeonsi/si_state_shaders.c
> +++ b/src/gallium/drivers/radeonsi/si_state_shaders.c
> @@ -1453,20 +1453,23 @@ static inline void si_shader_selector_key(struct pipe_context *ctx,
>                                  * of (i,j), which is the optimization here. */
>                                 key->part.ps.prolog.force_persp_center_interp =
>                                         sel->info.uses_persp_center +
>                                         sel->info.uses_persp_centroid +
>                                         sel->info.uses_persp_sample > 1;
>
>                                 key->part.ps.prolog.force_linear_center_interp =
>                                         sel->info.uses_linear_center +
>                                         sel->info.uses_linear_centroid +
>                                         sel->info.uses_linear_sample > 1;
> +
> +                               if (sel->info.opcode_count[TGSI_OPCODE_INTERP_SAMPLE])
> +                                       key->mono.u.ps.interpolate_at_sample_force_center = 1;
>                         }
>                 }
>
>                 key->part.ps.epilog.alpha_func = si_get_alpha_test_func(sctx);
>                 break;
>         }
>         default:
>                 assert(0);
>         }
>
> --
> 2.11.0
>
> _______________________________________________
> mesa-stable mailing list
> mesa-stable at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-stable


More information about the mesa-dev mailing list