i965: Add FS backend for builtin gl_SamplePosition
authorAnuj Phogat <anuj.phogat@gmail.com>
Thu, 24 Oct 2013 22:53:05 +0000 (15:53 -0700)
committerAnuj Phogat <anuj.phogat@gmail.com>
Fri, 1 Nov 2013 23:01:48 +0000 (16:01 -0700)
V2:
   - Update comments.
   - Add compute_pos_offset variable in brw_wm_prog_key.
   - Add variable uses_pos_offset in brw_wm_prog_data.

V3:
   - Make changes to support simd16 mode.

Signed-off-by: Anuj Phogat <anuj.phogat@gmail.com>
Reviewed-by: Paul Berry <stereotype441@gmail.com>
src/mesa/drivers/dri/i965/brw_context.h
src/mesa/drivers/dri/i965/brw_fs.cpp
src/mesa/drivers/dri/i965/brw_fs.h
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
src/mesa/drivers/dri/i965/brw_wm.c
src/mesa/drivers/dri/i965/brw_wm.h

index d30c963ad48d2e9191626a05dfa48509d380b15d..665807c8bf8b970ea9c79ed068d6043db5dec936 100644 (file)
@@ -383,6 +383,7 @@ struct brw_wm_prog_data {
    GLuint nr_params;       /**< number of float params/constants */
    GLuint nr_pull_params;
    bool dual_src_blend;
+   bool uses_pos_offset;
    uint32_t prog_offset_16;
 
    /**
index 7064910281f01a1efc42311e4da4c638e0f4c579..dfb0d15c031239118c50053e63c40816ec7297b2 100644 (file)
@@ -1145,6 +1145,78 @@ fs_visitor::emit_frontfacing_interpolation(ir_variable *ir)
    return reg;
 }
 
+void
+fs_visitor::compute_sample_position(fs_reg dst, fs_reg int_sample_pos)
+{
+   assert(dst.type == BRW_REGISTER_TYPE_F);
+
+   if (c->key.compute_pos_offset) {
+      /* Convert int_sample_pos to floating point */
+      emit(MOV(dst, int_sample_pos));
+      /* Scale to the range [0, 1] */
+      emit(MUL(dst, dst, fs_reg(1 / 16.0f)));
+   }
+   else {
+      /* From ARB_sample_shading specification:
+       * "When rendering to a non-multisample buffer, or if multisample
+       *  rasterization is disabled, gl_SamplePosition will always be
+       *  (0.5, 0.5).
+       */
+      emit(MOV(dst, fs_reg(0.5f)));
+   }
+}
+
+fs_reg *
+fs_visitor::emit_samplepos_setup(ir_variable *ir)
+{
+   assert(brw->gen >= 6);
+   assert(ir->type == glsl_type::vec2_type);
+
+   this->current_annotation = "compute sample position";
+   fs_reg *reg = new(this->mem_ctx) fs_reg(this, ir->type);
+   fs_reg pos = *reg;
+   fs_reg int_sample_x = fs_reg(this, glsl_type::int_type);
+   fs_reg int_sample_y = fs_reg(this, glsl_type::int_type);
+
+   /* WM will be run in MSDISPMODE_PERSAMPLE. So, only one of SIMD8 or SIMD16
+    * mode will be enabled.
+    *
+    * From the Ivy Bridge PRM, volume 2 part 1, page 344:
+    * R31.1:0         Position Offset X/Y for Slot[3:0]
+    * R31.3:2         Position Offset X/Y for Slot[7:4]
+    * .....
+    *
+    * The X, Y sample positions come in as bytes in  thread payload. So, read
+    * the positions using vstride=16, width=8, hstride=2.
+    */
+   struct brw_reg sample_pos_reg =
+      stride(retype(brw_vec1_grf(c->sample_pos_reg, 0),
+                    BRW_REGISTER_TYPE_B), 16, 8, 2);
+
+   emit(MOV(int_sample_x, fs_reg(sample_pos_reg)));
+   if (dispatch_width == 16) {
+      int_sample_x.sechalf = true;
+      fs_inst *inst = emit(MOV(int_sample_x,
+                               fs_reg(suboffset(sample_pos_reg, 16))));
+      inst->force_sechalf = true;
+      int_sample_x.sechalf = false;
+   }
+   /* Compute gl_SamplePosition.x */
+   compute_sample_position(pos, int_sample_x);
+   pos.reg_offset++;
+   emit(MOV(int_sample_y, fs_reg(suboffset(sample_pos_reg, 1))));
+   if (dispatch_width == 16) {
+      int_sample_y.sechalf = true;
+      fs_inst *inst = emit(MOV(int_sample_y,
+                               fs_reg(suboffset(sample_pos_reg, 17))));
+      inst->force_sechalf = true;
+      int_sample_y.sechalf = false;
+   }
+   /* Compute gl_SamplePosition.y */
+   compute_sample_position(pos, int_sample_y);
+   return reg;
+}
+
 fs_reg
 fs_visitor::fix_math_operand(fs_reg src)
 {
@@ -3056,7 +3128,14 @@ fs_visitor::setup_payload_gen6()
          c->nr_payload_regs++;
       }
    }
