vc4: Reuse list_for_each_entry_rev().
[mesa.git] / src / gallium / drivers / vc4 / vc4_qir.c
index a34eccf5091d8ccf7963b09dffe8206d022b7fc6..71f06aebfa04503eb88bae47c42283badda87455 100644 (file)
@@ -58,6 +58,7 @@ static const struct qir_op_info qir_op_info[] = {
         [QOP_ASR] = { "asr", 1, 2 },
         [QOP_SHL] = { "shl", 1, 2 },
         [QOP_MIN] = { "min", 1, 2 },
+        [QOP_MIN_NOIMM] = { "min_noimm", 1, 2 },
         [QOP_MAX] = { "max", 1, 2 },
         [QOP_AND] = { "and", 1, 2 },
         [QOP_OR] = { "or", 1, 2 },
@@ -75,13 +76,10 @@ static const struct qir_op_info qir_op_info[] = {
         [QOP_FRAG_Z] = { "frag_z", 1, 0 },
         [QOP_FRAG_W] = { "frag_w", 1, 0 },
 
-        [QOP_TEX_S] = { "tex_s", 0, 2, true },
-        [QOP_TEX_T] = { "tex_t", 0, 2, true },
-        [QOP_TEX_R] = { "tex_r", 0, 2, true },
-        [QOP_TEX_B] = { "tex_b", 0, 2, true },
-        [QOP_TEX_DIRECT] = { "tex_direct", 0, 2, true },
         [QOP_TEX_RESULT] = { "tex_result", 1, 0, true },
 
+        [QOP_THRSW] = { "thrsw", 0, 0, true },
+
         [QOP_LOAD_IMM] = { "load_imm", 0, 1 },
         [QOP_LOAD_IMM_U2] = { "load_imm_u2", 0, 1 },
         [QOP_LOAD_IMM_I2] = { "load_imm_i2", 0, 1 },
@@ -102,12 +100,35 @@ qir_get_op_name(enum qop qop)
 }
 
 int
-qir_get_op_nsrc(enum qop qop)
+qir_get_non_sideband_nsrc(struct qinst *inst)
 {
-        if (qop < ARRAY_SIZE(qir_op_info) && qir_op_info[qop].name)
-                return qir_op_info[qop].nsrc;
-        else
-                abort();
+        assert(qir_op_info[inst->op].name);
+        return qir_op_info[inst->op].nsrc;
+}
+
+int
+qir_get_nsrc(struct qinst *inst)
+{
+        assert(qir_op_info[inst->op].name);
+
+        int nsrc = qir_get_non_sideband_nsrc(inst);
+
+        /* Normal (non-direct) texture coordinate writes also implicitly load
+         * a uniform for the texture parameters.
+         */
+        if (qir_is_tex(inst) && inst->dst.file != QFILE_TEX_S_DIRECT)
+                nsrc++;
+
+        return nsrc;
+}
+
+/* The sideband uniform for textures gets stored after the normal ALU
+ * arguments.
+ */
+int
+qir_get_tex_uniform_src(struct qinst *inst)
+{
+        return qir_get_nsrc(inst) - 1;
 }
 
 /**
@@ -122,6 +143,11 @@ qir_has_side_effects(struct vc4_compile *c, struct qinst *inst)
         case QFILE_TLB_COLOR_WRITE:
         case QFILE_TLB_COLOR_WRITE_MS:
         case QFILE_TLB_STENCIL_SETUP:
+        case QFILE_TEX_S_DIRECT:
+        case QFILE_TEX_S:
+        case QFILE_TEX_T:
+        case QFILE_TEX_R:
+        case QFILE_TEX_B:
                 return true;
         default:
                 break;
@@ -138,7 +164,7 @@ qir_has_side_effect_reads(struct vc4_compile *c, struct qinst *inst)
          * point/line coordinates reads, because they're generated by
          * fixed-function hardware.
          */
-        for (int i = 0; i < qir_get_op_nsrc(inst->op); i++) {
+        for (int i = 0; i < qir_get_nsrc(inst); i++) {
                 if (inst->src[i].file == QFILE_VARY &&
                     c->input_slots[inst->src[i].index].slot == 0xff) {
                         return true;
@@ -154,6 +180,17 @@ qir_has_side_effect_reads(struct vc4_compile *c, struct qinst *inst)
         return false;
 }
 
+bool
+qir_has_uniform_read(struct qinst *inst)
+{
+        for (int i = 0; i < qir_get_nsrc(inst); i++) {
+                if (inst->src[i].file == QFILE_UNIF)
+                        return true;
+        }
+
+        return false;
+}
+
 bool
 qir_is_mul(struct qinst *inst)
 {
@@ -206,7 +243,30 @@ qir_is_raw_mov(struct qinst *inst)
 bool
 qir_is_tex(struct qinst *inst)
 {
-        return inst->op >= QOP_TEX_S && inst->op <= QOP_TEX_DIRECT;
+        switch (inst->dst.file) {
+        case QFILE_TEX_S_DIRECT:
+        case QFILE_TEX_S:
+        case QFILE_TEX_T:
+        case QFILE_TEX_R:
+        case QFILE_TEX_B:
+                return true;
+        default:
+                return false;
+        }
+}
+
+bool
+qir_has_implicit_tex_uniform(struct qinst *inst)
+{
+        switch (inst->dst.file) {
+        case QFILE_TEX_S:
+        case QFILE_TEX_T:
+        case QFILE_TEX_R:
+        case QFILE_TEX_B:
+                return true;
+        default:
+                return false;
+        }
 }
 
 bool
@@ -283,13 +343,57 @@ qir_channels_written(struct qinst *inst)
         unreachable("Bad pack field");
 }
 
+char *
+qir_describe_uniform(enum quniform_contents contents, uint32_t data,
+                     const uint32_t *uniforms)
+{
+        static const char *quniform_names[] = {
+                [QUNIFORM_VIEWPORT_X_SCALE] = "vp_x_scale",
+                [QUNIFORM_VIEWPORT_Y_SCALE] = "vp_y_scale",
+                [QUNIFORM_VIEWPORT_Z_OFFSET] = "vp_z_offset",
+                [QUNIFORM_VIEWPORT_Z_SCALE] = "vp_z_scale",
+                [QUNIFORM_TEXTURE_CONFIG_P0] = "tex_p0",
+                [QUNIFORM_TEXTURE_CONFIG_P1] = "tex_p1",
+                [QUNIFORM_TEXTURE_CONFIG_P2] = "tex_p2",
+                [QUNIFORM_TEXTURE_FIRST_LEVEL] = "tex_first_level",
+        };
+
+        switch (contents) {
+        case QUNIFORM_CONSTANT:
+                return ralloc_asprintf(NULL, "0x%08x / %f", data, uif(data));
+        case QUNIFORM_UNIFORM:
+                if (uniforms) {
+                        uint32_t unif = uniforms[data];
+                        return ralloc_asprintf(NULL, "unif[%d] = 0x%08x / %f",
+                                               data, unif, uif(unif));
+                } else {
+                        return ralloc_asprintf(NULL, "unif[%d]", data);
+                }
+
+        case QUNIFORM_TEXTURE_CONFIG_P0:
+        case QUNIFORM_TEXTURE_CONFIG_P1:
+        case QUNIFORM_TEXTURE_CONFIG_P2:
+        case QUNIFORM_TEXTURE_FIRST_LEVEL:
+                return ralloc_asprintf(NULL, "%s[%d]",
+                                       quniform_names[contents], data);
+
+        default:
+                if (contents < ARRAY_SIZE(quniform_names) &&
+                    quniform_names[contents]) {
+                        return ralloc_asprintf(NULL, "%s",
+                                               quniform_names[contents]);
+                } else {
+                        return ralloc_asprintf(NULL, "??? %d", contents);
+                }
+        }
+}
+
 static void
 qir_print_reg(struct vc4_compile *c, struct qreg reg, bool write)
 {
         static const char *files[] = {
                 [QFILE_TEMP] = "t",
                 [QFILE_VARY] = "v",
-                [QFILE_UNIF] = "u",
                 [QFILE_TLB_COLOR_WRITE] = "tlb_c",
                 [QFILE_TLB_COLOR_WRITE_MS] = "tlb_c_ms",
                 [QFILE_TLB_Z_WRITE] = "tlb_z",
@@ -298,6 +402,11 @@ qir_print_reg(struct vc4_compile *c, struct qreg reg, bool write)
                 [QFILE_FRAG_Y] = "frag_y",
                 [QFILE_FRAG_REV_FLAG] = "frag_rev_flag",
                 [QFILE_QPU_ELEMENT] = "elem",
+                [QFILE_TEX_S_DIRECT] = "tex_s_direct",
+                [QFILE_TEX_S] = "tex_s",
+                [QFILE_TEX_T] = "tex_t",
+                [QFILE_TEX_R] = "tex_r",
+                [QFILE_TEX_B] = "tex_b",
         };
 
         switch (reg.file) {
@@ -330,19 +439,26 @@ qir_print_reg(struct vc4_compile *c, struct qreg reg, bool write)
         case QFILE_TLB_COLOR_WRITE_MS:
         case QFILE_TLB_Z_WRITE:
         case QFILE_TLB_STENCIL_SETUP:
+        case QFILE_TEX_S_DIRECT:
+        case QFILE_TEX_S:
+        case QFILE_TEX_T:
+        case QFILE_TEX_R:
+        case QFILE_TEX_B:
                 fprintf(stderr, "%s", files[reg.file]);
                 break;
 
-        default:
-                fprintf(stderr, "%s%d", files[reg.file], reg.index);
+        case QFILE_UNIF: {
+                char *desc = qir_describe_uniform(c->uniform_contents[reg.index],
+                                                  c->uniform_data[reg.index],
+                                                  NULL);
+                fprintf(stderr, "u%d (%s)", reg.index, desc);
+                ralloc_free(desc);
                 break;
         }
 
-        if (reg.file == QFILE_UNIF &&
-            c->uniform_contents[reg.index] == QUNIFORM_CONSTANT) {
-                fprintf(stderr, " (0x%08x / %f)",
-                        c->uniform_data[reg.index],
-                        uif(c->uniform_data[reg.index]));
+        default:
+                fprintf(stderr, "%s%d", files[reg.file], reg.index);
+                break;
         }
 }
 
@@ -370,7 +486,7 @@ qir_dump_inst(struct vc4_compile *c, struct qinst *inst)
                 }
         }
 
-        for (int i = 0; i < qir_get_op_nsrc(inst->op); i++) {
+        for (int i = 0; i < qir_get_nsrc(inst); i++) {
                 fprintf(stderr, ", ");
                 qir_print_reg(c, inst->src[i], false);
                 vc4_qpu_disasm_unpack(stderr, inst->src[i].pack);
@@ -475,7 +591,6 @@ qir_inst(enum qop op, struct qreg dst, struct qreg src0, struct qreg src1)
 
         inst->op = op;
         inst->dst = dst;
-        inst->src = calloc(2, sizeof(inst->src[0]));
         inst->src[0] = src0;
         inst->src[1] = src1;
         inst->cond = QPU_COND_ALWAYS;
@@ -483,26 +598,6 @@ qir_inst(enum qop op, struct qreg dst, struct qreg src0, struct qreg src1)
         return inst;
 }
 
-struct qinst *
-qir_inst4(enum qop op, struct qreg dst,
-          struct qreg a,
-          struct qreg b,
-          struct qreg c,
-          struct qreg d)
-{
-        struct qinst *inst = CALLOC_STRUCT(qinst);
-
-        inst->op = op;
-        inst->dst = dst;
-        inst->src = calloc(4, sizeof(*inst->src));
-        inst->src[0] = a;
-        inst->src[1] = b;
-        inst->src[2] = c;
-        inst->src[3] = d;
-
-        return inst;
-}
-
 static void
 qir_emit(struct vc4_compile *c, struct qinst *inst)
 {
@@ -597,6 +692,7 @@ qir_compile_init(void)
 
         list_inithead(&c->blocks);
         qir_set_emit_block(c, qir_new_block(c));
+        c->last_top_block = c->cur_block;
 
         c->output_position_index = -1;
         c->output_color_index = -1;
@@ -616,7 +712,6 @@ qir_remove_instruction(struct vc4_compile *c, struct qinst *qinst)
                 c->defs[qinst->dst.index] = NULL;
 
         list_del(&qinst->link);
-        free(qinst->src);
         free(qinst);
 }
 
@@ -748,6 +843,7 @@ qir_optimize(struct vc4_compile *c)
                 OPTPASS(qir_opt_dead_code);
                 OPTPASS(qir_opt_small_immediates);
                 OPTPASS(qir_opt_vpm);
+                OPTPASS(qir_opt_coalesce_ff_writes);
 
                 if (!progress)
                         break;