summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/virgl/virgl_resource.c
diff options
context:
space:
mode:
authorAlexandros Frantzis <[email protected]>2019-05-24 14:03:28 +0300
committerChia-I Wu <[email protected]>2019-06-07 21:45:42 -0700
commit236c55f650d096e63a5de36e66a47a2f46bab5d3 (patch)
treeca0b892829102a126ed4b90765e118a83b791dee /src/gallium/drivers/virgl/virgl_resource.c
parenta22c5df0794515369ce0c2b35ef8cd089b6975f3 (diff)
virgl: Use copy transfers for textures
Extend copy transfers to also be used for busy textures. Performance results: Unigine Valley, qemu before: 22.7 FPS after: 23.1 FPS Signed-off-by: Alexandros Frantzis <[email protected]> Reviewed-by: Chia-I Wu <[email protected]>
Diffstat (limited to 'src/gallium/drivers/virgl/virgl_resource.c')
-rw-r--r--src/gallium/drivers/virgl/virgl_resource.c56
1 files changed, 52 insertions, 4 deletions
diff --git a/src/gallium/drivers/virgl/virgl_resource.c b/src/gallium/drivers/virgl/virgl_resource.c
index d9d79b9c0df..897e0c16c7e 100644
--- a/src/gallium/drivers/virgl/virgl_resource.c
+++ b/src/gallium/drivers/virgl/virgl_resource.c
@@ -106,8 +106,7 @@ virgl_resource_transfer_prepare(struct virgl_context *vctx,
xfer->base.level);
/* Check if we should perform a copy transfer through the transfer_uploader. */
- copy_transfer = res->u.b.target == PIPE_BUFFER &&
- discard &&
+ copy_transfer = discard &&
!readback &&
!unsynchronized &&
vctx->transfer_uploader &&
@@ -490,18 +489,58 @@ void virgl_resource_dirty(struct virgl_resource *res, uint32_t level)
}
}
+/* Calculate the minimum size of the memory required to service a resource
+ * transfer map. Also return the stride and layer_stride for the corresponding
+ * layout.
+ */
+static unsigned virgl_transfer_map_size(struct virgl_transfer *vtransfer,
+ unsigned *out_stride,
+ unsigned *out_layer_stride)
+{
+ struct pipe_resource *pres = vtransfer->base.resource;
+ struct pipe_box *box = &vtransfer->base.box;
+ unsigned stride;
+ unsigned layer_stride;
+ unsigned size;
+
+ assert(out_stride);
+ assert(out_layer_stride);
+
+ stride = util_format_get_stride(pres->format, box->width);
+ layer_stride = util_format_get_2d_size(pres->format, stride, box->height);
+
+ if (pres->target == PIPE_TEXTURE_CUBE ||
+ pres->target == PIPE_TEXTURE_CUBE_ARRAY ||
+ pres->target == PIPE_TEXTURE_3D ||
+ pres->target == PIPE_TEXTURE_2D_ARRAY) {
+ size = box->depth * layer_stride;
+ } else if (pres->target == PIPE_TEXTURE_1D_ARRAY) {
+ size = box->depth * stride;
+ } else {
+ size = layer_stride;
+ }
+
+ *out_stride = stride;
+ *out_layer_stride = layer_stride;
+
+ return size;
+}
+
+/* Maps a region from the transfer uploader to service the transfer. */
void *virgl_transfer_uploader_map(struct virgl_context *vctx,
struct virgl_transfer *vtransfer)
{
struct virgl_resource *vres = virgl_resource(vtransfer->base.resource);
unsigned size;
unsigned align_offset;
+ unsigned stride;
+ unsigned layer_stride;
void *map_addr;
assert(vctx->transfer_uploader);
assert(!vctx->transfer_uploader_in_use);
- size = vtransfer->base.box.width;
+ size = virgl_transfer_map_size(vtransfer, &stride, &layer_stride);
/* For buffers we need to ensure that the start of the buffer would be
* aligned to VIRGL_MAP_BUFFER_ALIGNMENT, even if our transfer doesn't
@@ -516,7 +555,9 @@ void *virgl_transfer_uploader_map(struct virgl_context *vctx,
* |---| ==> align_offset
* |------------| ==> allocation of size + align_offset
*/
- align_offset = vtransfer->base.box.x % VIRGL_MAP_BUFFER_ALIGNMENT;
+ align_offset = vres->u.b.target == PIPE_BUFFER ?
+ vtransfer->base.box.x % VIRGL_MAP_BUFFER_ALIGNMENT :
+ 0;
u_upload_alloc(vctx->transfer_uploader, 0, size + align_offset,
VIRGL_MAP_BUFFER_ALIGNMENT,
@@ -537,6 +578,13 @@ void *virgl_transfer_uploader_map(struct virgl_context *vctx,
/* The pointer returned by u_upload_alloc already has +offset
* applied. */
vctx->transfer_uploader_in_use = true;
+
+ /* We are using the minimum required size to hold the contents,
+ * possibly using a layout different from the layout of the resource,
+ * so update the transfer strides accordingly.
+ */
+ vtransfer->base.stride = stride;
+ vtransfer->base.layer_stride = layer_stride;
}
return map_addr;