[Mesa-dev] [PATCH 16/17] i965/fs: Refactor the texture emission logic into a single function.

Kenneth Graunke kenneth at whitecape.org
Mon Oct 13 21:54:46 PDT 2014


Before, we had 3 different emit functions for various different gen's,
as well as some ancilliary work that was the same across all gen's which
was either contained in functions or duplicated across the GLSL IR and
Mesa IR backends. Now, we have a single method, emit_texture(), that
takes all the information needed to make a texture instruction and
handles all the setup, and all we have to do to emit a texture
instruction while converting from GLSL IR, Mesa IR, or any new backend
is to extract the information emit_texture() needs and then call it.

v2: Significant rebasing (by Ken).

Signed-off-by: Connor Abbott <connor.abbott at intel.com>
Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
---
 src/mesa/drivers/dri/i965/brw_fs.h           |  14 ++
 src/mesa/drivers/dri/i965/brw_fs_fp.cpp      |  28 ++--
 src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 206 ++++++++++++++++-----------
 3 files changed, 144 insertions(+), 104 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index dc4e0c8..c62c1eb 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -488,6 +488,20 @@ public:
                               fs_reg lod, fs_reg lod2, int grad_components,
                               fs_reg sample_index, fs_reg mcs, fs_reg sampler,
                               fs_reg offset_value);
+   void emit_texture(ir_texture_opcode op,
+                     const glsl_type *dest_type,
+                     fs_reg coordinate, const struct glsl_type *coord_type,
+                     fs_reg shadow_c,
+                     fs_reg lod, fs_reg dpdy, int grad_components,
+                     fs_reg sample_index,
+                     fs_reg offset, unsigned offset_components,
+                     fs_reg mcs,
+                     int gather_component,
+                     bool is_cube_array,
+                     bool is_rect,
+                     uint32_t sampler,
+                     fs_reg sampler_reg,
+                     int texunit);
    fs_reg emit_mcs_fetch(fs_reg coordinate, int components, fs_reg sampler);
    void emit_gen6_gather_wa(uint8_t wa, fs_reg dst);
    fs_reg fix_math_operand(fs_reg src);
diff --git a/src/mesa/drivers/dri/i965/brw_fs_fp.cpp b/src/mesa/drivers/dri/i965/brw_fs_fp.cpp
index 825d793..1ba24a9 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_fp.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_fp.cpp
@@ -476,28 +476,18 @@ fs_visitor::emit_fragment_program_code()
             unreachable("not reached");
          }
 
-         int coord_components = coordinate_type->vector_elements;
-
          if (fpi->TexShadow)
             shadow_c = offset(coordinate, 2);
 
-         coordinate = rescale_texcoord(coordinate, coordinate_type,
-                                       fpi->TexSrcTarget == TEXTURE_RECT_INDEX,
-                                       fpi->TexSrcUnit, fpi->TexSrcUnit);
-
-         fs_inst *inst;
-         if (brw->gen >= 7) {
-            inst = emit_texture_gen7(ir->op, dst, coordinate, coord_components, shadow_c, lod, dpdy, 0, sample_index, fs_reg(0u), fs_reg(fpi->TexSrcUnit), texel_offset);
-         } else if (brw->gen >= 5) {
-            inst = emit_texture_gen5(ir->op, dst, coordinate, coord_components, shadow_c, lod, dpdy, 0, sample_index, fpi->TexSrcUnit, false);
-         } else {
-            inst = emit_texture_gen4(ir->op, dst, coordinate, coord_components, shadow_c, lod, dpdy, 0, fpi->TexSrcUnit);
-         }
-
-         inst->shadow_compare = fpi->TexShadow;
-
-         /* Reuse the GLSL swizzle_result() handler. */
-         swizzle_result(ir->op, 4, dst, fpi->TexSrcUnit);
+         emit_texture(ir->op, glsl_type::vec4_type, coordinate, coordinate_type,
+                      shadow_c, lod, dpdy, 0, sample_index,
+                      reg_undef, 0, /* offset, components */
+                      reg_undef, /* mcs */
+                      0, /* gather component */
+                      false, /* is cube array */
+                      fpi->TexSrcTarget == TEXTURE_RECT_INDEX,
+                      fpi->TexSrcUnit, fs_reg(fpi->TexSrcUnit),
+                      fpi->TexSrcUnit);
          dst = this->result;
 
          break;
diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
index 9008e16..8a11b04 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
@@ -1837,7 +1837,19 @@ fs_visitor::emit_mcs_fetch(fs_reg coordinate, int components, fs_reg sampler)
 }
 
 void
