i965/vec4: Optimize packSnorm4x8().
authorMatt Turner <mattst88@gmail.com>
Mon, 10 Mar 2014 21:11:05 +0000 (14:11 -0700)
committerMatt Turner <mattst88@gmail.com>
Wed, 26 Nov 2014 01:29:02 +0000 (17:29 -0800)
Reduces the number of instructions needed to implement packSnorm4x8()
from 13 -> 7.

src/mesa/drivers/dri/i965/brw_shader.cpp
src/mesa/drivers/dri/i965/brw_vec4.h
src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp

index d7a2a9163873b19bb882191bf9e8260187e2f064..8e4f7795d828343a3330efcb1a857263ad63fb46 100644 (file)
@@ -82,13 +82,13 @@ brw_lower_packing_builtins(struct brw_context *brw,
    int ops = LOWER_PACK_SNORM_2x16
            | LOWER_UNPACK_SNORM_2x16
            | LOWER_PACK_UNORM_2x16
-           | LOWER_UNPACK_UNORM_2x16
-           | LOWER_PACK_SNORM_4x8;
+           | LOWER_UNPACK_UNORM_2x16;
 
    if (shader_type == MESA_SHADER_FRAGMENT) {
       ops |= LOWER_UNPACK_UNORM_4x8
            | LOWER_UNPACK_SNORM_4x8
-           | LOWER_PACK_UNORM_4x8;
+           | LOWER_PACK_UNORM_4x8
+           | LOWER_PACK_SNORM_4x8;
    }
 
    if (brw->gen >= 7) {
index 150e20a0387dc0287efcdf46021c1eceb341a9cb..7d814ca65bdd6b8197999521739fe0fca8f3a7a6 100644 (file)
@@ -511,6 +511,7 @@ public:
    void emit_unpack_unorm_4x8(const dst_reg &dst, src_reg src0);
    void emit_unpack_snorm_4x8(const dst_reg &dst, src_reg src0);
    void emit_pack_unorm_4x8(const dst_reg &dst, const src_reg &src0);
+   void emit_pack_snorm_4x8(const dst_reg &dst, const src_reg &src0);
 
    uint32_t gather_channel(ir_texture *ir, uint32_t sampler);
    src_reg emit_mcs_fetch(ir_texture *ir, src_reg coordinate, src_reg sampler);
index 34f96070250732f6cb7118d81ee22f765866d0b8..c1c24ac0b4926087e243bd5b5dc6b838fafdcc0b 100644 (file)
@@ -535,6 +535,28 @@ vec4_visitor::emit_pack_unorm_4x8(const dst_reg &dst, const src_reg &src0)
    emit(VEC4_OPCODE_PACK_BYTES, dst, bytes);
 }
 
+void
+vec4_visitor::emit_pack_snorm_4x8(const dst_reg &dst, const src_reg &src0)
+{
+   dst_reg max(this, glsl_type::vec4_type);
+   emit_minmax(BRW_CONDITIONAL_G, max, src0, src_reg(-1.0f));
+
+   dst_reg min(this, glsl_type::vec4_type);
+   emit_minmax(BRW_CONDITIONAL_L, min, src_reg(max), src_reg(1.0f));
+
+   dst_reg scaled(this, glsl_type::vec4_type);
+   emit(MUL(scaled, src_reg(min), src_reg(127.0f)));
+
+   dst_reg rounded(this, glsl_type::vec4_type);
+   emit(RNDE(rounded, src_reg(scaled)));
+
+   dst_reg i(this, glsl_type::ivec4_type);
+   emit(MOV(i, src_reg(rounded)));
+
+   src_reg bytes(i);
+   emit(VEC4_OPCODE_PACK_BYTES, dst, bytes);
+}
+
 void
 vec4_visitor::visit_instructions(const exec_list *list)
 {
@@ -1825,8 +1847,10 @@ vec4_visitor::visit(ir_expression *ir)
    case ir_unop_pack_unorm_4x8:
       emit_pack_unorm_4x8(result_dst, op[0]);
       break;
-   case ir_unop_pack_snorm_2x16:
    case ir_unop_pack_snorm_4x8:
+      emit_pack_snorm_4x8(result_dst, op[0]);
+      break;
+   case ir_unop_pack_snorm_2x16:
    case ir_unop_pack_unorm_2x16:
    case ir_unop_unpack_snorm_2x16:
    case ir_unop_unpack_unorm_2x16: