[Mesa-dev] [PATCH 3/4] gallium: add facilities for indirect drawing

Brian Paul brianp at vmware.com
Thu Apr 4 12:23:46 PDT 2013


On 04/04/2013 12:18 PM, Christoph Bumiller wrote:
> ---
>   src/gallium/auxiliary/util/u_draw.c              |   39 ++++++++++++++++++++++
>   src/gallium/auxiliary/util/u_draw.h              |    5 +++
>   src/gallium/auxiliary/util/u_dump_state.c        |    3 ++
>   src/gallium/docs/source/screen.rst               |    3 ++
>   src/gallium/drivers/freedreno/freedreno_screen.c |    1 +
>   src/gallium/drivers/i915/i915_screen.c           |    1 +
>   src/gallium/drivers/llvmpipe/lp_draw_arrays.c    |    5 +++
>   src/gallium/drivers/llvmpipe/lp_screen.c         |    2 +
>   src/gallium/drivers/nv30/nv30_screen.c           |    1 +
>   src/gallium/drivers/nv50/nv50_screen.c           |    2 +
>   src/gallium/drivers/r300/r300_screen.c           |    1 +
>   src/gallium/drivers/r600/r600_pipe.c             |    1 +
>   src/gallium/drivers/radeonsi/radeonsi_pipe.c     |    1 +
>   src/gallium/drivers/softpipe/sp_draw_arrays.c    |    6 +++
>   src/gallium/drivers/softpipe/sp_screen.c         |    2 +
>   src/gallium/drivers/svga/svga_screen.c           |    1 +
>   src/gallium/drivers/trace/tr_dump_state.c        |    3 ++
>   src/gallium/include/pipe/p_defines.h             |    3 +-
>   src/gallium/include/pipe/p_state.h               |   22 ++++++++++++
>   19 files changed, 101 insertions(+), 1 deletions(-)
>
> diff --git a/src/gallium/auxiliary/util/u_draw.c b/src/gallium/auxiliary/util/u_draw.c
> index 83d9284..7a28cf1 100644
> --- a/src/gallium/auxiliary/util/u_draw.c
> +++ b/src/gallium/auxiliary/util/u_draw.c
> @@ -27,6 +27,7 @@
>
>
>   #include "util/u_debug.h"
> +#include "util/u_inlines.h"
>   #include "util/u_math.h"
>   #include "util/u_format.h"
>   #include "util/u_draw.h"
> @@ -123,3 +124,41 @@ util_draw_max_index(
>
>      return max_index + 1;
>   }
> +
> +


Could you put a comment on this function to explain exactly what it's 
doing?  E.g. convert an "indirect" draw into a "direct" draw by 
mapping the parameter buffer, etc.


> +void
> +util_draw_indirect(struct pipe_context *pipe,
> +                   const struct pipe_draw_info *_info)

I know there's other instances of this, but params with leading 
underscores look kind of weird.  Maybe "infoIn"?


