nvk: Move the winsys device to nvk_device
authorFaith Ekstrand <faith.ekstrand@collabora.com>
Thu, 20 Jul 2023 17:49:34 +0000 (12:49 -0500)
committerMarge Bot <emma+marge@anholt.net>
Fri, 4 Aug 2023 21:32:06 +0000 (21:32 +0000)
Vulkan requires that different VkDevices be unable to affect each other.
To correctly provide this invariant, each VkDevice really needs its on
virtual address space.  This means opening a new nouveau_device per
nvk_device.  This may make device creation a tiny bit less efficient but
we can fix that with some sort of caching if we absolutely need to.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>

src/nouveau/vulkan/nvk_device.c
src/nouveau/vulkan/nvk_physical_device.c
src/nouveau/vulkan/nvk_physical_device.h

index d6b9c8c..1bc91e9 100644 (file)
@@ -139,18 +139,33 @@ nvk_CreateDevice(VkPhysicalDevice physicalDevice,
    if (result != VK_SUCCESS)
       goto fail_alloc;
 
-   vk_device_set_drm_fd(&dev->vk, pdev->ws_dev->fd);
+   drmDevicePtr drm_device = NULL;
+   int ret = drmGetDeviceFromDevId(pdev->render_dev, 0, &drm_device);
+   if (ret != 0) {
+      result = vk_errorf(dev, VK_ERROR_INITIALIZATION_FAILED,
+                         "Failed to get DRM device: %m");
+      goto fail_init;
+   }
+
+   dev->ws_dev = nouveau_ws_device_new(drm_device);
+   drmFreeDevice(&drm_device);
+   if (dev->ws_dev == NULL) {
+      result = vk_errorf(dev, VK_ERROR_INITIALIZATION_FAILED,
+                         "Failed to get DRM device: %m");
+      goto fail_init;
+   }
+
+   vk_device_set_drm_fd(&dev->vk, dev->ws_dev->fd);
    dev->vk.command_buffer_ops = &nvk_cmd_buffer_ops;
    dev->pdev = pdev;
-   dev->ws_dev = pdev->ws_dev;
 
-   int ret = nouveau_ws_context_create(dev->ws_dev, &dev->ws_ctx);
+   ret = nouveau_ws_context_create(dev->ws_dev, &dev->ws_ctx);
    if (ret) {
       if (ret == -ENOSPC)
          result = vk_error(dev, VK_ERROR_TOO_MANY_OBJECTS);
       else
          result = vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
-      goto fail_init;
+      goto fail_ws_dev;
    }
 
    list_inithead(&dev->memory_objects);
@@ -159,7 +174,7 @@ nvk_CreateDevice(VkPhysicalDevice physicalDevice,
                                       8 * 4 /* tic entry size */,
                                       1024, 1024 * 1024);
    if (result != VK_SUCCESS)
-      goto fail_memory_objects;
+      goto fail_ws_ctx;
 
    /* Reserve the descriptor at offset 0 to be the null descriptor */
    uint32_t null_image[8] = { 0, };
@@ -268,8 +283,10 @@ fail_samplers:
    nvk_descriptor_table_finish(dev, &dev->samplers);
 fail_images:
    nvk_descriptor_table_finish(dev, &dev->images);
-fail_memory_objects:
+fail_ws_ctx:
    nouveau_ws_context_destroy(dev->ws_ctx);
+fail_ws_dev:
+   nouveau_ws_device_destroy(dev->ws_dev);
 fail_init:
    vk_device_finish(&dev->vk);
 fail_alloc:
@@ -301,6 +318,7 @@ nvk_DestroyDevice(VkDevice _device, const VkAllocationCallbacks *pAllocator)
    nvk_descriptor_table_finish(dev, &dev->images);
    assert(list_is_empty(&dev->memory_objects));
    nouveau_ws_context_destroy(dev->ws_ctx);
+   nouveau_ws_device_destroy(dev->ws_dev);
    vk_free(&dev->vk.alloc, dev);
 }
 
