From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x429.google.com (mail-wr1-x429.google.com [IPv6:2a00:1450:4864:20::429]) by gabe.freedesktop.org (Postfix) with ESMTPS id B5EA710ED07 for ; Thu, 16 Mar 2023 13:55:55 +0000 (UTC) Received: by mail-wr1-x429.google.com with SMTP id m2so1622419wrh.6 for ; Thu, 16 Mar 2023 06:55:55 -0700 (PDT) Message-ID: Date: Thu, 16 Mar 2023 15:55:52 +0200 MIME-Version: 1.0 Content-Language: en-US To: igt-dev@lists.freedesktop.org References: <20230316022659.73202-1-zack@kde.org> <20230316022659.73202-5-zack@kde.org> From: "Martin Krastev (VMware)" In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Subject: Re: [igt-dev] [PATCH i-g-t v2 4/8] igt/vmwgfx: Add execution buffer test List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: krastevm@vmware.com, banackm@vmware.com, mombasawalam@vmware.com Errors-To: igt-dev-bounces@lists.freedesktop.org Sender: "igt-dev" List-ID: From: Martin Krastev LGTM Reviewed-by: Martin Krastev Regards, Martin On 16.03.23 г. 14:54 ч., Martin Krastev wrote: > From: Maaz Mombasawala > > 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 > Signed-off-by: Maaz Mombasawala > --- > 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 > + > +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, ©Cmd, > + 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, > + ©Cmd, 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, ©Cmd, > + 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 >