[Mesa-dev] [PATCH] softpipe: handle vertex texture sampling when using llvm for draw

Roland Scheidegger sroland at vmware.com
Thu Aug 28 09:19:48 PDT 2014


Ahh wrong patch sent again. This one is unchanged.

Roland

Am 28.08.2014 18:17, schrieb sroland at vmware.com:
> From: Roland Scheidegger <sroland at vmware.com>
> 
> Pretty trivial, just fill in the offsets and such. The implementation
> is near 100% copy and paste from llvmpipe. Should be useful for debugging.
> 
> No piglit change when not using SOFTPIPE_USE_LLVM=1.
> Now that it can do the same tests with and without using llvm for vs/gs,
> with llvm more pass, the only things failing only with llvm seems to be
> edgeflags tests and vs/gs-pow-float-float (and for the latter I'm not
> convinced the zero tolerance it requires is somehow mandated by glsl).
> ---
>  src/gallium/drivers/llvmpipe/lp_setup.c         |   2 +-
>  src/gallium/drivers/llvmpipe/lp_state_sampler.c |   2 +-
>  src/gallium/drivers/softpipe/sp_context.h       |   2 +
>  src/gallium/drivers/softpipe/sp_draw_arrays.c   |  15 +++
>  src/gallium/drivers/softpipe/sp_screen.c        |  18 +--
>  src/gallium/drivers/softpipe/sp_state.h         |  15 +++
>  src/gallium/drivers/softpipe/sp_state_sampler.c | 156 ++++++++++++++++++++++++
>  src/gallium/drivers/softpipe/sp_texture.c       |  34 +++---
>  src/gallium/drivers/softpipe/sp_texture.h       |   1 +
>  9 files changed, 209 insertions(+), 36 deletions(-)
> 
> diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
> index e85c4ca..7d0c8cc 100644
> --- a/src/gallium/drivers/llvmpipe/lp_setup.c
> +++ b/src/gallium/drivers/llvmpipe/lp_setup.c
> @@ -873,7 +873,7 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup,
>                    /* probably don't really need to fill that out */
>                    jit_tex->mip_offsets[0] = 0;
>                    jit_tex->row_stride[0] = 0;
> -                  jit_tex->row_stride[0] = 0;
> +                  jit_tex->img_stride[0] = 0;
>  
>                    /* everything specified in number of elements here. */
>                    jit_tex->width = view->u.buf.last_element - view->u.buf.first_element + 1;
> diff --git a/src/gallium/drivers/llvmpipe/lp_state_sampler.c b/src/gallium/drivers/llvmpipe/lp_state_sampler.c
> index 0180e99..21da629 100644
> --- a/src/gallium/drivers/llvmpipe/lp_state_sampler.c
> +++ b/src/gallium/drivers/llvmpipe/lp_state_sampler.c
> @@ -266,7 +266,7 @@ prepare_shader_sampling(
>                 /* probably don't really need to fill that out */
>                 mip_offsets[0] = 0;
>                 row_stride[0] = 0;
> -               row_stride[0] = 0;
> +               img_stride[0] = 0;
>  
>                 /* everything specified in number of elements here. */
>                 width0 = view->u.buf.last_element - view->u.buf.first_element + 1;
> diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h
> index aac35f7..50a7336 100644
> --- a/src/gallium/drivers/softpipe/sp_context.h
> +++ b/src/gallium/drivers/softpipe/sp_context.h
> @@ -85,6 +85,8 @@ struct softpipe_context {
>     struct pipe_viewport_state viewport;
>     struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
>     struct pipe_index_buffer index_buffer;
> +   struct pipe_resource *mapped_vs_tex[PIPE_MAX_SHADER_SAMPLER_VIEWS];
> +   struct pipe_resource *mapped_gs_tex[PIPE_MAX_SHADER_SAMPLER_VIEWS];
>  
>     struct draw_so_target *so_targets[PIPE_MAX_SO_BUFFERS];
>     unsigned num_so_targets;
> diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c
> index b75c10f..03fcf64 100644
> --- a/src/gallium/drivers/softpipe/sp_draw_arrays.c
> +++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c
> @@ -41,6 +41,7 @@
>  #include "sp_query.h"
>  #include "sp_state.h"
>  #include "sp_texture.h"
> +#include "sp_screen.h"
>  
>  #include "draw/draw_context.h"
>  
> @@ -123,6 +124,15 @@ softpipe_draw_vbo(struct pipe_context *pipe,
>     draw_set_mapped_so_targets(draw, sp->num_so_targets,
>                                sp->so_targets);
>  
> +   if (softpipe_screen(sp->pipe.screen)->use_llvm) {
> +      softpipe_prepare_vertex_sampling(sp,
> +                                       sp->num_sampler_views[PIPE_SHADER_VERTEX],
> +                                       sp->sampler_views[PIPE_SHADER_VERTEX]);
> +      softpipe_prepare_geometry_sampling(sp,
> +                                         sp->num_sampler_views[PIPE_SHADER_GEOMETRY],
> +                                         sp->sampler_views[PIPE_SHADER_GEOMETRY]);
> +   }
> +
>     if (sp->gs && !sp->gs->shader.tokens) {
>        /* we have an empty geometry shader with stream output, so
>           attach the stream output info to the current vertex shader */
> @@ -146,6 +156,11 @@ softpipe_draw_vbo(struct pipe_context *pipe,
>  
>     draw_set_mapped_so_targets(draw, 0, NULL);
>  
> +   if (softpipe_screen(sp->pipe.screen)->use_llvm) {
> +      softpipe_cleanup_vertex_sampling(sp);
> +      softpipe_cleanup_geometry_sampling(sp);
> +   }
> +
>     /*
>      * TODO: Flush only when a user vertex/index buffer is present
>      * (or even better, modify draw module to do this
> diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
> index be9a6c8..e86a4d4 100644
> --- a/src/gallium/drivers/softpipe/sp_screen.c
> +++ b/src/gallium/drivers/softpipe/sp_screen.c
> @@ -240,20 +240,10 @@ softpipe_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe
>        return tgsi_exec_get_shader_param(param);
>     case PIPE_SHADER_VERTEX:
>     case PIPE_SHADER_GEOMETRY:
> -      switch (param) {
> -      case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
> -      case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:
> -         if (sp_screen->use_llvm)
> -            /* Softpipe doesn't yet know how to tell draw/llvm about textures */
> -            return 0;
> -         else
> -            return PIPE_MAX_SAMPLERS;
> -      default:
> -         if (sp_screen->use_llvm)
> -            return draw_get_shader_param(shader, param);
> -         else
> -            return draw_get_shader_param_no_llvm(shader, param);
> -      }
> +      if (sp_screen->use_llvm)
> +         return draw_get_shader_param(shader, param);
> +      else
> +         return draw_get_shader_param_no_llvm(shader, param);
>     default:
>        return 0;
>     }
> diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h
> index 775a1f5..c35534c 100644
> --- a/src/gallium/drivers/softpipe/sp_state.h
> +++ b/src/gallium/drivers/softpipe/sp_state.h
> @@ -192,5 +192,20 @@ softpipe_find_fs_variant(struct softpipe_context *softpipe,
>                           struct sp_fragment_shader *fs,
>                           const struct sp_fragment_shader_variant_key *key);
>  
> +void
> +softpipe_prepare_vertex_sampling(struct softpipe_context *ctx,
> +                                 unsigned num,
> +                                 struct pipe_sampler_view **views);
> +void
> +softpipe_cleanup_vertex_sampling(struct softpipe_context *ctx);
> +
> +
> +void
> +softpipe_prepare_geometry_sampling(struct softpipe_context *ctx,
> +                                   unsigned num,
> +                                   struct pipe_sampler_view **views);
> +void
> +softpipe_cleanup_geometry_sampling(struct softpipe_context *ctx);
> +
>  
>  #endif
> diff --git a/src/gallium/drivers/softpipe/sp_state_sampler.c b/src/gallium/drivers/softpipe/sp_state_sampler.c
> index e512418..e56fb5b 100644
> --- a/src/gallium/drivers/softpipe/sp_state_sampler.c
> +++ b/src/gallium/drivers/softpipe/sp_state_sampler.c
> @@ -31,6 +31,7 @@
>  
>  #include "util/u_memory.h"
>  #include "util/u_inlines.h"
> +#include "util/u_format.h"
>  
>  #include "draw/draw_context.h"
>  
> @@ -39,6 +40,8 @@
>  #include "sp_texture.h"
>  #include "sp_tex_sample.h"
>  #include "sp_tex_tile_cache.h"
> +#include "sp_screen.h"
> +#include "state_tracker/sw_winsys.h"
>  
>  
>  /**
> @@ -159,6 +162,159 @@ softpipe_delete_sampler_state(struct pipe_context *pipe,
>  }
>  
>  
> +static void
> +prepare_shader_sampling(
> +   struct softpipe_context *sp,
> +   unsigned num,
> +   struct pipe_sampler_view **views,
> +   unsigned shader_type,
> +   struct pipe_resource *mapped_tex[PIPE_MAX_SHADER_SAMPLER_VIEWS])
> +{
> +
> +   unsigned i;
> +   uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS];
> +   uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS];
> +   uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS];
> +   const void *addr;
> +
> +   assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
> +   if (!num)
> +      return;
> +
> +   for (i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) {
> +      struct pipe_sampler_view *view = i < num ? views[i] : NULL;
> +
> +      if (view) {
> +         struct pipe_resource *tex = view->texture;
> +         struct softpipe_resource *sp_tex = softpipe_resource(tex);
> +         unsigned width0 = tex->width0;
> +         unsigned num_layers = tex->depth0;
> +         unsigned first_level = 0;
> +         unsigned last_level = 0;
> +
> +         /* We're referencing the texture's internal data, so save a
> +          * reference to it.
> +          */
> +         pipe_resource_reference(&mapped_tex[i], tex);
> +
> +         if (!sp_tex->dt) {
> +            /* regular texture - setup array of mipmap level offsets */
> +            struct pipe_resource *res = view->texture;
> +            int j;
> +
> +            if (res->target != PIPE_BUFFER) {
> +               first_level = view->u.tex.first_level;
> +               last_level = view->u.tex.last_level;
> +               assert(first_level <= last_level);
> +               assert(last_level <= res->last_level);
> +               addr = sp_tex->data;
> +
> +               for (j = first_level; j <= last_level; j++) {
> +                  mip_offsets[j] = sp_tex->level_offset[j];
> +                  row_stride[j] = sp_tex->stride[j];
> +                  img_stride[j] = sp_tex->img_stride[j];
> +               }
> +               if (res->target == PIPE_TEXTURE_1D_ARRAY ||
> +                   res->target == PIPE_TEXTURE_2D_ARRAY ||
> +                   res->target == PIPE_TEXTURE_CUBE_ARRAY) {
> +                  num_layers = view->u.tex.last_layer - view->u.tex.first_layer + 1;
> +                  for (j = first_level; j <= last_level; j++) {
> +                     mip_offsets[j] += view->u.tex.first_layer *
> +                                       sp_tex->img_stride[j];
> +                  }
> +                  if (res->target == PIPE_TEXTURE_CUBE_ARRAY) {
> +                     assert(num_layers % 6 == 0);
> +                  }
> +                  assert(view->u.tex.first_layer <= view->u.tex.last_layer);
> +                  assert(view->u.tex.last_layer < res->array_size);
> +               }
> +            }
> +            else {
> +               unsigned view_blocksize = util_format_get_blocksize(view->format);
> +               addr = sp_tex->data;
> +               /* probably don't really need to fill that out */
> +               mip_offsets[0] = 0;
> +               row_stride[0] = 0;
> +               img_stride[0] = 0;
> +
> +               /* everything specified in number of elements here. */
> +               width0 = view->u.buf.last_element - view->u.buf.first_element + 1;
> +               addr = (uint8_t *)addr + view->u.buf.first_element *
> +                               view_blocksize;
> +               assert(view->u.buf.first_element <= view->u.buf.last_element);
> +               assert(view->u.buf.last_element * view_blocksize < res->width0);
> +            }
> +         }
> +         else {
> +            /* display target texture/surface */
> +            /*
> +             * XXX: Where should this be unmapped?
> +             */
> +            struct softpipe_screen *screen = softpipe_screen(tex->screen);
> +            struct sw_winsys *winsys = screen->winsys;
> +            addr = winsys->displaytarget_map(winsys, sp_tex->dt,
> +                                             PIPE_TRANSFER_READ);
> +            row_stride[0] = sp_tex->stride[0];
> +            img_stride[0] = sp_tex->img_stride[0];
> +            mip_offsets[0] = 0;
> +            assert(addr);
> +         }
> +         draw_set_mapped_texture(sp->draw,
> +                                 shader_type,
> +                                 i,
> +                                 width0, tex->height0, num_layers,
> +                                 first_level, last_level,
> +                                 addr,
> +                                 row_stride, img_stride, mip_offsets);
> +      }
> +   }
> +}
> +
> +
> +/**
> + * Called during state validation when SP_NEW_TEXTURE is set.
> + */
> +void
> +softpipe_prepare_vertex_sampling(struct softpipe_context *sp,
> +                                 unsigned num,
> +                                 struct pipe_sampler_view **views)
> +{
> +   prepare_shader_sampling(sp, num, views, PIPE_SHADER_VERTEX,
> +                           sp->mapped_vs_tex);
> +}
> +
> +void
> +softpipe_cleanup_vertex_sampling(struct softpipe_context *ctx)
> +{
> +   unsigned i;
> +   for (i = 0; i < Elements(ctx->mapped_vs_tex); i++) {
> +      pipe_resource_reference(&ctx->mapped_vs_tex[i], NULL);
> +   }
> +}
> +
> +
> +/**
> + * Called during state validation when SP_NEW_TEXTURE is set.
> + */
> +void
> +softpipe_prepare_geometry_sampling(struct softpipe_context *sp,
> +                                   unsigned num,
> +                                   struct pipe_sampler_view **views)
> +{
> +   prepare_shader_sampling(sp, num, views, PIPE_SHADER_GEOMETRY,
> +                           sp->mapped_gs_tex);
> +}
> +
> +void
> +softpipe_cleanup_geometry_sampling(struct softpipe_context *ctx)
> +{
> +   unsigned i;
> +   for (i = 0; i < Elements(ctx->mapped_gs_tex); i++) {
> +      pipe_resource_reference(&ctx->mapped_gs_tex[i], NULL);
> +   }
> +}
> +
> +
>  void
>  softpipe_init_sampler_funcs(struct pipe_context *pipe)
>  {
> diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c
> index 6538e46..c2df71e 100644
> --- a/src/gallium/drivers/softpipe/sp_texture.c
> +++ b/src/gallium/drivers/softpipe/sp_texture.c
> @@ -63,7 +63,9 @@ softpipe_resource_layout(struct pipe_screen *screen,
>     uint64_t buffer_size = 0;
>  
>     for (level = 0; level <= pt->last_level; level++) {
> -      unsigned slices;
> +      unsigned slices, nblocksy;
> +
> +      nblocksy = util_format_get_nblocksy(pt->format, height);
>  
>        if (pt->target == PIPE_TEXTURE_CUBE)
>           slices = 6;
> @@ -76,8 +78,15 @@ softpipe_resource_layout(struct pipe_screen *screen,
>  
>        spr->level_offset[level] = buffer_size;
>  
> -      buffer_size += (uint64_t) util_format_get_nblocksy(pt->format, height) *
> -                     slices * spr->stride[level];
> +      /* if row_stride * height > SP_MAX_TEXTURE_SIZE */
> +      if ((uint64_t)spr->stride[level] * nblocksy > SP_MAX_TEXTURE_SIZE) {
> +         /* image too large */
> +         return FALSE;
> +      }
> +
> +      spr->img_stride[level] = spr->stride[level] * nblocksy;
> +
> +      buffer_size += (uint64_t) spr->img_stride[level] * slices;
>  
>        width  = u_minify(width, 1);
>        height = u_minify(height, 1);
> @@ -253,22 +262,9 @@ static unsigned
>  sp_get_tex_image_offset(const struct softpipe_resource *spr,
>                          unsigned level, unsigned layer)
>  {
> -   const unsigned hgt = u_minify(spr->base.height0, level);
> -   const unsigned nblocksy = util_format_get_nblocksy(spr->base.format, hgt);
>     unsigned offset = spr->level_offset[level];
>  
> -   if (spr->base.target == PIPE_TEXTURE_CUBE ||
> -       spr->base.target == PIPE_TEXTURE_CUBE_ARRAY ||
> -       spr->base.target == PIPE_TEXTURE_3D ||
> -       spr->base.target == PIPE_TEXTURE_2D_ARRAY) {
> -      offset += layer * nblocksy * spr->stride[level];
> -   }
> -   else if (spr->base.target == PIPE_TEXTURE_1D_ARRAY) {
> -      offset += layer * spr->stride[level];
> -   }
> -   else {
> -      assert(layer == 0);
> -   }
> +   offset += layer * spr->img_stride[level];
>  
>     return offset;
>  }
> @@ -354,8 +350,6 @@ softpipe_transfer_map(struct pipe_context *pipe,
>     struct softpipe_transfer *spt;
>     struct pipe_transfer *pt;
>     enum pipe_format format = resource->format;
> -   const unsigned hgt = u_minify(spr->base.height0, level);
> -   const unsigned nblocksy = util_format_get_nblocksy(format, hgt);
>     uint8_t *map;
>  
>     assert(resource);
> @@ -414,7 +408,7 @@ softpipe_transfer_map(struct pipe_context *pipe,
>     pt->usage = usage;
>     pt->box = *box;
>     pt->stride = spr->stride[level];
> -   pt->layer_stride = pt->stride * nblocksy;
> +   pt->layer_stride = spr->img_stride[level];
>  
>     spt->offset = sp_get_tex_image_offset(spr, level, box->z);
>  
> diff --git a/src/gallium/drivers/softpipe/sp_texture.h b/src/gallium/drivers/softpipe/sp_texture.h
> index 90f35e1..1701bf5 100644
> --- a/src/gallium/drivers/softpipe/sp_texture.h
> +++ b/src/gallium/drivers/softpipe/sp_texture.h
> @@ -47,6 +47,7 @@ struct softpipe_resource
>  
>     unsigned long level_offset[SP_MAX_TEXTURE_2D_LEVELS];
>     unsigned stride[SP_MAX_TEXTURE_2D_LEVELS];
> +   unsigned img_stride[SP_MAX_TEXTURE_2D_LEVELS];
>  
>     /**
>      * Display target, only valid for PIPE_TEXTURE_2D with the
> 



More information about the mesa-dev mailing list