Mesa (9.0): i965: Do texture swizzling in hardware on Haswell.

Kenneth Graunke kwg at kemper.freedesktop.org
Thu Jan 31 00:22:15 UTC 2013


Module: Mesa
Branch: 9.0
Commit: 42df904f88a3515bf8bea5c1228380714c9146fb
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=42df904f88a3515bf8bea5c1228380714c9146fb

Author: Kenneth Graunke <kenneth at whitecape.org>
Date:   Fri Sep 21 03:13:36 2012 -0700

i965: Do texture swizzling in hardware on Haswell.

Haswell supports EXT_texture_swizzle and legacy DEPTH_TEXTURE_MODE
swizzling by setting SURFACE_STATE entries.  This means we don't have to
bake the swizzle settings into the shader code by emitting MOV
instructions, and thus don't have to recompile shaders whenever the
swizzles change.

Unfortunately, we can't handle GL_ALPHA this way: unlike all the others,
which store the comparison result in the .r channel (and possibly others
as well), GL_ALPHA puts it in the .a channel.  The GLSL 1.30+ style
functions which return a float always simply return the .r channel,
which would be zero if we handled this as a surface override.  In this
case, fall back to doing it the old way.  DEPTH_TEXTURE_MODE = GL_ALPHA
isn't an interesting performance path anyway.

Reviewed-by: Eric Anholt <eric at anholt.net>
Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
(cherry picked from commit 6d6aef79742ece3bb570ae44e6c13791aae15e01)

---

 src/mesa/drivers/dri/i965/brw_wm.c                |   12 +++++-
 src/mesa/drivers/dri/i965/gen7_wm_surface_state.c |   45 +++++++++++++++++++--
 2 files changed, 52 insertions(+), 5 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c
index 9f8eab7..4bd193b 100644
--- a/src/mesa/drivers/dri/i965/brw_wm.c
+++ b/src/mesa/drivers/dri/i965/brw_wm.c
@@ -436,6 +436,8 @@ brw_populate_sampler_prog_key_data(struct gl_context *ctx,
 				   const struct gl_program *prog,
 				   struct brw_sampler_prog_key_data *key)
 {
+   struct intel_context *intel = intel_context(ctx);
+
    for (int s = 0; s < MAX_SAMPLERS; s++) {
       key->swizzles[s] = SWIZZLE_NOOP;
 
@@ -450,7 +452,15 @@ brw_populate_sampler_prog_key_data(struct gl_context *ctx,
 	 const struct gl_texture_image *img = t->Image[0][t->BaseLevel];
 	 struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit_id);
 
-	 key->swizzles[s] = brw_get_texture_swizzle(t);
+         const bool alpha_depth = t->DepthMode == GL_ALPHA &&
+            (img->_BaseFormat == GL_DEPTH_COMPONENT ||
+             img->_BaseFormat == GL_DEPTH_STENCIL);
+
+         /* Haswell handles texture swizzling as surface format overrides
+          * (except for GL_ALPHA); all other platforms need MOVs in the shader.
+          */
+         if (!intel->is_haswell || alpha_depth)
+            key->swizzles[s] = brw_get_texture_swizzle(t);
 
 	 if (img->InternalFormat == GL_YCBCR_MESA) {
 	    key->yuvtex_mask |= 1 << s;
diff --git a/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c b/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c
index 97ae0e2..dd7b0d4 100644
--- a/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c
@@ -35,6 +35,32 @@
 #include "brw_defines.h"
 #include "brw_wm.h"
 
+/**
+ * Convert an swizzle enumeration (i.e. SWIZZLE_X) to one of the Gen7.5+
+ * "Shader Channel Select" enumerations (i.e. HSW_SCS_RED)
+ */
+static unsigned
+swizzle_to_scs(GLenum swizzle)
+{
+   switch (swizzle) {
+   case SWIZZLE_X:
+      return HSW_SCS_RED;
+   case SWIZZLE_Y:
+      return HSW_SCS_GREEN;
+   case SWIZZLE_Z:
+      return HSW_SCS_BLUE;
+   case SWIZZLE_W:
+      return HSW_SCS_ALPHA;
+   case SWIZZLE_ZERO:
+      return HSW_SCS_ZERO;
+   case SWIZZLE_ONE:
+      return HSW_SCS_ONE;
+   }
+
+   assert(!"Should not get here: invalid swizzle mode");
+   return HSW_SCS_ZERO;
+}
+
 void
 gen7_set_surface_tiling(struct gen7_surface_state *surf, uint32_t tiling)
 {
@@ -343,10 +369,21 @@ gen7_update_texture_surface(struct gl_context *ctx,
     */
 
    if (brw->intel.is_haswell) {
-      surf->ss7.shader_channel_select_r = HSW_SCS_RED;
-      surf->ss7.shader_channel_select_g = HSW_SCS_GREEN;
-      surf->ss7.shader_channel_select_b = HSW_SCS_BLUE;
-      surf->ss7.shader_channel_select_a = HSW_SCS_ALPHA;
+      /* Handling GL_ALPHA as a surface format override breaks 1.30+ style
+       * texturing functions that return a float, as our code generation always
+       * selects the .x channel (which would always be 0).
+       */
+      const bool alpha_depth = tObj->DepthMode == GL_ALPHA &&
+         (firstImage->_BaseFormat == GL_DEPTH_COMPONENT ||
+          firstImage->_BaseFormat == GL_DEPTH_STENCIL);
+
+      const int swizzle =
+         unlikely(alpha_depth) ? SWIZZLE_XYZW : brw_get_texture_swizzle(tObj);
+
+      surf->ss7.shader_channel_select_r = swizzle_to_scs(GET_SWZ(swizzle, 0));
+      surf->ss7.shader_channel_select_g = swizzle_to_scs(GET_SWZ(swizzle, 1));
+      surf->ss7.shader_channel_select_b = swizzle_to_scs(GET_SWZ(swizzle, 2));
+      surf->ss7.shader_channel_select_a = swizzle_to_scs(GET_SWZ(swizzle, 3));
    }
 
    /* Emit relocation to surface contents */




More information about the mesa-commit mailing list