[Mesa-dev] [PATCH] llvmpipe: support rendering to buffer render targets.
Roland Scheidegger
sroland at vmware.com
Wed Feb 27 05:25:15 PST 2013
Am 27.02.2013 14:11, schrieb Jose Fonseca:
> Looks good.
>
> I think the u_surface change could go in separately though.
Ok.
>
> BTW, now that we can render/sampler from buffers, llvmpipe_is_resource_referenced needs to be updated: buffer may be referenced if they have BIND_SAMPLER/RENDERTARGET.
You are right. I actually looked at that llvmpipe_flush_resource
function and the rest seemed ok but didn't notice that
llvmpipe_is_resource_referenced wouldn't do anything for buffers.
I'll fix that.
>
> Weshould do something like if !BIND_SAMPLER/RENDERTARGET, return UNREFERENCED.
>
> Jose
>
> ----- Original Message -----
>> 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
>>
More information about the mesa-dev
mailing list