[Mesa-dev] [RFC 01/13] i965: extend FS sampler to surface relation to 1:N

Topi Pohjolainen topi.pohjolainen at intel.com
Tue Feb 26 05:18:52 PST 2013


In preparation for supporting external image textures consisting of
multiple planes (YUV). One now reserves entries in the sampling engine
surface state table only for those samplers that are really used in the
current program using a binding table associating a sampler with a slot
in the state table. Previously the slot in the state table was
determined using the sampler id as the state table index directly. This
arrangement allows one to reserve continuous ranges in the state table
instead of fixed single entries.
Note that one does not have zero pointers in the state table anymore
as one only uses as many slots from the beginning that are really
needed by the program.

Signed-off-by: Topi Pohjolainen <topi.pohjolainen at intel.com>
---
 src/mesa/drivers/dri/i965/brw_context.h          |   29 +++++++++++++++++++---
 src/mesa/drivers/dri/i965/brw_fs.h               |    1 +
 src/mesa/drivers/dri/i965/brw_fs_emit.cpp        |    3 ++-
 src/mesa/drivers/dri/i965/brw_wm.c               |   15 +++++++++++
 src/mesa/drivers/dri/i965/brw_wm_surface_state.c |    7 +++---
 5 files changed, 48 insertions(+), 7 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index c173e49..531fc26 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -266,12 +266,38 @@ struct brw_vertex_program {
 };
 
 
+/** Number of texture sampler units */
+#define BRW_MAX_TEX_UNIT 16
+
 /** Subclass of Mesa fragment program */
 struct brw_fragment_program {
    struct gl_fragment_program program;
    GLuint id;  /**< serial no. to identify frag progs, never re-used */
+
+   /**
+    * Relation assigning shader samplers with a region in the HW surface state
+    * binding table. This used to be explicit one-sampler-one-surface-relation.
+    * However, in order to support image-external-textures a sampler
+    * representing, for example, multi-planar YUV texture may require up to
+    * three HW surfaces, one for each of the components/planes (Y, U and V). The
+    * actual number of HW surfaces associated with a sampler can be deduced from
+    * the format/layout of the texture image - here one simply stores the
+    * starting index.
+    * This relation can be set after linking but must in place before WM FS
+    * emission (one needs to know the surface state indices when generating the
+    * sampling commands). In addition, this relation must be accessible just
+    * before the actual execution of the shader is kicked off. (The contents of
+    * the surface state binding table itself are updated at that point).
+    */
+   uint32_t sampler_to_surf_state_start[BRW_MAX_TEX_UNIT];
 };
 
+static inline uint32_t brw_surf_index_texture(
+   const struct brw_fragment_program *fp, unsigned sampler)
+{
+   return fp->sampler_to_surf_state_start[sampler];
+}
+
 struct brw_shader {
    struct gl_shader base;
 
@@ -456,9 +482,6 @@ struct brw_vs_prog_data {
    const float **pull_param;
 };
 
-/** Number of texture sampler units */
-#define BRW_MAX_TEX_UNIT 16
-
 /** Max number of render targets in a shader */
 #define BRW_MAX_DRAW_BUFFERS 8
 
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index d1bb111..ac6e631 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -195,6 +195,7 @@ public:
    int base_mrf; /**< First MRF in the SEND message, if mlen is nonzero. */
    uint32_t texture_offset; /**< Texture offset bitfield */
    int sampler;
+   int surf_index_offset;
    int target; /**< MRT target. */
    bool eot;
    bool header_present;
diff --git a/src/mesa/drivers/dri/i965/brw_fs_emit.cpp b/src/mesa/drivers/dri/i965/brw_fs_emit.cpp
index 3d1f3b3..b5caace 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_emit.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_emit.cpp
@@ -489,7 +489,8 @@ fs_generator::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src
 	      retype(dst, BRW_REGISTER_TYPE_UW),
 	      inst->base_mrf,
 	      src,
-              SURF_INDEX_TEXTURE(inst->sampler),
+              brw_surf_index_texture((const struct brw_fragment_program*)fp,
+                 inst->sampler) + inst->surf_index_offset,
 	      inst->sampler,
 	      msg_type,
 	      rlen,
diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c
index 4b04465..05b4e68 100644
--- a/src/mesa/drivers/dri/i965/brw_wm.c
+++ b/src/mesa/drivers/dri/i965/brw_wm.c
@@ -130,6 +130,18 @@ brw_wm_prog_data_free(const void *in_prog_data)
    ralloc_free((void *)prog_data->pull_param);
 }
 
+static void brw_wm_fs_surf_setup(GLbitfield samplers,
+                                 uint32_t *sampler_to_surf_state_start)
+{
+   unsigned num_samplers = _mesa_fls(samplers);
+   unsigned surf_index = 0;
+
+   for (unsigned s = 0; s < num_samplers; s++) {
+      if (samplers & (1 << s))
+         sampler_to_surf_state_start[s] = SURF_INDEX_TEXTURE(surf_index++);
+   }
+}
+
 /**
  * All Mesa program -> GPU code generation goes through this function.
  * Depending on the instructions used (i.e. flow control instructions)
@@ -172,6 +184,9 @@ bool do_wm_prog(struct brw_context *brw,
       brw_compute_barycentric_interp_modes(brw, c->key.flat_shade,
                                            &fp->program);
 
+   brw_wm_fs_surf_setup(fp->program.Base.SamplersUsed,
+                        fp->sampler_to_surf_state_start);
+
    program = brw_wm_fs_emit(brw, c, &fp->program, prog, &program_size);
    if (program == NULL)
       return false;
diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
index 587ad05..7e17e5d 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -1374,7 +1374,6 @@ brw_update_texture_surfaces(struct brw_context *brw)
 
    for (unsigned s = 0; s < num_samplers; s++) {
       brw->vs.surf_offset[SURF_INDEX_VS_TEXTURE(s)] = 0;
-      brw->wm.surf_offset[SURF_INDEX_TEXTURE(s)] = 0;
 
       if (vs->SamplersUsed & (1 << s)) {
          const unsigned unit = vs->SamplerUnits[s];
@@ -1393,8 +1392,10 @@ brw_update_texture_surfaces(struct brw_context *brw)
          /* _NEW_TEXTURE */
          if (ctx->Texture.Unit[unit]._ReallyEnabled) {
             intel->vtbl.update_texture_surface(ctx, unit,
-                                               brw->wm.surf_offset,
-                                               SURF_INDEX_TEXTURE(s));
+               brw->wm.surf_offset,
+               brw_surf_index_texture(
+                  (const struct brw_fragment_program *)brw->fragment_program,
+                  s));
          }
       }
    }
-- 
1.7.9.5



More information about the mesa-dev mailing list