radeonsi: hard-code pixel center for interpolateAtSample without multisample buffers
authorNicolai Hähnle <nicolai.haehnle@amd.com>
Sun, 10 Sep 2017 17:46:31 +0000 (19:46 +0200)
committerNicolai Hähnle <nicolai.haehnle@amd.com>
Wed, 13 Sep 2017 16:25:45 +0000 (18:25 +0200)
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.*

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
src/gallium/drivers/radeonsi/si_shader.c
src/gallium/drivers/radeonsi/si_shader.h
src/gallium/drivers/radeonsi/si_state_shaders.c

index d151ba4c5c49bb792d6ce965278fd0c81e8d1427..c4e7f225a8f98efba1b1b1f5edf51b2be317edc0 100644 (file)
@@ -3711,7 +3711,33 @@ static void interp_fetch_args(
                                                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,
index 641f49cbac21626536072d194db48d758f4f849a..f457f8e20b13f858e8ad9a46af140d2d61fe3d03 100644 (file)
@@ -517,6 +517,9 @@ struct si_shader_key {
                        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;
 
index 6d87cab9883deba48b9a10ab33d506e3e783c9c5..bbc6b1d7080a54dd41c5bebfcd3acd32a138b377 100644 (file)
@@ -1462,6 +1462,9 @@ static inline void si_shader_selector_key(struct pipe_context *ctx,
                                        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;
                        }
                }