[Mesa-dev] [PATCH] llvmpipe: support rendering to buffer render targets.
Christoph Bumiller
e0425955 at student.tuwien.ac.at
Wed Feb 27 03:05:48 PST 2013
On 27.02.2013 10:44, Jose Fonseca wrote:
> ----- 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?)
I can think of rendering to vertex buffers. It's just annoying that
there are no alignment restrictions on the range that is bound (worst
case you have to render to a temporary buffer and copy stuff around);
but at least it has to be <= 8192 bytes (or elements, not sure) in D3D10.
>> 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
> _______________________________________________
> 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