i965: Use sample barycentric coordinates with per sample shading
authorAnuj Phogat <anuj.phogat@gmail.com>
Mon, 6 Jan 2014 21:59:18 +0000 (13:59 -0800)
committerAnuj Phogat <anuj.phogat@gmail.com>
Tue, 21 Jan 2014 22:42:27 +0000 (14:42 -0800)
Current implementation of arb_sample_shading doesn't set 'Barycentric
Interpolation Mode' correctly. We use pixel barycentric coordinates
for per sample shading. Instead we should select perspective sample
or non-perspective sample barycentric coordinates.

It also enables using sample barycentric coordinates in case of a
fragment shader variable declared with 'sample' qualifier.
e.g. sample in vec4 pos;

A piglit test to verify the implementation has been posted on piglit
mailing list for review.

V2: Do not interpolate all the 'in' variables at sample position
    if fragment shader uses 'sample' qualifier with one of them.
    For example we have a fragment shader:
    #version 330
    #extension ARB_gpu_shader5: require
    sample in vec4 a;
    in vec4 b;
    main()
    {
      ...
    }

    Only 'a' should be sampled at sample location, not 'b'.

Cc: mesa-stable@lists.freedesktop.org
Signed-off-by: Anuj Phogat <anuj.phogat@gmail.com>
Reviewed-by: Chris Forbes <chrisf@ijw.co.nz>
src/mesa/drivers/dri/i965/brw_fs.cpp
src/mesa/drivers/dri/i965/brw_fs.h
src/mesa/drivers/dri/i965/brw_wm.c
src/mesa/drivers/dri/i965/brw_wm.h

index 78ddf0d99cf9588d9b572110a5af1bfa22248230..430a530d2420b2eeb16d9a233b66602324a8b109 100644 (file)
@@ -998,7 +998,7 @@ fs_visitor::emit_fragcoord_interpolation(ir_variable *ir)
 fs_inst *
 fs_visitor::emit_linterp(const fs_reg &attr, const fs_reg &interp,
                          glsl_interp_qualifier interpolation_mode,
-                         bool is_centroid)
+                         bool is_centroid, bool is_sample)
 {
    brw_wm_barycentric_interp_mode barycoord_mode;
    if (brw->gen >= 6) {
@@ -1007,6 +1007,11 @@ fs_visitor::emit_linterp(const fs_reg &attr, const fs_reg &interp,
             barycoord_mode = BRW_WM_PERSPECTIVE_CENTROID_BARYCENTRIC;
          else
             barycoord_mode = BRW_WM_NONPERSPECTIVE_CENTROID_BARYCENTRIC;
+      } else if (is_sample) {
+          if (interpolation_mode == INTERP_QUALIFIER_SMOOTH)
+            barycoord_mode = BRW_WM_PERSPECTIVE_SAMPLE_BARYCENTRIC;
+         else
+            barycoord_mode = BRW_WM_NONPERSPECTIVE_SAMPLE_BARYCENTRIC;
       } else {
          if (interpolation_mode == INTERP_QUALIFIER_SMOOTH)
             barycoord_mode = BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC;
@@ -1084,7 +1089,8 @@ fs_visitor::emit_general_interpolation(ir_variable *ir)
                */
                struct brw_reg interp = interp_reg(location, k);
                emit_linterp(attr, fs_reg(interp), interpolation_mode,
-                            ir->data.centroid);
+                            ir->data.centroid,
+                            ir->data.sample || c->key.persample_shading);
                if (brw->needs_unlit_centroid_workaround && ir->data.centroid) {
                   /* Get the pixel/sample mask into f0 so that we know
                    * which pixels are lit.  Then, for each channel that is
@@ -1093,7 +1099,8 @@ fs_visitor::emit_general_interpolation(ir_variable *ir)
                    */
                   emit(FS_OPCODE_MOV_DISPATCH_TO_FLAGS);
                   fs_inst *inst = emit_linterp(attr, fs_reg(interp),
-                                               interpolation_mode, false);
+                                               interpolation_mode,
+                                               false, false);
                   inst->predicate = BRW_PREDICATE_NORMAL;
                   inst->predicate_inverse = true;
                }
index f493784012b86f0c58cbf901d67320ae42f8fc6d..a9039088a6e82c6496c588a113ca5c2d12f99b3d 100644 (file)
@@ -340,7 +340,7 @@ public:
    fs_reg *emit_fragcoord_interpolation(ir_variable *ir);
    fs_inst *emit_linterp(const fs_reg &attr, const fs_reg &interp,
                          glsl_interp_qualifier interpolation_mode,
-                         bool is_centroid);
+                         bool is_centroid, bool is_sample);
    fs_reg *emit_frontfacing_interpolation(ir_variable *ir);
    fs_reg *emit_samplepos_setup(ir_variable *ir);
    fs_reg *emit_sampleid_setup(ir_variable *ir);
