diff --git a/tests/test_virgl_transfer.c b/tests/test_virgl_transfer.c index e4bf2f5..6748e50 100644 --- a/tests/test_virgl_transfer.c +++ b/tests/test_virgl_transfer.c @@ -30,6 +30,7 @@ #include #include "pipe/p_defines.h" #include "virgl_hw.h" +#include "virgl_protocol.h" #include "testvirgl_encode.h" /* pass an illegal context to transfer fn */ @@ -727,6 +728,197 @@ START_TEST(virgl_test_transfer_inline_valid_large) } END_TEST +START_TEST(virgl_test_transfer_to_staging_without_iov_fails) +{ + static const unsigned bufsize = 50; + struct virgl_context ctx; + struct virgl_resource res; + struct pipe_box box; + int ret; + + ret = testvirgl_init_ctx_cmdbuf(&ctx); + ck_assert_int_eq(ret, 0); + + ret = testvirgl_create_unbacked_simple_buffer(&res, 1, bufsize, VIRGL_BIND_STAGING); + ck_assert_int_eq(ret, 0); + virgl_renderer_ctx_attach_resource(ctx.ctx_id, res.handle); + + box.width = bufsize; + virgl_encoder_transfer(&ctx, &res, 0, 0, &box, 0, VIRGL_TRANSFER_TO_HOST); + + ret = virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw); + ck_assert_int_eq(ret, EINVAL); + + virgl_renderer_ctx_detach_resource(ctx.ctx_id, res.handle); + virgl_renderer_resource_unref(res.handle); + testvirgl_fini_ctx_cmdbuf(&ctx); +} +END_TEST + +START_TEST(virgl_test_transfer_to_staging_with_iov_succeeds) +{ + static const unsigned bufsize = 50; + struct virgl_context ctx = {0}; + struct virgl_resource res = {0}; + struct pipe_box box = {0}; + int ret; + + ret = testvirgl_init_ctx_cmdbuf(&ctx); + ck_assert_int_eq(ret, 0); + + ret = testvirgl_create_backed_simple_buffer(&res, 1, bufsize, VIRGL_BIND_STAGING); + ck_assert_int_eq(ret, 0); + virgl_renderer_ctx_attach_resource(ctx.ctx_id, res.handle); + + box.width = bufsize; + virgl_encoder_transfer(&ctx, &res, 0, 0, &box, 0, VIRGL_TRANSFER_TO_HOST); + + ret = virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw); + ck_assert_int_eq(ret, 0); + + virgl_renderer_ctx_detach_resource(ctx.ctx_id, res.handle); + testvirgl_destroy_backed_res(&res); + testvirgl_fini_ctx_cmdbuf(&ctx); +} +END_TEST + +START_TEST(virgl_test_copy_transfer_from_staging_without_iov_fails) +{ + static const unsigned bufsize = 50; + static const unsigned synchronized = 1; + struct virgl_context ctx = {0}; + struct virgl_resource src_res = {0}; + struct virgl_resource dst_res = {0}; + struct pipe_box box = {0}; + int ret; + + ret = testvirgl_init_ctx_cmdbuf(&ctx); + ck_assert_int_eq(ret, 0); + + ret = testvirgl_create_unbacked_simple_buffer(&src_res, 1, bufsize, VIRGL_BIND_STAGING); + ck_assert_int_eq(ret, 0); + virgl_renderer_ctx_attach_resource(ctx.ctx_id, src_res.handle); + + ret = testvirgl_create_backed_simple_buffer(&dst_res, 2, bufsize, VIRGL_BIND_VERTEX_BUFFER); + ck_assert_int_eq(ret, 0); + virgl_renderer_ctx_attach_resource(ctx.ctx_id, dst_res.handle); + + box.width = bufsize; + virgl_encoder_copy_transfer(&ctx, &dst_res, 0, 0, &box, &src_res, 0, synchronized); + + ret = virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw); + ck_assert_int_eq(ret, EINVAL); + + virgl_renderer_ctx_detach_resource(ctx.ctx_id, src_res.handle); + virgl_renderer_ctx_detach_resource(ctx.ctx_id, dst_res.handle); + virgl_renderer_resource_unref(src_res.handle); + testvirgl_destroy_backed_res(&dst_res); + testvirgl_fini_ctx_cmdbuf(&ctx); +} +END_TEST + +START_TEST(virgl_test_copy_transfer_from_staging_with_iov_succeeds) +{ + static const unsigned bufsize = 50; + const unsigned synchronized = 1; + struct virgl_context ctx = {0}; + struct virgl_resource src_res = {0}; + struct virgl_resource dst_res = {0}; + struct pipe_box box = {0}; + int ret; + + ret = testvirgl_init_ctx_cmdbuf(&ctx); + ck_assert_int_eq(ret, 0); + + ret = testvirgl_create_backed_simple_buffer(&src_res, 1, bufsize, VIRGL_BIND_STAGING); + ck_assert_int_eq(ret, 0); + virgl_renderer_ctx_attach_resource(ctx.ctx_id, src_res.handle); + + ret = testvirgl_create_backed_simple_buffer(&dst_res, 2, bufsize, VIRGL_BIND_VERTEX_BUFFER); + ck_assert_int_eq(ret, 0); + virgl_renderer_ctx_attach_resource(ctx.ctx_id, dst_res.handle); + + box.width = bufsize; + virgl_encoder_copy_transfer(&ctx, &dst_res, 0, 0, &box, &src_res, 0, synchronized); + + ret = virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw); + ck_assert_int_eq(ret, 0); + + virgl_renderer_ctx_detach_resource(ctx.ctx_id, src_res.handle); + virgl_renderer_ctx_detach_resource(ctx.ctx_id, dst_res.handle); + testvirgl_destroy_backed_res(&src_res); + testvirgl_destroy_backed_res(&dst_res); + testvirgl_fini_ctx_cmdbuf(&ctx); +} +END_TEST + +START_TEST(virgl_test_copy_transfer_to_staging_without_iov_fails) +{ + const unsigned synchronized = 1; + struct virgl_context ctx = {0}; + struct virgl_resource src_res = {0}; + struct virgl_resource dst_res = {0}; + struct pipe_box box = {0}; + int ret; + + ret = testvirgl_init_ctx_cmdbuf(&ctx); + ck_assert_int_eq(ret, 0); + + ret = testvirgl_create_backed_simple_buffer(&src_res, 1, 50, VIRGL_BIND_STAGING); + ck_assert_int_eq(ret, 0); + virgl_renderer_ctx_attach_resource(ctx.ctx_id, src_res.handle); + + ret = testvirgl_create_unbacked_simple_buffer(&dst_res, 2, 50, VIRGL_BIND_STAGING); + ck_assert_int_eq(ret, 0); + virgl_renderer_ctx_attach_resource(ctx.ctx_id, dst_res.handle); + + box.width = 50; + virgl_encoder_copy_transfer(&ctx, &dst_res, 0, 0, &box, &src_res, 0, synchronized); + + ret = virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw); + ck_assert_int_eq(ret, 0); + + virgl_renderer_ctx_detach_resource(ctx.ctx_id, src_res.handle); + virgl_renderer_ctx_detach_resource(ctx.ctx_id, dst_res.handle); + testvirgl_destroy_backed_res(&src_res); + virgl_renderer_resource_unref(dst_res.handle); + testvirgl_fini_ctx_cmdbuf(&ctx); +} +END_TEST +START_TEST(virgl_test_copy_transfer_to_staging_with_iov_succeeds) +{ + const unsigned synchronized = 1; + struct virgl_context ctx = {0}; + struct virgl_resource src_res = {0}; + struct virgl_resource dst_res = {0}; + struct pipe_box box = {0}; + int ret; + + ret = testvirgl_init_ctx_cmdbuf(&ctx); + ck_assert_int_eq(ret, 0); + + ret = testvirgl_create_backed_simple_buffer(&src_res, 1, 50, VIRGL_BIND_STAGING); + ck_assert_int_eq(ret, 0); + virgl_renderer_ctx_attach_resource(ctx.ctx_id, src_res.handle); + + ret = testvirgl_create_backed_simple_buffer(&dst_res, 2, 50, VIRGL_BIND_STAGING); + ck_assert_int_eq(ret, 0); + virgl_renderer_ctx_attach_resource(ctx.ctx_id, dst_res.handle); + + box.width = 50; + virgl_encoder_copy_transfer(&ctx, &dst_res, 0, 0, &box, &src_res, 0, synchronized); + + ret = virgl_renderer_submit_cmd(ctx.cbuf->buf, ctx.ctx_id, ctx.cbuf->cdw); + ck_assert_int_eq(ret, 0); + + virgl_renderer_ctx_detach_resource(ctx.ctx_id, src_res.handle); + virgl_renderer_ctx_detach_resource(ctx.ctx_id, dst_res.handle); + testvirgl_destroy_backed_res(&src_res); + testvirgl_destroy_backed_res(&dst_res); + testvirgl_fini_ctx_cmdbuf(&ctx); +} +END_TEST + static Suite *virgl_init_suite(void) { Suite *s; @@ -770,6 +962,17 @@ static Suite *virgl_init_suite(void) tcase_add_loop_test(tc_core, virgl_test_transfer_inline_valid_large, 0, PIPE_MAX_TEXTURE_TYPES); suite_add_tcase(s, tc_core); + + tc_core = tcase_create("transfers_staging"); + tcase_add_test(tc_core, virgl_test_transfer_to_staging_without_iov_fails); + tcase_add_test(tc_core, virgl_test_transfer_to_staging_with_iov_succeeds); + tcase_add_test(tc_core, virgl_test_copy_transfer_from_staging_without_iov_fails); + tcase_add_test(tc_core, virgl_test_copy_transfer_from_staging_with_iov_succeeds); + tcase_add_test(tc_core, virgl_test_copy_transfer_to_staging_without_iov_fails); + tcase_add_test(tc_core, virgl_test_copy_transfer_to_staging_with_iov_succeeds); + + suite_add_tcase(s, tc_core); + return s; } diff --git a/tests/testvirgl.c b/tests/testvirgl.c index 971f1fb..965c88b 100644 --- a/tests/testvirgl.c +++ b/tests/testvirgl.c @@ -269,6 +269,25 @@ int testvirgl_create_backed_simple_buffer(struct virgl_resource *res, return 0; } +int testvirgl_create_unbacked_simple_buffer(struct virgl_resource *res, + int handle, int size, int binding) +{ + struct virgl_renderer_resource_create_args args; + int ret; + + testvirgl_init_simple_buffer_sized(&args, handle, size); + args.bind = binding; + ret = virgl_renderer_resource_create(&args, NULL, 0); + ck_assert_int_eq(ret, 0); + + res->handle = handle; + res->base.target = args.target; + res->base.format = args.format; + res->base.bind = args.bind; + + return 0; +} + static void *get_caps(void) { uint32_t max_ver, max_size; diff --git a/tests/testvirgl.h b/tests/testvirgl.h index 108a5f8..839f14e 100644 --- a/tests/testvirgl.h +++ b/tests/testvirgl.h @@ -79,6 +79,8 @@ int testvirgl_create_backed_simple_2d_res(struct virgl_resource *res, int testvirgl_create_backed_simple_buffer(struct virgl_resource *res, int handle, int size, int bind); void testvirgl_destroy_backed_res(struct virgl_resource *res); +int testvirgl_create_unbacked_simple_buffer(struct virgl_resource *res, + int handle, int size, int bind); uint32_t testvirgl_get_glsl_level_from_caps(void); unsigned testvirgl_get_multisample_from_caps(void); #endif diff --git a/tests/testvirgl_encode.c b/tests/testvirgl_encode.c index d4ff0be..5707482 100644 --- a/tests/testvirgl_encode.c +++ b/tests/testvirgl_encode.c @@ -456,11 +456,11 @@ int virgl_encoder_create_so_target(struct virgl_context *ctx, return 0; } -static void virgl_encoder_iw_emit_header_1d(struct virgl_context *ctx, - struct virgl_resource *res, - unsigned level, unsigned usage, - const struct pipe_box *box, - unsigned stride, unsigned layer_stride) +static void virgl_encoder_transfer3d_common(struct virgl_context *ctx, + struct virgl_resource *res, + unsigned level, unsigned usage, + const struct pipe_box *box, + unsigned stride, unsigned layer_stride) { virgl_encoder_write_res(ctx, res); virgl_encoder_write_dword(ctx->cbuf, level); @@ -483,7 +483,7 @@ static void virgl_encoder_inline_send_box(struct virgl_context *ctx, unsigned layer_stride, int length) { virgl_encoder_write_cmd_dword(ctx, VIRGL_CMD0(VIRGL_CCMD_RESOURCE_INLINE_WRITE, 0, ((length + 3) / 4) + 11)); - virgl_encoder_iw_emit_header_1d(ctx, res, level, usage, box, stride, layer_stride); + virgl_encoder_transfer3d_common(ctx, res, level, usage, box, stride, layer_stride); virgl_encoder_write_block(ctx->cbuf, data, length); } @@ -563,6 +563,39 @@ int virgl_encoder_inline_write(struct virgl_context *ctx, return 0; } +int virgl_encoder_transfer(struct virgl_context *ctx, + struct virgl_resource *res, + unsigned level, unsigned usage, + const struct pipe_box *box, + unsigned offset, unsigned direction) +{ + uint32_t command; + command = VIRGL_CMD0(VIRGL_CCMD_TRANSFER3D, 0, VIRGL_TRANSFER3D_SIZE); + virgl_encoder_write_dword(ctx->cbuf, command); + virgl_encoder_transfer3d_common(ctx, res, level, usage, box, 0, 0); + virgl_encoder_write_dword(ctx->cbuf, offset); + virgl_encoder_write_dword(ctx->cbuf, direction); + return 0; +} + +int virgl_encoder_copy_transfer(struct virgl_context *ctx, + struct virgl_resource *res, + unsigned level, unsigned usage, + const struct pipe_box *box, + struct virgl_resource *src_res, + unsigned src_offset, + unsigned synchronized) +{ + uint32_t command; + command = VIRGL_CMD0(VIRGL_CCMD_COPY_TRANSFER3D, 0, VIRGL_COPY_TRANSFER3D_SIZE); + virgl_encoder_write_dword(ctx->cbuf, command); + virgl_encoder_transfer3d_common(ctx, res, level, usage, box, 0, 0); + virgl_encoder_write_res(ctx, src_res); + virgl_encoder_write_dword(ctx->cbuf, src_offset); + virgl_encoder_write_dword(ctx->cbuf, synchronized); + return 0; +} + int virgl_encoder_flush_frontbuffer(UNUSED struct virgl_context *ctx, UNUSED struct virgl_resource *res) { diff --git a/tests/testvirgl_encode.h b/tests/testvirgl_encode.h index 82b7acb..a41d4ce 100644 --- a/tests/testvirgl_encode.h +++ b/tests/testvirgl_encode.h @@ -142,6 +142,21 @@ int virgl_encoder_inline_write(struct virgl_context *ctx, const struct pipe_box *box, const void *data, unsigned stride, unsigned layer_stride); + +int virgl_encoder_transfer(struct virgl_context *ctx, + struct virgl_resource *res, + unsigned level, unsigned usage, + const struct pipe_box *box, + unsigned offset, unsigned direction); + +int virgl_encoder_copy_transfer(struct virgl_context *ctx, + struct virgl_resource *res, + unsigned level, unsigned usage, + const struct pipe_box *box, + struct virgl_resource *src_res, + unsigned src_offset, + unsigned synchronized); + int virgl_encode_sampler_state(struct virgl_context *ctx, uint32_t handle, const struct pipe_sampler_state *state);