summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_context.h2
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_program.c87
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c2
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 */
}