diff options
author | Matt Turner <[email protected]> | 2014-12-21 06:56:54 -0800 |
---|---|---|
committer | Matt Turner <[email protected]> | 2014-12-29 10:08:18 -0800 |
commit | 7bc6e455e231076bfac6c678c375ea4aca94ebf0 (patch) | |
tree | 020bcc025f5902d6a2a36ffba45ad0df4747bd8b | |
parent | 3978585bccf69ff8f607cad0de025ea91c418587 (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]>
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs.cpp | 16 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_shader.cpp | 47 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_shader.h | 1 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_vec4.cpp | 16 |
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; |