zink: Create one queue lock per device

We currently only create one queue per queue family on the device. The
device can be shared between multiple zink_screens, so having one lock
per screen can still lead to multiple locks per queue. Fix this by
allocating queue_lock along with the device.

This fixes an issue that was causing crashes with nvk+zink and
QtWebEngine with QTWEBENGINE_FORCE_USE_GBM=1 This can be reproduced by
resizing the window in either:

 * anki - https://apps.ankiweb.net/ or
 * Qt's simplebrowser example
   https://doc.qt.io/qt-6/qtwebengine-webenginewidgets-simplebrowser-example.html

which would then cause this dmesg error:

    nouveau 0000:01:00.0: anki[92007]: Failed to find syncobj (-> in): handle=40

along with a context loss.
With VK_LOADER_LAYERS_ENABLE=VK_LAYER_KHRONOS_validation we would additionally
get warnings like:

    Validation Error: [ UNASSIGNED-Threading-MultipleThreads-Write ] | MessageID = 0xa05b236e
    vkQueueSubmit(): THREADING ERROR : object of type VkQueue is simultaneously used in current thread 139824449189568 and thread 139823901816512
    Objects: 1
        [0] VkQueue 0x557a666783e0

Fixes: 015eda4a41 ("zink: deduplicate VkDevice and VkInstance")
Reviewed-by: Dave Airlie <airlied@redhat.com>
(cherry picked from commit 9acce36652)

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38803>
This commit is contained in:
Mel Henning 2025-11-12 17:44:36 -05:00 committed by Dylan Baker
parent 81f1cefcea
commit 3b6f03bd49
3 changed files with 7 additions and 6 deletions

View file

@ -844,7 +844,7 @@
"description": "zink: Create one queue lock per device",
"nominated": true,
"nomination_type": 2,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": "015eda4a4186c75538a0aa915e380c5ce5863319",
"notes": null

View file

@ -145,6 +145,7 @@ struct zink_device {
VkPhysicalDevice pdev;
VkDevice dev;
struct zink_device_info *info;
simple_mtx_t queue_lock;
};
static simple_mtx_t device_lock = SIMPLE_MTX_INITIALIZER;
@ -1831,8 +1832,6 @@ update_queue_props(struct zink_screen *screen)
static void
init_queue(struct zink_screen *screen)
{
simple_mtx_init(&screen->queue_lock_storage, mtx_plain);
screen->queue_lock = &screen->queue_lock_storage;
VKSCR(GetDeviceQueue)(screen->dev, screen->gfx_queue, 0, &screen->queue);
if (screen->sparse_queue != screen->gfx_queue)
VKSCR(GetDeviceQueue)(screen->dev, screen->sparse_queue, 0, &screen->queue_sparse);
@ -2759,6 +2758,7 @@ get_device(struct zink_screen *screen, VkDeviceCreateInfo *dci)
zdev->refcount = 1;
zdev->pdev = screen->pdev;
zdev->dev = dev;
simple_mtx_init(&zdev->queue_lock, mtx_plain);
_mesa_set_add(&device_table, zdev);
simple_mtx_unlock(&device_lock);
return zdev;
@ -3522,9 +3522,11 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev
init_driver_workarounds(screen);
disable_features(screen);
screen->dev = zink_create_logical_device(screen)->dev;
if (!screen->dev)
struct zink_device *zdev = zink_create_logical_device(screen);
if (!zdev->dev)
goto fail;
screen->dev = zdev->dev;
screen->queue_lock = &zdev->queue_lock;
vk_device_uncompacted_dispatch_table_load(&screen->vk.device,
screen->vk_GetDeviceProcAddr,

View file

@ -1481,7 +1481,6 @@ struct zink_screen {
VkQueue queue; //gfx+compute
VkQueue queue_sparse;
simple_mtx_t *queue_lock;
simple_mtx_t queue_lock_storage;
VkDebugUtilsMessengerEXT debugUtilsCallbackHandle;
uint32_t cur_custom_border_color_samplers;