> +{
> +   struct pipe_draw_info info;
> +   struct pipe_transfer *transfer;
> +   uint32_t *params;
> +
> +   assert(_info->indirect);
> +   assert(!_info->count_from_stream_output);
> +
> +   memcpy(&info, _info, sizeof(info));
> +
> +   params = (uint32_t *)
> +      pipe_buffer_map_range(pipe,
> +                            _info->indirect,
> +                            _info->indirect_offset,
> +                            _info->indexed ? (4 * 4) : (3 * 4),

Document those magic numbers?


> +                            PIPE_TRANSFER_READ,
> +&transfer);
> +   if (!transfer) {
> +      debug_printf("%s: failed to map indirect buffer\n", __FUNCTION__);
> +      return;
> +   }
> +
> +   info.count = params[0];
> +   info.instance_count = params[1];
> +   info.start = params[2];
> +   info.index_bias = _info->indexed ? params[3] : 0;
> +   info.start_instance = _info->indexed ? params[4] : params[3];
> +   info.indirect = NULL;
> +
> +   pipe_buffer_unmap(pipe, transfer);
> +
> +   pipe->draw_vbo(pipe,&info);
> +}
> diff --git a/src/gallium/auxiliary/util/u_draw.h b/src/gallium/auxiliary/util/u_draw.h
> index 3dc6918..acec56e 100644
> --- a/src/gallium/auxiliary/util/u_draw.h
> +++ b/src/gallium/auxiliary/util/u_draw.h
> @@ -142,6 +142,11 @@ util_draw_range_elements(struct pipe_context *pipe,
>   }
>
>
> +void
> +util_draw_indirect(struct pipe_context *pipe,
> +                   const struct pipe_draw_info *info);
> +
> +
>   unsigned
>   util_draw_max_index(
>         const struct pipe_vertex_buffer *vertex_buffers,
> diff --git a/src/gallium/auxiliary/util/u_dump_state.c b/src/gallium/auxiliary/util/u_dump_state.c
> index 2f28f3c..21b6044 100644
> --- a/src/gallium/auxiliary/util/u_dump_state.c
> +++ b/src/gallium/auxiliary/util/u_dump_state.c
> @@ -758,6 +758,9 @@ util_dump_draw_info(FILE *stream, const struct pipe_draw_info *state)
>
>      util_dump_member(stream, ptr, state, count_from_stream_output);
>
> +   util_dump_member(stream, ptr, state, indirect);
> +   util_dump_member(stream, uint, state, indirect_offset);
> +
>      util_dump_struct_end(stream);
>   }
>
> diff --git a/src/gallium/docs/source/screen.rst b/src/gallium/docs/source/screen.rst
> index f8cdded..ed4749d 100644
> --- a/src/gallium/docs/source/screen.rst
> +++ b/src/gallium/docs/source/screen.rst
> @@ -151,6 +151,9 @@ The integer capabilities:
>     dedicated memory should return 1 and all software rasterizers should return 0.
>   * ``PIPE_CAP_QUERY_PIPELINE_STATISTICS``: Whether PIPE_QUERY_PIPELINE_STATISTICS
>     is supported.
> +* ``PIPE_CAP_DRAW_INDIRECT``: Whether the driver supports taking draw arguments
> +  { count, instance_count, start, index_bias } from a PIPE_BUFFER resource.
> +  See pipe_draw_info.
>
>
>   .. _pipe_capf:
> diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c
> index 283d07f..2b13e29 100644
> --- a/src/gallium/drivers/freedreno/freedreno_screen.c
> +++ b/src/gallium/drivers/freedreno/freedreno_screen.c
> @@ -200,6 +200,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
>   	case PIPE_CAP_USER_VERTEX_BUFFERS:
>   	case PIPE_CAP_USER_INDEX_BUFFERS:
>   	case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
> +	case PIPE_CAP_DRAW_INDIRECT:
>   		return 0;
>
>   	/* Stream output. */
> diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c
> index 54b2154..5a04c42 100644
> --- a/src/gallium/drivers/i915/i915_screen.c
> +++ b/src/gallium/drivers/i915/i915_screen.c
> @@ -213,6 +213,7 @@ i915_get_param(struct pipe_screen *screen, enum pipe_cap cap)
>      case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
>      case PIPE_CAP_TEXTURE_MULTISAMPLE:
>      case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
> +   case PIPE_CAP_DRAW_INDIRECT:
>         return 0;
>
>      case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
> diff --git a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c
> index efeca25..720960d 100644
> --- a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c
> +++ b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c
> @@ -60,6 +60,11 @@ llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
>      if (!llvmpipe_check_render_cond(lp))
>         return;
>
> +   if (unlikely(info->indirect)) {

I'm not sure the use of unlikely busy us much here.


> +      util_draw_indirect(pipe, info);
> +      return;
> +   }
> +
>      if (lp->dirty)
>         llvmpipe_update_derived( lp );
>
> diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c
> index 6700887..5cef99b 100644
> --- a/src/gallium/drivers/llvmpipe/lp_screen.c
> +++ b/src/gallium/drivers/llvmpipe/lp_screen.c
> @@ -212,6 +212,8 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
>      case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
>      case PIPE_CAP_TGSI_TEXCOORD:
>         return 0;
> +   case PIPE_CAP_DRAW_INDIRECT:
> +      return 1;
>
>      case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
>         return 16;
> diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c
> index e33710e..06a16c8 100644
> --- a/src/gallium/drivers/nv30/nv30_screen.c
> +++ b/src/gallium/drivers/nv30/nv30_screen.c
> @@ -123,6 +123,7 @@ nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
>      case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
>      case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
>      case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
> +   case PIPE_CAP_DRAW_INDIRECT:
>         return 0;
>      case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
>      case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
> diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c
> index 55081be..4da0dce 100644
> --- a/src/gallium/drivers/nv50/nv50_screen.c
> +++ b/src/gallium/drivers/nv50/nv50_screen.c
> @@ -186,6 +186,8 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
>         return 1;
>      case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
>         return 0;
> +   case PIPE_CAP_DRAW_INDIRECT:
> +      return 0;
>      default:
>         NOUVEAU_ERR("unknown PIPE_CAP %d\n", param);
>         return 0;
> diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c
> index 3175b3b..4e29a2e 100644
> --- a/src/gallium/drivers/r300/r300_screen.c
> +++ b/src/gallium/drivers/r300/r300_screen.c
> @@ -162,6 +162,7 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
>           case PIPE_CAP_CUBE_MAP_ARRAY:
>           case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
>           case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
> +        case PIPE_CAP_DRAW_INDIRECT:
>               return 0;
>
>           /* SWTCL-only features. */
> diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
> index 1e4c964..0cf6ab7 100644
> --- a/src/gallium/drivers/r600/r600_pipe.c
> +++ b/src/gallium/drivers/r600/r600_pipe.c
> @@ -603,6 +603,7 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
>   	case PIPE_CAP_USER_VERTEX_BUFFERS:
>   	case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
>   	case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
> +	case PIPE_CAP_DRAW_INDIRECT:
>   		return 0;
>
>   	/* Stream output. */
> diff --git a/src/gallium/drivers/radeonsi/radeonsi_pipe.c b/src/gallium/drivers/radeonsi/radeonsi_pipe.c
> index 17d825b..d49cd8a 100644
> --- a/src/gallium/drivers/radeonsi/radeonsi_pipe.c
> +++ b/src/gallium/drivers/radeonsi/radeonsi_pipe.c
> @@ -361,6 +361,7 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
>   	case PIPE_CAP_CUBE_MAP_ARRAY:
>   	case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
>   	case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
> +	case PIPE_CAP_DRAW_INDIRECT:
>   		return 0;
>
>   	/* Stream output. */
> diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c
> index ba9e781..f0898a8 100644
> --- a/src/gallium/drivers/softpipe/sp_draw_arrays.c
> +++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c
> @@ -34,6 +34,7 @@
>   #include "pipe/p_defines.h"
>   #include "pipe/p_context.h"
>   #include "util/u_inlines.h"
> +#include "util/u_draw.h"
>   #include "util/u_prim.h"
>
>   #include "sp_context.h"
> @@ -67,6 +68,11 @@ softpipe_draw_vbo(struct pipe_context *pipe,
>      if (!softpipe_check_render_cond(sp))
>         return;
>
> +   if (unlikely(info->indirect)) {

unlikely?


> +      util_draw_indirect(pipe, info);
> +      return;
> +   }
> +
>      sp->reduced_api_prim = u_reduced_prim(info->mode);
>
>      if (sp->dirty) {
> diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
> index 6915f91..8114165 100644
> --- a/src/gallium/drivers/softpipe/sp_screen.c
> +++ b/src/gallium/drivers/softpipe/sp_screen.c
> @@ -178,6 +178,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
>      case PIPE_CAP_TGSI_TEXCOORD:
>      case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
>         return 0;
> +   case PIPE_CAP_DRAW_INDIRECT:
> +      return 1;
>      }
>      /* should only get here on unhandled cases */
>      debug_printf("Unexpected PIPE_CAP %d query\n", param);
> diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c
> index 6213535..c046a4b 100644
> --- a/src/gallium/drivers/svga/svga_screen.c
> +++ b/src/gallium/drivers/svga/svga_screen.c
> @@ -263,6 +263,7 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
>      case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
>      case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
>      case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
> +   case PIPE_CAP_DRAW_INDIRECT:
>         return 0;
>      case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
>         return 1;
> diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c
> index 006082b..5ed3f91 100644
> --- a/src/gallium/drivers/trace/tr_dump_state.c
> +++ b/src/gallium/drivers/trace/tr_dump_state.c
> @@ -708,6 +708,9 @@ void trace_dump_draw_info(const struct pipe_draw_info *state)
>
>      trace_dump_member(ptr, state, count_from_stream_output);
>
> +   trace_dump_member(ptr, state, indirect);
> +   trace_dump_member(uint, state, indirect_offset);
> +
>      trace_dump_struct_end();
>   }
>
> diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h
> index 2b79f2a..d30db1b 100644
> --- a/src/gallium/include/pipe/p_defines.h
> +++ b/src/gallium/include/pipe/p_defines.h
> @@ -506,7 +506,8 @@ enum pipe_cap {
>      PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT = 78,
>      PIPE_CAP_TGSI_TEXCOORD = 79,
>      PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER = 80,
> -   PIPE_CAP_QUERY_PIPELINE_STATISTICS = 81
> +   PIPE_CAP_QUERY_PIPELINE_STATISTICS = 81,
> +   PIPE_CAP_DRAW_INDIRECT = 82
>   };
>
>   /**
> diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h
> index dfafd0b..3e96cb5 100644
> --- a/src/gallium/include/pipe/p_state.h
> +++ b/src/gallium/include/pipe/p_state.h
> @@ -559,6 +559,28 @@ struct pipe_draw_info
>       * be set via set_vertex_buffers manually.
>       */
>      struct pipe_stream_output_target *count_from_stream_output;
> +
> +   /* Indirect parameters resource: If not NULL, most values are taken
> +    * from this buffer instead, which is laid out as follows:
> +    *
> +    * if indexed is TRUE:
> +    *  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 *indirect;
> +   unsigned indirect_offset; /**<  must be 4 byte aligned */
>   };
>
>

Reviewed-by: Brian Paul <brianp at vmware.com>



More information about the mesa-dev mailing list