mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-28 21:10:12 +01:00
nvk/nvkmd: Implement dev and pdev for nouveau
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30033>
This commit is contained in:
parent
c8b36bbcc0
commit
4db1bd5846
5 changed files with 304 additions and 1 deletions
|
|
@ -57,6 +57,9 @@ nvk_files = files(
|
|||
'nvk_upload_queue.h',
|
||||
'nvk_wsi.c',
|
||||
'nvk_wsi.h',
|
||||
'nvkmd/nouveau/nvkmd_nouveau.h',
|
||||
'nvkmd/nouveau/nvkmd_nouveau_dev.c',
|
||||
'nvkmd/nouveau/nvkmd_nouveau_pdev.c',
|
||||
'nvkmd/nvkmd.c',
|
||||
'nvkmd/nvkmd.h',
|
||||
)
|
||||
|
|
|
|||
46
src/nouveau/vulkan/nvkmd/nouveau/nvkmd_nouveau.h
Normal file
46
src/nouveau/vulkan/nvkmd/nouveau/nvkmd_nouveau.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright © 2024 Collabora Ltd. and Red Hat Inc.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#ifndef NVKMD_DRM_H
|
||||
#define NVKMD_DRM_H 1
|
||||
|
||||
#include "nvkmd/nvkmd.h"
|
||||
#include "vk_drm_syncobj.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
struct nouveau_ws_device;
|
||||
|
||||
struct nvkmd_nouveau_pdev {
|
||||
struct nvkmd_pdev base;
|
||||
|
||||
/* Used for get_vram_used() */
|
||||
struct nouveau_ws_device *ws_dev;
|
||||
|
||||
int primary_fd;
|
||||
|
||||
struct vk_sync_type syncobj_sync_type;
|
||||
const struct vk_sync_type *sync_types[2];
|
||||
};
|
||||
|
||||
NVKMD_DECL_SUBCLASS(pdev, nouveau);
|
||||
|
||||
VkResult nvkmd_nouveau_try_create_pdev(struct _drmDevice *drm_device,
|
||||
struct vk_object_base *log_obj,
|
||||
enum nvk_debug debug_flags,
|
||||
struct nvkmd_pdev **pdev_out);
|
||||
|
||||
struct nvkmd_nouveau_dev {
|
||||
struct nvkmd_dev base;
|
||||
|
||||
struct nouveau_ws_device *ws_dev;
|
||||
};
|
||||
|
||||
NVKMD_DECL_SUBCLASS(dev, nouveau);
|
||||
|
||||
VkResult nvkmd_nouveau_create_dev(struct nvkmd_pdev *pdev,
|
||||
struct vk_object_base *log_obj,
|
||||
struct nvkmd_dev **dev_out);
|
||||
|
||||
#endif /* NVKMD_DRM_H */
|
||||
76
src/nouveau/vulkan/nvkmd/nouveau/nvkmd_nouveau_dev.c
Normal file
76
src/nouveau/vulkan/nvkmd/nouveau/nvkmd_nouveau_dev.c
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright © 2024 Collabora Ltd. and Red Hat Inc.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "nvkmd_nouveau.h"
|
||||
|
||||
#include "nouveau_device.h"
|
||||
#include "vk_log.h"
|
||||
|
||||
#include <xf86drm.h>
|
||||
|
||||
VkResult
|
||||
nvkmd_nouveau_create_dev(struct nvkmd_pdev *_pdev,
|
||||
struct vk_object_base *log_obj,
|
||||
struct nvkmd_dev **dev_out)
|
||||
{
|
||||
struct nvkmd_nouveau_pdev *pdev = nvkmd_nouveau_pdev(_pdev);
|
||||
|
||||
struct nvkmd_nouveau_dev *dev = CALLOC_STRUCT(nvkmd_nouveau_dev);
|
||||
if (dev == NULL)
|
||||
return vk_error(log_obj, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
dev->base.ops = &nvkmd_nouveau_dev_ops;
|
||||
|
||||
drmDevicePtr drm_device = NULL;
|
||||
int ret = drmGetDeviceFromDevId(pdev->base.drm.render_dev, 0, &drm_device);
|
||||
if (ret != 0) {
|
||||
FREE(dev);
|
||||
return vk_errorf(log_obj, VK_ERROR_INITIALIZATION_FAILED,
|
||||
"Failed to get DRM device: %m");
|
||||
}
|
||||
|
||||
dev->ws_dev = nouveau_ws_device_new(drm_device, pdev->ws_dev->debug_flags);
|
||||
drmFreeDevice(&drm_device);
|
||||
if (dev->ws_dev == NULL) {
|
||||
FREE(dev);
|
||||
return vk_errorf(log_obj, VK_ERROR_INITIALIZATION_FAILED,
|
||||
"Failed to get DRM device: %m");
|
||||
}
|
||||
|
||||
*dev_out = &dev->base;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
nvkmd_nouveau_dev_destroy(struct nvkmd_dev *_dev)
|
||||
{
|
||||
struct nvkmd_nouveau_dev *dev = nvkmd_nouveau_dev(_dev);
|
||||
|
||||
nouveau_ws_device_destroy(dev->ws_dev);
|
||||
FREE(dev);
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
nvkmd_nouveau_dev_get_gpu_timestamp(struct nvkmd_dev *_dev)
|
||||
{
|
||||
struct nvkmd_nouveau_dev *dev = nvkmd_nouveau_dev(_dev);
|
||||
|
||||
return nouveau_ws_device_timestamp(dev->ws_dev);
|
||||
}
|
||||
|
||||
static int
|
||||
nvkmd_nouveau_dev_get_drm_fd(struct nvkmd_dev *_dev)
|
||||
{
|
||||
struct nvkmd_nouveau_dev *dev = nvkmd_nouveau_dev(_dev);
|
||||
|
||||
return dev->ws_dev->fd;
|
||||
}
|
||||
|
||||
const struct nvkmd_dev_ops nvkmd_nouveau_dev_ops = {
|
||||
.destroy = nvkmd_nouveau_dev_destroy,
|
||||
.get_gpu_timestamp = nvkmd_nouveau_dev_get_gpu_timestamp,
|
||||
.get_drm_fd = nvkmd_nouveau_dev_get_drm_fd,
|
||||
};
|
||||
176
src/nouveau/vulkan/nvkmd/nouveau/nvkmd_nouveau_pdev.c
Normal file
176
src/nouveau/vulkan/nvkmd/nouveau/nvkmd_nouveau_pdev.c
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* Copyright © 2024 Collabora Ltd. and Red Hat Inc.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "nvkmd_nouveau.h"
|
||||
|
||||
#include "nouveau_device.h"
|
||||
#include "vk_log.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <xf86drm.h>
|
||||
|
||||
static bool
|
||||
drm_device_is_nouveau(const char *path)
|
||||
{
|
||||
int fd = open(path, O_RDWR | O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
return false;
|
||||
|
||||
drmVersionPtr ver = drmGetVersion(fd);
|
||||
if (!ver) {
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool is_nouveau = !strncmp("nouveau", ver->name, ver->name_len);
|
||||
|
||||
drmFreeVersion(ver);
|
||||
close(fd);
|
||||
|
||||
return is_nouveau;
|
||||
}
|
||||
|
||||
VkResult
|
||||
nvkmd_nouveau_try_create_pdev(struct _drmDevice *drm_device,
|
||||
struct vk_object_base *log_obj,
|
||||
enum nvk_debug debug_flags,
|
||||
struct nvkmd_pdev **pdev_out)
|
||||
{
|
||||
if (!(drm_device->available_nodes & (1 << DRM_NODE_RENDER)))
|
||||
return VK_ERROR_INCOMPATIBLE_DRIVER;
|
||||
|
||||
switch (drm_device->bustype) {
|
||||
case DRM_BUS_PCI:
|
||||
if (drm_device->deviceinfo.pci->vendor_id != NVIDIA_VENDOR_ID)
|
||||
return VK_ERROR_INCOMPATIBLE_DRIVER;
|
||||
break;
|
||||
|
||||
case DRM_BUS_PLATFORM: {
|
||||
const char *compat_prefix = "nvidia,";
|
||||
bool found = false;
|
||||
for (int i = 0; drm_device->deviceinfo.platform->compatible[i] != NULL; i++) {
|
||||
if (strncmp(drm_device->deviceinfo.platform->compatible[0], compat_prefix, strlen(compat_prefix)) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
return VK_ERROR_INCOMPATIBLE_DRIVER;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return VK_ERROR_INCOMPATIBLE_DRIVER;
|
||||
}
|
||||
|
||||
if (!drm_device_is_nouveau(drm_device->nodes[DRM_NODE_RENDER]))
|
||||
return VK_ERROR_INCOMPATIBLE_DRIVER;
|
||||
|
||||
struct nouveau_ws_device *ws_dev =
|
||||
nouveau_ws_device_new(drm_device, debug_flags);
|
||||
if (!ws_dev)
|
||||
return vk_error(log_obj, VK_ERROR_INCOMPATIBLE_DRIVER);
|
||||
|
||||
if (!ws_dev->has_vm_bind) {
|
||||
nouveau_ws_device_destroy(ws_dev);
|
||||
return vk_errorf(log_obj, VK_ERROR_INCOMPATIBLE_DRIVER,
|
||||
"NVK Requires a Linux kernel version 6.6 or later");
|
||||
}
|
||||
|
||||
struct stat st;
|
||||
if (stat(drm_device->nodes[DRM_NODE_RENDER], &st)) {
|
||||
nouveau_ws_device_destroy(ws_dev);
|
||||
return vk_errorf(log_obj, VK_ERROR_INITIALIZATION_FAILED,
|
||||
"fstat() failed on %s: %m",
|
||||
drm_device->nodes[DRM_NODE_RENDER]);
|
||||
}
|
||||
const dev_t render_dev = st.st_rdev;
|
||||
|
||||
struct nvkmd_nouveau_pdev *pdev = CALLOC_STRUCT(nvkmd_nouveau_pdev);
|
||||
if (pdev == NULL) {
|
||||
nouveau_ws_device_destroy(ws_dev);
|
||||
return vk_error(log_obj, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
}
|
||||
|
||||
pdev->base.ops = &nvkmd_nouveau_pdev_ops;
|
||||
pdev->base.dev_info = ws_dev->info;
|
||||
pdev->base.kmd_info = (struct nvkmd_info) {
|
||||
.has_get_vram_used = nouveau_ws_device_vram_used(ws_dev) != 0,
|
||||
.has_alloc_tiled = nouveau_ws_device_has_tiled_bo(ws_dev),
|
||||
.has_map_fixed = true,
|
||||
.has_overmap = true,
|
||||
};
|
||||
|
||||
pdev->base.drm.render_dev = render_dev;
|
||||
|
||||
/* DRM primary is optional */
|
||||
if ((drm_device->available_nodes & (1 << DRM_NODE_PRIMARY)) &&
|
||||
!stat(drm_device->nodes[DRM_NODE_PRIMARY], &st))
|
||||
pdev->base.drm.primary_dev = st.st_rdev;
|
||||
|
||||
pdev->primary_fd = -1;
|
||||
pdev->ws_dev = ws_dev;
|
||||
|
||||
pdev->syncobj_sync_type = vk_drm_syncobj_get_type(ws_dev->fd);
|
||||
pdev->sync_types[0] = &pdev->syncobj_sync_type;
|
||||
pdev->sync_types[1] = NULL;
|
||||
pdev->base.sync_types = pdev->sync_types;
|
||||
|
||||
*pdev_out = &pdev->base;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
nvkmd_nouveau_pdev_destroy(struct nvkmd_pdev *_pdev)
|
||||
{
|
||||
struct nvkmd_nouveau_pdev *pdev = nvkmd_nouveau_pdev(_pdev);
|
||||
|
||||
nouveau_ws_device_destroy(pdev->ws_dev);
|
||||
FREE(pdev);
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
nvkmd_nouveau_pdev_get_vram_used(struct nvkmd_pdev *_pdev)
|
||||
{
|
||||
struct nvkmd_nouveau_pdev *pdev = nvkmd_nouveau_pdev(_pdev);
|
||||
|
||||
return nouveau_ws_device_vram_used(pdev->ws_dev);
|
||||
}
|
||||
|
||||
static int
|
||||
nvkmd_nouveau_pdev_get_drm_primary_fd(struct nvkmd_pdev *_pdev)
|
||||
{
|
||||
struct nvkmd_nouveau_pdev *pdev = nvkmd_nouveau_pdev(_pdev);
|
||||
|
||||
if (pdev->primary_fd >= 0)
|
||||
return pdev->primary_fd;
|
||||
|
||||
if (pdev->base.drm.primary_dev == 0)
|
||||
return -1;
|
||||
|
||||
drmDevicePtr drm_device = NULL;
|
||||
int ret = drmGetDeviceFromDevId(pdev->base.drm.primary_dev, 0, &drm_device);
|
||||
if (ret != 0)
|
||||
return -1;
|
||||
|
||||
int fd = open(drm_device->nodes[DRM_NODE_PRIMARY], O_RDWR | O_CLOEXEC);
|
||||
drmFreeDevice(&drm_device);
|
||||
|
||||
/* TODO: Test if the FD is usable? */
|
||||
|
||||
pdev->primary_fd = fd;
|
||||
|
||||
return pdev->primary_fd;
|
||||
}
|
||||
|
||||
const struct nvkmd_pdev_ops nvkmd_nouveau_pdev_ops = {
|
||||
.destroy = nvkmd_nouveau_pdev_destroy,
|
||||
.get_vram_used = nvkmd_nouveau_pdev_get_vram_used,
|
||||
.get_drm_primary_fd = nvkmd_nouveau_pdev_get_drm_primary_fd,
|
||||
.create_dev = nvkmd_nouveau_create_dev,
|
||||
};
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
#include "nvkmd.h"
|
||||
#include "nouveau/nvkmd_nouveau.h"
|
||||
|
||||
VkResult
|
||||
nvkmd_try_create_pdev_for_drm(struct _drmDevice *drm_device,
|
||||
|
|
@ -11,5 +12,6 @@ nvkmd_try_create_pdev_for_drm(struct _drmDevice *drm_device,
|
|||
enum nvk_debug debug_flags,
|
||||
struct nvkmd_pdev **pdev_out)
|
||||
{
|
||||
return VK_ERROR_INCOMPATIBLE_DRIVER;
|
||||
return nvkmd_nouveau_try_create_pdev(drm_device, log_obj,
|
||||
debug_flags, pdev_out);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue