[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