[Mesa-dev] [PATCH 19/29] i965/fs: Import image memory offset calculation code.

Francisco Jerez currojerez at riseup.net
Sat May 2 08:29:46 PDT 2015


Define a function to calculate the memory address of the image
location given by a vector of coordinates.  This is required in cases
where we need to fall back to untyped surface access, which take a raw
memory offset and know nothing about surface coordinates, type
conversion or memory tiling and swizzling.  They are still useful
because typed surface reads don't support any 64 or 128-bit formats on
IVB, and they don't support any 128-bit formats on HSW and BDW.

The tiling algorithm is implemented based on a number of parameters
which are passed in as uniforms and determine whether the surface
layout is X-tiled, Y-tiled or untiled.  This allows binding surfaces
of different tiling layouts to the pipeline without recompiling the
program.

v2: Drop VEC4 suport.
---
 .../drivers/dri/i965/brw_fs_surface_builder.cpp    | 100 +++++++++++++++++++++
 1 file changed, 100 insertions(+)

diff --git a/src/mesa/drivers/dri/i965/brw_fs_surface_builder.cpp b/src/mesa/drivers/dri/i965/brw_fs_surface_builder.cpp
index ed67cfc..b429442 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_surface_builder.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_surface_builder.cpp
@@ -564,4 +564,104 @@ namespace {
          return BRW_PREDICATE_NORMAL;
       }
    }
+
+   namespace image_coordinates {
+      /**
+       * Calculate the offset in memory of the texel given by \p coord.
+       *
+       * This is meant to be used with untyped surface messages to access a
+       * tiled surface, what involves taking into account the tiling and
+       * swizzling modes of the surface manually so it will hopefully not
+       * happen very often.
+       */
+      fs_reg
+      emit_address_calculation(const fs_builder &bld, const fs_reg &image,
+                               const fs_reg &coord, unsigned dims)
+      {
+         const fs_reg off = offset(image, BRW_IMAGE_PARAM_OFFSET_OFFSET);
+         const fs_reg stride = offset(image, BRW_IMAGE_PARAM_STRIDE_OFFSET);
+         const fs_reg tile = offset(image, BRW_IMAGE_PARAM_TILING_OFFSET);
+         const fs_reg swz = offset(image, BRW_IMAGE_PARAM_SWIZZLING_OFFSET);
+         const fs_reg addr = bld.vgrf(BRW_REGISTER_TYPE_UD, 2);
+         const fs_reg tmp = bld.vgrf(BRW_REGISTER_TYPE_UD, 2);
+         const fs_reg minor = bld.vgrf(BRW_REGISTER_TYPE_UD, 2);
+         const fs_reg major = bld.vgrf(BRW_REGISTER_TYPE_UD, 2);
+         const fs_reg dst = bld.vgrf(BRW_REGISTER_TYPE_UD);
+
+         /* Shift the coordinates by the fixed surface offset. */
+         for (unsigned c = 0; c < 2; ++c)
+            bld.ADD(offset(addr, c), offset(off, c),
+                    (c < dims ? offset(retype(coord, BRW_REGISTER_TYPE_UD), c) :
+                     fs_reg(0)));
+
+         if (dims > 2) {
+            /* Decompose z into a major (tmp.y) and a minor (tmp.x)
+             * index.
+             */
+            bld.BFE(offset(tmp, 0), offset(tile, 2), fs_reg(0),
+                    offset(retype(coord, BRW_REGISTER_TYPE_UD), 2));
+            bld.SHR(offset(tmp, 1),
+                    offset(retype(coord, BRW_REGISTER_TYPE_UD), 2),
+                    offset(tile, 2));
+
+            /* Take into account the horizontal (tmp.x) and vertical (tmp.y)
+             * slice offset.
+             */
+            for (unsigned c = 0; c < 2; ++c) {
+               bld.MUL(offset(tmp, c), offset(stride, 2 + c), offset(tmp, c));
+               bld.ADD(offset(addr, c), offset(addr, c), offset(tmp, c));
+            }
+         }
+
+         if (dims > 1) {
+            for (unsigned c = 0; c < 2; ++c) {
+               /* Calculate the minor x and y indices. */
+               bld.BFE(offset(minor, c), offset(tile, c),
+                       fs_reg(0), offset(addr, c));
+
+               /* Calculate the major x and y indices. */
+               bld.SHR(offset(major, c), offset(addr, c), offset(tile, c));
+            }
+
+            /* Calculate the texel index from the start of the tile row and
+             * the vertical coordinate of the row.
+             * Equivalent to:
+             *   tmp.x = (major.x << tile.y << tile.x) +
+             *           (minor.y << tile.x) + minor.x
+             *   tmp.y = major.y << tile.y
+             */
+            bld.SHL(tmp, major, offset(tile, 1));
+            bld.ADD(tmp, tmp, offset(minor, 1));
+            bld.SHL(tmp, tmp, offset(tile, 0));
+            bld.ADD(tmp, tmp, minor);
+            bld.SHL(offset(tmp, 1), offset(major, 1), offset(tile, 1));
+
+            /* Add it to the start of the tile row. */
+            bld.MUL(offset(tmp, 1), offset(tmp, 1), offset(stride, 1));
+            bld.ADD(tmp, tmp, offset(tmp, 1));
+
+            /* Multiply by the Bpp value. */
+            bld.MUL(dst, tmp, stride);
+
+            if (bld.devinfo->gen < 8 && !bld.devinfo->is_baytrail) {
+               /* Take into account the two dynamically specified shifts. */
+               for (unsigned c = 0; c < 2; ++c)
+                  bld.SHR(offset(tmp, c), dst, offset(swz, c));
+
+               /* XOR tmp.x and tmp.y with bit 6 of the memory address. */
+               bld.XOR(tmp, tmp, offset(tmp, 1));
+               bld.AND(tmp, tmp, fs_reg(1 << 6));
+               bld.XOR(dst, dst, tmp);
+            }
+
+         } else {
+            /* Multiply by the Bpp/stride value. */
+            bld.MUL(offset(addr, 1), offset(addr, 1), offset(stride, 1));
+            bld.ADD(addr, addr, offset(addr, 1));
+            bld.MUL(dst, addr, stride);
+         }
+
+         return dst;
+      }
+   }
 }
-- 
2.3.5



More information about the mesa-dev mailing list