[Mesa-dev] [PATCH v2 5/8] mesa: Add a new GetTransformFeedbackVertexCount() driver hook.

Marek Olšák maraeo at gmail.com
Sat Oct 26 16:43:16 CEST 2013


This looks good. I recommend porting all_varyings_in_vbos from
st_draw.c to vbo_all_varyings_in_vbos, because it also takes instanced
arrays into account.

Reviewed-by: Marek Olšák <marek.olsak at amd.com>

Marek

On Sat, Oct 26, 2013 at 7:35 AM, Kenneth Graunke <kenneth at whitecape.org> wrote:
> DrawTransformFeedback() needs to obtain the number of vertices written
> to a particular stream during the last Begin/EndTransformFeedback block.
> The new driver hook returns exactly that information.
>
> Gallium drivers already implement this by passing the transform feedback
> object to the drawing function, counting the number of vertices written
> on the GPU, and using draw indirect.  This is efficient, but doesn't
> always work:
>
> If vertex data comes from user arrays, then the VBO module needs to
> know how many vertices to upload, so we need to synchronously count.
> Gallium drivers are currently broken in this case.
>
> It also doesn't work if primitive restart is done in software.  For
> normal drawing, vbo_draw_arrays() performs software primitive restart,
> splitting the draw call in two.  vbo_draw_transform_feedback() currently
> doesn't because it has no idea how many vertices need to be drawn.
>
> The new driver hook gives it that information, allowing us to reuse
> the existing vbo_draw_arrays() code to do everything right.
>
> On Intel hardware (at least Ivybridge), using the draw indirect approach
> is difficult since the hardware counts primitives, rather than vertices,
> which requires doing some simple math.  So we always use this hook.
>
> Gallium drivers will likely want to use this hook in some cases, but
> want to use the existing draw indirect approach where possible.  Hence,
> I've added a flag to allow drivers to opt-in to this call.
>
> v2: Make it possible to implement this hook but only use this path
>     when necessary (suggested by Marek).
>
> Cc: Marek Olšák <maraeo at gmail.com>
> Cc: Eric Anholt <eric at anholt.net>
> Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
> ---
>  src/mesa/drivers/dri/i965/brw_context.c |  2 ++
>  src/mesa/main/dd.h                      |  8 ++++++++
>  src/mesa/main/mtypes.h                  |  6 ++++++
>  src/mesa/vbo/vbo_exec_array.c           | 10 ++++++++++
>  4 files changed, 26 insertions(+)
>
> Marek,
>
> Does this look like what you wanted?  I feel a bit silly adding all of this
> seeing as the later conditions are totally untested - i965 sets the "always
> use this hook" flag, so it short-circuits them, and Gallium drivers don't
> yet implement the hook, so they don't hit it either. :)
>
> But I think this is probably roughly what you're going to want...
>
> Eric, does this look reasonable?
>
> Thanks for everything!
>
> diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
> index 90d9be4..623273c 100644
> --- a/src/mesa/drivers/dri/i965/brw_context.c
> +++ b/src/mesa/drivers/dri/i965/brw_context.c
> @@ -329,6 +329,8 @@ brw_initialize_context_constants(struct brw_context *brw)
>     ctx->Const.MaxTransformFeedbackSeparateComponents =
>        BRW_MAX_SOL_BINDINGS / BRW_MAX_SOL_BUFFERS;
>
> +   ctx->Const.AlwaysUseGetTransformFeedbackVertexCount = true;
> +
>     if (brw->gen == 6) {
>        ctx->Const.MaxSamples = 4;
>        ctx->Const.MaxColorTextureSamples = 4;
> diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
> index 29469ce..11d5a9e 100644
> --- a/src/mesa/main/dd.h
> +++ b/src/mesa/main/dd.h
> @@ -843,6 +843,14 @@ struct dd_function_table {
>                                     struct gl_transform_feedback_object *obj);
>
>     /**
> +    * Return the number of vertices written to a stream during the last
> +    * Begin/EndTransformFeedback block.
> +    */
> +   GLsizei (*GetTransformFeedbackVertexCount)(struct gl_context *ctx,
> +                                              struct gl_transform_feedback_object *obj,
> +                                              GLuint stream);
> +
> +   /**
>      * \name GL_NV_texture_barrier interface
>      */
>     void (*TextureBarrier)(struct gl_context *ctx);
> diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
> index 97ed1bd..f5e1f01 100644
> --- a/src/mesa/main/mtypes.h
> +++ b/src/mesa/main/mtypes.h
> @@ -3131,6 +3131,12 @@ struct gl_constants
>      */
>     GLboolean PrimitiveRestartInSoftware;
>
> +   /**
> +    * Always use the GetTransformFeedbackVertexCount() driver hook, rather
> +    * than passing the transform feedback object to the drawing function.
> +    */
> +   GLboolean AlwaysUseGetTransformFeedbackVertexCount;
> +
>     /** GL_ARB_map_buffer_alignment */
>     GLuint MinMapBufferAlignment;
>
> diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
> index 1670409..f25a9de 100644
> --- a/src/mesa/vbo/vbo_exec_array.c
> +++ b/src/mesa/vbo/vbo_exec_array.c
> @@ -1464,6 +1464,16 @@ vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
>        return;
>     }
>
> +   if (ctx->Driver.GetTransformFeedbackVertexCount &&
> +       (ctx->Const.AlwaysUseGetTransformFeedbackVertexCount ||
> +        (ctx->Const.PrimitiveRestartInSoftware &&
> +         ctx->Array._PrimitiveRestart) ||
> +        !vbo_all_varyings_in_vbos(exec->array.inputs))) {
> +      GLsizei n = ctx->Driver.GetTransformFeedbackVertexCount(ctx, obj, stream);
> +      vbo_draw_arrays(ctx, mode, 0, n, numInstances, 0);
> +      return;
> +   }
> +
>     vbo_bind_arrays(ctx);
>
>     /* init most fields to zero */
> --
> 1.8.3.2
>


More information about the mesa-dev mailing list