index 3495502..14cd583 100644 (file)
@@ -14,6 +14,8 @@
 #include "vulkan/runtime/vk_device.h"
 #include "vulkan/wsi/wsi_common.h"
 
+#include <sys/stat.h>
+
 #include "cl90c0.h"
 #include "cl91c0.h"
 #include "cla0c0.h"
@@ -619,16 +621,31 @@ nvk_create_drm_physical_device(struct vk_instance *_instance,
    if (!ws_dev)
       return vk_error(instance, VK_ERROR_INCOMPATIBLE_DRIVER);
 
+   const struct nv_device_info info = ws_dev->info;
+
+   nouveau_ws_device_destroy(ws_dev);
+
+   if (!(drm_device->available_nodes & (1 << DRM_NODE_RENDER))) {
+      return vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
+                       "NVK requires a render node");
+   }
+
+   struct stat st;
+   if (stat(drm_device->nodes[DRM_NODE_RENDER], &st)) {
+      return vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
+                       "fstat() failed on %s: %m",
+                       drm_device->nodes[DRM_NODE_RENDER]);
+   }
+   const dev_t render_dev = st.st_rdev;
+
    vk_warn_non_conformant_implementation("NVK");
 
    struct nvk_physical_device *pdev =
       vk_zalloc(&instance->vk.alloc, sizeof(*pdev),
                 8, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 
-   if (pdev == NULL) {
-      result = vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
-      goto fail_dev_alloc;
-   }
+   if (pdev == NULL)
+      return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
 
    struct vk_physical_device_dispatch_table dispatch_table;
    vk_physical_device_dispatch_table_from_entrypoints(
@@ -637,21 +654,20 @@ nvk_create_drm_physical_device(struct vk_instance *_instance,
       &dispatch_table, &wsi_physical_device_entrypoints, false);
 
    struct vk_device_extension_table supported_extensions;
-   nvk_get_device_extensions(&ws_dev->info, &supported_extensions);
+   nvk_get_device_extensions(&info, &supported_extensions);
 
    struct vk_features supported_features;
-   nvk_get_device_features(&ws_dev->info, &supported_features);
+   nvk_get_device_features(&info, &supported_features);
 
    result = vk_physical_device_init(&pdev->vk, &instance->vk,
                                     &supported_extensions,
                                     &supported_features,
                                     &dispatch_table);
-
    if (result != VK_SUCCESS)
       goto fail_alloc;
 
-   pdev->ws_dev = ws_dev;
-   pdev->info = ws_dev->info;
+   pdev->render_dev = render_dev;
+   pdev->info = info;
 
    const struct {
       uint16_t vendor_id;
@@ -713,8 +729,6 @@ fail_init:
    vk_physical_device_finish(&pdev->vk);
 fail_alloc:
    vk_free(&instance->vk.alloc, pdev);
-fail_dev_alloc:
-   nouveau_ws_device_destroy(ws_dev);
    return result;
 }
 
@@ -725,7 +739,6 @@ nvk_physical_device_destroy(struct vk_physical_device *vk_pdev)
       container_of(vk_pdev, struct nvk_physical_device, vk);
 
    nvk_finish_wsi(pdev);
-   nouveau_ws_device_destroy(pdev->ws_dev);
    vk_physical_device_finish(&pdev->vk);
    vk_free(&pdev->vk.instance->alloc, pdev);
 }
index 6249f95..7d74763 100644 (file)
 
 #include "wsi_common.h"
 
+#include <sys/types.h>
+
 struct nvk_instance;
 
 struct nvk_physical_device {
    struct vk_physical_device vk;
-   struct nouveau_ws_device *ws_dev;
    struct nv_device_info info;
+   dev_t render_dev;
    struct wsi_device wsi_device;
 
    uint8_t device_uuid[VK_UUID_SIZE];