[igt-dev] [PATCH i-g-t v2 4/8] igt/vmwgfx: Add execution buffer test

Martin Krastev (VMware) martinkrastev768 at gmail.com
Thu Mar 16 13:55:52 UTC 2023


From: Martin Krastev <krastevm at vmware.com>


LGTM

Reviewed-by: Martin Krastev <krastevm at vmware.com>


Regards,

Martin


On 16.03.23 г. 14:54 ч., Martin Krastev wrote:
> From: Maaz Mombasawala <mombasawalam at vmware.com>
>
> Add execution buffer related tests in vmwgfx, includes execution buffer
> submit and syncs, mob creation and execution buffer stress test.
>
> Signed-off-by: Zack Rusin <zackr at vmware.com>
> Signed-off-by: Maaz Mombasawala <mombasawalam at vmware.com>
> ---
>   tests/vmwgfx/execution_buffer.c | 307 ++++++++++++++++++++++++++++++++
>   tests/vmwgfx/meson.build        |   3 +-
>   2 files changed, 309 insertions(+), 1 deletion(-)
>   create mode 100644 tests/vmwgfx/execution_buffer.c
>
> diff --git a/tests/vmwgfx/execution_buffer.c b/tests/vmwgfx/execution_buffer.c
> new file mode 100644
> index 00000000..71b6f00e
> --- /dev/null
> +++ b/tests/vmwgfx/execution_buffer.c
> @@ -0,0 +1,307 @@
> +// SPDX-License-Identifier: GPL-2.0 OR MIT
> +/**********************************************************
> + * Copyright 2021-2022 VMware, Inc.
> + *
> + * Permission is hereby granted, free of charge, to any person
> + * obtaining a copy of this software and associated documentation
> + * files (the "Software"), to deal in the Software without
> + * restriction, including without limitation the rights to use, copy,
> + * modify, merge, publish, distribute, sublicense, and/or sell copies
> + * of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> + * included in all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + *
> + **********************************************************/
> +
> +#include "igt_vmwgfx.h"
> +
> +#include <stdatomic.h>
> +
> +struct {
> +       bool stress_test;
> +} options;
> +
> +static struct option long_options[] = {
> +       { "stress-test", 0, 0, 's' },
> +       { NULL, 0, 0, 0 },
> +};
> +
> +static int parse_options(int opt, int opt_index, void *data)
> +{
> +       switch (opt) {
> +       case 's':
> +               options.stress_test = 1;
> +               igt_info("stress-test mode\n");
> +               break;
> +       default:
> +               return IGT_OPT_HANDLER_ERROR;
> +       }
> +       return IGT_OPT_HANDLER_SUCCESS;
> +}
> +
> +static void check_mob_create_map(int fd)
> +{
> +       struct vmw_mob *mob_obj;
> +       uint32 size = 4096;
> +
> +       /* create a new mob */
> +       mob_obj = vmw_ioctl_mob_create(fd, size);
> +       /* takes the created mob and maps it */
> +       vmw_ioctl_mob_map(fd, mob_obj);
> +       /* test that mapping is successful */
> +       igt_assert_neq(mob_obj->map_count, 0);
> +
> +       vmw_ioctl_mob_unmap(mob_obj);
> +       vmw_ioctl_mob_close_handle(fd, mob_obj);
> +}
> +
> +static void check_buffer_create(int fd)
> +{
> +       struct vmw_surface *buffer_obj;
> +       struct vmw_mob *mob_obj;
> +       uint32 size = 4096;
> +
> +       mob_obj = vmw_ioctl_mob_create(fd, size);
> +       /* creates a buffer from mob */
> +       buffer_obj = vmw_ioctl_buffer_create(fd, 0, size, mob_obj);
> +       /* checks that the buffer is allocated */
> +       igt_assert_eq(buffer_obj->base.backup_size, size);
> +
> +       vmw_ioctl_surface_unref(fd, buffer_obj);
> +       vmw_ioctl_mob_close_handle(fd, mob_obj);
> +}
> +
> +static void check_execbuf_submit_fence(int fd, int32 cid)
> +{
> +       struct vmw_execbuf *command_buffer;
> +       struct drm_vmw_fence_rep cmd_fence = { 0 };
> +       const uint32 buffer_size = 128;
> +
> +       struct vmw_mob *mob;
> +       struct vmw_surface *src_buffer;
> +       struct vmw_surface *dst_buffer1, *dst_buffer2, *dst_buffer3;
> +
> +       uint32_t total_size = 0;
> +       SVGA3dCmdDXBufferCopy copyCmd = { 0 };
> +       uint32_t total_cmd_len = sizeof(SVGA3dCmdHeader) + sizeof(copyCmd);
> +
> +       SVGA3dCmdReadbackGBSurface cmd;
> +       struct vmw_mob fake_mob = { 0 };
> +       char *readback;
> +
> +       char *data;
> +       int i;
> +
> +       mob = vmw_ioctl_mob_create(fd, buffer_size);
> +
> +       data = vmw_ioctl_mob_map(fd, mob);
> +       for (i = 0; i < buffer_size; ++i)
> +               data[i] = i;
> +       vmw_ioctl_mob_unmap(mob);
> +
> +       src_buffer = vmw_ioctl_buffer_create(
> +               fd, SVGA3D_SURFACE_BIND_SHADER_RESOURCE, buffer_size, mob);
> +       dst_buffer1 = vmw_ioctl_buffer_create(
> +               fd, SVGA3D_SURFACE_BIND_SHADER_RESOURCE, buffer_size, NULL);
> +       dst_buffer2 = vmw_ioctl_buffer_create(
> +               fd, SVGA3D_SURFACE_BIND_SHADER_RESOURCE, buffer_size, NULL);
> +       dst_buffer3 = vmw_ioctl_buffer_create(
> +               fd, SVGA3D_SURFACE_BIND_SHADER_RESOURCE, buffer_size, NULL);
> +       /* Create command buffer */
> +       command_buffer = vmw_execbuf_create(fd, cid);
> +       igt_assert(command_buffer != NULL);
> +
> +       copyCmd.src = src_buffer->base.handle;
> +       copyCmd.dest = dst_buffer1->base.handle;
> +       copyCmd.width = buffer_size;
> +       copyCmd.srcX = 0;
> +       copyCmd.destX = 0;
> +       vmw_execbuf_append(command_buffer, SVGA_3D_CMD_DX_BUFFER_COPY, &copyCmd,
> +                          sizeof(copyCmd), NULL, 0);
> +       total_size += total_cmd_len;
> +       igt_assert_eq(command_buffer->offset, total_size);
> +       igt_assert(command_buffer->offset < command_buffer->buffer_size);
> +
> +       for (i = 0; i < 4096; ++i) {
> +               copyCmd.src = dst_buffer1->base.handle;
> +               copyCmd.dest = dst_buffer2->base.handle;
> +               vmw_execbuf_append(command_buffer, SVGA_3D_CMD_DX_BUFFER_COPY,
> +                                  &copyCmd, sizeof(copyCmd), NULL, 0);
> +               total_size += total_cmd_len;
> +       }
> +
> +       copyCmd.src = dst_buffer2->base.handle;
> +       copyCmd.dest = dst_buffer3->base.handle;
> +       vmw_execbuf_append(command_buffer, SVGA_3D_CMD_DX_BUFFER_COPY, &copyCmd,
> +                          sizeof(copyCmd), NULL, 0);
> +       total_size += total_cmd_len;
> +
> +       igt_assert_eq(command_buffer->offset, total_size);
> +       igt_assert(command_buffer->offset < command_buffer->buffer_size);
> +
> +       vmw_execbuf_submit(command_buffer, &cmd_fence);
> +       vmw_ioctl_fence_finish(fd, &cmd_fence);
> +
> +       cmd.sid = dst_buffer1->base.handle;
> +       vmw_execbuf_append(command_buffer, SVGA_3D_CMD_READBACK_GB_SURFACE,
> +                          &cmd, sizeof(cmd), NULL, 0);
> +       vmw_execbuf_submit(command_buffer, &cmd_fence);
> +       vmw_ioctl_fence_finish(fd, &cmd_fence);
> +
> +       fake_mob.size = dst_buffer1->base.buffer_size;
> +       fake_mob.handle = dst_buffer1->base.buffer_handle;
> +       fake_mob.map_handle = dst_buffer1->base.buffer_map_handle;
> +       readback = vmw_ioctl_mob_map(fd, &fake_mob);
> +       for (i = 0; i < buffer_size; i++) {
> +               int val = readback[i];
> +
> +               igt_assert_eq(i, val);
> +       }
> +       vmw_ioctl_mob_unmap(&fake_mob);
> +
> +       vmw_ioctl_surface_unref(fd, src_buffer);
> +       vmw_ioctl_surface_unref(fd, dst_buffer1);
> +       vmw_ioctl_surface_unref(fd, dst_buffer2);
> +       vmw_ioctl_surface_unref(fd, dst_buffer3);
> +       vmw_execbuf_destroy(command_buffer);
> +       vmw_ioctl_mob_close_handle(fd, mob);
> +}
> +
> +static int32 vmw_ioctl_command2(int drm_fd, int32_t cid, void *commands,
> +                               uint32_t size, struct drm_vmw_fence_rep *fence)
> +{
> +       struct drm_vmw_execbuf_arg arg = { 0 };
> +       int ret;
> +       const int argsize = sizeof(arg);
> +
> +       memset(&arg, 0, sizeof(arg));
> +
> +       arg.fence_rep = (unsigned long)fence;
> +       arg.commands = (unsigned long)commands;
> +       arg.command_size = size;
> +       arg.throttle_us = 0; /* deprecated */
> +       arg.version = DRM_VMW_EXECBUF_VERSION;
> +       arg.context_handle = cid;
> +
> +       do {
> +               ret = drmCommandWrite(drm_fd, DRM_VMW_EXECBUF, &arg, argsize);
> +               if (ret == -EBUSY)
> +                       usleep(1000);
> +       } while (ret == -ERESTART || ret == -EBUSY);
> +       if (ret)
> +               return 1;
> +       return 0;
> +}
> +
> +static _Atomic(int32_t) context_id;
> +static const uint32_t max_tries = 100000;
> +
> +static void *create_contexts(void *data)
> +{
> +       int fd = (uintptr_t)data;
> +       uint32_t i;
> +
> +       for (i = 0; i < max_tries; ++i) {
> +               int32_t cid = vmw_ioctl_context_create(fd);
> +
> +               atomic_store(&context_id, cid);
> +
> +               vmw_ioctl_context_destroy(fd, cid);
> +       }
> +       return 0;
> +}
> +
> +static void *submit_queries(void *data)
> +{
> +       int fd = (uintptr_t)data;
> +       uint32_t i;
> +
> +       for (i = 0; i < max_tries; ++i) {
> +               struct vmw_execbuf *cmd_buf;
> +               SVGA3dCmdDXDefineQuery cmd = {
> +                       .queryId = 0,
> +                       .type = SVGA3D_QUERYTYPE_TIMESTAMP,
> +                       .flags = 0,
> +               };
> +               int32_t cid = atomic_load(&context_id);
> +
> +               cmd_buf = vmw_execbuf_create(fd, cid);
> +
> +               vmw_execbuf_append(cmd_buf, SVGA_3D_CMD_DX_DEFINE_QUERY, &cmd,
> +                                  sizeof(cmd), NULL, 0);
> +
> +               vmw_ioctl_command2(fd, cid, cmd_buf->buffer, cmd_buf->offset,
> +                                  NULL);
> +               cmd_buf->offset = 0;
> +               vmw_execbuf_destroy(cmd_buf);
> +       }
> +       return 0;
> +}
> +
> +static void execbuf_stress_test(int fd)
> +{
> +       pthread_t threads[2];
> +       void *status;
> +       int ret;
> +
> +       ret = pthread_create(&threads[0], NULL, create_contexts,
> +                            (void *)(uintptr_t)fd);
> +       igt_assert_eq(ret, 0);
> +       ret = pthread_create(&threads[1], NULL, submit_queries,
> +                            (void *)(uintptr_t)fd);
> +       igt_assert_eq(ret, 0);
> +
> +       pthread_join(threads[0], &status);
> +       pthread_join(threads[1], &status);
> +}
> +
> +igt_main_args("st:", long_options, NULL, parse_options, NULL)
> +{
> +       int fd;
> +       int32 cid;
> +
> +       igt_fixture
> +       {
> +               fd = drm_open_driver_render(DRIVER_VMWGFX);
> +               cid = vmw_ioctl_context_create(fd);
> +       }
> +
> +       igt_subtest("mob-create-map")
> +       {
> +               check_mob_create_map(fd);
> +       }
> +
> +       igt_subtest("buffer-create")
> +       {
> +               check_buffer_create(fd);
> +       }
> +
> +       igt_subtest("execution-buffer-submit-sync")
> +       {
> +               check_execbuf_submit_fence(fd, cid);
> +       }
> +
> +       if (options.stress_test) {
> +               igt_subtest("execution-buffer-stress-test")
> +               {
> +                       execbuf_stress_test(fd);
> +               }
> +       }
> +
> +       igt_fixture
> +       {
> +               vmw_ioctl_context_destroy(fd, cid);
> +               close(fd);
> +       }
> +}
> diff --git a/tests/vmwgfx/meson.build b/tests/vmwgfx/meson.build
> index 46961503..0b4a87e4 100644
> --- a/tests/vmwgfx/meson.build
> +++ b/tests/vmwgfx/meson.build
> @@ -1,6 +1,7 @@
>
>   vmwgfx_progs = [
> -       'tri'
> +       'tri',
> +       'execution_buffer'
>   ]
>   vmwgfx_deps = test_deps
>
> --
> 2.38.1
>


More information about the igt-dev mailing list