[Mesa-dev] [PATCH 11/23] i965: Import image memory offset calculation code.

Francisco Jerez currojerez at riseup.net
Tue Apr 28 11:44:22 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.
---
 src/mesa/drivers/dri/i965/brw_ir_surface_builder.h | 108 +++++++++++++++++++++
 1 file changed, 108 insertions(+)

diff --git a/src/mesa/drivers/dri/i965/brw_ir_surface_builder.h b/src/mesa/drivers/dri/i965/brw_ir_surface_builder.h
index 6fbade1..e46c7c1 100644
--- a/src/mesa/drivers/dri/i965/brw_ir_surface_builder.h
+++ b/src/mesa/drivers/dri/i965/brw_ir_surface_builder.h
@@ -611,6 +611,114 @@ namespace brw {
          return bld.reduced_predicate(BRW_PREDICATE_ALIGN16_ALL4H);
       }
    }
+
+   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.
+       */
+      template<typename B, typename S>
+      S
+      emit_address_calculation(const B &bld, const S &image, const S &coord,
+                               unsigned dims)
+      {
+         const unsigned chan_size = S::traits::chan_size;
+         const unsigned mask = (1 << dims) - 1;
+         const S off = offset(image, BRW_IMAGE_PARAM_OFFSET_OFFSET / chan_size);
+         const S stride = offset(image, BRW_IMAGE_PARAM_STRIDE_OFFSET / chan_size);
+         const S tile = offset(image, BRW_IMAGE_PARAM_TILING_OFFSET / chan_size);
+         const S swz = offset(image, BRW_IMAGE_PARAM_SWIZZLING_OFFSET / chan_size);
+         const typename B::dst_reg addr = bld.natural_reg(BRW_REGISTER_TYPE_UD);
+         const typename B::dst_reg tmp = bld.natural_reg(BRW_REGISTER_TYPE_UD);
+         const typename B::dst_reg dst = bld.scalar_reg(BRW_REGISTER_TYPE_UD);
+
+         /* Shift the coordinates by the fixed surface offset. */
+         bld.MOV(writemask(addr, mask), retype(coord, BRW_REGISTER_TYPE_UD));
+
+         if (dims < 2)
+            bld.MOV(writemask(addr, ~mask & WRITEMASK_XY), 0);
+
+         bld.ADD(writemask(addr, WRITEMASK_XY), addr, off);
+
+         if (dims > 2) {
+            /* Decompose z into a major (tmp.w) and a minor (tmp.z)
+             * index.
+             */
+            bld.BFE(writemask(tmp, WRITEMASK_Z), tile, 0, addr);
+            bld.SHR(writemask(tmp, WRITEMASK_W),
+                    swizzle(addr, BRW_SWIZZLE_ZZZZ),
+                    swizzle(tile, BRW_SWIZZLE_ZZZZ));
+
+            /* Calculate the horizontal (tmp.z) and vertical (tmp.w) slice
+             * offset.
+             */
+            bld.MUL(writemask(tmp, WRITEMASK_ZW), stride, tmp);
+            bld.ADD(writemask(addr, WRITEMASK_XY), addr,
+                    swizzle(tmp, BRW_SWIZZLE_ZWZW));
+         }
+
+         if (dims > 1) {
+            /* Calculate the minor x (tmp.x) and y (tmp.y) indices. */
+            bld.BFE(writemask(tmp, WRITEMASK_XY), tile, 0, addr);
+
+            /* Calculate the major x (tmp.z) and y (tmp.w) indices. */
+            bld.SHR(writemask(tmp, WRITEMASK_ZW),
+                    swizzle(addr, BRW_SWIZZLE_XYXY),
+                    swizzle(tile, BRW_SWIZZLE_XYXY));
+
+            /* 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(writemask(tmp, WRITEMASK_Z), tmp,
+                    swizzle(tile, BRW_SWIZZLE_YYYY));
+            bld.ADD(writemask(tmp, WRITEMASK_Z), tmp,
+                    swizzle(tmp, BRW_SWIZZLE_YYYY));
+            bld.SHL(writemask(tmp, WRITEMASK_YZ),
+                    swizzle(tmp, BRW_SWIZZLE_ZWZW),
+                    swizzle(tile, BRW_SWIZZLE_XYXY));
+            bld.ADD(writemask(tmp, WRITEMASK_X), tmp,
+                    swizzle(tmp, BRW_SWIZZLE_ZZZZ));
+
+            /* Add it to the start of the tile row. */
+            bld.MUL(writemask(tmp, WRITEMASK_Y), tmp, stride);
+            bld.ADD(writemask(tmp, WRITEMASK_X), tmp,
+                    swizzle(tmp, BRW_SWIZZLE_YYYY));
+
+            /* Multiply by the Bpp value. */
+            bld.MUL(writemask(dst, WRITEMASK_X), tmp, stride);
+
+            if (bld.devinfo->gen < 8 && !bld.devinfo->is_baytrail) {
+               /* Take into account the two dynamically specified shifts. */
+               bld.SHR(writemask(tmp, WRITEMASK_XY),
+                       swizzle(dst, BRW_SWIZZLE_XXXX), swz);
+
+               /* XOR tmp.x and tmp.y with bit 6 of the memory address. */
+               bld.XOR(writemask(tmp, WRITEMASK_X),
+                       swizzle(tmp, BRW_SWIZZLE_XXXX),
+                       swizzle(tmp, BRW_SWIZZLE_YYYY));
+               bld.AND(writemask(tmp, WRITEMASK_X), tmp, 1 << 6);
+               bld.XOR(writemask(dst, WRITEMASK_X), dst, tmp);
+            }
+
+         } else {
+            /* Multiply by the Bpp/stride value. */
+            bld.MUL(writemask(addr, WRITEMASK_Y), addr, stride);
+            bld.ADD(writemask(addr, WRITEMASK_X), addr,
+                    swizzle(addr, BRW_SWIZZLE_YYYY));
+            bld.MUL(writemask(dst, WRITEMASK_X), addr, stride);
+         }
+
+         return dst;
+      }
+   }
 }
 
 #endif
-- 
2.3.5



More information about the mesa-dev mailing list