[Mesa-dev] [PATCH 2/2] i965: handle gl_PointCoord for Gen4 and Gen5 platform

Liu Aleaxander aleaxander at gmail.com
Sat Feb 18 07:07:32 PST 2012


This patch add the support of gl_PointCoord gl builtin var for platform
gen4 and gen5(ILK).

We can get the point start coord and the current pixel coord from PS
payload, and the only left element needed is the point size. Then handle
that in SF thread.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=45975
Piglit: glsl-fs-pointcoord and fbo-gl_pointcoord

NOTE: This is a candidate for stable release branches.

v2: comments from Eric, handle FRAG_ATTRIB_PNTC at
    brw_emit_point_sprite_setup().

Signed-off-by: Yuanhan Liu <yuanhan.liu at linux.intel.com>
---
 src/mesa/drivers/dri/i965/brw_fs.cpp         |   39 ++++++++++++++++++++++++++
 src/mesa/drivers/dri/i965/brw_fs.h           |    1 +
 src/mesa/drivers/dri/i965/brw_fs_visitor.cpp |    2 +
 src/mesa/drivers/dri/i965/brw_sf.c           |    2 +
 src/mesa/drivers/dri/i965/brw_sf.h           |    1 +
 src/mesa/drivers/dri/i965/brw_sf_emit.c      |   23 ++++++++++++--
 6 files changed, 64 insertions(+), 4 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp
b/src/mesa/drivers/dri/i965/brw_fs.cpp
index cbbef11..6e247f7 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -421,6 +421,37 @@ fs_visitor::emit_fragcoord_interpolation(ir_variable *ir)
 }

 fs_reg *
+fs_visitor::emit_pointcoord_interpolation_gen4(ir_variable *ir)
+{
+   fs_reg *reg = new(this->mem_ctx) fs_reg(this, ir->type);
+   fs_reg pntcoord = *reg;
+   int urb_start = c->nr_payload_regs + c->prog_data.curb_read_length;
+   fs_reg pnt_size_rcp = fs_reg(brw_vec1_grf(urb_start +
+                                             urb_setup[FRAG_ATTRIB_PNTC] *
+                                             urb_entries_per_attr, 0));
+   bool render_to_fbo = ctx->DrawBuffer->Name != 0;
+
+   /* gl_PointCoord.x */
+   emit(BRW_OPCODE_MUL, pntcoord, pnt_size_rcp,
+        this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC]);
+   pntcoord.reg_offset++;
+
+   /* gl_PointCoord.y */
+   emit(BRW_OPCODE_MUL, pntcoord, pnt_size_rcp,
+        this->delta_y[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC]);
+   /*
+    * Window coordinates in an FBO are inverted, which means coord in Y
+    * must be inverted, too.
+    */
+   if ((ctx->Point.SpriteOrigin == GL_LOWER_LEFT) != render_to_fbo) {
+      pntcoord.negate = true;
+      emit(BRW_OPCODE_ADD, pntcoord, pntcoord, fs_reg(1.0f));
+   }
+
+   return reg;
+}
+
+fs_reg *
 fs_visitor::emit_general_interpolation(ir_variable *ir)
 {
    fs_reg *reg = new(this->mem_ctx) fs_reg(this, ir->type);
@@ -710,6 +741,14 @@ fs_visitor::calculate_urb_setup()
 	       urb_setup[fp_index] = urb_next++;
 	 }
       }
+      /*
+       * It's a FS only attribute, and we did interpolation for this attribute
+       * in SF thread. So, count it here, too.
+       *
+       * See brw_emit_point_sprite_setup() for more info.
+       */
+      if (brw->fragment_program->Base.InputsRead &
BITFIELD64_BIT(FRAG_ATTRIB_PNTC))
+         urb_setup[FRAG_ATTRIB_PNTC] = urb_next++;
    }

    c->prog_data.urb_read_length = urb_next * urb_entries_per_attr;
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h
b/src/mesa/drivers/dri/i965/brw_fs.h
index 1b4f2e3..06afeb4 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -547,6 +547,7 @@ public:
    void emit_dummy_fs();
    fs_reg *emit_fragcoord_interpolation(ir_variable *ir);
    fs_reg *emit_frontfacing_interpolation(ir_variable *ir);
