virgl_encoder_set_sub_ctx(ctx, ctx->hw_sub_ctx_id);
ctx->cbuf_initial_cdw = ctx->cbuf->cdw;
+
+ /* We have flushed the command queue, including any pending copy transfers
+ * involving staging resources.
+ */
+ ctx->queued_staging_res_size = 0;
}
static void virgl_flush_from_st(struct pipe_context *ctx,
struct primconvert_context *primconvert;
uint32_t hw_sub_ctx_id;
+
+ /* The total size of staging resources used in queued copy transfers. */
+ uint64_t queued_staging_res_size;
};
static inline struct virgl_sampler_view *
#include "virgl_resource.h"
#include "virgl_screen.h"
+/* A (soft) limit for the amount of memory we want to allow for queued staging
+ * resources. This is used to decide when we should force a flush, in order to
+ * avoid exhausting virtio-gpu memory.
+ */
+#define VIRGL_QUEUED_STAGING_RES_SIZE_LIMIT (128 * 1024 * 1024)
+
/* We need to flush to properly sync the transfer with the current cmdbuf.
* But there are cases where the flushing can be skipped:
*
copy_transfer = false;
}
- /* When performing a copy transfer there is no need to flush or wait for
- * the target resource.
+ /* When performing a copy transfer there is no need wait for the target
+ * resource. There is normally no need to flush either, unless the amount of
+ * memory we are using for staging resources starts growing, in which case
+ * we want to flush to keep our memory consumption in check.
*/
if (copy_transfer) {
- flush = false;
+ flush = (vctx->queued_staging_res_size > VIRGL_QUEUED_STAGING_RES_SIZE_LIMIT);
wait = false;
}
*/
vtransfer->base.stride = stride;
vtransfer->base.layer_stride = layer_stride;
+
+ /* Track the total size of active staging resources. */
+ vctx->queued_staging_res_size += size + align_offset;
}
return map_addr;