freedreno: Split ir3_const's user buffer and indirect upload APIs.
authorEric Anholt <eric@anholt.net>
Thu, 9 Jul 2020 23:57:29 +0000 (16:57 -0700)
committerMarge Bot <eric+marge@anholt.net>
Wed, 5 Aug 2020 23:06:55 +0000 (23:06 +0000)
They're almost entirely split by whether you're uploading user buffer or
from a BO.  While I'm rewriting the API, drop the emit_const ->
fdN_emit_const wrapper in favor of a #define before the header and a
little helper for the asserts.

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

src/gallium/drivers/freedreno/a3xx/fd3_emit.c
src/gallium/drivers/freedreno/a4xx/fd4_emit.c
src/gallium/drivers/freedreno/a5xx/fd5_emit.c
src/gallium/drivers/freedreno/a6xx/fd6_const.c
src/gallium/drivers/freedreno/ir3/ir3_const.h

index 09817c092e52cf3583dee82e8542dbb20a1d7dd3..5d5be9d39e8dc5c9679593122d2cf28907812bf4 100644 (file)
@@ -43,6 +43,8 @@
 #include "fd3_format.h"
 #include "fd3_zsa.h"
 
+#define emit_const_user fd3_emit_const_user
+#define emit_const_bo fd3_emit_const_bo
 #include "ir3_const.h"
 
 static const enum adreno_state_block sb[] = {
@@ -55,41 +57,37 @@ static const enum adreno_state_block sb[] = {
  * sizedwords:     size of const value buffer
  */
 static void
-fd3_emit_const(struct fd_ringbuffer *ring, gl_shader_stage type,
-               uint32_t regid, uint32_t offset, uint32_t sizedwords,
-               const uint32_t *dwords, struct pipe_resource *prsc)
+fd3_emit_const_user(struct fd_ringbuffer *ring,
+               const struct ir3_shader_variant *v,
+               uint32_t regid, uint32_t sizedwords, const uint32_t *dwords)
 {
-       uint32_t i, sz;
-       enum adreno_state_src src;
-
-       debug_assert((regid % 4) == 0);
-       debug_assert((sizedwords % 4) == 0);
-
-       if (prsc) {
-               sz = 0;
-               src = SS_INDIRECT;
-       } else {
-               sz = sizedwords;
-               src = SS_DIRECT;
-       }
+       emit_const_asserts(ring, v, regid, sizedwords);
 
-       OUT_PKT3(ring, CP_LOAD_STATE, 2 + sz);
+       OUT_PKT3(ring, CP_LOAD_STATE, 2 + sizedwords);
        OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(regid/2) |
-                       CP_LOAD_STATE_0_STATE_SRC(src) |
-                       CP_LOAD_STATE_0_STATE_BLOCK(sb[type]) |
+                       CP_LOAD_STATE_0_STATE_SRC(SS_DIRECT) |
+                       CP_LOAD_STATE_0_STATE_BLOCK(sb[v->type]) |
                        CP_LOAD_STATE_0_NUM_UNIT(sizedwords/2));
-       if (prsc) {
-               struct fd_bo *bo = fd_resource(prsc)->bo;
-               OUT_RELOC(ring, bo, offset,
-                               CP_LOAD_STATE_1_STATE_TYPE(ST_CONSTANTS), 0);
-       } else {
-               OUT_RING(ring, CP_LOAD_STATE_1_EXT_SRC_ADDR(0) |
-                               CP_LOAD_STATE_1_STATE_TYPE(ST_CONSTANTS));
-               dwords = (uint32_t *)&((uint8_t *)dwords)[offset];
-       }
-       for (i = 0; i < sz; i++) {
+       OUT_RING(ring, CP_LOAD_STATE_1_EXT_SRC_ADDR(0) |
+                       CP_LOAD_STATE_1_STATE_TYPE(ST_CONSTANTS));
+       for (int i = 0; i < sizedwords; i++)
                OUT_RING(ring, dwords[i]);
-       }
+}
+
+static void
+fd3_emit_const_bo(struct fd_ringbuffer *ring, const struct ir3_shader_variant *v,
+               uint32_t regid, uint32_t offset, uint32_t sizedwords,
+               struct fd_bo *bo)
+{
+       emit_const_asserts(ring, v, regid, sizedwords);
+
+       OUT_PKT3(ring, CP_LOAD_STATE, 2);
+       OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(regid/2) |
+                       CP_LOAD_STATE_0_STATE_SRC(SS_INDIRECT) |
+                       CP_LOAD_STATE_0_STATE_BLOCK(sb[v->type]) |
+                       CP_LOAD_STATE_0_NUM_UNIT(sizedwords/2));
+       OUT_RELOC(ring, bo, offset,
+                       CP_LOAD_STATE_1_STATE_TYPE(ST_CONSTANTS), 0);
 }
 
 static void
