nvc0: refactor the program upload process
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Wed, 31 Aug 2016 20:52:42 +0000 (22:52 +0200)
committerSamuel Pitoiset <samuel.pitoiset@gmail.com>
Thu, 1 Sep 2016 19:25:17 +0000 (21:25 +0200)
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 <samuel.pitoiset@gmail.com>
Reviewed-by: Ilia Mirkin <imirkin@alum.mit.edu>
src/gallium/drivers/nouveau/nvc0/nvc0_context.h
src/gallium/drivers/nouveau/nvc0/nvc0_program.c
src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c

index eddca4889e2d578af4132e357e0d3e307ecc08ed..ae65f8a20c682640e2f92823bef7db78d4308319 100644 (file)
@@ -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 *,
index 8d972012e19bdd5c7ce52353512a0f7593a79126..0e0d436a7cf3b2e1d6dfdb58e3907f59a1a4ac20 100644 (file)
@@ -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);
 
index 0ae4bb1be343de01fab50ad9f2eadc87c47f7490..c644fe9925ec6ea8c9bb41cbb9ae9982894a84fb 100644 (file)
@@ -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 */
 }