summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolai Hähnle <nicolai.haehnle@amd.com>2018-01-16 14:00:40 +0100
committerNicolai Hähnle <nicolai.haehnle@amd.com>2018-01-16 20:15:32 +0100
commit9add4eaf3032f5c8d64b8a365817b4f4ce8180c5 (patch)
tree3c98b509d4a100fbd3730b7467354a54bcf1614c
parentda3bdb4fec60be58a1df8fa0451ff21daed90021 (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.c33
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;