@@ -127,18 +125,6 @@ is_stateobj(struct fd_ringbuffer *ring)
        return false;
 }
 
-void
-emit_const(struct fd_ringbuffer *ring,
-               const struct ir3_shader_variant *v, uint32_t dst_offset,
-               uint32_t offset, uint32_t size, const void *user_buffer,
-               struct pipe_resource *buffer)
-{
-       /* TODO inline this */
-       assert(dst_offset + size <= v->constlen * 4);
-       fd3_emit_const(ring, v->type, dst_offset,
-                       offset, size, user_buffer, buffer);
-}
-
 static void
 emit_const_ptrs(struct fd_ringbuffer *ring,
                const struct ir3_shader_variant *v, uint32_t dst_offset,
index 9e9f80b43b0ed6b55e34fcd41ea8cbb5260fc038..603a81f753608032b31c6a80344213cc63b86a05 100644 (file)
@@ -43,6 +43,8 @@
 #include "fd4_format.h"
 #include "fd4_zsa.h"
 
+#define emit_const_user fd4_emit_const_user
+#define emit_const_bo fd4_emit_const_bo
 #include "ir3_const.h"
 
 /* regid:          base const register
  * sizedwords:     size of const value buffer
  */
 static void
-fd4_emit_const(struct fd_ringbuffer *ring, gl_shader_stage type,
-               uint32_t regid, uint32_t offset, uint32_t sizedwords,
-               const uint32_t *dwords, struct pipe_resource *prsc)
+fd4_emit_const_user(struct fd_ringbuffer *ring,
+               const struct ir3_shader_variant *v, uint32_t regid, uint32_t sizedwords,
+               const uint32_t *dwords)
 {
-       uint32_t i, sz;
-       enum a4xx_state_src src;
+       emit_const_asserts(ring, v, regid, sizedwords);
 
-       debug_assert((regid % 4) == 0);
-       debug_assert((sizedwords % 4) == 0);
+       OUT_PKT3(ring, CP_LOAD_STATE4, 2 + sizedwords);
+       OUT_RING(ring, CP_LOAD_STATE4_0_DST_OFF(regid/4) |
+                       CP_LOAD_STATE4_0_STATE_SRC(SS4_DIRECT) |
+                       CP_LOAD_STATE4_0_STATE_BLOCK(fd4_stage2shadersb(v->type)) |
+                       CP_LOAD_STATE4_0_NUM_UNIT(sizedwords/4));
+       OUT_RING(ring, CP_LOAD_STATE4_1_EXT_SRC_ADDR(0) |
+                       CP_LOAD_STATE4_1_STATE_TYPE(ST4_CONSTANTS));
+       for (int i = 0; i < sizedwords; i++)
+               OUT_RING(ring, dwords[i]);
+}
 
-       if (prsc) {
-               sz = 0;
-               src = SS4_INDIRECT;
-       } else {
-               sz = sizedwords;
-               src = SS4_DIRECT;
-       }
+static void
+fd4_emit_const_bo(struct fd_ringbuffer *ring, const struct ir3_shader_variant *v,
+               uint32_t regid, uint32_t offset, uint32_t sizedwords,
+               struct fd_bo *bo)
+{
+       emit_const_asserts(ring, v, regid, sizedwords);
 
-       OUT_PKT3(ring, CP_LOAD_STATE4, 2 + sz);
+       OUT_PKT3(ring, CP_LOAD_STATE4, 2);
        OUT_RING(ring, CP_LOAD_STATE4_0_DST_OFF(regid/4) |
-                       CP_LOAD_STATE4_0_STATE_SRC(src) |
-                       CP_LOAD_STATE4_0_STATE_BLOCK(fd4_stage2shadersb(type)) |
+                       CP_LOAD_STATE4_0_STATE_SRC(SS4_INDIRECT) |
+                       CP_LOAD_STATE4_0_STATE_BLOCK(fd4_stage2shadersb(v->type)) |
                        CP_LOAD_STATE4_0_NUM_UNIT(sizedwords/4));
-       if (prsc) {
-               struct fd_bo *bo = fd_resource(prsc)->bo;
-               OUT_RELOC(ring, bo, offset,
-                               CP_LOAD_STATE4_1_STATE_TYPE(ST4_CONSTANTS), 0);
-       } else {
-               OUT_RING(ring, CP_LOAD_STATE4_1_EXT_SRC_ADDR(0) |
-                               CP_LOAD_STATE4_1_STATE_TYPE(ST4_CONSTANTS));
-               dwords = (uint32_t *)&((uint8_t *)dwords)[offset];
-       }
-       for (i = 0; i < sz; i++) {
-               OUT_RING(ring, dwords[i]);
-       }
+       OUT_RELOC(ring, bo, offset,
+                       CP_LOAD_STATE4_1_STATE_TYPE(ST4_CONSTANTS), 0);
 }
 
 static void
@@ -122,18 +120,6 @@ is_stateobj(struct fd_ringbuffer *ring)
        return false;
 }
 
