summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTopi Pohjolainen <topi.pohjolainen@intel.com>2014-10-01 10:03:11 +0300
committerTopi Pohjolainen <topi.pohjolainen@intel.com>2014-10-01 10:36:48 +0300
commitc7cff16a7404d2b6eab1ef6d5714dba110d35a49 (patch)
treed4a165a1b05886a2a9a625c9759957f47126ead1
parent7986237345b216145f8588ece0e8c27f9e9c7f85 (diff)
i965/fs: Lower double precision scalars into vectors
Signed-off-by: Topi Pohjolainen <topi.pohjolainen@intel.com>
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.h2
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_visitor.cpp44
2 files changed, 45 insertions, 1 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index de4a25dc22..d8ab47998f 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -547,6 +547,8 @@ public:
void visit_atomic_counter_intrinsic(ir_call *ir);
+ fs_reg lower_double_scalar(const fs_reg *reg);
+
const struct brw_wm_prog_key *const key;
struct brw_wm_prog_data *prog_data;
unsigned int sanity_param_count;
diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
index a733037af8..f2ee142178 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
@@ -150,6 +150,44 @@ fs_visitor::visit(ir_variable *ir)
hash_table_insert(this->variable_ht, reg, ir);
}
+/**
+ * Lower double precision scalar into a vector. Hardware can operate only
+ * with scalars of single precision.
+ *
+ * Quotes from the docs:
+ *
+ * IVB PRM vol4 part 3, section 3.1 (about align1 mode):
+ * "A single precision float scalar is allowed."
+ *
+ * Section 3.3.9 (Register region restrictions):
+ * "If ExecSize = Width = 1, both VertStride and HorzStride must be 0. This
+ * defines a scalar."
+ * "If VertStride = HorzStride = 0, Width must be 1 regardless of the value of
+ * ExecSize."
+ *
+ * "In Align1 mode, all regioning parameters like stride, execution size, and
+ * width must use the syntax of a pair of packed floats. The offsets for
+ * these data types must be 64 - bit aligned. The execution size and
+ * regioning parameters are in terms of floats.
+ *
+ * Example: mov (8) r10.0<1>:df r11.0<8;8,1>:df
+ * The above instruction moves four double floats"
+ *
+ * Hence in case of "double scalar", one should set width = 2 violating the
+ * second constraint.
+ */
+fs_reg
+fs_visitor::lower_double_scalar(const fs_reg *reg)
+{
+ fs_reg res = fs_reg(this, glsl_type::double_type);
+ fs_reg lo = retype(*reg, BRW_REGISTER_TYPE_UD);
+ fs_reg hi = offset(lo, 1);
+
+ emit(FS_OPCODE_PACK_DOUBLE_2x32, res, lo, hi);
+
+ return res;
+}
+
void
fs_visitor::visit(ir_dereference_variable *ir)
{
@@ -160,7 +198,11 @@ fs_visitor::visit(ir_dereference_variable *ir)
this->result = fs_reg(reg_null_d);
return;
}
- this->result = *reg;
+
+ if (reg->file == UNIFORM && reg->type == BRW_REGISTER_TYPE_DF)
+ this->result = lower_double_scalar(reg);
+ else
+ this->result = *reg;
}
void