Instead of having a single physical device in anv_instance, have a
linked list of them. What we have now works today because we our GPUs
are build into the CPU and so you're guaranteed to only ever have one of
them. One day, that will change and we want ANV to be ready.
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3461>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3461>
-anv_physical_device_init(struct anv_physical_device *device,
- struct anv_instance *instance,
- drmDevicePtr drm_device)
+anv_physical_device_try_create(struct anv_instance *instance,
+ drmDevicePtr drm_device,
+ struct anv_physical_device **device_out)
{
const char *primary_path = drm_device->nodes[DRM_NODE_PRIMARY];
const char *path = drm_device->nodes[DRM_NODE_RENDER];
{
const char *primary_path = drm_device->nodes[DRM_NODE_PRIMARY];
const char *path = drm_device->nodes[DRM_NODE_RENDER];
struct gen_device_info devinfo;
if (!gen_get_device_info_from_fd(fd, &devinfo)) {
result = vk_error(VK_ERROR_INCOMPATIBLE_DRIVER);
struct gen_device_info devinfo;
if (!gen_get_device_info_from_fd(fd, &devinfo)) {
result = vk_error(VK_ERROR_INCOMPATIBLE_DRIVER);
}
const char *device_name = gen_get_device_name(devinfo.chipset_id);
}
const char *device_name = gen_get_device_name(devinfo.chipset_id);
} else {
result = vk_errorfi(instance, NULL, VK_ERROR_INCOMPATIBLE_DRIVER,
"Vulkan not yet supported on %s", device_name);
} else {
result = vk_errorfi(instance, NULL, VK_ERROR_INCOMPATIBLE_DRIVER,
"Vulkan not yet supported on %s", device_name);
+ goto fail_fd;
+ }
+
+ struct anv_physical_device *device =
+ vk_alloc(&instance->alloc, sizeof(*device), 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (device == NULL) {
+ result = vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+ goto fail_fd;
}
device->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
}
device->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
result = vk_errorfi(device->instance, NULL,
VK_ERROR_INITIALIZATION_FAILED,
"failed to get command parser version");
result = vk_errorfi(device->instance, NULL,
VK_ERROR_INITIALIZATION_FAILED,
"failed to get command parser version");
result = vk_errorfi(device->instance, NULL,
VK_ERROR_INITIALIZATION_FAILED,
"kernel missing gem wait");
result = vk_errorfi(device->instance, NULL,
VK_ERROR_INITIALIZATION_FAILED,
"kernel missing gem wait");
}
if (!anv_gem_get_param(fd, I915_PARAM_HAS_EXECBUF2)) {
result = vk_errorfi(device->instance, NULL,
VK_ERROR_INITIALIZATION_FAILED,
"kernel missing execbuf2");
}
if (!anv_gem_get_param(fd, I915_PARAM_HAS_EXECBUF2)) {
result = vk_errorfi(device->instance, NULL,
VK_ERROR_INITIALIZATION_FAILED,
"kernel missing execbuf2");
}
if (!device->info.has_llc &&
}
if (!device->info.has_llc &&
result = vk_errorfi(device->instance, NULL,
VK_ERROR_INITIALIZATION_FAILED,
"kernel missing wc mmap");
result = vk_errorfi(device->instance, NULL,
VK_ERROR_INITIALIZATION_FAILED,
"kernel missing wc mmap");
}
device->has_softpin = anv_gem_get_param(fd, I915_PARAM_HAS_EXEC_SOFTPIN);
}
device->has_softpin = anv_gem_get_param(fd, I915_PARAM_HAS_EXEC_SOFTPIN);
result = anv_physical_device_init_heaps(device, fd);
if (result != VK_SUCCESS)
result = anv_physical_device_init_heaps(device, fd);
if (result != VK_SUCCESS)
device->use_softpin = device->has_softpin &&
device->supports_48bit_addresses;
device->use_softpin = device->has_softpin &&
device->supports_48bit_addresses;
device->compiler = brw_compiler_create(NULL, &device->info);
if (device->compiler == NULL) {
result = vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
device->compiler = brw_compiler_create(NULL, &device->info);
if (device->compiler == NULL) {
result = vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
}
device->compiler->shader_debug_log = compiler_debug_log;
device->compiler->shader_perf_log = compiler_perf_log;
}
device->compiler->shader_debug_log = compiler_debug_log;
device->compiler->shader_perf_log = compiler_perf_log;
result = anv_physical_device_init_uuids(device);
if (result != VK_SUCCESS)
result = anv_physical_device_init_uuids(device);
if (result != VK_SUCCESS)
anv_physical_device_init_disk_cache(device);
anv_physical_device_init_disk_cache(device);
device->master_fd = master_fd;
result = anv_init_wsi(device);
device->master_fd = master_fd;
result = anv_init_wsi(device);
- if (result != VK_SUCCESS) {
- ralloc_free(device->compiler);
- anv_physical_device_free_disk_cache(device);
- goto fail;
- }
+ if (result != VK_SUCCESS)
+ goto fail_disk_cache;
device->perf = anv_get_perf(&device->info, fd);
device->perf = anv_get_perf(&device->info, fd);
+ *device_out = device;
+
+fail_disk_cache:
+ anv_physical_device_free_disk_cache(device);
+fail_compiler:
+ ralloc_free(device->compiler);
+fail_alloc:
+ vk_free(&instance->alloc, device);
+fail_fd:
close(fd);
if (master_fd != -1)
close(master_fd);
close(fd);
if (master_fd != -1)
close(master_fd);
-anv_physical_device_finish(struct anv_physical_device *device)
+anv_physical_device_destroy(struct anv_physical_device *device)
{
anv_finish_wsi(device);
anv_physical_device_free_disk_cache(device);
{
anv_finish_wsi(device);
anv_physical_device_free_disk_cache(device);
close(device->local_fd);
if (device->master_fd >= 0)
close(device->master_fd);
close(device->local_fd);
if (device->master_fd >= 0)
close(device->master_fd);
+ vk_free(&device->instance->alloc, device);
- instance->physicalDeviceCount = -1;
+ instance->physical_devices_enumerated = false;
+ list_inithead(&instance->physical_devices);
result = vk_debug_report_instance_init(&instance->debug_report_callbacks);
if (result != VK_SUCCESS) {
result = vk_debug_report_instance_init(&instance->debug_report_callbacks);
if (result != VK_SUCCESS) {
- if (instance->physicalDeviceCount > 0) {
- /* We support at most one physical device. */
- assert(instance->physicalDeviceCount == 1);
- anv_physical_device_finish(&instance->physicalDevice);
- }
+ list_for_each_entry_safe(struct anv_physical_device, pdevice,
+ &instance->physical_devices, link)
+ anv_physical_device_destroy(pdevice);
vk_free(&instance->alloc, (char *)instance->app_info.app_name);
vk_free(&instance->alloc, (char *)instance->app_info.engine_name);
vk_free(&instance->alloc, (char *)instance->app_info.app_name);
vk_free(&instance->alloc, (char *)instance->app_info.engine_name);
-anv_enumerate_devices(struct anv_instance *instance)
+anv_enumerate_physical_devices(struct anv_instance *instance)
+ if (instance->physical_devices_enumerated)
+ return VK_SUCCESS;
+
+ instance->physical_devices_enumerated = true;
+
/* TODO: Check for more devices ? */
drmDevicePtr devices[8];
VkResult result = VK_ERROR_INCOMPATIBLE_DRIVER;
int max_devices;
/* TODO: Check for more devices ? */
drmDevicePtr devices[8];
VkResult result = VK_ERROR_INCOMPATIBLE_DRIVER;
int max_devices;
- instance->physicalDeviceCount = 0;
-
max_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices));
if (max_devices < 1)
return VK_ERROR_INCOMPATIBLE_DRIVER;
max_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices));
if (max_devices < 1)
return VK_ERROR_INCOMPATIBLE_DRIVER;
devices[i]->bustype == DRM_BUS_PCI &&
devices[i]->deviceinfo.pci->vendor_id == 0x8086) {
devices[i]->bustype == DRM_BUS_PCI &&
devices[i]->deviceinfo.pci->vendor_id == 0x8086) {
- result = anv_physical_device_init(&instance->physicalDevice,
- instance, devices[i]);
- if (result != VK_ERROR_INCOMPATIBLE_DRIVER)
- break;
+ struct anv_physical_device *pdevice;
+ result = anv_physical_device_try_create(instance, devices[i],
+ &pdevice);
+ if (result != VK_SUCCESS)
+ continue;
+
+ list_addtail(&pdevice->link, &instance->physical_devices);
}
}
drmFreeDevices(devices, max_devices);
}
}
drmFreeDevices(devices, max_devices);
- if (result == VK_SUCCESS)
- instance->physicalDeviceCount = 1;
-
- return result;
-}
-
-static VkResult
-anv_instance_ensure_physical_device(struct anv_instance *instance)
-{
- if (instance->physicalDeviceCount < 0) {
- VkResult result = anv_enumerate_devices(instance);
- if (result != VK_SUCCESS &&
- result != VK_ERROR_INCOMPATIBLE_DRIVER)
- return result;
- }
-
- return VK_SUCCESS;
+ /* If we successfully enumerated any devices, call it success */
+ return !list_is_empty(&instance->physical_devices) ? VK_SUCCESS : result;
}
VkResult anv_EnumeratePhysicalDevices(
}
VkResult anv_EnumeratePhysicalDevices(
ANV_FROM_HANDLE(anv_instance, instance, _instance);
VK_OUTARRAY_MAKE(out, pPhysicalDevices, pPhysicalDeviceCount);
ANV_FROM_HANDLE(anv_instance, instance, _instance);
VK_OUTARRAY_MAKE(out, pPhysicalDevices, pPhysicalDeviceCount);
- VkResult result = anv_instance_ensure_physical_device(instance);
+ VkResult result = anv_enumerate_physical_devices(instance);
if (result != VK_SUCCESS)
return result;
if (result != VK_SUCCESS)
return result;
- if (instance->physicalDeviceCount == 0)
- return VK_SUCCESS;
-
- assert(instance->physicalDeviceCount == 1);
- vk_outarray_append(&out, i) {
- *i = anv_physical_device_to_handle(&instance->physicalDevice);
+ list_for_each_entry(struct anv_physical_device, pdevice,
+ &instance->physical_devices, link) {
+ vk_outarray_append(&out, i) {
+ *i = anv_physical_device_to_handle(pdevice);
+ }
}
return vk_outarray_status(&out);
}
return vk_outarray_status(&out);
VK_OUTARRAY_MAKE(out, pPhysicalDeviceGroupProperties,
pPhysicalDeviceGroupCount);
VK_OUTARRAY_MAKE(out, pPhysicalDeviceGroupProperties,
pPhysicalDeviceGroupCount);
- VkResult result = anv_instance_ensure_physical_device(instance);
+ VkResult result = anv_enumerate_physical_devices(instance);
if (result != VK_SUCCESS)
return result;
if (result != VK_SUCCESS)
return result;
- if (instance->physicalDeviceCount == 0)
- return VK_SUCCESS;
-
- assert(instance->physicalDeviceCount == 1);
-
- vk_outarray_append(&out, p) {
- p->physicalDeviceCount = 1;
- memset(p->physicalDevices, 0, sizeof(p->physicalDevices));
- p->physicalDevices[0] =
- anv_physical_device_to_handle(&instance->physicalDevice);
- p->subsetAllocation = false;
+ list_for_each_entry(struct anv_physical_device, pdevice,
+ &instance->physical_devices, link) {
+ vk_outarray_append(&out, p) {
+ p->physicalDeviceCount = 1;
+ memset(p->physicalDevices, 0, sizeof(p->physicalDevices));
+ p->physicalDevices[0] = anv_physical_device_to_handle(pdevice);
+ p->subsetAllocation = false;
- vk_foreach_struct(ext, p->pNext)
- anv_debug_ignored_stype(ext->sType);
+ vk_foreach_struct(ext, p->pNext)
+ anv_debug_ignored_stype(ext->sType);
+ }
}
return vk_outarray_status(&out);
}
return vk_outarray_status(&out);
struct anv_physical_device {
VK_LOADER_DATA _loader_data;
struct anv_physical_device {
VK_LOADER_DATA _loader_data;
+ /* Link in anv_instance::physical_devices */
+ struct list_head link;
+
struct anv_instance * instance;
bool no_hw;
char path[20];
struct anv_instance * instance;
bool no_hw;
char path[20];
struct anv_physical_device_dispatch_table physical_device_dispatch;
struct anv_device_dispatch_table device_dispatch;
struct anv_physical_device_dispatch_table physical_device_dispatch;
struct anv_device_dispatch_table device_dispatch;
- int physicalDeviceCount;
- struct anv_physical_device physicalDevice;
+ bool physical_devices_enumerated;
+ struct list_head physical_devices;
bool pipeline_cache_enabled;
bool pipeline_cache_enabled;