summaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers
diff options
context:
space:
mode:
authorMatt Turner <[email protected]>2014-12-21 06:56:54 -0800
committerMatt Turner <[email protected]>2014-12-29 10:08:18 -0800
commit7bc6e455e231076bfac6c678c375ea4aca94ebf0 (patch)
tree020bcc025f5902d6a2a36ffba45ad0df4747bd8b /src/mesa/drivers
parent3978585bccf69ff8f607cad0de025ea91c418587 (diff)
i965: Add support for saturating immediates.
I don't feel great about assert(!"unimplemented: ...") but these cases do only seem possible under some currently impossible circumstances. Reviewed-by: Ian Romanick <[email protected]>
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.cpp16
-rw-r--r--src/mesa/drivers/dri/i965/brw_shader.cpp47
-rw-r--r--src/mesa/drivers/dri/i965/brw_shader.h1
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4.cpp16
4 files changed, 80 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index 2837fc0477d..78c068f0e3f 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -2292,6 +2292,22 @@ fs_visitor::opt_algebraic()
foreach_block_and_inst(block, fs_inst, inst, cfg) {
switch (inst->opcode) {
+ case BRW_OPCODE_MOV:
+ if (inst->src[0].file != IMM)
+ break;
+
+ if (inst->saturate) {
+ if (inst->dst.type != inst->src[0].type)
+ assert(!"unimplemented: saturate mixed types");
+
+ if (brw_saturate_immediate(inst->dst.type,
+ &inst->src[0].fixed_hw_reg)) {
+ inst->saturate = false;
+ progress = true;
+ }
+ }
+ break;
+
case BRW_OPCODE_MUL:
if (inst->src[1].file != IMM)
continue;
diff --git a/src/mesa/drivers/dri/i965/brw_shader.cpp b/src/mesa/drivers/dri/i965/brw_shader.cpp
index 1e5227c6c88..e38dfd6635d 100644
--- a/src/mesa/drivers/dri/i965/brw_shader.cpp
+++ b/src/mesa/drivers/dri/i965/brw_shader.cpp
@@ -575,6 +575,53 @@ brw_instruction_name(enum opcode op)
unreachable("not reached");
}
+bool
+brw_saturate_immediate(enum brw_reg_type type, struct brw_reg *reg)
+{
+ union {
+ unsigned ud;
+ int d;
+ float f;
+ } imm = { reg->dw1.ud }, sat_imm;
+
+ switch (type) {
+ case BRW_REGISTER_TYPE_UD:
+ case BRW_REGISTER_TYPE_D:
+ case BRW_REGISTER_TYPE_UQ:
+ case BRW_REGISTER_TYPE_Q:
+ /* Nothing to do. */
+ return false;
+ case BRW_REGISTER_TYPE_UW:
+ sat_imm.ud = CLAMP(imm.ud, 0, USHRT_MAX);
+ break;
+ case BRW_REGISTER_TYPE_W:
+ sat_imm.d = CLAMP(imm.d, SHRT_MIN, SHRT_MAX);
+ break;
+ case BRW_REGISTER_TYPE_F:
+ sat_imm.f = CLAMP(imm.f, 0.0f, 1.0f);
+ break;
+ case BRW_REGISTER_TYPE_UB:
+ sat_imm.ud = CLAMP(imm.ud, 0, UCHAR_MAX);
+ break;
+ case BRW_REGISTER_TYPE_B:
+ sat_imm.d = CLAMP(imm.d, CHAR_MIN, CHAR_MAX);
+ break;
+ case BRW_REGISTER_TYPE_V:
+ case BRW_REGISTER_TYPE_UV:
+ case BRW_REGISTER_TYPE_VF:
+ assert(!"unimplemented: saturate vector immediate");
+ case BRW_REGISTER_TYPE_DF:
+ case BRW_REGISTER_TYPE_HF:
+ assert(!"unimplemented: saturate DF/HF immediate");
+ }
+
+ if (imm.ud != sat_imm.ud) {
+ reg->dw1.ud = sat_imm.ud;
+ return true;
+ }
+ return false;
+}
+
backend_visitor::backend_visitor(struct brw_context *brw,
struct gl_shader_program *shader_prog,
struct gl_program *prog,
diff --git a/src/mesa/drivers/dri/i965/brw_shader.h b/src/mesa/drivers/dri/i965/brw_shader.h
index 05434a7f76e..233e224c22a 100644
--- a/src/mesa/drivers/dri/i965/brw_shader.h
+++ b/src/mesa/drivers/dri/i965/brw_shader.h
@@ -192,6 +192,7 @@ enum brw_reg_type brw_type_for_base_type(const struct glsl_type *type);
enum brw_conditional_mod brw_conditional_for_comparison(unsigned int op);
uint32_t brw_math_function(enum opcode op);
const char *brw_instruction_name(enum opcode op);
+bool brw_saturate_immediate(enum brw_reg_type type, struct brw_reg *reg);
#ifdef __cplusplus
extern "C" {
diff --git a/src/mesa/drivers/dri/i965/brw_vec4.cpp b/src/mesa/drivers/dri/i965/brw_vec4.cpp
index b303eb68699..36de76ae404 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4.cpp
@@ -572,6 +572,22 @@ vec4_visitor::opt_algebraic()
foreach_block_and_inst(block, vec4_instruction, inst, cfg) {
switch (inst->opcode) {
+ case BRW_OPCODE_MOV:
+ if (inst->src[0].file != IMM)
+ break;
+
+ if (inst->saturate) {
+ if (inst->dst.type != inst->src[0].type)
+ assert(!"unimplemented: saturate mixed types");
+
+ if (brw_saturate_immediate(inst->dst.type,
+ &inst->src[0].fixed_hw_reg)) {
+ inst->saturate = false;
+ progress = true;
+ }
+ }
+ break;
+
case VEC4_OPCODE_UNPACK_UNIFORM:
if (inst->src[0].file != UNIFORM) {
inst->opcode = BRW_OPCODE_MOV;