diff options
author | Samuel Pitoiset <[email protected]> | 2016-08-31 22:52:42 +0200 |
---|---|---|
committer | Samuel Pitoiset <[email protected]> | 2016-09-01 21:25:17 +0200 |
commit | 34883626d12a09b4e02c771e7af133522a673ad1 (patch) | |
tree | 7204153357c144b9a463b8b1e182457ceb00d601 /src/gallium/drivers/nouveau/nvc0 | |
parent | 49c24d8a241ead2f0906d8e9523ab3aba0d8a73d (diff) |
nvc0: refactor the program upload process
This refactoring will help for fixing the "out of code space"
eviction issue because we will need to reupload the code for
all currently bound shaders but it's slightly different than
uploading a new fresh code.
Signed-off-by: Samuel Pitoiset <[email protected]>
Reviewed-by: Ilia Mirkin <[email protected]>
Diffstat (limited to 'src/gallium/drivers/nouveau/nvc0')
-rw-r--r-- | src/gallium/drivers/nouveau/nvc0/nvc0_context.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/nouveau/nvc0/nvc0_program.c | 87 | ||||
-rw-r--r-- | src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c | 2 |
3 files changed, 59 insertions, 32 deletions
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h index eddca4889e2..ae65f8a20c6 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h @@ -289,7 +289,7 @@ extern struct draw_stage *nvc0_draw_render_stage(struct nvc0_context *); /* nvc0_program.c */ bool nvc0_program_translate(struct nvc0_program *, uint16_t chipset, struct pipe_debug_callback *); -bool nvc0_program_upload_code(struct nvc0_context *, struct nvc0_program *); +bool nvc0_program_upload(struct nvc0_context *, struct nvc0_program *); void nvc0_program_destroy(struct nvc0_context *, struct nvc0_program *); void nvc0_program_library_upload(struct nvc0_context *); uint32_t nvc0_program_symbol_offset(const struct nvc0_program *, diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c index 8d972012e19..0e0d436a7cf 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c @@ -680,15 +680,13 @@ out: return !ret; } -bool -nvc0_program_upload_code(struct nvc0_context *nvc0, struct nvc0_program *prog) +static inline int +nvc0_program_alloc_code(struct nvc0_context *nvc0, struct nvc0_program *prog) { struct nvc0_screen *screen = nvc0->screen; const bool is_cp = prog->type == PIPE_SHADER_COMPUTE; int ret; uint32_t size = prog->code_size + (is_cp ? 0 : NVC0_SHADER_HEADER_SIZE); - uint32_t lib_pos = screen->lib_code->start; - uint32_t code_pos; /* On Fermi, SP_START_ID must be aligned to 0x40. * On Kepler, the first instruction must be aligned to 0x80 because @@ -699,23 +697,8 @@ nvc0_program_upload_code(struct nvc0_context *nvc0, struct nvc0_program *prog) size = align(size, 0x40); ret = nouveau_heap_alloc(screen->text_heap, size, prog, &prog->mem); - if (ret) { - struct nouveau_heap *heap = screen->text_heap; - /* Note that the code library, which is allocated before anything else, - * does not have a priv pointer. We can stop once we hit it. - */ - while (heap->next && heap->next->priv) { - struct nvc0_program *evict = heap->next->priv; - nouveau_heap_free(&evict->mem); - } - debug_printf("WARNING: out of code space, evicting all shaders.\n"); - ret = nouveau_heap_alloc(heap, size, prog, &prog->mem); - if (ret) { - NOUVEAU_ERR("shader too large (0x%x) to fit in code space ?\n", size); - return false; - } - IMMED_NVC0(nvc0->base.pushbuf, NVC0_3D(SERIALIZE), 0); - } + if (ret) + return ret; prog->code_base = prog->mem->start; if (!is_cp) { @@ -730,18 +713,27 @@ nvc0_program_upload_code(struct nvc0_context *nvc0, struct nvc0_program *prog) break; } } - code_pos = prog->code_base + NVC0_SHADER_HEADER_SIZE; } else { if (screen->base.class_3d >= NVE4_3D_CLASS) { if (prog->mem->start & 0x40) prog->code_base += 0x40; assert((prog->code_base & 0x7f) == 0x00); } - code_pos = prog->code_base; } + return 0; +} + +static inline void +nvc0_program_upload_code(struct nvc0_context *nvc0, struct nvc0_program *prog) +{ + struct nvc0_screen *screen = nvc0->screen; + const bool is_cp = prog->type == PIPE_SHADER_COMPUTE; + uint32_t code_pos = prog->code_base + (is_cp ? 0 : NVC0_SHADER_HEADER_SIZE); + if (prog->relocs) - nv50_ir_relocate_code(prog->relocs, prog->code, code_pos, lib_pos, 0); + nv50_ir_relocate_code(prog->relocs, prog->code, code_pos, + screen->lib_code->start, 0); if (prog->fixups) { nv50_ir_apply_fixups(prog->fixups, prog->code, prog->fp.force_persample_interp, @@ -761,17 +753,52 @@ nvc0_program_upload_code(struct nvc0_context *nvc0, struct nvc0_program *prog) } } + if (!is_cp) + nvc0->base.push_data(&nvc0->base, screen->text, prog->code_base, + NV_VRAM_DOMAIN(&screen->base), + NVC0_SHADER_HEADER_SIZE, prog->hdr); + + nvc0->base.push_data(&nvc0->base, screen->text, code_pos, + NV_VRAM_DOMAIN(&screen->base), prog->code_size, + prog->code); +} + +bool +nvc0_program_upload(struct nvc0_context *nvc0, struct nvc0_program *prog) +{ + struct nvc0_screen *screen = nvc0->screen; + const bool is_cp = prog->type == PIPE_SHADER_COMPUTE; + int ret; + uint32_t size = prog->code_size + (is_cp ? 0 : NVC0_SHADER_HEADER_SIZE); + + ret = nvc0_program_alloc_code(nvc0, prog); + if (ret) { + struct nouveau_heap *heap = screen->text_heap; + + /* Note that the code library, which is allocated before anything else, + * does not have a priv pointer. We can stop once we hit it. + */ + while (heap->next && heap->next->priv) { + struct nvc0_program *evict = heap->next->priv; + nouveau_heap_free(&evict->mem); + } + debug_printf("WARNING: out of code space, evicting all shaders.\n"); + + ret = nvc0_program_alloc_code(nvc0, prog); + if (ret) { + NOUVEAU_ERR("shader too large (0x%x) to fit in code space ?\n", size); + return false; + } + IMMED_NVC0(nvc0->base.pushbuf, NVC0_3D(SERIALIZE), 0); + } + + nvc0_program_upload_code(nvc0, prog); + #ifdef DEBUG if (debug_get_bool_option("NV50_PROG_DEBUG", false)) nvc0_program_dump(prog); #endif - if (!is_cp) - nvc0->base.push_data(&nvc0->base, screen->text, prog->code_base, - NV_VRAM_DOMAIN(&screen->base), NVC0_SHADER_HEADER_SIZE, prog->hdr); - nvc0->base.push_data(&nvc0->base, screen->text, code_pos, - NV_VRAM_DOMAIN(&screen->base), prog->code_size, prog->code); - BEGIN_NVC0(nvc0->base.pushbuf, NVC0_3D(MEM_BARRIER), 1); PUSH_DATA (nvc0->base.pushbuf, 0x1011); diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c b/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c index 0ae4bb1be34..c644fe9925e 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c @@ -60,7 +60,7 @@ nvc0_program_validate(struct nvc0_context *nvc0, struct nvc0_program *prog) } if (likely(prog->code_size)) - return nvc0_program_upload_code(nvc0, prog); + return nvc0_program_upload(nvc0, prog); return true; /* stream output info only */ } |