[Mesa-dev] [RFC 25/27] i965/fs: Emit coordinate translation from W to Y-tiling
Topi Pohjolainen
topi.pohjolainen at intel.com
Sat Feb 22 01:05:51 PST 2014
Signed-off-by: Topi Pohjolainen <topi.pohjolainen at intel.com>
---
src/mesa/drivers/dri/i965/brw_fs.h | 2 +
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 69 ++++++++++++++++++++++++++++
2 files changed, 71 insertions(+)
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index 2b3ac34..28053da 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -520,6 +520,8 @@ public:
void denormalize(const fs_reg& unorm,
const fs_reg& norm,
const fs_reg& range);
+ void translate_norm_w_to_y_tiling(int sampler, fs_reg coord);
+ void translate_unorm_w_to_y_tiling(int sampler, fs_reg coord);
struct gl_fragment_program *fp;
diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
index 10afe5d..e84f0a2 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
@@ -1627,6 +1627,68 @@ fs_visitor::normalize(const fs_reg& norm,
emit(MUL(norm, unorm_f, range_inv));
}
+/**
+ * Emit translation of coordinates in W-tiling layout to Y-tiling. In the
+ * latter a tile holds twice as many pixels horizontally and half as few
+ * vertically.
+ * First the dimensions in Y-tiling layout are queried from the hardware. Then
+ * the width is divided and the height in turn multiplied by two in order to
+ * work with matching W-layout dimensions. These are used the translate the
+ * normalized coordinates into screen equivalent which can be then translated
+ * to corresponding screen coordinates in Y-layout. Finally the translated
+ * coordinates are normalized back.
+ */
+void
+fs_visitor::translate_norm_w_to_y_tiling(int sampler, fs_reg coord)
+{
+ fs_reg unorm_x = fs_reg(this, glsl_type::uint_type);
+ fs_reg unorm_y = fs_reg(this, glsl_type::uint_type);
+ fs_reg dst_x = fs_reg(this, glsl_type::uint_type);
+ fs_reg dst_y = fs_reg(this, glsl_type::uint_type);
+ fs_reg res_info = fetch_resinfo(sampler, fs_reg(0));
+
+ denormalize(unorm_x, coord, res_info);
+ emit(SHR(unorm_x, unorm_x, fs_reg(1)));
+ coord.reg_offset++;
+ res_info.reg_offset++;
+
+ denormalize(unorm_y, coord, res_info);
+ emit(SHL(unorm_y, unorm_y, fs_reg(1)));
+
+ emit_translate_w_to_y_tiling(fs_reg(this, glsl_type::uint_type),
+ fs_reg(this, glsl_type::uint_type),
+ unorm_x, unorm_y, dst_x, dst_y);
+
+ res_info.reg_offset = 0;
+ coord.reg_offset = 0;
+ normalize(coord, dst_x, res_info);
+ res_info.reg_offset++;
+ coord.reg_offset++;
+ normalize(coord, dst_y, res_info);
+}
+
+void
+fs_visitor::translate_unorm_w_to_y_tiling(int sampler, fs_reg coord)
+{
+ fs_reg unorm_x = fs_reg(this, glsl_type::uint_type);
+ fs_reg unorm_y = fs_reg(this, glsl_type::uint_type);
+ fs_reg dst_x = fs_reg(this, glsl_type::uint_type);
+ fs_reg dst_y = fs_reg(this, glsl_type::uint_type);
+
+ emit(MOV(unorm_x, coord));
+ coord.reg_offset++;
+ emit(MOV(unorm_y, coord));
+
+ emit_translate_w_to_y_tiling(fs_reg(this, glsl_type::uint_type),
+ fs_reg(this, glsl_type::uint_type),
+ unorm_x, unorm_y, dst_x, dst_y);
+
+ coord.reg_offset = 0;
+ emit(MOV(coord, dst_x));
+ coord.reg_offset++;
+ emit(MOV(coord, dst_y));
+}
+
void
fs_visitor::visit(ir_texture *ir)
{
@@ -1721,6 +1783,13 @@ fs_visitor::visit(ir_texture *ir)
default:
assert(!"Unrecognized texture opcode");
};
+
+ if (c->key.tex.translate_y_to_w[sampler]) {
+ if (ir->op == ir_txf)
+ translate_unorm_w_to_y_tiling(sampler, coordinate);
+ else
+ translate_norm_w_to_y_tiling(sampler, coordinate);
+ }
/* Writemasking doesn't eliminate channels on SIMD8 texture
* samples, so don't worry about them.
--
1.8.3.1
More information about the mesa-dev
mailing list