X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fvc4%2Fvc4_qir_lower_uniforms.c;h=d7c22e75c2938fc52513fb64c8deb9a7627d7a60;hb=1a99fc0fd022018ed056cd42f299d5ad1a02c264;hp=29e3ee3120167ddf2a9e5a5c33222be56e7f9f70;hpb=d18d1ba5877c234a2cf4e3e834df27f03c7b6a11;p=mesa.git diff --git a/src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c b/src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c index 29e3ee31201..d7c22e75c29 100644 --- a/src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c +++ b/src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c @@ -66,7 +66,7 @@ remove_uniform(struct hash_table *ht, struct qreg reg) entry = _mesa_hash_table_search(ht, key); assert(entry); - entry->data--; + entry->data = (void *)(((uintptr_t) entry->data) - 1); if (entry->data == NULL) _mesa_hash_table_remove(ht, entry); } @@ -77,10 +77,37 @@ is_lowerable_uniform(struct qinst *inst, int i) if (inst->src[i].file != QFILE_UNIF) return false; if (qir_is_tex(inst)) - return i != 1; + return i != qir_get_tex_uniform_src(inst); return true; } +/* Returns the number of different uniform values referenced by the + * instruction. + */ +static uint32_t +qir_get_instruction_uniform_count(struct qinst *inst) +{ + uint32_t count = 0; + + for (int i = 0; i < qir_get_nsrc(inst); i++) { + if (inst->src[i].file != QFILE_UNIF) + continue; + + bool is_duplicate = false; + for (int j = 0; j < i; j++) { + if (inst->src[j].file == QFILE_UNIF && + inst->src[j].index == inst->src[i].index) { + is_duplicate = true; + break; + } + } + if (!is_duplicate) + count++; + } + + return count; +} + void qir_lower_uniforms(struct vc4_compile *c) { @@ -91,16 +118,10 @@ qir_lower_uniforms(struct vc4_compile *c) * than one uniform referenced, and add those uniform values to the * ht. */ - list_for_each_entry(struct qinst, inst, &c->instructions, link) { - uint32_t nsrc = qir_get_op_nsrc(inst->op); + qir_for_each_inst_inorder(inst, c) { + uint32_t nsrc = qir_get_nsrc(inst); - uint32_t count = 0; - for (int i = 0; i < nsrc; i++) { - if (inst->src[i].file == QFILE_UNIF) - count++; - } - - if (count <= 1) + if (qir_get_instruction_uniform_count(inst) <= 1) continue; for (int i = 0; i < nsrc; i++) { @@ -115,7 +136,6 @@ qir_lower_uniforms(struct vc4_compile *c) */ uint32_t max_count = 0; uint32_t max_index = 0; - struct hash_entry *entry; hash_table_foreach(ht, entry) { uint32_t count = (uintptr_t)entry->data; uint32_t index = (uintptr_t)entry->key - 1; @@ -125,42 +145,56 @@ qir_lower_uniforms(struct vc4_compile *c) } } + struct qreg unif = qir_reg(QFILE_UNIF, max_index); + /* Now, find the instructions using this uniform and make them * reference a temp instead. */ - struct qreg temp = qir_get_temp(c); - struct qreg unif = { QFILE_UNIF, max_index }; - struct qinst *mov = qir_inst(QOP_MOV, temp, unif, c->undef); - list_add(&mov->link, &c->instructions); - c->defs[temp.index] = mov; - list_for_each_entry(struct qinst, inst, &c->instructions, link) { - uint32_t nsrc = qir_get_op_nsrc(inst->op); - - uint32_t count = 0; - for (int i = 0; i < nsrc; i++) { - if (inst->src[i].file == QFILE_UNIF) - count++; - } - - if (count <= 1) - continue; - - for (int i = 0; i < nsrc; i++) { - if (is_lowerable_uniform(inst, i) && - inst->src[i].index == max_index) { - inst->src[i] = temp; - remove_uniform(ht, unif); - count--; + qir_for_each_block(block, c) { + struct qinst *mov = NULL; + + qir_for_each_inst(inst, block) { + uint32_t nsrc = qir_get_nsrc(inst); + + uint32_t count = qir_get_instruction_uniform_count(inst); + + if (count <= 1) + continue; + + /* If the block doesn't have a load of hte + * uniform yet, add it. We could potentially + * do better and CSE MOVs from multiple blocks + * into dominating blocks, except that may + * cause troubles for register allocation. + */ + if (!mov) { + mov = qir_inst(QOP_MOV, qir_get_temp(c), + unif, c->undef); + list_add(&mov->link, + &block->instructions); + c->defs[mov->dst.index] = mov; } - } - /* If the instruction doesn't need lowering any more, - * then drop it from the list. - */ - if (count <= 1) { + bool removed = false; for (int i = 0; i < nsrc; i++) { - if (is_lowerable_uniform(inst, i)) - remove_uniform(ht, inst->src[i]); + if (is_lowerable_uniform(inst, i) && + inst->src[i].index == max_index) { + inst->src[i] = mov->dst; + remove_uniform(ht, unif); + removed = true; + } + } + if (removed) + count--; + + /* If the instruction doesn't need lowering any more, + * then drop it from the list. + */ + if (count <= 1) { + for (int i = 0; i < nsrc; i++) { + if (is_lowerable_uniform(inst, i)) + remove_uniform(ht, inst->src[i]); + } } } }