[virglrenderer-devel] [PATCH] vrend: add support for indirect draws.

Dave Airlie airlied at gmail.com
Tue Feb 13 06:10:04 UTC 2018


Oops, I accidentally pushed to master, and can't back it off. I've
left these two patches since I was happy with them, I've reverted the
partial gs5 hacks.

Apologies,
Dave.


On 13 February 2018 at 13:58, Dave Airlie <airlied at gmail.com> wrote:
> From: Dave Airlie <airlied at redhat.com>
>
> These are needed for ARB_draw_indirect and GL4.0
>
> This enables support and turns in the cap when
> support is present.
>
> This also enhances the draw packets to cover
> future features, it doesn't enable or show these
> yet, since other work is required in the shaders.
>
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> ---
>  src/gallium/include/pipe/p_state.h | 35 +++++++++++++++++++++++++++++++++++
>  src/virgl_protocol.h               | 12 ++++++++++++
>  src/vrend_decode.c                 | 20 ++++++++++++++++++--
>  src/vrend_renderer.c               | 36 +++++++++++++++++++++++++++++++++---
>  src/vrend_renderer.h               |  2 +-
>  5 files changed, 99 insertions(+), 6 deletions(-)
>
> diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h
> index 56934ed..a99b386 100644
> --- a/src/gallium/include/pipe/p_state.h
> +++ b/src/gallium/include/pipe/p_state.h
> @@ -526,6 +526,38 @@ struct pipe_index_buffer
>     const void *user_buffer;  /**< pointer to a user buffer if buffer == NULL */
>  };
>
> +struct pipe_draw_indirect_info
> +{
> +   unsigned offset; /**< must be 4 byte aligned */
> +   unsigned stride; /**< must be 4 byte aligned */
> +   unsigned draw_count; /**< number of indirect draws */
> +   unsigned indirect_draw_count_offset; /**< must be 4 byte aligned */
> +
> +   /* Indirect draw parameters resource is laid out as follows:
> +    *
> +    * if using indexed drawing:
> +    *  struct {
> +    *     uint32_t count;
> +    *     uint32_t instance_count;
> +    *     uint32_t start;
> +    *     int32_t index_bias;
> +    *     uint32_t start_instance;
> +    *  };
> +    * otherwise:
> +    *  struct {
> +    *     uint32_t count;
> +    *     uint32_t instance_count;
> +    *     uint32_t start;
> +    *     uint32_t start_instance;
> +    *  };
> +    */
> +   struct pipe_resource *buffer;
> +
> +   /* Indirect draw count resource: If not NULL, contains a 32-bit value which
> +    * is to be used as the real draw_count.
> +    */
> +   struct pipe_resource *indirect_draw_count;
> +};
>
>  /**
>   * Information to describe a draw_vbo call.
> @@ -533,6 +565,7 @@ struct pipe_index_buffer
>  struct pipe_draw_info
>  {
>     boolean indexed;  /**< use index buffer */
> +   ubyte vertices_per_patch; /**< the number of vertices per patch */
>
>     unsigned mode;  /**< the mode of the primitive */
>     unsigned start;  /**< the index of the first vertex */
> @@ -541,6 +574,7 @@ struct pipe_draw_info
>     unsigned start_instance; /**< first instance id */
>     unsigned instance_count; /**< number of instances */
>
> +   unsigned drawid; /**< id of this draw in a multidraw */
>     /**
>      * For indexed drawing, these fields apply after index lookup.
>      */
> @@ -554,6 +588,7 @@ struct pipe_draw_info
>     boolean primitive_restart;
>     unsigned restart_index;
>
> +   struct pipe_draw_indirect_info indirect;
>     /**
>      * Stream output target. If not NULL, it's used to provide the 'count'
>      * parameter based on the number vertices captured by the stream output
> diff --git a/src/virgl_protocol.h b/src/virgl_protocol.h
> index a2f1e81..1430422 100644
> --- a/src/virgl_protocol.h
> +++ b/src/virgl_protocol.h
> @@ -275,6 +275,8 @@ enum virgl_context_cmd {
>
>  /* draw VBO */
>  #define VIRGL_DRAW_VBO_SIZE 12
> +#define VIRGL_DRAW_VBO_SIZE_TESS 14
> +#define VIRGL_DRAW_VBO_SIZE_INDIRECT 20
>  #define VIRGL_DRAW_VBO_START 1
>  #define VIRGL_DRAW_VBO_COUNT 2
>  #define VIRGL_DRAW_VBO_MODE 3
> @@ -287,6 +289,16 @@ enum virgl_context_cmd {
>  #define VIRGL_DRAW_VBO_MIN_INDEX 10
>  #define VIRGL_DRAW_VBO_MAX_INDEX 11
>  #define VIRGL_DRAW_VBO_COUNT_FROM_SO 12
> +/* tess packet */
> +#define VIRGL_DRAW_VBO_VERTICES_PER_PATCH 13
> +#define VIRGL_DRAW_VBO_DRAWID 14
> +/* indirect packet */
> +#define VIRGL_DRAW_VBO_INDIRECT_HANDLE 15
> +#define VIRGL_DRAW_VBO_INDIRECT_OFFSET 16
> +#define VIRGL_DRAW_VBO_INDIRECT_STRIDE 17
> +#define VIRGL_DRAW_VBO_INDIRECT_DRAW_COUNT 18
> +#define VIRGL_DRAW_VBO_INDIRECT_DRAW_COUNT_OFFSET 19
> +#define VIRGL_DRAW_VBO_INDIRECT_DRAW_COUNT_HANDLE 20
>
>  /* create surface */
>  #define VIRGL_OBJ_SURFACE_SIZE 5
> diff --git a/src/vrend_decode.c b/src/vrend_decode.c
> index e429369..3b18596 100644
> --- a/src/vrend_decode.c
> +++ b/src/vrend_decode.c
> @@ -352,7 +352,9 @@ static int vrend_decode_draw_vbo(struct vrend_decode_ctx *ctx, int length)
>  {
>     struct pipe_draw_info info;
>     uint32_t cso;
> -   if (length != VIRGL_DRAW_VBO_SIZE)
> +   uint32_t handle = 0, indirect_draw_count_handle = 0;
> +   if (length != VIRGL_DRAW_VBO_SIZE && length != VIRGL_DRAW_VBO_SIZE_TESS &&
> +       length != VIRGL_DRAW_VBO_SIZE_INDIRECT)
>        return EINVAL;
>     memset(&info, 0, sizeof(struct pipe_draw_info));
>
> @@ -368,9 +370,23 @@ static int vrend_decode_draw_vbo(struct vrend_decode_ctx *ctx, int length)
>     info.min_index = get_buf_entry(ctx, VIRGL_DRAW_VBO_MIN_INDEX);
>     info.max_index = get_buf_entry(ctx, VIRGL_DRAW_VBO_MAX_INDEX);
>
> +   if (length >= VIRGL_DRAW_VBO_SIZE_TESS) {
> +      info.vertices_per_patch = get_buf_entry(ctx, VIRGL_DRAW_VBO_VERTICES_PER_PATCH);
> +      info.drawid = get_buf_entry(ctx, VIRGL_DRAW_VBO_DRAWID);
> +   }
> +
> +   if (length == VIRGL_DRAW_VBO_SIZE_INDIRECT) {
> +      handle = get_buf_entry(ctx, VIRGL_DRAW_VBO_INDIRECT_HANDLE);
> +      info.indirect.offset = get_buf_entry(ctx, VIRGL_DRAW_VBO_INDIRECT_OFFSET);
> +      info.indirect.stride = get_buf_entry(ctx, VIRGL_DRAW_VBO_INDIRECT_STRIDE);
> +      info.indirect.draw_count = get_buf_entry(ctx, VIRGL_DRAW_VBO_INDIRECT_DRAW_COUNT);
> +      info.indirect.indirect_draw_count_offset = get_buf_entry(ctx, VIRGL_DRAW_VBO_INDIRECT_DRAW_COUNT_OFFSET);
> +      indirect_draw_count_handle = get_buf_entry(ctx, VIRGL_DRAW_VBO_INDIRECT_DRAW_COUNT_HANDLE);
> +   }
> +
>     cso = get_buf_entry(ctx, VIRGL_DRAW_VBO_COUNT_FROM_SO);
>
> -   vrend_draw_vbo(ctx->grctx, &info, cso);
> +   vrend_draw_vbo(ctx->grctx, &info, cso, handle, indirect_draw_count_handle);
>     return 0;
>  }
>
> diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
> index 46fc8db..087139e 100644
> --- a/src/vrend_renderer.c
> +++ b/src/vrend_renderer.c
> @@ -2821,15 +2821,31 @@ static void vrend_draw_bind_ubo(struct vrend_context *ctx)
>
>  void vrend_draw_vbo(struct vrend_context *ctx,
>                      const struct pipe_draw_info *info,
> -                    uint32_t cso)
> +                    uint32_t cso, uint32_t indirect_handle,
> +                    uint32_t indirect_draw_count_handle)
>  {
>     int i;
>     bool new_program = false;
>     uint32_t shader_type;
> +   struct vrend_resource *indirect_res = NULL;
>
>     if (ctx->in_error)
>        return;
>
> +   if (indirect_handle) {
> +      indirect_res = vrend_renderer_ctx_res_lookup(ctx, indirect_handle);
> +      if (!indirect_res) {
> +         report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, indirect_handle);
> +         return;
> +      }
> +   }
> +
> +   /* this must be zero until we support the feature */
> +   if (indirect_draw_count_handle) {
> +      report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, indirect_handle);
> +      return;
> +   }
> +
>     if (ctx->ctx_switch_pending)
>        vrend_finish_context_switch(ctx);
>
> @@ -2972,12 +2988,21 @@ void vrend_draw_vbo(struct vrend_context *ctx,
>           glPrimitiveRestartIndex(info->restart_index);
>        }
>     }
> +
> +   if (indirect_res)
> +      glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirect_res->id);
> +   else
> +      glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
> +
>     /* set the vertex state up now on a delay */
>     if (!info->indexed) {
>        GLenum mode = info->mode;
>        int count = cso ? cso : info->count;
>        int start = cso ? 0 : info->start;
> -      if (info->instance_count <= 1)
> +
> +      if (indirect_handle)
> +         glDrawArraysIndirect(mode, (GLvoid const *)(unsigned long)info->indirect.offset);
> +      else if (info->instance_count <= 1)
>           glDrawArrays(mode, start, count);
>        else if (info->start_instance)
>           glDrawArraysInstancedBaseInstance(mode, start, count, info->instance_count, info->start_instance);
> @@ -2999,7 +3024,9 @@ void vrend_draw_vbo(struct vrend_context *ctx,
>           break;
>        }
>
> -      if (info->index_bias) {
> +      if (indirect_handle)
> +         glDrawElementsIndirect(mode, elsz, (GLvoid const *)(unsigned long)info->indirect.offset);
> +      else if (info->index_bias) {
>           if (info->instance_count > 1)
>              glDrawElementsInstancedBaseVertex(mode, info->count, elsz, (void *)(unsigned long)ctx->sub->ib.offset, info->instance_count, info->index_bias);
>           else if (info->min_index != 0 || info->max_index != -1)
> @@ -6309,6 +6336,7 @@ void vrend_renderer_fill_caps(uint32_t set, uint32_t version,
>        caps->v1.bset.indep_blend_func = 1;
>        caps->v1.bset.cube_map_array = 1;
>        caps->v1.bset.texture_query_lod = 1;
> +      caps->v1.bset.has_indirect_draw = 1;
>     } else {
>        if (epoxy_has_gl_extension("GL_ARB_draw_buffers_blend"))
>           caps->v1.bset.indep_blend_func = 1;
> @@ -6316,6 +6344,8 @@ void vrend_renderer_fill_caps(uint32_t set, uint32_t version,
>           caps->v1.bset.cube_map_array = 1;
>        if (epoxy_has_gl_extension("GL_ARB_texture_query_lod"))
>           caps->v1.bset.texture_query_lod = 1;
> +      if (epoxy_has_gl_extension("GL_ARB_indirect_draw"))
> +         caps->v1.bset.has_indirect_draw = 1;
>     }
>
>     if (gl_ver >= 42) {
> diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h
> index b9eeb71..9bbd9dd 100644
> --- a/src/vrend_renderer.h
> +++ b/src/vrend_renderer.h
> @@ -124,7 +124,7 @@ void vrend_clear(struct vrend_context *ctx,
>
>  void vrend_draw_vbo(struct vrend_context *ctx,
>                      const struct pipe_draw_info *info,
> -                    uint32_t cso);
> +                    uint32_t cso, uint32_t indirect_handle, uint32_t indirect_draw_count_handle);
>
>  void vrend_set_framebuffer_state(struct vrend_context *ctx,
>                                   uint32_t nr_cbufs, uint32_t surf_handle[PIPE_MAX_COLOR_BUFS],
> --
> 2.9.5
>
> _______________________________________________
> virglrenderer-devel mailing list
> virglrenderer-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/virglrenderer-devel


More information about the virglrenderer-devel mailing list