-void
-emit_const(struct fd_ringbuffer *ring,
-               const struct ir3_shader_variant *v, uint32_t dst_offset,
-               uint32_t offset, uint32_t size, const void *user_buffer,
-               struct pipe_resource *buffer)
-{
-       /* TODO inline this */
-       assert(dst_offset + size <= v->constlen * 4);
-       fd4_emit_const(ring, v->type, dst_offset,
-                       offset, size, user_buffer, buffer);
-}
-
 static void
 emit_const_ptrs(struct fd_ringbuffer *ring,
                const struct ir3_shader_variant *v, uint32_t dst_offset,
index 62bcfd1ca18b05940abcbc87f523960882cce142..1a1037c3a0ee5616f3a23d9aad15197f2bafad8f 100644 (file)
@@ -46,6 +46,8 @@
 #include "fd5_format.h"
 #include "fd5_zsa.h"
 
+#define emit_const_user fd5_emit_const_user
+#define emit_const_bo fd5_emit_const_bo
 #include "ir3_const.h"
 
 /* regid:          base const register
  * sizedwords:     size of const value buffer
  */
 static void
-fd5_emit_const(struct fd_ringbuffer *ring, gl_shader_stage type,
-               uint32_t regid, uint32_t offset, uint32_t sizedwords,
-               const uint32_t *dwords, struct pipe_resource *prsc)
+fd5_emit_const_user(struct fd_ringbuffer *ring,
+               const struct ir3_shader_variant *v, uint32_t regid, uint32_t sizedwords,
+               const uint32_t *dwords)
 {
-       uint32_t i, sz;
-       enum a4xx_state_src src;
+       emit_const_asserts(ring, v, regid, sizedwords);
 
-       debug_assert((regid % 4) == 0);
-       debug_assert((sizedwords % 4) == 0);
+       OUT_PKT7(ring, CP_LOAD_STATE4, 3 + sizedwords);
+       OUT_RING(ring, CP_LOAD_STATE4_0_DST_OFF(regid/4) |
+                       CP_LOAD_STATE4_0_STATE_SRC(SS4_DIRECT) |
+                       CP_LOAD_STATE4_0_STATE_BLOCK(fd4_stage2shadersb(v->type)) |
+                       CP_LOAD_STATE4_0_NUM_UNIT(sizedwords/4));
+       OUT_RING(ring, CP_LOAD_STATE4_1_EXT_SRC_ADDR(0) |
+                       CP_LOAD_STATE4_1_STATE_TYPE(ST4_CONSTANTS));
+       OUT_RING(ring, CP_LOAD_STATE4_2_EXT_SRC_ADDR_HI(0));
+       for (int i = 0; i < sizedwords; i++)
+               OUT_RING(ring, ((uint32_t *)dwords)[i]);
+}
 
-       if (prsc) {
-               sz = 0;
-               src = SS4_INDIRECT;
-       } else {
-               sz = sizedwords;
-               src = SS4_DIRECT;
-       }
+static void
+fd5_emit_const_bo(struct fd_ringbuffer *ring, const struct ir3_shader_variant *v,
+               uint32_t regid, uint32_t offset, uint32_t sizedwords, struct fd_bo *bo)
+{
+       emit_const_asserts(ring, v, regid, sizedwords);
 
-       OUT_PKT7(ring, CP_LOAD_STATE4, 3 + sz);
+       OUT_PKT7(ring, CP_LOAD_STATE4, 3);
        OUT_RING(ring, CP_LOAD_STATE4_0_DST_OFF(regid/4) |
-                       CP_LOAD_STATE4_0_STATE_SRC(src) |
-                       CP_LOAD_STATE4_0_STATE_BLOCK(fd4_stage2shadersb(type)) |
+                       CP_LOAD_STATE4_0_STATE_SRC(SS4_INDIRECT) |
+                       CP_LOAD_STATE4_0_STATE_BLOCK(fd4_stage2shadersb(v->type)) |
                        CP_LOAD_STATE4_0_NUM_UNIT(sizedwords/4));
-       if (prsc) {
-               struct fd_bo *bo = fd_resource(prsc)->bo;
-               OUT_RELOC(ring, bo, offset,
-                               CP_LOAD_STATE4_1_STATE_TYPE(ST4_CONSTANTS), 0);
-       } else {
-               OUT_RING(ring, CP_LOAD_STATE4_1_EXT_SRC_ADDR(0) |
-                               CP_LOAD_STATE4_1_STATE_TYPE(ST4_CONSTANTS));
-               OUT_RING(ring, CP_LOAD_STATE4_2_EXT_SRC_ADDR_HI(0));
-               dwords = (uint32_t *)&((uint8_t *)dwords)[offset];
-       }
-       for (i = 0; i < sz; i++) {
-               OUT_RING(ring, dwords[i]);
-       }
+       OUT_RELOC(ring, bo, offset,
+                       CP_LOAD_STATE4_1_STATE_TYPE(ST4_CONSTANTS), 0);
 }
 
 static void
@@ -130,18 +127,6 @@ is_stateobj(struct fd_ringbuffer *ring)
        return false;
 }
 
