[Mesa-dev] [PATCH 1/6] nvc0: refactor the program upload process

Samuel Pitoiset samuel.pitoiset at gmail.com
Wed Aug 31 20:52:42 UTC 2016


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 at gmail.com>
---
 src/gallium/drivers/nouveau/nvc0/nvc0_context.h    |  2 +-
 src/gallium/drivers/nouveau/nvc0/nvc0_program.c    | 87 ++++++++++++++--------
 .../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 eddca48..ae65f8a 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 8d97201..0e0d436 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 0ae4bb1..c644fe9 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 */
 }
 
-- 
2.9.3



More information about the mesa-dev mailing list