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-03-14 09:06:06 +0100 |
commit | 1568f9fe94f2f43e50b9657da87af143b705dea3 (patch) | |
tree | 1ed39bc614d6843015d4ba98ca3c9338af28bebf | |
parent | 9198e790b71c2c876bd2340d073a3e82b95e9dbd (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 7158a77c84..009693fa30 100644 --- a/src/gallium/drivers/radeon/r600_texture.c +++ b/src/gallium/drivers/radeon/r600_texture.c @@ -176,14 +176,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) @@ -197,8 +210,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; @@ -1690,7 +1701,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 = @@ -1782,9 +1795,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; |