summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/nouveau/nvc0/nvc0_program.c
diff options
context:
space:
mode:
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>2016-08-31 22:52:43 +0200
committerSamuel Pitoiset <samuel.pitoiset@gmail.com>2016-09-01 21:25:25 +0200
commit3d928d9082cab625ea4189b2bba96648f712ef3d (patch)
tree508d4c3d6b9eccd7f4ebb69dd3d026a54323d1ce /src/gallium/drivers/nouveau/nvc0/nvc0_program.c
parent34883626d12a09b4e02c771e7af133522a673ad1 (diff)
nvc0: re-upload currently bound shaders after code eviction
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>
Diffstat (limited to 'src/gallium/drivers/nouveau/nvc0/nvc0_program.c')
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_program.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c
index 0e0d436a7cf..66640eacbe8 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c
@@ -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);