Make COPY_TRANSFER3D bidirectional

COPY_TRANSFER3D was designed to handle transfers
to host. This patch is making it possible to use
this CCMD in both directions.

If guest would like to have this data available
immediately, then it should encode, flush and wait on
the guest side.

The data is copied from host to iovec attached to resource.
In most cases resource is a staging buffer.

Reviewed-by: Gert Wollny <gert.wollny@collabora.com>
macos/master
mwezdeck 3 years ago committed by Maksym Wezdecki
parent 453017e32a
commit 778ad42253
  1. 1
      src/virgl_hw.h
  2. 8
      src/virgl_protocol.h
  3. 26
      src/vrend_decode.c
  4. 47
      src/vrend_renderer.c
  5. 5
      src/vrend_renderer.h

@ -442,6 +442,7 @@ enum virgl_formats {
#define VIRGL_CAP_V2_STRING_MARKER (1 << 4) #define VIRGL_CAP_V2_STRING_MARKER (1 << 4)
#define VIRGL_CAP_V2_DIFFERENT_GPU (1 << 5) #define VIRGL_CAP_V2_DIFFERENT_GPU (1 << 5)
#define VIRGL_CAP_V2_IMPLICIT_MSAA (1 << 6) #define VIRGL_CAP_V2_IMPLICIT_MSAA (1 << 6)
#define VIRGL_CAP_V2_COPY_TRANSFER_BOTH_DIRECTIONS (1 << 7)
/* virgl bind flags - these are compatible with mesa 10.5 gallium. /* virgl bind flags - these are compatible with mesa 10.5 gallium.
* but are fixed, no other should be passed to virgl either. * but are fixed, no other should be passed to virgl either.

@ -608,12 +608,16 @@ enum virgl_context_cmd {
#define VIRGL_TRANSFER3D_DATA_OFFSET 12 #define VIRGL_TRANSFER3D_DATA_OFFSET 12
#define VIRGL_TRANSFER3D_DIRECTION 13 #define VIRGL_TRANSFER3D_DIRECTION 13
/* Copy transfer */ /* Copy transfer to host and from host*/
#define VIRGL_COPY_TRANSFER3D_SIZE 14 #define VIRGL_COPY_TRANSFER3D_SIZE 14
/* The first 11 dwords are the same as VIRGL_RESOURCE_IW_* */ /* The first 11 dwords are the same as VIRGL_RESOURCE_IW_* */
#define VIRGL_COPY_TRANSFER3D_SRC_RES_HANDLE 12 #define VIRGL_COPY_TRANSFER3D_SRC_RES_HANDLE 12
#define VIRGL_COPY_TRANSFER3D_SRC_RES_OFFSET 13 #define VIRGL_COPY_TRANSFER3D_SRC_RES_OFFSET 13
#define VIRGL_COPY_TRANSFER3D_SYNCHRONIZED 14 #define VIRGL_COPY_TRANSFER3D_FLAGS 14
#define VIRGL_COPY_TRANSFER3D_FLAGS_SYNCHRONIZED (1 << 0)
/* 1 << 1 means transfer from host.
0 << 1 means transfer to host.*/
#define VIRGL_COPY_TRANSFER3D_FLAGS_READ_FROM_HOST (1 << 1)
/* set tweak flags */ /* set tweak flags */
#define VIRGL_SET_TWEAKS_SIZE 2 #define VIRGL_SET_TWEAKS_SIZE 2

@ -1420,19 +1420,39 @@ static int vrend_decode_copy_transfer3d(struct vrend_context *ctx, const uint32_
uint32_t dst_handle; uint32_t dst_handle;
uint32_t src_handle; uint32_t src_handle;
memset(&info, 0, sizeof(info));
info.box = &box;
if (length != VIRGL_COPY_TRANSFER3D_SIZE) if (length != VIRGL_COPY_TRANSFER3D_SIZE)
return EINVAL; return EINVAL;
memset(&info, 0, sizeof(info)); // synchronized is set either to 1 or 0. This means that we can use other bits
info.box = &box; // to identify the direction of copy transfer
uint32_t flags = get_buf_entry(buf, VIRGL_COPY_TRANSFER3D_FLAGS);
bool read_from_host = flags & (1 << 1);
bool synchronized = flags & (1 << 0);
if (!read_from_host) {
// this means that guest would like to make transfer to host
// it can also mean that guest is using legacy copy transfer path
vrend_decode_transfer_common(buf, &dst_handle, &info); vrend_decode_transfer_common(buf, &dst_handle, &info);
info.offset = get_buf_entry(buf, VIRGL_COPY_TRANSFER3D_SRC_RES_OFFSET); info.offset = get_buf_entry(buf, VIRGL_COPY_TRANSFER3D_SRC_RES_OFFSET);
info.synchronized = (get_buf_entry(buf, VIRGL_COPY_TRANSFER3D_SYNCHRONIZED) != 0); info.synchronized = (synchronized != 0);
src_handle = get_buf_entry(buf, VIRGL_COPY_TRANSFER3D_SRC_RES_HANDLE); src_handle = get_buf_entry(buf, VIRGL_COPY_TRANSFER3D_SRC_RES_HANDLE);
return vrend_renderer_copy_transfer3d(ctx, dst_handle, src_handle, return vrend_renderer_copy_transfer3d(ctx, dst_handle, src_handle,
&info); &info);
} else {
vrend_decode_transfer_common(buf, &src_handle, &info);
info.offset = get_buf_entry(buf, VIRGL_COPY_TRANSFER3D_SRC_RES_OFFSET);
info.synchronized = (synchronized != 0);
dst_handle = get_buf_entry(buf, VIRGL_COPY_TRANSFER3D_SRC_RES_HANDLE);
return vrend_renderer_copy_transfer3d_from_host(ctx, dst_handle, src_handle,
&info);
}
} }
static int vrend_decode_pipe_resource_create(struct vrend_context *ctx, const uint32_t *buf, uint32_t length) static int vrend_decode_pipe_resource_create(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)

