[Mesa-dev] [PATCH 1/2] gallium/u_blitter: implement buffer clearing

Brian Paul brianp at vmware.com
Mon Apr 22 07:42:53 PDT 2013


On 04/21/2013 05:25 PM, Marek Olšák wrote:
> Although this might be useful for ARB_clear_buffer_object,
> I need it for initializating resources in r600g.
> ---
>   src/gallium/auxiliary/util/u_blitter.c |   81 +++++++++++++++++++++++++++++---
>   src/gallium/auxiliary/util/u_blitter.h |   18 ++++++-
>   2 files changed, 91 insertions(+), 8 deletions(-)
>
> diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
> index 2a4a13e..2f7a1a8 100644
> --- a/src/gallium/auxiliary/util/u_blitter.c
> +++ b/src/gallium/auxiliary/util/u_blitter.c
> @@ -100,7 +100,7 @@ struct blitter_context_priv
>      void *velem_state;
>      void *velem_uint_state;
>      void *velem_sint_state;
> -   void *velem_state_readbuf;
> +   void *velem_state_readbuf[4];

It took me a minute to understand what '4' is all about.  Maybe add a 
comment like this:

void *velem_state_readbuf[4];  /**< X, XY, XYZ, XYZW */


>
>      /* Sampler state. */
>      void *sampler_state;
> @@ -285,9 +285,19 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
>      }
>
>      if (ctx->has_stream_out) {
> -      velem[0].src_format = PIPE_FORMAT_R32_UINT;
> -      velem[0].vertex_buffer_index = ctx->base.vb_slot;
> -      ctx->velem_state_readbuf = pipe->create_vertex_elements_state(pipe, 1,&velem[0]);
> +      static enum pipe_format formats[4] = {
> +         PIPE_FORMAT_R32_UINT,
> +         PIPE_FORMAT_R32G32_UINT,
> +         PIPE_FORMAT_R32G32B32_UINT,
> +         PIPE_FORMAT_R32G32B32A32_UINT
> +      };
> +
> +      for (i = 0; i<  4; i++) {
> +         velem[0].src_format = formats[i];
> +         velem[0].vertex_buffer_index = ctx->base.vb_slot;
> +         ctx->velem_state_readbuf[i] =
> +               pipe->create_vertex_elements_state(pipe, 1,&velem[0]);
> +      }
>      }
>
>      /* fragment shaders are created on-demand */
> @@ -352,8 +362,11 @@ void util_blitter_destroy(struct blitter_context *blitter)
>         pipe->delete_vertex_elements_state(pipe, ctx->velem_sint_state);
>         pipe->delete_vertex_elements_state(pipe, ctx->velem_uint_state);
>      }
> -   if (ctx->velem_state_readbuf)
> -      pipe->delete_vertex_elements_state(pipe, ctx->velem_state_readbuf);
> +   for (i = 0; i<  4; i++) {
> +      if (ctx->velem_state_readbuf[i]) {
> +         pipe->delete_vertex_elements_state(pipe, ctx->velem_state_readbuf[i]);
> +      }
> +   }
>
>      for (i = 0; i<  PIPE_MAX_TEXTURE_TYPES; i++) {
>         if (ctx->fs_texfetch_col[i])
> @@ -1739,7 +1752,7 @@ void util_blitter_copy_buffer(struct blitter_context *blitter,
>      vb.stride = 4;
>
>      pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1,&vb);
> -   pipe->bind_vertex_elements_state(pipe, ctx->velem_state_readbuf);
> +   pipe->bind_vertex_elements_state(pipe, ctx->velem_state_readbuf[0]);
>      pipe->bind_vs_state(pipe, ctx->vs_pos_only);
>      if (ctx->has_geometry_shader)
>         pipe->bind_gs_state(pipe, NULL);
> @@ -1756,6 +1769,60 @@ void util_blitter_copy_buffer(struct blitter_context *blitter,
>      pipe_so_target_reference(&so_target, NULL);
>   }
>
> +void util_blitter_clear_buffer(struct blitter_context *blitter,
> +                               struct pipe_resource *dst,
> +                               unsigned offset, unsigned size,
> +                               unsigned num_channels,
> +                               const union pipe_color_union *clear_value)
> +{
> +   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
> +   struct pipe_context *pipe = ctx->base.pipe;
> +   struct pipe_vertex_buffer vb = {0};
> +   struct pipe_stream_output_target *so_target;
> +
> +   assert(num_channels>= 1);
> +   assert(num_channels<= 4);

Do we want some sort of assertion to check that the driver actually 
supports SO?


> +
> +   /* IMPORTANT:  DON'T DO ANY BOUNDS CHECKING HERE!
> +    *
> +    * R600 uses this to initialize texture resources, so width0 might not be
> +    * what you think it is.
> +    */
> +
> +   /* Some alignment is required. */
> +   if (offset % 4 != 0 || size % 4 != 0 || !ctx->has_stream_out) {
> +      assert(0);

assert(!"Bad alignment in util_blitter_clear_buffer()");

There's way too many assert(0) macros in gallium, btw.


> +      return;
> +   }
> +
> +   u_upload_data(ctx->upload, 0, num_channels*4, clear_value,
> +&vb.buffer_offset,&vb.buffer);
> +   vb.stride = 0;
> +
> +   blitter_set_running_flag(ctx);
> +   blitter_check_saved_vertex_states(ctx);
> +   blitter_disable_render_cond(ctx);
> +
> +   pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1,&vb);
> +   pipe->bind_vertex_elements_state(pipe,
> +                                    ctx->velem_state_readbuf[num_channels-1]);
> +   pipe->bind_vs_state(pipe, ctx->vs_pos_only);
> +   if (ctx->has_geometry_shader)
> +      pipe->bind_gs_state(pipe, NULL);
> +   pipe->bind_rasterizer_state(pipe, ctx->rs_discard_state);
> +
> +   so_target = pipe->create_stream_output_target(pipe, dst, offset, size);
> +   pipe->set_stream_output_targets(pipe, 1,&so_target, 0);
> +
> +   util_draw_arrays(pipe, PIPE_PRIM_POINTS, 0, size / 4);
> +
> +   blitter_restore_vertex_states(ctx);
> +   blitter_restore_render_cond(ctx);
> +   blitter_unset_running_flag(ctx);
> +   pipe_so_target_reference(&so_target, NULL);
> +   pipe_resource_reference(&vb.buffer, NULL);
> +}
> +
>   /* probably radeon specific */
>   void util_blitter_custom_resolve_color(struct blitter_context *blitter,
>   				       struct pipe_resource *dst,
> diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h
> index 20e69ed..1901584 100644
> --- a/src/gallium/auxiliary/util/u_blitter.h
> +++ b/src/gallium/auxiliary/util/u_blitter.h
> @@ -276,7 +276,7 @@ void util_blitter_default_src_texture(struct pipe_sampler_view *src_templ,
>
>   /**
>    * Copy data from one buffer to another using the Stream Output functionality.
> - * Some alignment is required, otherwise software fallback is used.
> + * 4-byte alignment is required, otherwise software fallback is used.
>    */
>   void util_blitter_copy_buffer(struct blitter_context *blitter,
>                                 struct pipe_resource *dst,
> @@ -286,6 +286,22 @@ void util_blitter_copy_buffer(struct blitter_context *blitter,
>                                 unsigned size);
>
>   /**
> + * Clear the contents of a buffer using the Stream Output functionality.
> + * 4-byte alignment is required.
> + *
> + * "num_channels" can be 1, 2, 3, or 4, and specifies if the clear value is
> + * R, RG, RGB, or RGBA.
> + *
> + * For each element, only "num_channels" components of "clear_value" are
> + * copied to the buffer, then the offset is incremented by num_channels*4.
> + */
> +void util_blitter_clear_buffer(struct blitter_context *blitter,
> +                               struct pipe_resource *dst,
> +                               unsigned offset, unsigned size,
> +                               unsigned num_channels,
> +                               const union pipe_color_union *clear_value);
> +
> +/**
>    * Clear a region of a (color) surface to a constant value.
>    *
>    * These states must be saved in the blitter in addition to the state objects

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


More information about the mesa-dev mailing list