-fs_visitor::visit(ir_texture *ir)
+fs_visitor::emit_texture(ir_texture_opcode op,
+                         const glsl_type *dest_type,
+                         fs_reg coordinate, const struct glsl_type *coord_type,
+                         fs_reg shadow_c,
+                         fs_reg lod, fs_reg lod2, int grad_components,
+                         fs_reg sample_index,
+                         fs_reg offset_value, unsigned offset_components,
+                         fs_reg mcs,
+                         int gather_component,
+                         bool is_cube_array,
+                         bool is_rect,
+                         uint32_t sampler,
+                         fs_reg sampler_reg, int texunit)
 {
    const struct brw_sampler_prog_key_data *tex =
       (stage == MESA_SHADER_FRAGMENT) ?
@@ -1845,6 +1857,98 @@ fs_visitor::visit(ir_texture *ir)
    assert(tex);
    fs_inst *inst = NULL;
 
+   if (op == ir_tg4) {
+      /* When tg4 is used with the degenerate ZERO/ONE swizzles, don't bother
+       * emitting anything other than setting up the constant result.
+       */
+      int swiz = GET_SWZ(tex->swizzles[sampler], gather_component);
+      if (swiz == SWIZZLE_ZERO || swiz == SWIZZLE_ONE) {
+
+         fs_reg res = fs_reg(this, glsl_type::vec4_type);
+         this->result = res;
+
+         for (int i=0; i<4; i++) {
+            emit(MOV(res, fs_reg(swiz == SWIZZLE_ZERO ? 0.0f : 1.0f)));
+            res = offset(res, 1);
+         }
+         return;
+      }
+   }
+
+   if (coordinate.file != BAD_FILE) {
+      /* FINISHME: Texture coordinate rescaling doesn't work with non-constant
+       * samplers.  This should only be a problem with GL_CLAMP on Gen7.
+       */
+      coordinate = rescale_texcoord(coordinate, coord_type, is_rect,
+                                    sampler, texunit);
+   }
+
+   /* Writemasking doesn't eliminate channels on SIMD8 texture
+    * samples, so don't worry about them.
+    */
+   fs_reg dst(this, glsl_type::get_instance(dest_type->base_type, 4, 1));
+
+   int coord_components = coord_type ? coord_type->vector_elements : 0;
+
+   if (brw->gen >= 7) {
+      inst = emit_texture_gen7(op, dst, coordinate, coord_components,
+                               shadow_c, lod, lod2, grad_components,
+                               sample_index, mcs, sampler_reg,
+                               offset_value);
+   } else if (brw->gen >= 5) {
+      inst = emit_texture_gen5(op, dst, coordinate, coord_components,
+                               shadow_c, lod, lod2, grad_components,
+                               sample_index, sampler,
+                               offset_value.file != BAD_FILE);
+   } else {
+      inst = emit_texture_gen4(op, dst, coordinate, coord_components,
+                               shadow_c, lod, lod2, grad_components,
+                               sampler);
+   }
+
+   if (shadow_c.file != BAD_FILE)
+      inst->shadow_compare = true;
+
+   if (offset_value.file == IMM)
+      inst->texture_offset = offset_value.fixed_hw_reg.dw1.ud;
+
+   if (op == ir_tg4) {
+      inst->texture_offset |=
+         gather_channel(gather_component, sampler) << 16; /* M0.2:16-17 */
+
+      if (brw->gen == 6)
+         emit_gen6_gather_wa(tex->gen6_gather_wa[sampler], dst);
+   }
+
+   /* fixup #layers for cube map arrays */
+   if (op == ir_txs && is_cube_array) {
+      fs_reg depth = offset(dst, 2);
+      fs_reg fixed_depth = fs_reg(this, glsl_type::int_type);
+      emit_math(SHADER_OPCODE_INT_QUOTIENT, fixed_depth, depth, fs_reg(6));
+
+      fs_reg *fixed_payload = ralloc_array(mem_ctx, fs_reg, inst->regs_written);
+      int components = inst->regs_written / (dst.width / 8);
+      for (int i = 0; i < components; i++) {
+         if (i == 2) {
+            fixed_payload[i] = fixed_depth;
+         } else {
+            fixed_payload[i] = offset(dst, i);
+         }
+      }
+      emit(LOAD_PAYLOAD(dst, fixed_payload, components));
+   }
+
+   swizzle_result(op, dest_type->vector_elements, dst, sampler);
+}
+
+void
+fs_visitor::visit(ir_texture *ir)
+{
+   const struct brw_sampler_prog_key_data *tex =
+      (stage == MESA_SHADER_FRAGMENT) ?
+      &((brw_wm_prog_key*) this->key)->tex : NULL;
+   assert(tex);
+
    uint32_t sampler =
       _mesa_get_sampler_uniform_value(ir->sampler, shader_prog, prog);
 
@@ -1889,25 +1993,6 @@ fs_visitor::visit(ir_texture *ir)
     */
    int texunit = prog->SamplerUnits[sampler];
 
-   if (ir->op == ir_tg4) {
-      /* When tg4 is used with the degenerate ZERO/ONE swizzles, don't bother
-       * emitting anything other than setting up the constant result.
-       */
-      ir_constant *chan = ir->lod_info.component->as_constant();
-      int swiz = GET_SWZ(tex->swizzles[sampler], chan->value.i[0]);
-      if (swiz == SWIZZLE_ZERO || swiz == SWIZZLE_ONE) {
-
-         fs_reg res = fs_reg(this, glsl_type::vec4_type);
-         this->result = res;
-
-         for (int i=0; i<4; i++) {
-            emit(MOV(res, fs_reg(swiz == SWIZZLE_ZERO ? 0.0f : 1.0f)));
-            res = offset(res, 1);
-         }
-         return;
-      }
-   }
-
    /* Should be lowered by do_lower_texture_projection */
    assert(!ir->projector);
 
@@ -1919,19 +2004,13 @@ fs_visitor::visit(ir_texture *ir)
     * generating these values may involve SEND messages that need the MRFs.
     */
    fs_reg coordinate;
+   const glsl_type *coord_type = NULL;
    if (ir->coordinate) {
+      coord_type = ir->coordinate->type;
       ir->coordinate->accept(this);
-
-      coordinate = rescale_texcoord(this->result,
-                                    ir->coordinate->type,
-                                    ir->sampler->type->sampler_dimensionality ==
-                                    GLSL_SAMPLER_DIM_RECT,
-                                    sampler, texunit);
+      coordinate = this->result;
    }
 
-   int coord_components =
-      ir->coordinate ? ir->coordinate->type->vector_elements : 0;
-
    fs_reg shadow_comparitor;
    if (ir->shadow_comparitor) {
       ir->shadow_comparitor->accept(this);
@@ -1939,6 +2018,7 @@ fs_visitor::visit(ir_texture *ir)
    }
 
    fs_reg offset_value;
+   int offset_components = 0;
    if (ir->offset) {
       ir_constant *const_offset = ir->offset->as_constant();
       if (const_offset) {
@@ -1953,6 +2033,7 @@ fs_visitor::visit(ir_texture *ir)
          ir->offset->accept(this);
          offset_value = this->result;
       }
+      offset_components = ir->offset->type->vector_elements;
    }
 
    fs_reg lod, lod2, sample_index, mcs;
@@ -1996,66 +2077,21 @@ fs_visitor::visit(ir_texture *ir)
       unreachable("Unrecognized texture opcode");
    };
 
-   /* Writemasking doesn't eliminate channels on SIMD8 texture
-    * samples, so don't worry about them.
-    */
-   fs_reg dst = fs_reg(this, glsl_type::get_instance(ir->type->base_type, 4, 1));
-
-   if (brw->gen >= 7) {
-      inst = emit_texture_gen7(ir->op, dst, coordinate, coord_components,
-                               shadow_comparitor,
-                               lod, lod2, grad_components,
-                               sample_index, mcs, sampler_reg,
-                               offset_value);
-   } else if (brw->gen >= 5) {
-      inst = emit_texture_gen5(ir->op, dst, coordinate, coord_components,
-                               shadow_comparitor,
-                               lod, lod2, grad_components,
-                               sample_index, sampler,
-                               ir->offset != NULL);
-   } else {
-      inst = emit_texture_gen4(ir->op, dst, coordinate, coord_components,
-                               shadow_comparitor,
-                               lod, lod2, grad_components,
-                               sampler);
-   }
-
-   if (offset_value.file == IMM)
-      inst->texture_offset = offset_value.fixed_hw_reg.dw1.ud;
-
+   int gather_component = 0;
    if (ir->op == ir_tg4)
-      inst->texture_offset |= gather_channel(ir->lod_info.component->as_constant()->value.i[0], sampler) << 16; // M0.2:16-17
+      gather_component = ir->lod_info.component->as_constant()->value.i[0];
 
-   if (ir->shadow_comparitor)
-      inst->shadow_compare = true;
-
-   /* fixup #layers for cube map arrays */
-   if (ir->op == ir_txs) {
-      glsl_type const *type = ir->sampler->type;
-      if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE &&
-          type->sampler_array) {
-         fs_reg depth = offset(dst, 2);
-         fs_reg fixed_depth = fs_reg(this, glsl_type::int_type);
-         emit_math(SHADER_OPCODE_INT_QUOTIENT, fixed_depth, depth, fs_reg(6));
-
-         fs_reg *fixed_payload = ralloc_array(mem_ctx, fs_reg, inst->regs_written);
-         int components = inst->regs_written / (dst.width / 8);
-         for (int i = 0; i < components; i++) {
-            if (i == 2) {
-               fixed_payload[i] = fixed_depth;
-            } else {
-               fixed_payload[i] = offset(dst, i);
-            }
-         }
-         emit(LOAD_PAYLOAD(dst, fixed_payload, components));
-      }
-   }
+   bool is_rect =
+      ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_RECT;
 
-   if (brw->gen == 6 && ir->op == ir_tg4) {
-      emit_gen6_gather_wa(tex->gen6_gather_wa[sampler], dst);
-   }
+   bool is_cube_array =
+      ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE &&
+      ir->sampler->type->sampler_array;
 
-   swizzle_result(ir->op, ir->type->vector_elements, dst, sampler);
+   emit_texture(ir->op, ir->type, coordinate, coord_type, shadow_comparitor,
+                lod, lod2, grad_components, sample_index, offset_value,
+                offset_components, mcs, gather_component,
+                is_cube_array, is_rect, sampler, sampler_reg, texunit);
 }
 
 /**
-- 
2.1.2



More information about the mesa-dev mailing list