Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2015 Intel Corporation
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21.  * IN THE SOFTWARE.
  22.  */
  23.  
  24. #include <gtest/gtest.h>
  25. #include "brw_fs.h"
  26. #include "brw_cfg.h"
  27. #include "program/program.h"
  28.  
  29. class saturate_propagation_test : public ::testing::Test {
  30.    virtual void SetUp();
  31.  
  32. public:
  33.    struct brw_context *brw;
  34.    struct brw_device_info *devinfo;
  35.    struct gl_context *ctx;
  36.    struct brw_wm_prog_data *prog_data;
  37.    struct gl_shader_program *shader_prog;
  38.    struct brw_fragment_program *fp;
  39.    fs_visitor *v;
  40. };
  41.  
  42. class saturate_propagation_fs_visitor : public fs_visitor
  43. {
  44. public:
  45.    saturate_propagation_fs_visitor(struct brw_context *brw,
  46.                                    struct brw_wm_prog_data *prog_data,
  47.                                    struct gl_shader_program *shader_prog)
  48.       : fs_visitor(brw, NULL, MESA_SHADER_FRAGMENT, NULL, &prog_data->base,
  49.                    shader_prog, (struct gl_program *) NULL, 8) {}
  50. };
  51.  
  52.  
  53. void saturate_propagation_test::SetUp()
  54. {
  55.    brw = (struct brw_context *)calloc(1, sizeof(*brw));
  56.    devinfo = (struct brw_device_info *)calloc(1, sizeof(*brw));
  57.    brw->intelScreen = (struct intel_screen *)calloc(1, sizeof(*brw->intelScreen));
  58.    brw->intelScreen->devinfo = devinfo;
  59.    ctx = &brw->ctx;
  60.  
  61.    fp = ralloc(NULL, struct brw_fragment_program);
  62.    prog_data = ralloc(NULL, struct brw_wm_prog_data);
  63.    shader_prog = ralloc(NULL, struct gl_shader_program);
  64.  
  65.    v = new saturate_propagation_fs_visitor(brw, prog_data, shader_prog);
  66.  
  67.    _mesa_init_fragment_program(ctx, &fp->program, GL_FRAGMENT_SHADER, 0);
  68.  
  69.    brw->gen = devinfo->gen = 4;
  70. }
  71.  
  72. static fs_inst *
  73. instruction(bblock_t *block, int num)
  74. {
  75.    fs_inst *inst = (fs_inst *)block->start();
  76.    for (int i = 0; i < num; i++) {
  77.       inst = (fs_inst *)inst->next;
  78.    }
  79.    return inst;
  80. }
  81.  
  82. static bool
  83. saturate_propagation(fs_visitor *v)
  84. {
  85.    const bool print = false;
  86.  
  87.    if (print) {
  88.       fprintf(stderr, "= Before =\n");
  89.       v->cfg->dump(v);
  90.    }
  91.  
  92.    bool ret = v->opt_saturate_propagation();
  93.  
  94.    if (print) {
  95.       fprintf(stderr, "\n= After =\n");
  96.       v->cfg->dump(v);
  97.    }
  98.  
  99.    return ret;
  100. }
  101.  
  102. TEST_F(saturate_propagation_test, basic)
  103. {
  104.    fs_reg dst0 = v->vgrf(glsl_type::float_type);
  105.    fs_reg dst1 = v->vgrf(glsl_type::float_type);
  106.    fs_reg src0 = v->vgrf(glsl_type::float_type);
  107.    fs_reg src1 = v->vgrf(glsl_type::float_type);
  108.    v->emit(BRW_OPCODE_ADD, dst0, src0, src1);
  109.    v->emit(BRW_OPCODE_MOV, dst1, dst0)
  110.       ->saturate = true;
  111.  
  112.    /* = Before =
  113.     *
  114.     * 0: add(8)        dst0  src0  src1
  115.     * 1: mov.sat(8)    dst1  dst0
  116.     *
  117.     * = After =
  118.     * 0: add.sat(8)    dst0  src0  src1
  119.     * 1: mov(8)        dst1  dst0
  120.     */
  121.  
  122.    v->calculate_cfg();
  123.    bblock_t *block0 = v->cfg->blocks[0];
  124.  
  125.    EXPECT_EQ(0, block0->start_ip);
  126.    EXPECT_EQ(1, block0->end_ip);
  127.  
  128.    EXPECT_TRUE(saturate_propagation(v));
  129.    EXPECT_EQ(0, block0->start_ip);
  130.    EXPECT_EQ(1, block0->end_ip);
  131.    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
  132.    EXPECT_TRUE(instruction(block0, 0)->saturate);
  133.    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
  134.    EXPECT_FALSE(instruction(block0, 1)->saturate);
  135. }
  136.  
  137. TEST_F(saturate_propagation_test, other_non_saturated_use)
  138. {
  139.    fs_reg dst0 = v->vgrf(glsl_type::float_type);
  140.    fs_reg dst1 = v->vgrf(glsl_type::float_type);
  141.    fs_reg dst2 = v->vgrf(glsl_type::float_type);
  142.    fs_reg src0 = v->vgrf(glsl_type::float_type);
  143.    fs_reg src1 = v->vgrf(glsl_type::float_type);
  144.    v->emit(BRW_OPCODE_ADD, dst0, src0, src1);
  145.    v->emit(BRW_OPCODE_MOV, dst1, dst0)
  146.       ->saturate = true;
  147.    v->emit(BRW_OPCODE_ADD, dst2, dst0, src0);
  148.  
  149.    /* = Before =
  150.     *
  151.     * 0: add(8)        dst0  src0  src1
  152.     * 1: mov.sat(8)    dst1  dst0
  153.     * 2: add(8)        dst2  dst0  src0
  154.     *
  155.     * = After =
  156.     * (no changes)
  157.     */
  158.  
  159.    v->calculate_cfg();
  160.    bblock_t *block0 = v->cfg->blocks[0];
  161.  
  162.    EXPECT_EQ(0, block0->start_ip);
  163.    EXPECT_EQ(2, block0->end_ip);
  164.  
  165.    EXPECT_FALSE(saturate_propagation(v));
  166.    EXPECT_EQ(0, block0->start_ip);
  167.    EXPECT_EQ(2, block0->end_ip);
  168.    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
  169.    EXPECT_FALSE(instruction(block0, 0)->saturate);
  170.    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
  171.    EXPECT_TRUE(instruction(block0, 1)->saturate);
  172.    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 2)->opcode);
  173. }
  174.  
  175. TEST_F(saturate_propagation_test, predicated_instruction)
  176. {
  177.    fs_reg dst0 = v->vgrf(glsl_type::float_type);
  178.    fs_reg dst1 = v->vgrf(glsl_type::float_type);
  179.    fs_reg src0 = v->vgrf(glsl_type::float_type);
  180.    fs_reg src1 = v->vgrf(glsl_type::float_type);
  181.    v->emit(BRW_OPCODE_ADD, dst0, src0, src1)
  182.       ->predicate = BRW_PREDICATE_NORMAL;
  183.    v->emit(BRW_OPCODE_MOV, dst1, dst0)
  184.       ->saturate = true;
  185.  
  186.    /* = Before =
  187.     *
  188.     * 0: (+f0) add(8)  dst0  src0  src1
  189.     * 1: mov.sat(8)    dst1  dst0
  190.     *
  191.     * = After =
  192.     * (no changes)
  193.     */
  194.  
  195.    v->calculate_cfg();
  196.    bblock_t *block0 = v->cfg->blocks[0];
  197.  
  198.    EXPECT_EQ(0, block0->start_ip);
  199.    EXPECT_EQ(1, block0->end_ip);
  200.  
  201.    EXPECT_FALSE(saturate_propagation(v));
  202.    EXPECT_EQ(0, block0->start_ip);
  203.    EXPECT_EQ(1, block0->end_ip);
  204.    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
  205.    EXPECT_FALSE(instruction(block0, 0)->saturate);
  206.    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
  207.    EXPECT_TRUE(instruction(block0, 1)->saturate);
  208. }
  209.  
  210. TEST_F(saturate_propagation_test, neg_mov_sat)
  211. {
  212.    fs_reg dst0 = v->vgrf(glsl_type::float_type);
  213.    fs_reg dst1 = v->vgrf(glsl_type::float_type);
  214.    fs_reg src0 = v->vgrf(glsl_type::float_type);
  215.    fs_reg src1 = v->vgrf(glsl_type::float_type);
  216.    v->emit(BRW_OPCODE_ADD, dst0, src0, src1);
  217.    dst0.negate = true;
  218.    v->emit(BRW_OPCODE_MOV, dst1, dst0)
  219.       ->saturate = true;
  220.  
  221.    /* = Before =
  222.     *
  223.     * 0: add(8)        dst0  src0  src1
  224.     * 1: mov.sat(8)    dst1  -dst0
  225.     *
  226.     * = After =
  227.     * (no changes)
  228.     */
  229.  
  230.    v->calculate_cfg();
  231.    bblock_t *block0 = v->cfg->blocks[0];
  232.  
  233.    EXPECT_EQ(0, block0->start_ip);
  234.    EXPECT_EQ(1, block0->end_ip);
  235.  
  236.    EXPECT_FALSE(saturate_propagation(v));
  237.    EXPECT_EQ(0, block0->start_ip);
  238.    EXPECT_EQ(1, block0->end_ip);
  239.    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
  240.    EXPECT_FALSE(instruction(block0, 0)->saturate);
  241.    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
  242.    EXPECT_TRUE(instruction(block0, 1)->saturate);
  243. }
  244.  
  245. TEST_F(saturate_propagation_test, abs_mov_sat)
  246. {
  247.    fs_reg dst0 = v->vgrf(glsl_type::float_type);
  248.    fs_reg dst1 = v->vgrf(glsl_type::float_type);
  249.    fs_reg src0 = v->vgrf(glsl_type::float_type);
  250.    fs_reg src1 = v->vgrf(glsl_type::float_type);
  251.    v->emit(BRW_OPCODE_ADD, dst0, src0, src1);
  252.    dst0.abs = true;
  253.    v->emit(BRW_OPCODE_MOV, dst1, dst0)
  254.       ->saturate = true;
  255.  
  256.    /* = Before =
  257.     *
  258.     * 0: add(8)        dst0  src0  src1
  259.     * 1: mov.sat(8)    dst1  (abs)dst0
  260.     *
  261.     * = After =
  262.     * (no changes)
  263.     */
  264.  
  265.    v->calculate_cfg();
  266.    bblock_t *block0 = v->cfg->blocks[0];
  267.  
  268.    EXPECT_EQ(0, block0->start_ip);
  269.    EXPECT_EQ(1, block0->end_ip);
  270.  
  271.    EXPECT_FALSE(saturate_propagation(v));
  272.    EXPECT_EQ(0, block0->start_ip);
  273.    EXPECT_EQ(1, block0->end_ip);
  274.    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
  275.    EXPECT_FALSE(instruction(block0, 0)->saturate);
  276.    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
  277.    EXPECT_TRUE(instruction(block0, 1)->saturate);
  278. }
  279.  
  280. TEST_F(saturate_propagation_test, producer_saturates)
  281. {
  282.    fs_reg dst0 = v->vgrf(glsl_type::float_type);
  283.    fs_reg dst1 = v->vgrf(glsl_type::float_type);
  284.    fs_reg dst2 = v->vgrf(glsl_type::float_type);
  285.    fs_reg src0 = v->vgrf(glsl_type::float_type);
  286.    fs_reg src1 = v->vgrf(glsl_type::float_type);
  287.    v->emit(BRW_OPCODE_ADD, dst0, src0, src1)
  288.       ->saturate = true;
  289.    v->emit(BRW_OPCODE_MOV, dst1, dst0)
  290.       ->saturate = true;
  291.    v->emit(BRW_OPCODE_MOV, dst2, dst0);
  292.  
  293.    /* = Before =
  294.     *
  295.     * 0: add.sat(8)    dst0  src0  src1
  296.     * 1: mov.sat(8)    dst1  dst0
  297.     * 2: mov(8)        dst2  dst0
  298.     *
  299.     * = After =
  300.     * 0: add.sat(8)    dst0  src0  src1
  301.     * 1: mov(8)        dst1  dst0
  302.     * 2: mov(8)        dst2  dst0
  303.     */
  304.  
  305.    v->calculate_cfg();
  306.    bblock_t *block0 = v->cfg->blocks[0];
  307.  
  308.    EXPECT_EQ(0, block0->start_ip);
  309.    EXPECT_EQ(2, block0->end_ip);
  310.  
  311.    EXPECT_TRUE(saturate_propagation(v));
  312.    EXPECT_EQ(0, block0->start_ip);
  313.    EXPECT_EQ(2, block0->end_ip);
  314.    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
  315.    EXPECT_TRUE(instruction(block0, 0)->saturate);
  316.    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
  317.    EXPECT_FALSE(instruction(block0, 1)->saturate);
  318. }
  319.  
  320. TEST_F(saturate_propagation_test, intervening_saturating_copy)
  321. {
  322.    fs_reg dst0 = v->vgrf(glsl_type::float_type);
  323.    fs_reg dst1 = v->vgrf(glsl_type::float_type);
  324.    fs_reg dst2 = v->vgrf(glsl_type::float_type);
  325.    fs_reg src0 = v->vgrf(glsl_type::float_type);
  326.    fs_reg src1 = v->vgrf(glsl_type::float_type);
  327.    v->emit(BRW_OPCODE_ADD, dst0, src0, src1);
  328.    v->emit(BRW_OPCODE_MOV, dst1, dst0)
  329.       ->saturate = true;
  330.    v->emit(BRW_OPCODE_MOV, dst2, dst0)
  331.       ->saturate = true;
  332.  
  333.    /* = Before =
  334.     *
  335.     * 0: add(8)    dst0  src0  src1
  336.     * 1: mov.sat(8)    dst1  dst0
  337.     * 2: mov.sat(8)    dst2  dst0
  338.     *
  339.     * = After =
  340.     * 0: add.sat(8)    dst0  src0  src1
  341.     * 1: mov(8)        dst1  dst0
  342.     * 2: mov(8)        dst2  dst0
  343.     */
  344.  
  345.    v->calculate_cfg();
  346.    bblock_t *block0 = v->cfg->blocks[0];
  347.  
  348.    EXPECT_EQ(0, block0->start_ip);
  349.    EXPECT_EQ(2, block0->end_ip);
  350.  
  351.    EXPECT_TRUE(saturate_propagation(v));
  352.    EXPECT_EQ(0, block0->start_ip);
  353.    EXPECT_EQ(2, block0->end_ip);
  354.    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
  355.    EXPECT_TRUE(instruction(block0, 0)->saturate);
  356.    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
  357.    EXPECT_FALSE(instruction(block0, 1)->saturate);
  358.    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
  359.    EXPECT_FALSE(instruction(block0, 2)->saturate);
  360. }
  361.  
  362. TEST_F(saturate_propagation_test, intervening_dest_write)
  363. {
  364.    fs_reg dst0 = v->vgrf(glsl_type::vec4_type);
  365.    fs_reg dst1 = v->vgrf(glsl_type::float_type);
  366.    fs_reg src0 = v->vgrf(glsl_type::float_type);
  367.    fs_reg src1 = v->vgrf(glsl_type::float_type);
  368.    fs_reg src2 = v->vgrf(glsl_type::vec2_type);
  369.    v->emit(BRW_OPCODE_ADD, offset(dst0, 2), src0, src1);
  370.    v->emit(SHADER_OPCODE_TEX, dst0, src2)
  371.       ->regs_written = 4;
  372.    v->emit(BRW_OPCODE_MOV, dst1, offset(dst0, 2))
  373.       ->saturate = true;
  374.  
  375.    /* = Before =
  376.     *
  377.     * 0: add(8)        dst0+2  src0    src1
  378.     * 1: tex(8) rlen 4 dst0+0  src2
  379.     * 2: mov.sat(8)    dst1    dst0+2
  380.     *
  381.     * = After =
  382.     * (no changes)
  383.     */
  384.  
  385.    v->calculate_cfg();
  386.    bblock_t *block0 = v->cfg->blocks[0];
  387.  
  388.    EXPECT_EQ(0, block0->start_ip);
  389.    EXPECT_EQ(2, block0->end_ip);
  390.  
  391.    EXPECT_FALSE(saturate_propagation(v));
  392.    EXPECT_EQ(0, block0->start_ip);
  393.    EXPECT_EQ(2, block0->end_ip);
  394.    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
  395.    EXPECT_FALSE(instruction(block0, 0)->saturate);
  396.    EXPECT_EQ(SHADER_OPCODE_TEX, instruction(block0, 1)->opcode);
  397.    EXPECT_FALSE(instruction(block0, 0)->saturate);
  398.    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
  399.    EXPECT_TRUE(instruction(block0, 2)->saturate);
  400. }
  401.  
  402. TEST_F(saturate_propagation_test, mul_neg_mov_sat_mov_sat)
  403. {
  404.    fs_reg dst0 = v->vgrf(glsl_type::float_type);
  405.    fs_reg dst1 = v->vgrf(glsl_type::float_type);
  406.    fs_reg dst2 = v->vgrf(glsl_type::float_type);
  407.    fs_reg src0 = v->vgrf(glsl_type::float_type);
  408.    fs_reg src1 = v->vgrf(glsl_type::float_type);
  409.    v->emit(BRW_OPCODE_MUL, dst0, src0, src1);
  410.    dst0.negate = true;
  411.    v->emit(BRW_OPCODE_MOV, dst1, dst0)
  412.       ->saturate = true;
  413.    dst0.negate = false;
  414.    v->emit(BRW_OPCODE_MOV, dst2, dst0)
  415.       ->saturate = true;
  416.  
  417.    /* = Before =
  418.     *
  419.     * 0: mul(8)        dst0  src0  src1
  420.     * 1: mov.sat(8)    dst1  -dst0
  421.     * 2: mov.sat(8)    dst2  dst0
  422.     *
  423.     * = After =
  424.     * (no changes)
  425.     */
  426.  
  427.    v->calculate_cfg();
  428.    bblock_t *block0 = v->cfg->blocks[0];
  429.  
  430.    EXPECT_EQ(0, block0->start_ip);
  431.    EXPECT_EQ(2, block0->end_ip);
  432.  
  433.    EXPECT_FALSE(saturate_propagation(v));
  434.    EXPECT_EQ(0, block0->start_ip);
  435.    EXPECT_EQ(2, block0->end_ip);
  436.    EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode);
  437.    EXPECT_FALSE(instruction(block0, 0)->saturate);
  438.    EXPECT_FALSE(instruction(block0, 0)->src[1].negate);
  439.    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
  440.    EXPECT_TRUE(instruction(block0, 1)->saturate);
  441.    EXPECT_TRUE(instruction(block0, 1)->src[0].negate);
  442.    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
  443.    EXPECT_TRUE(instruction(block0, 2)->saturate);
  444. }
  445.