diff options
author | Samuel Pitoiset <[email protected]> | 2016-08-31 22:52:43 +0200 |
---|---|---|
committer | Samuel Pitoiset <[email protected]> | 2016-09-01 21:25:25 +0200 |
commit | 3d928d9082cab625ea4189b2bba96648f712ef3d (patch) | |
tree | 508d4c3d6b9eccd7f4ebb69dd3d026a54323d1ce | |
parent | 34883626d12a09b4e02c771e7af133522a673ad1 (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 <[email protected]>
Reviewed-by: Ilia Mirkin <[email protected]>
-rw-r--r-- | src/gallium/drivers/nouveau/nvc0/nvc0_program.c | 27 |
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); |