v3dv: use v3d primary node for VK_EXT_physical_device_drm

Follow the implementation of all other Mesa drivers and use the
primary node of the render device for VK_EXT_physical_device_drm.
The topic of which node should be returned here has been the topic
of a long debate, but at least for Mesa drivers, there is the
consensus that this extension should not mix nodes from different
DRM devices. So align v3dv with the other Mesa implementations.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37584>
This commit is contained in:
Erico Nunes 2025-09-25 21:32:40 +02:00 committed by Marge Bot
parent 32e4dd6978
commit 451a0bd490
2 changed files with 25 additions and 14 deletions

View file

@ -1249,7 +1249,8 @@ get_device_properties(const struct v3dv_physical_device *device,
static VkResult static VkResult
create_physical_device(struct v3dv_instance *instance, create_physical_device(struct v3dv_instance *instance,
int32_t render_fd, int32_t display_fd) int32_t primary_fd, int32_t render_fd,
int32_t display_fd)
{ {
VkResult result = VK_SUCCESS; VkResult result = VK_SUCCESS;
@ -1272,18 +1273,14 @@ create_physical_device(struct v3dv_instance *instance,
if (result != VK_SUCCESS) if (result != VK_SUCCESS)
goto fail; goto fail;
struct stat display_stat = {0}, render_stat = {0}; struct stat primary_stat = {0}, render_stat = {0};
if (fstat(primary_fd, &primary_stat) != 0) {
device->has_primary = display_fd >= 0;
if (device->has_primary) {
if (fstat(display_fd, &display_stat) != 0) {
result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED, result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
"failed to stat DRM display node"); "failed to stat DRM primary node");
goto fail; goto fail;
} }
device->has_primary = true;
device->primary_devid = display_stat.st_rdev; device->primary_devid = primary_stat.st_rdev;
}
if (fstat(render_fd, &render_stat) != 0) { if (fstat(render_fd, &render_stat) != 0) {
result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED, result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
@ -1298,6 +1295,7 @@ create_physical_device(struct v3dv_instance *instance,
device->sim_file = v3d_simulator_init(render_fd); device->sim_file = v3d_simulator_init(render_fd);
#endif #endif
device->primary_fd = primary_fd;
device->render_fd = render_fd; device->render_fd = render_fd;
device->display_fd = display_fd; device->display_fd = display_fd;
@ -1411,6 +1409,8 @@ fail:
vk_physical_device_finish(&device->vk); vk_physical_device_finish(&device->vk);
vk_free(&instance->vk.alloc, device); vk_free(&instance->vk.alloc, device);
if (primary_fd >= 0)
close(primary_fd);
if (render_fd >= 0) if (render_fd >= 0)
close(render_fd); close(render_fd);
if (display_fd >= 0) if (display_fd >= 0)
@ -1543,6 +1543,7 @@ enumerate_devices(struct vk_instance *vk_instance)
VkResult result = VK_SUCCESS; VkResult result = VK_SUCCESS;
int32_t primary_fd = -1;
int32_t render_fd = -1; int32_t render_fd = -1;
int32_t display_fd = -1; int32_t display_fd = -1;
for (unsigned i = 0; i < (unsigned)max_devices; i++) { for (unsigned i = 0; i < (unsigned)max_devices; i++) {
@ -1553,9 +1554,11 @@ enumerate_devices(struct vk_instance *vk_instance)
devices[i]->bustype == DRM_BUS_PCI && devices[i]->bustype == DRM_BUS_PCI &&
(devices[i]->deviceinfo.pci->vendor_id == 0x8086 || (devices[i]->deviceinfo.pci->vendor_id == 0x8086 ||
devices[i]->deviceinfo.pci->vendor_id == 0x1002)) { devices[i]->deviceinfo.pci->vendor_id == 0x1002)) {
if (try_device(devices[i]->nodes[DRM_NODE_RENDER], &render_fd, NULL)) if (try_device(devices[i]->nodes[DRM_NODE_RENDER], &render_fd, NULL)) {
try_device(devices[i]->nodes[DRM_NODE_PRIMARY], &primary_fd, NULL);
try_device(devices[i]->nodes[DRM_NODE_PRIMARY], &display_fd, NULL); try_device(devices[i]->nodes[DRM_NODE_PRIMARY], &display_fd, NULL);
} }
}
#else #else
/* On actual hardware, we should have a gpu device (v3d) and a display /* On actual hardware, we should have a gpu device (v3d) and a display
* device. We will need to use the display device to allocate WSI * device. We will need to use the display device to allocate WSI
@ -1567,6 +1570,7 @@ enumerate_devices(struct vk_instance *vk_instance)
continue; continue;
if ((devices[i]->available_nodes & 1 << DRM_NODE_RENDER)) { if ((devices[i]->available_nodes & 1 << DRM_NODE_RENDER)) {
try_device(devices[i]->nodes[DRM_NODE_PRIMARY], &primary_fd, "v3d");
try_device(devices[i]->nodes[DRM_NODE_RENDER], &render_fd, "v3d"); try_device(devices[i]->nodes[DRM_NODE_RENDER], &render_fd, "v3d");
} else if (display_fd == -1 && } else if (display_fd == -1 &&
(devices[i]->available_nodes & 1 << DRM_NODE_PRIMARY)) { (devices[i]->available_nodes & 1 << DRM_NODE_PRIMARY)) {
@ -1578,10 +1582,12 @@ enumerate_devices(struct vk_instance *vk_instance)
break; break;
} }
assert(primary_fd >= 0);
if (render_fd < 0) if (render_fd < 0)
result = VK_ERROR_INCOMPATIBLE_DRIVER; result = VK_ERROR_INCOMPATIBLE_DRIVER;
else else
result = create_physical_device(instance, render_fd, display_fd); result = create_physical_device(instance, primary_fd, render_fd, display_fd);
drmFreeDevices(devices, max_devices); drmFreeDevices(devices, max_devices);

View file

@ -128,7 +128,12 @@ struct v3dv_physical_device {
struct vk_physical_device vk; struct vk_physical_device vk;
char *name; char *name;
/* primary node (cardN) of the render device */
int32_t primary_fd;
/* render node (renderN) of the render device */
int32_t render_fd; int32_t render_fd;
/* primary node (cardN) of the display device, if available */
int32_t display_fd; int32_t display_fd;
/* We need these because it is not clear how to detect /* We need these because it is not clear how to detect