-void
-emit_const(struct fd_ringbuffer *ring,
-               const struct ir3_shader_variant *v, uint32_t dst_offset,
-               uint32_t offset, uint32_t size, const void *user_buffer,
-               struct pipe_resource *buffer)
-{
-       /* TODO inline this */
-       assert(dst_offset + size <= v->constlen * 4);
-       fd5_emit_const(ring, v->type, dst_offset,
-                       offset, size, user_buffer, buffer);
-}
-
 static void
 emit_const_ptrs(struct fd_ringbuffer *ring,
                const struct ir3_shader_variant *v, uint32_t dst_offset,
index ecd81f5aff295a130ce6e60404399841550dac13..419a22d070805f7fc59a76d03ee131454f4c4637 100644 (file)
 #include "fd6_const.h"
 #include "fd6_pack.h"
 
+#define emit_const_user fd6_emit_const_user
+#define emit_const_bo fd6_emit_const_bo
 #include "ir3_const.h"
 
 /* regid:          base const register
  * prsc or dwords: buffer containing constant values
  * sizedwords:     size of const value buffer
  */
-static void
-fd6_emit_const(struct fd_ringbuffer *ring, gl_shader_stage type,
-               uint32_t regid, uint32_t offset, uint32_t sizedwords,
-               const uint32_t *dwords, struct pipe_resource *prsc)
+void
+fd6_emit_const_user(struct fd_ringbuffer *ring,
+               const struct ir3_shader_variant *v, uint32_t regid,
+               uint32_t sizedwords, const uint32_t *dwords)
 {
-       if (prsc) {
-               struct fd_bo *bo = fd_resource(prsc)->bo;
-
-               if (fd6_geom_stage(type)) {
-                       OUT_PKT(ring, CP_LOAD_STATE6_GEOM,
-                                       CP_LOAD_STATE6_0(
-                                                       .dst_off     = regid/4,
-                                                       .state_type  = ST6_CONSTANTS,
-                                                       .state_src   = SS6_INDIRECT,
-                                                       .state_block = fd6_stage2shadersb(type),
-                                                       .num_unit    = DIV_ROUND_UP(sizedwords, 4)
-                                               ),
-                                       CP_LOAD_STATE6_EXT_SRC_ADDR(
-                                                       .bo          = bo,
-                                                       .bo_offset   = offset
-                                               )
-                               );
-               } else {
-                       OUT_PKT(ring, CP_LOAD_STATE6_FRAG,
-                                       CP_LOAD_STATE6_0(
-                                                       .dst_off     = regid/4,
-                                                       .state_type  = ST6_CONSTANTS,
-                                                       .state_src   = SS6_INDIRECT,
-                                                       .state_block = fd6_stage2shadersb(type),
-                                                       .num_unit    = DIV_ROUND_UP(sizedwords, 4)
-                                               ),
-                                       CP_LOAD_STATE6_EXT_SRC_ADDR(
-                                                       .bo          = bo,
-                                                       .bo_offset   = offset
-                                               )
-                               );
-               }
+       emit_const_asserts(ring, v, regid, sizedwords);
+
+       /* NOTE we cheat a bit here, since we know mesa is aligning
+        * the size of the user buffer to 16 bytes.  And we want to
+        * cut cycles in a hot path.
+        */
+       uint32_t align_sz = align(sizedwords, 4);
+
+       if (fd6_geom_stage(v->type)) {
+               OUT_PKTBUF(ring, CP_LOAD_STATE6_GEOM, dwords, align_sz,
+                               CP_LOAD_STATE6_0(
+                                       .dst_off     = regid/4,
+                                       .state_type  = ST6_CONSTANTS,
+                                       .state_src   = SS6_DIRECT,
+                                       .state_block = fd6_stage2shadersb(v->type),
+                                       .num_unit    = DIV_ROUND_UP(sizedwords, 4)
+                                       ),
+                               CP_LOAD_STATE6_1(),
+                               CP_LOAD_STATE6_2()
+                       );
        } else {
-               /* NOTE we cheat a bit here, since we know mesa is aligning
-                * the size of the user buffer to 16 bytes.  And we want to
-                * cut cycles in a hot path.
-                */
-               uint32_t align_sz = align(sizedwords, 4);
-               dwords = (uint32_t *)&((uint8_t *)dwords)[offset];
-
-               if (fd6_geom_stage(type)) {
-                       OUT_PKTBUF(ring, CP_LOAD_STATE6_GEOM, dwords, align_sz,
-                                       CP_LOAD_STATE6_0(
-                                                       .dst_off     = regid/4,
-                                                       .state_type  = ST6_CONSTANTS,
-                                                       .state_src   = SS6_DIRECT,
-                                                       .state_block = fd6_stage2shadersb(type),
-                                                       .num_unit    = DIV_ROUND_UP(sizedwords, 4)
-                                               ),
-                                       CP_LOAD_STATE6_1(),
-                                       CP_LOAD_STATE6_2()
-                               );
-               } else {
-                       OUT_PKTBUF(ring, CP_LOAD_STATE6_FRAG, dwords, align_sz,
-                                       CP_LOAD_STATE6_0(
-                                                       .dst_off     = regid/4,
-                                                       .state_type  = ST6_CONSTANTS,
-                                                       .state_src   = SS6_DIRECT,
-                                                       .state_block = fd6_stage2shadersb(type),
-                                                       .num_unit    = DIV_ROUND_UP(sizedwords, 4)
-                                               ),
-                                       CP_LOAD_STATE6_1(),
-                                       CP_LOAD_STATE6_2()
-                               );
-               }
+               OUT_PKTBUF(ring, CP_LOAD_STATE6_FRAG, dwords, align_sz,
+                               CP_LOAD_STATE6_0(
+                                       .dst_off     = regid/4,
+                                       .state_type  = ST6_CONSTANTS,
+                                       .state_src   = SS6_DIRECT,
+                                       .state_block = fd6_stage2shadersb(v->type),
+                                       .num_unit    = DIV_ROUND_UP(sizedwords, 4)
+                                       ),
+                               CP_LOAD_STATE6_1(),
+                               CP_LOAD_STATE6_2()
+                       );
+       }
+}
+void
+fd6_emit_const_bo(struct fd_ringbuffer *ring,
+               const struct ir3_shader_variant *v, uint32_t regid,
+               uint32_t offset, uint32_t sizedwords, struct fd_bo *bo)
+{
+       emit_const_asserts(ring, v, regid, sizedwords);
+
+       if (fd6_geom_stage(v->type)) {
+               OUT_PKT(ring, CP_LOAD_STATE6_GEOM,
+                               CP_LOAD_STATE6_0(
+                                       .dst_off     = regid/4,
+                                       .state_type  = ST6_CONSTANTS,
+                                       .state_src   = SS6_INDIRECT,
+                                       .state_block = fd6_stage2shadersb(v->type),
+                                       .num_unit    = DIV_ROUND_UP(sizedwords, 4)
+                                       ),
+                               CP_LOAD_STATE6_EXT_SRC_ADDR(
+                                       .bo          = bo,
+                                       .bo_offset   = offset
+                                       )
+                       );
+       } else {
+               OUT_PKT(ring, CP_LOAD_STATE6_FRAG,
+                               CP_LOAD_STATE6_0(
+                                       .dst_off     = regid/4,
+                                       .state_type  = ST6_CONSTANTS,
+                                       .state_src   = SS6_INDIRECT,
+                                       .state_block = fd6_stage2shadersb(v->type),
+                                       .num_unit    = DIV_ROUND_UP(sizedwords, 4)
+                                       ),
+                               CP_LOAD_STATE6_EXT_SRC_ADDR(
+                                       .bo          = bo,
+                                       .bo_offset   = offset
+                                       )
+                       );
        }
 }
 
@@ -110,18 +116,6 @@ is_stateobj(struct fd_ringbuffer *ring)
        return true;
 }
 
-void
-emit_const(struct fd_ringbuffer *ring,
-               const struct ir3_shader_variant *v, uint32_t dst_offset,
-               uint32_t offset, uint32_t size, const void *user_buffer,
-               struct pipe_resource *buffer)
-{
-       /* TODO inline this */
-       assert(dst_offset + size <= v->constlen * 4);
-       fd6_emit_const(ring, v->type, dst_offset,
-                       offset, size, user_buffer, buffer);
-}
-
 static void
 emit_const_ptrs(struct fd_ringbuffer *ring,
                const struct ir3_shader_variant *v, uint32_t dst_offset,
@@ -155,7 +149,7 @@ emit_stage_tess_consts(struct fd_ringbuffer *ring, struct ir3_shader_variant *v,
        const unsigned regid = const_state->offsets.primitive_param;
        int size = MIN2(1 + regid, v->constlen) - regid;
        if (size > 0)
-               fd6_emit_const(ring, v->type, regid * 4, 0, num_params, params, NULL);
+               fd6_emit_const_user(ring, v, regid * 4, num_params, params);
 }
 
 static void
index a17f3bc8a4f986459c270c2980b345f60c41acb8..f840e5ee1d7a98da59a7695707da74638b787aa7 100644 (file)
 
 static bool is_stateobj(struct fd_ringbuffer *ring);
 
-static void emit_const(struct fd_ringbuffer *ring,
-               const struct ir3_shader_variant *v, uint32_t dst_offset,
+static void emit_const_user(struct fd_ringbuffer *ring,
+               const struct ir3_shader_variant *v, uint32_t regid,
+               uint32_t size, const uint32_t *user_buffer);
+
+static void emit_const_bo(struct fd_ringbuffer *ring,
+               const struct ir3_shader_variant *v, uint32_t regid,
+               uint32_t offset, uint32_t size,
+               struct fd_bo *bo);
+
+static void emit_const_prsc(struct fd_ringbuffer *ring,
+               const struct ir3_shader_variant *v, uint32_t regid,
                uint32_t offset, uint32_t size,
-               const void *user_buffer, struct pipe_resource *buffer);
+               struct pipe_resource *buffer)
+{
+       struct fd_resource *rsc = fd_resource(buffer);
+       emit_const_bo(ring, v, regid, offset, size, rsc->bo);
+}
 
 static void emit_const_ptrs(struct fd_ringbuffer *ring,
                const struct ir3_shader_variant *v, uint32_t dst_offset,
                uint32_t num, struct pipe_resource **prscs, uint32_t *offsets);
 
+static void
+emit_const_asserts(struct fd_ringbuffer *ring,
+               const struct ir3_shader_variant *v,
+               uint32_t regid, uint32_t sizedwords)
+{
+       assert((regid % 4) == 0);
+       assert((sizedwords % 4) == 0);
+       assert(regid + sizedwords <= v->constlen * 4);
+}
 
 static void
 ring_wfi(struct fd_batch *batch, struct fd_ringbuffer *ring)
@@ -125,8 +147,13 @@ ir3_emit_user_consts(struct fd_screen *screen, const struct ir3_shader_variant *
                debug_assert((size % 16) == 0);
                debug_assert((offset % 16) == 0);
 
-               emit_const(ring, v, state->range[i].offset / 4,
-                               offset, size / 4, cb->user_buffer, cb->buffer);
+               if (cb->user_buffer) {
+                       emit_const_user(ring, v, state->range[i].offset / 4,
+                               size / 4, cb->user_buffer + state->range[i].start);
+               } else {
+                       emit_const_prsc(ring, v, state->range[i].offset / 4,
+                                       offset, size / 4, cb->buffer);
+               }
        }
 }
 
@@ -196,7 +223,7 @@ ir3_emit_ssbo_sizes(struct fd_screen *screen, const struct ir3_shader_variant *v
                        sizes[off] = sb->sb[index].buffer_size;
                }
 
-               emit_const(ring, v, offset * 4, 0, ARRAY_SIZE(sizes), sizes, NULL);
+               emit_const_user(ring, v, offset * 4, ARRAY_SIZE(sizes), sizes);
        }
 }
 