+   fs_reg *emit_pointcoord_interpolation_gen4(ir_variable *ir);
    fs_reg *emit_general_interpolation(ir_variable *ir);
    void emit_interpolation_setup_gen4();
    void emit_interpolation_setup_gen6();
diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
index bf1da9d..399d8b8 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
@@ -63,6 +63,8 @@ fs_visitor::visit(ir_variable *ir)
 	 reg = emit_fragcoord_interpolation(ir);
       } else if (!strcmp(ir->name, "gl_FrontFacing")) {
 	 reg = emit_frontfacing_interpolation(ir);
+      } else if (!strcmp(ir->name, "gl_PointCoord") && intel->gen < 6) {
+         reg = emit_pointcoord_interpolation_gen4(ir);
       } else {
 	 reg = emit_general_interpolation(ir);
       }
diff --git a/src/mesa/drivers/dri/i965/brw_sf.c
b/src/mesa/drivers/dri/i965/brw_sf.c
index 54c27f9..d4544fe 100644
--- a/src/mesa/drivers/dri/i965/brw_sf.c
+++ b/src/mesa/drivers/dri/i965/brw_sf.c
@@ -167,6 +167,8 @@ brw_upload_sf_prog(struct brw_context *brw)
 	    key.point_sprite_coord_replace |= (1 << i);
       }
    }
+   if (brw->fragment_program->Base.InputsRead &
BITFIELD64_BIT(FRAG_ATTRIB_PNTC))
+      key.do_point_coord = 1;
    key.sprite_origin_lower_left = (ctx->Point.SpriteOrigin == GL_LOWER_LEFT);
    /* _NEW_LIGHT */
    key.do_flat_shading = (ctx->Light.ShadeModel == GL_FLAT);
diff --git a/src/mesa/drivers/dri/i965/brw_sf.h
b/src/mesa/drivers/dri/i965/brw_sf.h
index 4ef0240..f908fc0 100644
--- a/src/mesa/drivers/dri/i965/brw_sf.h
+++ b/src/mesa/drivers/dri/i965/brw_sf.h
@@ -52,6 +52,7 @@ struct brw_sf_prog_key {
    GLuint do_flat_shading:1;
    GLuint frontface_ccw:1;
    GLuint do_point_sprite:1;
+   GLuint do_point_coord:1;
    GLuint sprite_origin_lower_left:1;
    GLuint userclip_active:1;
 };
diff --git a/src/mesa/drivers/dri/i965/brw_sf_emit.c
b/src/mesa/drivers/dri/i965/brw_sf_emit.c
index 1ee0098..6cad4e5 100644
--- a/src/mesa/drivers/dri/i965/brw_sf_emit.c
+++ b/src/mesa/drivers/dri/i965/brw_sf_emit.c
@@ -569,15 +569,30 @@ void brw_emit_point_sprite_setup(struct
brw_sf_compile *c, bool allocate)
    if (allocate)
       alloc_regs(c);

+   /*
+    * gl_PointCoord is a FS instead of VS builtin variable, thus is not
+    * included in c->nr_setup_regs. But FS need SF do the interpolation,
+    * so that here padding the interpolation for gl_PointCoord in last.
+    */
+   if (c->key.do_point_coord)
+      c->nr_setup_regs++;
+
    copy_z_inv_w(c);
    for (i = 0; i < c->nr_setup_regs; i++)
    {
       struct brw_reg a0 = offset(c->vert[0], i);
       GLushort pc, pc_persp, pc_linear, pc_coord_replace;
-      bool last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
-
-      pc_coord_replace = calculate_point_sprite_mask(c, i);
-      pc_persp &= ~pc_coord_replace;
+      bool last = (i == c->nr_setup_regs - 1);
+
+      if (last && c->key.do_point_coord) {
+         pc = 0x0f;
+         pc_coord_replace = 0x0f;
+         pc_persp = 0;
+      } else {
+         calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
+         pc_coord_replace = calculate_point_sprite_mask(c, i);
+         pc_persp &= ~pc_coord_replace;
+      }

       if (pc_persp) {
 	 brw_set_predicate_control_flag_value(p, pc_persp);
-- 
1.7.3.1


More information about the mesa-dev mailing list