v3d: Create a state uploader for packing our shaders together.
authorEric Anholt <eric@anholt.net>
Fri, 7 Dec 2018 20:18:34 +0000 (12:18 -0800)
committerEric Anholt <eric@anholt.net>
Sat, 8 Dec 2018 00:48:23 +0000 (16:48 -0800)
Shaders are usually quite short, and are private to the context.  We can
save memory and reduce the work the kernel needs to do at exec time by
packing them together in a stream uploader for long-lived state.

src/gallium/drivers/v3d/v3d_context.c
src/gallium/drivers/v3d/v3d_context.h
src/gallium/drivers/v3d/v3d_program.c
src/gallium/drivers/v3d/v3dx_draw.c

index 12741b578e3524bf12251a98744ef448b654dd23..36c8f497824acdc4054a7d7fde2b217304ca4395 100644 (file)
@@ -98,6 +98,8 @@ v3d_context_destroy(struct pipe_context *pctx)
 
         if (v3d->uploader)
                 u_upload_destroy(v3d->uploader);
+        if (v3d->state_uploader)
+                u_upload_destroy(v3d->state_uploader);
 
         slab_destroy_child(&v3d->transfer_pool);
 
@@ -159,6 +161,10 @@ v3d_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
         v3d->uploader = u_upload_create_default(&v3d->base);
         v3d->base.stream_uploader = v3d->uploader;
         v3d->base.const_uploader = v3d->uploader;
+        v3d->state_uploader = u_upload_create(&v3d->base,
+                                              4096,
+                                              PIPE_BIND_CONSTANT_BUFFER,
+                                              PIPE_USAGE_STREAM, 0);
 
         v3d->blitter = util_blitter_create(pctx);
         if (!v3d->blitter)
index 8c55eadfa157bd8c84f881ba2d1c82226b50393d..ab4756aa76fcbf70ae084258fc220859bdb3877e 100644 (file)
@@ -143,7 +143,8 @@ struct v3d_uncompiled_shader {
 };
 
 struct v3d_compiled_shader {
-        struct v3d_bo *bo;
+        struct pipe_resource *resource;
+        uint32_t offset;
 
         union {
                 struct v3d_prog_data *base;
@@ -368,7 +369,15 @@ struct v3d_context {
         /** Sync object that our RCL or TFU job will update as its out_sync. */
         uint32_t out_sync;
 
+        /* Stream uploader used by gallium internals.  This could also be used
+         * by driver internals, but we tend to use the v3d_cl.h interfaces
+         * instead.
+         */
         struct u_upload_mgr *uploader;
+        /* State uploader used inside the driver.  This is for packing bits of
+         * long-term state inside buffers.
+         */
+        struct u_upload_mgr *state_uploader;
 
         /** @{ Current pipeline state objects */
         struct pipe_scissor_state scissor;
index 1dceade950a36843ee3349dbcec740570d36a45f..25b346fd11b1e678950b174335fd8c8fba8c6481 100644 (file)
@@ -27,6 +27,7 @@
 #include "util/u_memory.h"
 #include "util/ralloc.h"
 #include "util/hash_table.h"
+#include "util/u_upload_mgr.h"
 #include "tgsi/tgsi_dump.h"
 #include "tgsi/tgsi_parse.h"
 #include "compiler/nir/nir.h"
@@ -301,9 +302,8 @@ v3d_get_compiled_shader(struct v3d_context *v3d, struct v3d_key *key)
 
         v3d_set_shader_uniform_dirty_flags(shader);
 
-        shader->bo = v3d_bo_alloc(v3d->screen, shader_size, "shader");
-        v3d_bo_map(shader->bo);
-        memcpy(shader->bo->map, qpu_insts, shader_size);
+        u_upload_data(v3d->state_uploader, 0, shader_size, 8,
+                      qpu_insts, &shader->offset, &shader->resource);
 
         free(qpu_insts);
 
@@ -330,6 +330,13 @@ v3d_get_compiled_shader(struct v3d_context *v3d, struct v3d_key *key)
         return shader;
 }
 
+static void
+v3d_free_compiled_shader(struct v3d_compiled_shader *shader)
+{
+        pipe_resource_reference(&shader->resource, NULL);
+        ralloc_free(shader);
+}
+
 static void
 v3d_setup_shared_key(struct v3d_context *v3d, struct v3d_key *key,
                      struct v3d_texture_stateobj *texstate)
@@ -606,12 +613,11 @@ delete_from_cache_if_matches(struct hash_table *ht,
         if (key->shader_state == so) {
                 struct v3d_compiled_shader *shader = entry->data;
                 _mesa_hash_table_remove(ht, entry);
-                v3d_bo_unreference(&shader->bo);
 
                 if (shader == *last_compile)
                         *last_compile = NULL;
 
-                ralloc_free(shader);
+                v3d_free_compiled_shader(shader);
         }
 }
 
@@ -677,15 +683,13 @@ v3d_program_fini(struct pipe_context *pctx)
 
         hash_table_foreach(v3d->fs_cache, entry) {
                 struct v3d_compiled_shader *shader = entry->data;
-                v3d_bo_unreference(&shader->bo);
-                ralloc_free(shader);
+                v3d_free_compiled_shader(shader);
                 _mesa_hash_table_remove(v3d->fs_cache, entry);
         }
 
         hash_table_foreach(v3d->vs_cache, entry) {
                 struct v3d_compiled_shader *shader = entry->data;
-                v3d_bo_unreference(&shader->bo);
-                ralloc_free(shader);
+                v3d_free_compiled_shader(shader);
                 _mesa_hash_table_remove(v3d->vs_cache, entry);
         }
 
index 7db1285f11d452f10ba654f13d5419e71770859b..2016db7fa81476ba36f3fa4aedccf5ec2d633f27 100644 (file)
@@ -192,11 +192,14 @@ v3d_emit_gl_shader_state(struct v3d_context *v3d,
                 shader.fragment_shader_propagate_nans = true;
 
                 shader.coordinate_shader_code_address =
-                        cl_address(v3d->prog.cs->bo, 0);
+                        cl_address(v3d_resource(v3d->prog.cs->resource)->bo,
+                                   v3d->prog.cs->offset);
                 shader.vertex_shader_code_address =
-                        cl_address(v3d->prog.vs->bo, 0);
+                        cl_address(v3d_resource(v3d->prog.vs->resource)->bo,
+                                   v3d->prog.vs->offset);
                 shader.fragment_shader_code_address =
-                        cl_address(v3d->prog.fs->bo, 0);
+                        cl_address(v3d_resource(v3d->prog.fs->resource)->bo,
+                                   v3d->prog.fs->offset);
 
                 /* XXX: Use combined input/output size flag in the common
                  * case.