@@ -249,7 +276,7 @@ ir3_emit_image_dims(struct fd_screen *screen, const struct ir3_shader_variant *v
                }
                uint32_t size = MIN2(ARRAY_SIZE(dims), v->constlen * 4 - offset * 4);
 
-               emit_const(ring, v, offset * 4, 0, size, dims, NULL);
+               emit_const_user(ring, v, offset * 4, size, dims);
        }
 }
 
@@ -271,7 +298,7 @@ ir3_emit_immediates(struct fd_screen *screen, const struct ir3_shader_variant *v
        size *= 4;
 
        if (size > 0)
-               emit_const(ring, v, base, 0, size, const_state->immediates, NULL);
+               emit_const_user(ring, v, base, size, const_state->immediates);
 }
 
 static inline void
@@ -297,7 +324,7 @@ ir3_emit_link_map(struct fd_screen *screen,
        size *= 4;
 
        if (size > 0)
-               emit_const(ring, v, base, 0, size, patch_locs, NULL);
+               emit_const_user(ring, v, base, size, patch_locs);
 }
 
 /* emit stream-out buffers: */
@@ -505,13 +532,13 @@ ir3_emit_vs_driver_params(const struct ir3_shader_variant *v,
                ctx->screen->mem_to_mem(ring, vertex_params_rsc, 0,
                                indirect->buffer, src_off, 1);
 
-               emit_const(ring, v, offset * 4, 0,
-                               vertex_params_size, NULL, vertex_params_rsc);
+               emit_const_prsc(ring, v, offset * 4, 0,
+                               vertex_params_size, vertex_params_rsc);
 
                pipe_resource_reference(&vertex_params_rsc, NULL);
        } else {
-               emit_const(ring, v, offset * 4, 0,
-                               vertex_params_size, vertex_params, NULL);
+               emit_const_user(ring, v, offset * 4,
+                               vertex_params_size, vertex_params);
        }
 
        /* if needed, emit stream-out buffer addresses: */
@@ -584,7 +611,7 @@ ir3_emit_cs_consts(const struct ir3_shader_variant *v, struct fd_ringbuffer *rin
                                indirect_offset = info->indirect_offset;
                        }
 
-                       emit_const(ring, v, offset * 4, indirect_offset, 4, NULL, indirect);
+                       emit_const_prsc(ring, v, offset * 4, indirect_offset, 4, indirect);
 
                        pipe_resource_reference(&indirect, NULL);
                } else {
@@ -599,7 +626,7 @@ ir3_emit_cs_consts(const struct ir3_shader_variant *v, struct fd_ringbuffer *rin
                        uint32_t size = MIN2(const_state->num_driver_params,
                                        v->constlen * 4 - offset * 4);
 
-                       emit_const(ring, v, offset * 4, 0, size, compute_params, NULL);
+                       emit_const_user(ring, v, offset * 4, size, compute_params);
                }
        }
 }