nvc0: re-upload currently bound shaders after code eviction
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Wed, 31 Aug 2016 20:52:43 +0000 (22:52 +0200)
committerSamuel Pitoiset <samuel.pitoiset@gmail.com>
Thu, 1 Sep 2016 19:25:25 +0000 (21:25 +0200)
This fixes a very old issue which happens when the code segment
size is full. A bunch of real applications like Tomb Raider,
F1 2015, Elemental, hit that issue because they use a ton of shaders.

In this case, all shaders are evicted (for freeing space) but all
currently bound shaders also need to be re-uploaded and SP_START_ID
have to be updated accordingly.

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Ilia Mirkin <imirkin@alum.mit.edu>
src/gallium/drivers/nouveau/nvc0/nvc0_program.c

index 0e0d436a7cf3b2e1d6dfdb58e3907f59a1a4ac20..66640eacbe8eb5f4914dcdfdddcc7711f621ac5b 100644 (file)
@@ -774,6 +774,10 @@ nvc0_program_upload(struct nvc0_context *nvc0, struct nvc0_program *prog)
    ret = nvc0_program_alloc_code(nvc0, prog);
    if (ret) {
       struct nouveau_heap *heap = screen->text_heap;
+      struct nvc0_program *progs[] = { /* Sorted accordingly to SP_START_ID */
+         nvc0->compprog, nvc0->vertprog, nvc0->tctlprog,
+         nvc0->tevlprog, nvc0->gmtyprog, nvc0->fragprog
+      };
 
       /* Note that the code library, which is allocated before anything else,
        * does not have a priv pointer. We can stop once we hit it.
@@ -790,6 +794,29 @@ nvc0_program_upload(struct nvc0_context *nvc0, struct nvc0_program *prog)
          return false;
       }
       IMMED_NVC0(nvc0->base.pushbuf, NVC0_3D(SERIALIZE), 0);
+
+      /* All currently bound shaders have to be reuploaded. */
+      for (int i = 0; i < ARRAY_SIZE(progs); i++) {
+         if (!progs[i] || progs[i] == prog)
+            continue;
+
+         ret = nvc0_program_alloc_code(nvc0, progs[i]);
+         if (ret) {
+            NOUVEAU_ERR("failed to re-upload a shader after code eviction.\n");
+            return false;
+         }
+         nvc0_program_upload_code(nvc0, progs[i]);
+
+         if (progs[i]->type == PIPE_SHADER_COMPUTE) {
+            /* Caches have to be invalidated but the CP_START_ID will be
+             * updated in the launch_grid functions. */
+            BEGIN_NVC0(nvc0->base.pushbuf, NVC0_CP(FLUSH), 1);
+            PUSH_DATA (nvc0->base.pushbuf, NVC0_COMPUTE_FLUSH_CODE);
+         } else {
+            BEGIN_NVC0(nvc0->base.pushbuf, NVC0_3D(SP_START_ID(i)), 1);
+            PUSH_DATA (nvc0->base.pushbuf, progs[i]->code_base);
+         }
+      }
    }
 
    nvc0_program_upload_code(nvc0, prog);