+
+   c->prog_data.uses_pos_offset = c->key.compute_pos_offset;
    /* R31: MSAA position offsets. */
+   if (c->prog_data.uses_pos_offset) {
+      c->sample_pos_reg = c->nr_payload_regs;
+      c->nr_payload_regs++;
+   }
+
    /* R32-: bary for 32-pixel. */
    /* R58-59: interp W for 32-pixel. */
 
index 43e47617c172b588288b0f9011d24b72546518da..7eb82fc5a3c88006a93bf999be63724185d1df3e 100644 (file)
@@ -340,9 +340,11 @@ public:
                          glsl_interp_qualifier interpolation_mode,
                          bool is_centroid);
    fs_reg *emit_frontfacing_interpolation(ir_variable *ir);
+   fs_reg *emit_samplepos_setup(ir_variable *ir);
    fs_reg *emit_general_interpolation(ir_variable *ir);
    void emit_interpolation_setup_gen4();
    void emit_interpolation_setup_gen6();
+   void compute_sample_position(fs_reg dst, fs_reg int_sample_pos);
    fs_reg rescale_texcoord(ir_texture *ir, fs_reg coordinate,
                            bool is_rect, int sampler, int texunit);
    fs_inst *emit_texture_gen4(ir_texture *ir, fs_reg dst, fs_reg coordinate,
index 0e2dfd30016bc7ef2da2ee7a54eff1ef16f79cff..0404fffe9b856a8b4cff61ed6201b91a3c22ca3b 100644 (file)
@@ -125,6 +125,11 @@ fs_visitor::visit(ir_variable *ir)
 
       reg = new(this->mem_ctx) fs_reg(UNIFORM, param_index);
       reg->type = brw_type_for_base_type(ir->type);
+
+   } else if (ir->mode == ir_var_system_value) {
+      if (ir->location == SYSTEM_VALUE_SAMPLE_POS) {
+        reg = emit_samplepos_setup(ir);
+      }
    }
 
    if (!reg)
index 0fda4900aae00239eeddcc76699871362b0425ce..d2a5a9fb3be8d861becb917f20f2c60d8033b98d 100644 (file)
@@ -37,6 +37,7 @@
 #include "main/fbobject.h"
 #include "main/samplerobj.h"
 #include "program/prog_parameter.h"
+#include "program/program.h"
 
 #include "glsl/ralloc.h"
 
@@ -483,6 +484,11 @@ static void brw_wm_populate_key( struct brw_context *brw,
    key->replicate_alpha = ctx->DrawBuffer->_NumColorDrawBuffers > 1 &&
       (ctx->Multisample.SampleAlphaToCoverage || ctx->Color.AlphaEnabled);
 
+   /* _NEW_BUFFERS _NEW_MULTISAMPLE */
+   key->compute_pos_offset =
+      _mesa_get_min_invocations_per_fragment(ctx, &fp->program) > 1 &&
+      fp->program.Base.SystemValuesRead & SYSTEM_BIT_SAMPLE_POS;
+
    /* BRW_NEW_VUE_MAP_GEOM_OUT */
    if (brw->gen < 6 || _mesa_bitcount_64(fp->program.Base.InputsRead &
                                          BRW_FS_VARYING_INPUT_MASK) > 16)
index 259a4b67573b81b123a386bfc54dc4aee89e7362..eb740adffe639fd5c0e4d181085b0dd588ad445d 100644 (file)
@@ -65,6 +65,7 @@ struct brw_wm_prog_key {
    GLuint replicate_alpha:1;
    GLuint render_to_fbo:1;
    GLuint clamp_fragment_color:1;
+   GLuint compute_pos_offset:1;
    GLuint line_aa:2;
    GLuint high_quality_derivatives:1;
 
@@ -83,6 +84,7 @@ struct brw_wm_compile {
    uint8_t source_w_reg;
    uint8_t aa_dest_stencil_reg;
    uint8_t dest_depth_reg;
+   uint8_t sample_pos_reg;
    uint8_t barycentric_coord_reg[BRW_WM_BARYCENTRIC_INTERP_MODE_COUNT];
    uint8_t nr_payload_regs;
    GLuint source_depth_to_render_target:1;