lima: fix vertex shader uniform buffer size
authorErico Nunes <nunes.erico@gmail.com>
Wed, 9 Sep 2020 22:02:38 +0000 (00:02 +0200)
committerErico Nunes <nunes.erico@gmail.com>
Sat, 19 Sep 2020 09:53:28 +0000 (11:53 +0200)
In some cases when switching shader programs, mesa does not switch the
currently set pipe_constant_buffer, which keeps pointing to the one
previously set.
If the two shader programs have a different number of uniforms, the size
of the constant buffer may be different and this needs to be considered
while generating the next draw command.
This patch fixes the uniform buffer creation in the lima vertex shader
command to avoid an out of bounds memcpy due to a previously set
pipe_constant_buffer.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6701>

src/gallium/drivers/lima/ir/gp/nir.c
src/gallium/drivers/lima/lima_context.h
src/gallium/drivers/lima/lima_draw.c

index 33fa35c..5143f2b 100644 (file)
@@ -456,7 +456,7 @@ bool gpir_compile_nir(struct lima_vs_shader_state *prog, struct nir_shader *nir,
       return false;
 
    comp->constant_base = nir->num_uniforms;
-   prog->uniform_pending_offset = nir->num_uniforms * 16;
+   prog->uniform_size = nir->num_uniforms * 16;
    prog->gl_pos_idx = 0;
    prog->point_size_idx = -1;
 
index f74554e..c8f4cf6 100644 (file)
@@ -66,11 +66,7 @@ struct lima_vs_shader_state {
    int shader_size;
    int prefetch;
 
-   /* pipe_constant_buffer.size is aligned with some pad bytes,
-    * so record here for the real start place of gpir lowered
-    * uniforms */
-   int uniform_pending_offset;
-
+   int uniform_size;
    void *constant;
    int constant_size;
 
index 15474a0..469f18e 100644 (file)
@@ -255,6 +255,9 @@ lima_pipe_format_to_attrib_type(enum pipe_format format)
 static void
 lima_pack_vs_cmd(struct lima_context *ctx, const struct pipe_draw_info *info)
 {
+   struct lima_context_constant_buffer *ccb =
+      ctx->const_buffer + PIPE_SHADER_VERTEX;
+   struct lima_vs_shader_state *vs = ctx->vs;
    struct lima_job *job = lima_job_get(ctx);
 
    VS_CMD_BEGIN(&job->vs_cmd_array, 24);
@@ -263,11 +266,12 @@ lima_pack_vs_cmd(struct lima_context *ctx, const struct pipe_draw_info *info)
       VS_CMD_ARRAYS_SEMAPHORE_BEGIN_1();
       VS_CMD_ARRAYS_SEMAPHORE_BEGIN_2();
    }
+   int uniform_size = MIN2(vs->uniform_size, ccb->size);
 
-   int uniform_size = ctx->vs->uniform_pending_offset + ctx->vs->constant_size + 32;
+   int size = uniform_size + vs->constant_size + 32;
    VS_CMD_UNIFORMS_ADDRESS(
       lima_ctx_buff_va(ctx, lima_ctx_buff_gp_uniform),
-      align(uniform_size, 16));
+      align(size, 16));
 
    VS_CMD_SHADER_ADDRESS(ctx->vs->bo->va, ctx->vs->shader_size);
    VS_CMD_SHADER_INFO(ctx->vs->prefetch, ctx->vs->shader_size);
@@ -824,23 +828,24 @@ lima_update_gp_uniform(struct lima_context *ctx)
    struct lima_context_constant_buffer *ccb =
       ctx->const_buffer + PIPE_SHADER_VERTEX;
    struct lima_vs_shader_state *vs = ctx->vs;
+   int uniform_size = MIN2(vs->uniform_size, ccb->size);
 
-   int size = vs->uniform_pending_offset + vs->constant_size + 32;
+   int size = uniform_size + vs->constant_size + 32;
    void *vs_const_buff =
       lima_ctx_buff_alloc(ctx, lima_ctx_buff_gp_uniform, size);
 
    if (ccb->buffer)
-      memcpy(vs_const_buff, ccb->buffer, ccb->size);
+      memcpy(vs_const_buff, ccb->buffer, uniform_size);
 
-   memcpy(vs_const_buff + vs->uniform_pending_offset,
+   memcpy(vs_const_buff + uniform_size,
           ctx->viewport.transform.scale,
           sizeof(ctx->viewport.transform.scale));
-   memcpy(vs_const_buff + vs->uniform_pending_offset + 16,
+   memcpy(vs_const_buff + uniform_size + 16,
           ctx->viewport.transform.translate,
           sizeof(ctx->viewport.transform.translate));
 
    if (vs->constant)
-      memcpy(vs_const_buff + vs->uniform_pending_offset + 32,
+      memcpy(vs_const_buff + uniform_size + 32,
              vs->constant, vs->constant_size);
 
    struct lima_job *job = lima_job_get(ctx);