index 0a308862c4785cf1673f92c7315bfd7318a1f3b4..a6b558fd6a245ee51c711bd1a6e88f942500fdd6 100644 (file)
@@ -49,6 +49,7 @@
 static unsigned
 brw_compute_barycentric_interp_modes(struct brw_context *brw,
                                      bool shade_model_flat,
+                                     bool persample_shading,
                                      const struct gl_fragment_program *fprog)
 {
    unsigned barycentric_interp_modes = 0;
@@ -62,6 +63,8 @@ brw_compute_barycentric_interp_modes(struct brw_context *brw,
       enum glsl_interp_qualifier interp_qualifier =
          fprog->InterpQualifier[attr];
       bool is_centroid = fprog->IsCentroid & BITFIELD64_BIT(attr);
+      bool is_sample = (fprog->IsSample & BITFIELD64_BIT(attr)) ||
+         persample_shading;
       bool is_gl_Color = attr == VARYING_SLOT_COL0 || attr == VARYING_SLOT_COL1;
 
       /* Ignore unused inputs. */
@@ -82,8 +85,12 @@ brw_compute_barycentric_interp_modes(struct brw_context *brw,
          if (is_centroid) {
             barycentric_interp_modes |=
                1 << BRW_WM_NONPERSPECTIVE_CENTROID_BARYCENTRIC;
+         } else if (is_sample) {
+            barycentric_interp_modes |=
+               1 << BRW_WM_NONPERSPECTIVE_SAMPLE_BARYCENTRIC;
          }
-         if (!is_centroid || brw->needs_unlit_centroid_workaround) {
+         if ((!is_centroid && !is_sample) ||
+             brw->needs_unlit_centroid_workaround) {
             barycentric_interp_modes |=
                1 << BRW_WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC;
          }
@@ -93,8 +100,12 @@ brw_compute_barycentric_interp_modes(struct brw_context *brw,
          if (is_centroid) {
             barycentric_interp_modes |=
                1 << BRW_WM_PERSPECTIVE_CENTROID_BARYCENTRIC;
+         } else if (is_sample) {
+            barycentric_interp_modes |=
+               1 << BRW_WM_PERSPECTIVE_SAMPLE_BARYCENTRIC;
          }
-         if (!is_centroid || brw->needs_unlit_centroid_workaround) {
+         if ((!is_centroid && !is_sample) ||
+             brw->needs_unlit_centroid_workaround) {
             barycentric_interp_modes |=
                1 << BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC;
          }
@@ -171,6 +182,7 @@ bool do_wm_prog(struct brw_context *brw,
 
    c->prog_data.barycentric_interp_modes =
       brw_compute_barycentric_interp_modes(brw, c->key.flat_shade,
+                                           c->key.persample_shading,
                                            &fp->program);
 
    program = brw_wm_fs_emit(brw, c, &fp->program, prog, &program_size);
@@ -503,6 +515,10 @@ static void brw_wm_populate_key( struct brw_context *brw,
       (ctx->Multisample.SampleAlphaToCoverage || ctx->Color.AlphaEnabled);
 
    /* _NEW_BUFFERS _NEW_MULTISAMPLE */
+   /* Ignore sample qualifier while computing this flag. */
+   key->persample_shading =
+      _mesa_get_min_invocations_per_fragment(ctx, &fp->program, true) > 1;
+
    key->compute_pos_offset =
       _mesa_get_min_invocations_per_fragment(ctx, &fp->program, false) > 1 &&
       fp->program.Base.SystemValuesRead & SYSTEM_BIT_SAMPLE_POS;
index 211db0bdd2ba793ca75b8fe7385e69cdb1f3a329..14a4b8bb5a6c5720dfb7ab20fa6c63393120f801 100644 (file)
@@ -61,6 +61,7 @@ struct brw_wm_prog_key {
    uint8_t iz_lookup;
    GLuint stats_wm:1;
    GLuint flat_shade:1;
+   GLuint persample_shading:1;
    GLuint nr_color_regions:5;
    GLuint replicate_alpha:1;
    GLuint render_to_fbo:1;