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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev