Added few more stubs so that control reaches to DestroyDevice().
[mesa.git] / src / gallium / drivers / vc4 / vc4_qir_lower_uniforms.c
index 29e3ee3120167ddf2a9e5a5c33222be56e7f9f70..d7c22e75c2938fc52513fb64c8deb9a7627d7a60 100644 (file)
@@ -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]);
+                                        }
                                 }
                         }
                 }