freedreno: Upload gallium constbufs as needed when referenced as a UBO.
authorEric Anholt <eric@anholt.net>
Mon, 1 Jun 2020 18:53:22 +0000 (11:53 -0700)
committerEric Anholt <eric@anholt.net>
Fri, 5 Jun 2020 20:36:29 +0000 (13:36 -0700)
For now we never ask to set up UBO 0 as a real UBO, so this doesn't
trigger, but it gets us ready for handling the case where UBO 0 is too big
to be push constants in the HW.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5273>

src/gallium/drivers/freedreno/a6xx/fd6_const.c
src/gallium/drivers/freedreno/ir3/ir3_const.h

index 1d24d8aafe25e1837fcb9b8a82fd7a09ef090d8a..5b7f7518ab709efd1e3d1b1d2bce10ebd970cf9e 100644 (file)
@@ -228,7 +228,7 @@ emit_tess_consts(struct fd6_emit *emit)
 }
 
 static void
-fd6_emit_ubos(const struct ir3_shader_variant *v,
+fd6_emit_ubos(struct fd_context *ctx, const struct ir3_shader_variant *v,
                struct fd_ringbuffer *ring, struct fd_constbuf_stateobj *constbuf)
 {
        if (!v->shader->num_ubos)
@@ -250,6 +250,21 @@ fd6_emit_ubos(const struct ir3_shader_variant *v,
                 * and UBO load indices decremented by one.
                 */
                struct pipe_constant_buffer *cb = &constbuf->cb[i + 1];
+
+               /* If we have user pointers (constbuf 0, aka GL uniforms), upload them
+                * to a buffer now, and save it in the constbuf so that we don't have
+                * to reupload until they get changed.
+                */
+               if (cb->user_buffer) {
+                       struct pipe_context *pctx = &ctx->base;
+                       u_upload_data(pctx->stream_uploader, 0,
+                                       cb->buffer_size,
+                                       64,
+                                       cb->user_buffer,
+                                       &cb->buffer_offset, &cb->buffer);
+                       cb->user_buffer = NULL;
+               }
+
                if (cb->buffer) {
                        int size_vec4s = DIV_ROUND_UP(cb->buffer_size, 16);
                        OUT_RELOC(ring, fd_resource(cb->buffer)->bo,
@@ -289,7 +304,7 @@ emit_user_consts(struct fd6_emit *emit)
                if (!variants[i])
                        continue;
                ir3_emit_user_consts(ctx->screen, variants[i], constobj, &ctx->constbuf[types[i]]);
-               fd6_emit_ubos(variants[i], constobj, &ctx->constbuf[types[i]]);
+               fd6_emit_ubos(ctx, variants[i], constobj, &ctx->constbuf[types[i]]);
        }
 
        fd6_emit_take_group(emit, constobj, FD6_GROUP_CONST, ENABLE_ALL);
@@ -336,7 +351,7 @@ fd6_emit_cs_consts(const struct ir3_shader_variant *v, struct fd_ringbuffer *rin
                struct fd_context *ctx, const struct pipe_grid_info *info)
 {
        ir3_emit_cs_consts(v, ring, ctx, info);
-       fd6_emit_ubos(v, ring, &ctx->constbuf[PIPE_SHADER_COMPUTE]);
+       fd6_emit_ubos(ctx, v, ring, &ctx->constbuf[PIPE_SHADER_COMPUTE]);
 }
 
 void
index 64cd39684ad3045ee6a4246c5cad3287dee10464..6ed49baa8faf6e4ac29015224b9052831e41e14f 100644 (file)
@@ -131,7 +131,7 @@ ir3_emit_user_consts(struct fd_screen *screen, const struct ir3_shader_variant *
 }
 
 static inline void
-ir3_emit_ubos(struct fd_screen *screen, const struct ir3_shader_variant *v,
+ir3_emit_ubos(struct fd_context *ctx, const struct ir3_shader_variant *v,
                struct fd_ringbuffer *ring, struct fd_constbuf_stateobj *constbuf)
 {
        const struct ir3_const_state *const_state = &v->shader->const_state;
@@ -144,7 +144,20 @@ ir3_emit_ubos(struct fd_screen *screen, const struct ir3_shader_variant *v,
                for (uint32_t i = 0; i < params; i++) {
                        const uint32_t index = i + 1;   /* UBOs start at index 1 */
                        struct pipe_constant_buffer *cb = &constbuf->cb[index];
-                       assert(!cb->user_buffer);
+
+                       /* If we have user pointers (constbuf 0, aka GL uniforms), upload
+                        * them to a buffer now, and save it in the constbuf so that we
+                        * don't have to reupload until they get changed.
+                        */
+                       if (cb->user_buffer) {
+                               struct pipe_context *pctx = &ctx->base;
+                               u_upload_data(pctx->stream_uploader, 0,
+                                               cb->buffer_size,
+                                               64,
+                                               cb->user_buffer,
+                                               &cb->buffer_offset, &cb->buffer);
+                               cb->user_buffer = NULL;
+                       }
 
                        if ((constbuf->enabled_mask & (1 << index)) && cb->buffer) {
                                offsets[i] = cb->buffer_offset;
@@ -391,7 +404,7 @@ emit_common_consts(const struct ir3_shader_variant *v, struct fd_ringbuffer *rin
                ring_wfi(ctx->batch, ring);
 
                ir3_emit_user_consts(ctx->screen, v, ring, constbuf);
-               ir3_emit_ubos(ctx->screen, v, ring, constbuf);
+               ir3_emit_ubos(ctx, v, ring, constbuf);
                if (shader_dirty)
                        ir3_emit_immediates(ctx->screen, v, ring);
        }