diff options
author | Nicolai Hähnle <nicolai.haehnle@amd.com> | 2018-01-16 14:00:40 +0100 |
---|---|---|
committer | Nicolai Hähnle <nicolai.haehnle@amd.com> | 2018-01-16 20:15:32 +0100 |
commit | 9add4eaf3032f5c8d64b8a365817b4f4ce8180c5 (patch) | |
tree | 3c98b509d4a100fbd3730b7467354a54bcf1614c | |
parent | da3bdb4fec60be58a1df8fa0451ff21daed90021 (diff) |
radeonsi: implement transfer_map with user_stride
The stride ends up being aligned by AddrLib in ways that are
inconvenient to express clearly, but basically, a stride that
is aligned to both 64 pixels and 256 bytes will go through
unchanged in practice.
-rw-r--r-- | src/gallium/drivers/radeon/r600_texture.c | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c index c1f55b47bb..71816220f4 100644 --- a/src/gallium/drivers/radeon/r600_texture.c +++ b/src/gallium/drivers/radeon/r600_texture.c @@ -178,14 +178,27 @@ static void r600_copy_from_staging_texture(struct pipe_context *ctx, struct r600 src, 0, &sbox); } +static unsigned r600_texture_get_stride(struct si_screen *sscreen, + struct r600_texture *rtex, + unsigned level) +{ + if (sscreen->info.chip_class >= GFX9) { + return rtex->surface.u.gfx9.surf_pitch * rtex->surface.bpe; + } else { + return rtex->surface.u.legacy.level[level].nblk_x * + rtex->surface.bpe; + } +} + static unsigned r600_texture_get_offset(struct si_screen *sscreen, struct r600_texture *rtex, unsigned level, const struct pipe_box *box, unsigned *stride, unsigned *layer_stride) { + *stride = r600_texture_get_stride(sscreen, rtex, level); + if (sscreen->info.chip_class >= GFX9) { - *stride = rtex->surface.u.gfx9.surf_pitch * rtex->surface.bpe; *layer_stride = rtex->surface.u.gfx9.surf_slice_size; if (!box) @@ -199,8 +212,6 @@ static unsigned r600_texture_get_offset(struct si_screen *sscreen, rtex->surface.u.gfx9.surf_pitch + box->x / rtex->surface.blk_w) * rtex->surface.bpe; } else { - *stride = rtex->surface.u.legacy.level[level].nblk_x * - rtex->surface.bpe; assert((uint64_t)rtex->surface.u.legacy.level[level].slice_size_dw * 4 <= UINT_MAX); *layer_stride = (uint64_t)rtex->surface.u.legacy.level[level].slice_size_dw * 4; @@ -1671,7 +1682,9 @@ static void *r600_texture_transfer_map(struct pipe_context *ctx, * Use the staging texture for uploads if the underlying BO * is busy. */ - if (!rtex->surface.is_linear) + if (!rtex->surface.is_linear || + (user_stride && + user_stride != r600_texture_get_stride(rctx->screen, rtex, level))) use_staging_texture = true; else if (usage & PIPE_TRANSFER_READ) use_staging_texture = @@ -1763,9 +1776,19 @@ static void *r600_texture_transfer_map(struct pipe_context *ctx, } else if (use_staging_texture) { struct pipe_resource resource; struct r600_texture *staging; + struct pipe_box staging_box = *box; + + if (user_stride) { + if (user_stride % rtex->surface.bpe != 0) + goto fail_trans; - r600_init_temp_resource_from_box(&resource, texture, box, level, + staging_box.width = user_stride / rtex->surface.bpe; + assert(staging_box.width >= box->width); + } + + r600_init_temp_resource_from_box(&resource, texture, &staging_box, level, R600_RESOURCE_FLAG_TRANSFER); + resource.usage = (usage & PIPE_TRANSFER_READ) ? PIPE_USAGE_STAGING : PIPE_USAGE_STREAM; |