[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 },
[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 },
}
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;
}
/**
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;
* 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;
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)
{
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
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",
[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) {
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;
}
}
}
}
- 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);
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;
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)
{
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;
c->defs[qinst->dst.index] = NULL;
list_del(&qinst->link);
- free(qinst->src);
free(qinst);
}
OPTPASS(qir_opt_dead_code);
OPTPASS(qir_opt_small_immediates);
OPTPASS(qir_opt_vpm);
+ OPTPASS(qir_opt_coalesce_ff_writes);
if (!progress)
break;