[Mesa-dev] [PATCH] llvmpipe: support rendering to buffer render targets.

Jose Fonseca jfonseca at vmware.com
Wed Feb 27 01:44:53 PST 2013


----- Original Message -----
> What is this good for? Is it for UAVs? (unordered access views)

No, it is just a standard D3D10 feature: http://msdn.microsoft.com/en-gb/library/windows/desktop/bb204897.aspx

Not sure if there's a particular use case for it (e.g, maybe DirectCompute uses this extensively), or just a matter of symmetry in the API (ie., if one can sample from buffer textures, then why not render into them?)

> For UAVs, I think there is ARB_shader_storage_buffer_object and
> pipe_context::set_shader_resources.

Yeah, D3D11 UAVs are also supposed to be bound separately in the pipeline.

Jose

> 
> Marek
> 
> On Wed, Feb 27, 2013 at 3:18 AM,  <sroland at vmware.com> wrote:
> > From: Roland Scheidegger <sroland at vmware.com>
> >
> > Unfortunately not usable from OpenGL, and no cap bit.
> > Pretty similar to a 1d texture, though allows specifying a start element.
> > The util code for handling clears also needs adjustments (and fix
> > a bug causing crashes for handling pure integer formats there too).
> > ---
> >  src/gallium/auxiliary/util/u_surface.c      |   55
> >  +++++++++++++++++++++++----
> >  src/gallium/drivers/llvmpipe/lp_rast.c      |   25 ++----------
> >  src/gallium/drivers/llvmpipe/lp_rast_priv.h |    4 +-
> >  src/gallium/drivers/llvmpipe/lp_scene.c     |   35 +++++++++++------
> >  src/gallium/drivers/llvmpipe/lp_texture.c   |   44 +++++++++++++++------
> >  5 files changed, 108 insertions(+), 55 deletions(-)
> >
> > diff --git a/src/gallium/auxiliary/util/u_surface.c
> > b/src/gallium/auxiliary/util/u_surface.c
> > index b948b46..fba0798 100644
> > --- a/src/gallium/auxiliary/util/u_surface.c
> > +++ b/src/gallium/auxiliary/util/u_surface.c
> > @@ -323,20 +323,59 @@ util_clear_render_target(struct pipe_context *pipe,
> >     if (!dst->texture)
> >        return;
> >     /* XXX: should handle multiple layers */
> > -   dst_map = pipe_transfer_map(pipe,
> > -                               dst->texture,
> > -                               dst->u.tex.level,
> > -                               dst->u.tex.first_layer,
> > -                               PIPE_TRANSFER_WRITE,
> > -                               dstx, dsty, width, height, &dst_trans);
> > +
> > +   if (dst->texture->target == PIPE_BUFFER) {
> > +      /*
> > +       * The fill naturally works on the surface format, however
> > +       * the transfer uses resource format which is just bytes for
> > buffers.
> > +       */
> > +      unsigned dx, w;
> > +      unsigned pixstride = util_format_get_blocksize(dst->format);
> > +      dx = dstx * pixstride;
> > +      w = width * pixstride;
> > +      dst_map = pipe_transfer_map(pipe,
> > +                                  dst->texture,
> > +                                  0, 0,
> > +                                  PIPE_TRANSFER_WRITE,
> > +                                  dx, 0, w, 1,
> > +                                  &dst_trans);
> > +      dst_map = (uint8_t *)dst_map + dst->u.buf.first_element * pixstride;
> > +   }
> > +   else {
> > +      /* XXX: should handle multiple layers */
> > +      dst_map = pipe_transfer_map(pipe,
> > +                                  dst->texture,
> > +                                  dst->u.tex.level,
> > +                                  dst->u.tex.first_layer,
> > +                                  PIPE_TRANSFER_WRITE,
> > +                                  dstx, dsty, width, height, &dst_trans);
> > +
> > +   }
> >
> >     assert(dst_map);
> >
> >     if (dst_map) {
> > +      enum pipe_format format = dst->format;
> >        assert(dst_trans->stride > 0);
> >
> > -      util_pack_color(color->f, dst->texture->format, &uc);
> > -      util_fill_rect(dst_map, dst->texture->format,
> > +      if (util_format_is_pure_integer(format)) {
> > +         /*
> > +          * We expect int/uint clear values here, though some APIs
> > +          * might disagree (but in any case util_pack_color()
> > +          * couldn't handle it)...
> > +          */
> > +         if (util_format_is_pure_sint(format)) {
> > +            util_format_write_4i(format, color->i, 0, &uc, 0, 0, 0, 1, 1);
> > +         }
> > +         else {
> > +            assert(util_format_is_pure_uint(format));
> > +            util_format_write_4ui(format, color->ui, 0, &uc, 0, 0, 0, 1,
> > 1);
> > +         }
> > +      }
> > +      else {
> > +         util_pack_color(color->f, dst->format, &uc);
> > +      }
> > +      util_fill_rect(dst_map, dst->format,
> >                       dst_trans->stride,
> >                       0, 0, width, height, &uc);
> >
> > diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c
> > b/src/gallium/drivers/llvmpipe/lp_rast.c
> > index b5e5da6..6183f41 100644
> > --- a/src/gallium/drivers/llvmpipe/lp_rast.c
> > +++ b/src/gallium/drivers/llvmpipe/lp_rast.c
> > @@ -165,32 +165,13 @@ lp_rast_clear_color(struct lp_rasterizer_task *task,
> >
> >           for (i = 0; i < scene->fb.nr_cbufs; i++) {
> >              enum pipe_format format = scene->fb.cbufs[i]->format;
> > -            /*
> > -             * XXX the format_write_4i/ui functions do clamping to max
> > value
> > -             * and I'm not sure that's actually right - spec doesn't seem
> > to
> > -             * say much about that topic. If it is should probably adjust
> > the
> > -             * border color handling to do the same. If not and chopping
> > off
> > -             * bits is the way to go, the write_4i and write_4ui functions
> > -             * would be identical.
> > -             */
> > -            if (util_format_is_pure_sint(format)) {
> > -               int rgba[4];
> > -               rgba[0] = arg.clear_color.i[0];
> > -               rgba[1] = arg.clear_color.i[1];
> > -               rgba[2] = arg.clear_color.i[2];
> > -               rgba[3] = arg.clear_color.i[3];
> >
> > -               util_format_write_4i(format, rgba, 0, &uc, 0, 0, 0, 1, 1);
> > +            if (util_format_is_pure_sint(format)) {
> > +               util_format_write_4i(format, arg.clear_color.i, 0, &uc, 0,
> > 0, 0, 1, 1);
> >              }
> >              else {
> > -               unsigned rgba[4];
> > -               rgba[0] = arg.clear_color.ui[0];
> > -               rgba[1] = arg.clear_color.ui[1];
> > -               rgba[2] = arg.clear_color.ui[2];
> > -               rgba[3] = arg.clear_color.ui[3];
> > -
> >                 assert(util_format_is_pure_uint(format));
> > -               util_format_write_4ui(format, rgba, 0, &uc, 0, 0, 0, 1, 1);
> > +               util_format_write_4ui(format, arg.clear_color.ui, 0, &uc,
> > 0, 0, 0, 1, 1);
> >              }
> >
> >              util_fill_rect(scene->cbufs[i].map,
> > diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h
> > b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
> > index 5db8fcd..c0f41f6 100644
> > --- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h
> > +++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
> > @@ -196,7 +196,7 @@ lp_rast_get_unswizzled_color_tile_pointer(struct
> > lp_rasterizer_task *task,
> >        struct pipe_surface *cbuf = scene->fb.cbufs[buf];
> >        assert(cbuf);
> >
> > -      format_bytes = util_format_description(cbuf->format)->block.bits /
> > 8;
> > +      format_bytes = util_format_get_blocksize(cbuf->format);
> >        task->color_tiles[buf] = scene->cbufs[buf].map +
> >        scene->cbufs[buf].stride * task->y + format_bytes * task->x;
> >     }
> >
> > @@ -221,7 +221,7 @@ lp_rast_get_unswizzled_color_block_pointer(struct
> > lp_rasterizer_task *task,
> >     assert((y % TILE_VECTOR_HEIGHT) == 0);
> >     assert(buf < task->scene->fb.nr_cbufs);
> >
> > -   format_bytes =
> > util_format_description(task->scene->fb.cbufs[buf]->format)->block.bits /
> > 8;
> > +   format_bytes =
> > util_format_get_blocksize(task->scene->fb.cbufs[buf]->format);
> >
> >     color = lp_rast_get_unswizzled_color_tile_pointer(task, buf,
> >     LP_TEX_USAGE_READ_WRITE);
> >     assert(color);
> > diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c
> > b/src/gallium/drivers/llvmpipe/lp_scene.c
> > index 328c0f7..fec2f74 100644
> > --- a/src/gallium/drivers/llvmpipe/lp_scene.c
> > +++ b/src/gallium/drivers/llvmpipe/lp_scene.c
> > @@ -141,15 +141,24 @@ lp_scene_begin_rasterization(struct lp_scene *scene)
> >
> >     for (i = 0; i < scene->fb.nr_cbufs; i++) {
> >        struct pipe_surface *cbuf = scene->fb.cbufs[i];
> > -      assert(cbuf->u.tex.first_layer == cbuf->u.tex.last_layer);
> > -      scene->cbufs[i].stride = llvmpipe_resource_stride(cbuf->texture,
> > -
> > cbuf->u.tex.level);
> > -
> > -      scene->cbufs[i].map = llvmpipe_resource_map(cbuf->texture,
> > -                                                  cbuf->u.tex.level,
> > -                                                  cbuf->u.tex.first_layer,
> > -                                                  LP_TEX_USAGE_READ_WRITE,
> > -                                                  LP_TEX_LAYOUT_LINEAR);
> > +      if (llvmpipe_resource_is_texture(cbuf->texture)) {
> > +         assert(cbuf->u.tex.first_layer == cbuf->u.tex.last_layer);
> > +         scene->cbufs[i].stride = llvmpipe_resource_stride(cbuf->texture,
> > +
> > cbuf->u.tex.level);
> > +
> > +         scene->cbufs[i].map = llvmpipe_resource_map(cbuf->texture,
> > +                                                     cbuf->u.tex.level,
> > +
> > cbuf->u.tex.first_layer,
> > +
> > LP_TEX_USAGE_READ_WRITE,
> > +
> > LP_TEX_LAYOUT_LINEAR);
> > +      }
> > +      else {
> > +         struct llvmpipe_resource *lpr = llvmpipe_resource(cbuf->texture);
> > +         unsigned pixstride = util_format_get_blocksize(cbuf->format);
> > +         scene->cbufs[i].stride = cbuf->texture->width0;
> > +         scene->cbufs[i].map = lpr->data;
> > +         scene->cbufs[i].map += cbuf->u.buf.first_element * pixstride;
> > +      }
> >     }
> >
> >     if (fb->zsbuf) {
> > @@ -182,9 +191,11 @@ lp_scene_end_rasterization(struct lp_scene *scene )
> >     for (i = 0; i < scene->fb.nr_cbufs; i++) {
> >        if (scene->cbufs[i].map) {
> >           struct pipe_surface *cbuf = scene->fb.cbufs[i];
> > -         llvmpipe_resource_unmap(cbuf->texture,
> > -                                 cbuf->u.tex.level,
> > -                                 cbuf->u.tex.first_layer);
> > +         if (llvmpipe_resource_is_texture(cbuf->texture)) {
> > +            llvmpipe_resource_unmap(cbuf->texture,
> > +                                    cbuf->u.tex.level,
> > +                                    cbuf->u.tex.first_layer);
> > +         }
> >           scene->cbufs[i].map = NULL;
> >        }
> >     }
> > diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c
> > b/src/gallium/drivers/llvmpipe/lp_texture.c
> > index f923292..7387166 100644
> > --- a/src/gallium/drivers/llvmpipe/lp_texture.c
> > +++ b/src/gallium/drivers/llvmpipe/lp_texture.c
> > @@ -297,6 +297,12 @@ llvmpipe_resource_create(struct pipe_screen *_screen,
> >        assert(templat->depth0 == 1);
> >        assert(templat->last_level == 0);
> >        lpr->data = align_malloc(bytes, 16);
> > +      /*
> > +       * buffers don't really have stride but it's probably safer
> > +       * (for code doing same calculations for buffers and textures)
> > +       * to put something sane in there.
> > +       */
> > +      lpr->row_stride[0] = bytes;
> >        if (!lpr->data)
> >           goto fail;
> >        memset(lpr->data, 0, bytes);
> > @@ -578,12 +584,23 @@ llvmpipe_create_surface(struct pipe_context *pipe,
> >        pipe_resource_reference(&ps->texture, pt);
> >        ps->context = pipe;
> >        ps->format = surf_tmpl->format;
> > -      ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level);
> > -      ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level);
> > -
> > -      ps->u.tex.level = surf_tmpl->u.tex.level;
> > -      ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
> > -      ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
> > +      if (llvmpipe_resource_is_texture(pt)) {
> > +         assert(surf_tmpl->u.tex.level <= pt->last_level);
> > +         ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level);
> > +         ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level);
> > +         ps->u.tex.level = surf_tmpl->u.tex.level;
> > +         ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
> > +         ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
> > +      }
> > +      else {
> > +         const enum pipe_format format = surf_tmpl->format;
> > +         ps->width = pt->width0 / util_format_get_blocksize(format);
> > +         ps->height = pt->height0;
> > +         ps->u.buf.first_element = surf_tmpl->u.buf.first_element;
> > +         ps->u.buf.last_element = surf_tmpl->u.buf.last_element;
> > +         assert(ps->u.buf.first_element <= ps->u.buf.last_element);
> > +         assert(ps->u.buf.last_element < ps->width);
> > +      }
> >     }
> >     return ps;
> >  }
> > @@ -1342,12 +1359,17 @@ llvmpipe_resource_size(const struct pipe_resource
> > *resource)
> >     const struct llvmpipe_resource *lpr =
> >     llvmpipe_resource_const(resource);
> >     unsigned lvl, size = 0;
> >
> > -   for (lvl = 0; lvl <= lpr->base.last_level; lvl++) {
> > -      if (lpr->linear_img.data)
> > -         size += tex_image_size(lpr, lvl, LP_TEX_LAYOUT_LINEAR);
> > +   if (llvmpipe_resource_is_texture(resource)) {
> > +      for (lvl = 0; lvl <= lpr->base.last_level; lvl++) {
> > +         if (lpr->linear_img.data)
> > +            size += tex_image_size(lpr, lvl, LP_TEX_LAYOUT_LINEAR);
> >
> > -      if (lpr->tiled_img.data)
> > -         size += tex_image_size(lpr, lvl, LP_TEX_LAYOUT_TILED);
> > +         if (lpr->tiled_img.data)
> > +            size += tex_image_size(lpr, lvl, LP_TEX_LAYOUT_TILED);
> > +      }
> > +   }
> > +   else {
> > +      size = resource->width0;
> >     }
> >
> >     return size;
> > --
> > 1.7.9.5
> >
> > _______________________________________________
> > mesa-dev mailing list
> > mesa-dev at lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/mesa-dev
> 


More information about the mesa-dev mailing list