@ -8574,6 +8574,45 @@ int vrend_renderer_copy_transfer3d(struct vrend_context *ctx,
src_res->num_iovs, info); src_res->num_iovs, info);
} }
int vrend_renderer_copy_transfer3d_from_host(struct vrend_context *ctx,
uint32_t dst_handle,
uint32_t src_handle,
const struct vrend_transfer_info *info)
{
struct vrend_resource *src_res, *dst_res;
src_res = vrend_renderer_ctx_res_lookup(ctx, src_handle);
dst_res = vrend_renderer_ctx_res_lookup(ctx, dst_handle);
if (!src_res) {
vrend_report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, src_handle);
return EINVAL;
}
if (!dst_res) {
vrend_report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, dst_handle);
return EINVAL;
}
if (!dst_res->iov) {
vrend_report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, dst_handle);
return EINVAL;
}
if (!check_transfer_bounds(src_res, info)) {
vrend_report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_CMD_BUFFER, dst_handle);
return EINVAL;
}
if (!check_iov_bounds(src_res, info, dst_res->iov, dst_res->num_iovs)) {
vrend_report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_CMD_BUFFER, dst_handle);
return EINVAL;
}
return vrend_renderer_transfer_send_iov(ctx, src_res, dst_res->iov,
dst_res->num_iovs, info);
}
void vrend_set_stencil_ref(struct vrend_context *ctx, void vrend_set_stencil_ref(struct vrend_context *ctx,
struct pipe_stencil_ref *ref) struct pipe_stencil_ref *ref)
{ {
@ -10888,6 +10927,14 @@ static void vrend_renderer_fill_caps_v2(int gl_ver, int gles_ver, union virgl_c
if (vrend_winsys_different_gpu()) if (vrend_winsys_different_gpu())
caps->v2.capability_bits_v2 |= VIRGL_CAP_V2_DIFFERENT_GPU; caps->v2.capability_bits_v2 |= VIRGL_CAP_V2_DIFFERENT_GPU;
// we use capability bits (not a version of protocol), because
// we disable this on client side if virglrenderer is used under
// vtest. vtest can't support this, because size of resource
// is used to create shmem. On drm path, we can use this, because
// size of drm resource (bo) is not passed to virglrenderer and
// we can pass "1" as size on drm path, but not on vtest.
caps->v2.capability_bits_v2 |= VIRGL_CAP_V2_COPY_TRANSFER_BOTH_DIRECTIONS;
if (has_feature(feat_anisotropic_filter)) { if (has_feature(feat_anisotropic_filter)) {
float max_aniso; float max_aniso;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &max_aniso); glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &max_aniso);

@ -256,6 +256,11 @@ int vrend_renderer_copy_transfer3d(struct vrend_context *ctx,
uint32_t src_handle, uint32_t src_handle,
const struct vrend_transfer_info *info); const struct vrend_transfer_info *info);
int vrend_renderer_copy_transfer3d_from_host(struct vrend_context *ctx,
uint32_t dst_handle,
uint32_t src_handle,
const struct vrend_transfer_info *info);
void vrend_set_viewport_states(struct vrend_context *ctx, void vrend_set_viewport_states(struct vrend_context *ctx,
uint32_t start_slot, uint32_t num_viewports, uint32_t start_slot, uint32_t num_viewports,
const struct pipe_viewport_state *state); const struct pipe_viewport_state *state);

Loading…
Cancel
Save