zink: deduplicate VkDevice and VkInstance

it's illegal to mix and match objects between different VkDevices even
if the creation params are identical, and this can cause issues on some
drivers

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33204>
This commit is contained in:
Mike Blumenkrantz 2025-01-24 08:15:48 -05:00 committed by Marge Bot
parent a1333d60e9
commit 015eda4a41
5 changed files with 105 additions and 37 deletions

View file

@ -585,7 +585,7 @@ zink_get_physical_device_info(struct zink_screen *screen)
%endif %endif
%endfor %endfor
if (screen->vk_version < VK_MAKE_VERSION(1,2,0) && screen->instance_info.have_KHR_external_memory_capabilities) { if (screen->vk_version < VK_MAKE_VERSION(1,2,0) && screen->instance_info->have_KHR_external_memory_capabilities) {
info->deviceid_props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES; info->deviceid_props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
info->deviceid_props.pNext = props.pNext; info->deviceid_props.pNext = props.pNext;
props.pNext = &info->deviceid_props; props.pNext = &info->deviceid_props;

View file

@ -97,8 +97,8 @@ struct zink_instance_info {
%endfor %endfor
}; };
bool VkInstance
zink_create_instance(struct zink_screen *screen); zink_create_instance(struct zink_screen *screen, struct zink_instance_info *instance_info);
void void
zink_verify_instance_extensions(struct zink_screen *screen); zink_verify_instance_extensions(struct zink_screen *screen);
@ -128,11 +128,9 @@ impl_code = """
#include "zink_instance.h" #include "zink_instance.h"
#include "zink_screen.h" #include "zink_screen.h"
bool VkInstance
zink_create_instance(struct zink_screen *screen) zink_create_instance(struct zink_screen *screen, struct zink_instance_info *instance_info)
{ {
struct zink_instance_info *instance_info = &screen->instance_info;
/* reserve one slot for MoltenVK */ /* reserve one slot for MoltenVK */
const char *layers[${len(layers) + 1}] = {0}; const char *layers[${len(layers) + 1}] = {0};
uint32_t num_layers = 0; uint32_t num_layers = 0;
@ -266,14 +264,14 @@ zink_create_instance(struct zink_screen *screen)
GET_PROC_ADDR_INSTANCE_LOCAL(screen, NULL, CreateInstance); GET_PROC_ADDR_INSTANCE_LOCAL(screen, NULL, CreateInstance);
assert(vk_CreateInstance); assert(vk_CreateInstance);
VkResult err = vk_CreateInstance(&ici, NULL, &screen->instance); VkInstance instance;
VkResult err = vk_CreateInstance(&ici, NULL, &instance);
if (err != VK_SUCCESS) { if (err != VK_SUCCESS) {
if (!screen->driver_name_is_inferred) if (!screen->driver_name_is_inferred)
mesa_loge("ZINK: vkCreateInstance failed (%s)", vk_Result_to_str(err)); mesa_loge("ZINK: vkCreateInstance failed (%s)", vk_Result_to_str(err));
return false;
} }
return true; return instance;
} }
void void
@ -284,7 +282,7 @@ zink_verify_instance_extensions(struct zink_screen *screen)
%if ext.platform_guard: %if ext.platform_guard:
#ifdef ${ext.platform_guard} #ifdef ${ext.platform_guard}
%endif %endif
if (screen->instance_info.have_${ext.name_with_vendor()}) { if (screen->instance_info->have_${ext.name_with_vendor()}) {
%for cmd in registry.get_registry_entry(ext.name).instance_commands: %for cmd in registry.get_registry_entry(ext.name).instance_commands:
if (!screen->vk.${cmd.lstrip("vk")}) { if (!screen->vk.${cmd.lstrip("vk")}) {
#ifndef NDEBUG #ifndef NDEBUG

View file

@ -2440,7 +2440,7 @@ overwrite:
// This is a known limitation of MoltenVK. // This is a known limitation of MoltenVK.
// See https://github.com/KhronosGroup/MoltenVK/blob/master/Docs/MoltenVK_Runtime_UserGuide.md#known-moltenvk-limitations // See https://github.com/KhronosGroup/MoltenVK/blob/master/Docs/MoltenVK_Runtime_UserGuide.md#known-moltenvk-limitations
|| screen->instance_info.have_MVK_moltenvk || screen->instance_info->have_MVK_moltenvk
#endif #endif
) { ) {
VkDeviceSize size = box->width; VkDeviceSize size = box->width;
@ -3230,7 +3230,7 @@ zink_screen_resource_init(struct pipe_screen *pscreen)
if (screen->info.have_EXT_external_memory_host) { if (screen->info.have_EXT_external_memory_host) {
pscreen->resource_from_user_memory = zink_resource_from_user_memory; pscreen->resource_from_user_memory = zink_resource_from_user_memory;
} }
if (screen->instance_info.have_KHR_external_memory_capabilities) { if (screen->instance_info->have_KHR_external_memory_capabilities) {
pscreen->memobj_create_from_handle = zink_memobj_create_from_handle; pscreen->memobj_create_from_handle = zink_memobj_create_from_handle;
pscreen->memobj_destroy = zink_memobj_destroy; pscreen->memobj_destroy = zink_memobj_destroy;
pscreen->resource_from_memobj = zink_resource_from_memobj; pscreen->resource_from_memobj = zink_resource_from_memobj;

View file

@ -139,6 +139,21 @@ DEBUG_GET_ONCE_FLAGS_OPTION(zink_descriptor_mode, "ZINK_DESCRIPTORS", zink_descr
enum zink_descriptor_mode zink_descriptor_mode; enum zink_descriptor_mode zink_descriptor_mode;
struct zink_device {
unsigned refcount;
VkPhysicalDevice pdev;
VkDevice dev;
struct zink_device_info *info;
};
static simple_mtx_t device_lock = SIMPLE_MTX_INITIALIZER;
static struct set device_table;
static simple_mtx_t instance_lock = SIMPLE_MTX_INITIALIZER;
static struct zink_instance_info instance_info;
static unsigned instance_refcount;
static VkInstance instance;
static const char * static const char *
zink_get_vendor(struct pipe_screen *pscreen) zink_get_vendor(struct pipe_screen *pscreen)
{ {
@ -793,14 +808,14 @@ zink_init_screen_caps(struct zink_screen *screen)
caps->fbfetch_coherent = screen->info.have_EXT_rasterization_order_attachment_access; caps->fbfetch_coherent = screen->info.have_EXT_rasterization_order_attachment_access;
caps->memobj = caps->memobj =
screen->instance_info.have_KHR_external_memory_capabilities && screen->instance_info->have_KHR_external_memory_capabilities &&
(screen->info.have_KHR_external_memory_fd || (screen->info.have_KHR_external_memory_fd ||
screen->info.have_KHR_external_memory_win32); screen->info.have_KHR_external_memory_win32);
caps->fence_signal = caps->fence_signal =
screen->info.have_KHR_external_semaphore_fd || screen->info.have_KHR_external_semaphore_fd ||
screen->info.have_KHR_external_semaphore_win32; screen->info.have_KHR_external_semaphore_win32;
caps->native_fence_fd = caps->native_fence_fd =
screen->instance_info.have_KHR_external_semaphore_capabilities && screen->instance_info->have_KHR_external_semaphore_capabilities &&
screen->info.have_KHR_external_semaphore_fd; screen->info.have_KHR_external_semaphore_fd;
caps->resource_from_user_memory = screen->info.have_EXT_external_memory_host; caps->resource_from_user_memory = screen->info.have_EXT_external_memory_host;
@ -1175,7 +1190,7 @@ zink_init_screen_caps(struct zink_screen *screen)
caps->post_depth_coverage = screen->info.have_EXT_post_depth_coverage; caps->post_depth_coverage = screen->info.have_EXT_post_depth_coverage;
caps->string_marker = screen->instance_info.have_EXT_debug_utils; caps->string_marker = screen->instance_info->have_EXT_debug_utils;
caps->min_line_width = caps->min_line_width =
caps->min_line_width_aa = caps->min_line_width_aa =
@ -1550,11 +1565,31 @@ zink_destroy_screen(struct pipe_screen *pscreen)
if (screen->bindless_layout) if (screen->bindless_layout)
VKSCR(DestroyDescriptorSetLayout)(screen->dev, screen->bindless_layout, NULL); VKSCR(DestroyDescriptorSetLayout)(screen->dev, screen->bindless_layout, NULL);
if (screen->dev) if (screen->dev) {
VKSCR(DestroyDevice)(screen->dev, NULL); simple_mtx_lock(&device_lock);
set_foreach(&device_table, entry) {
struct zink_device *zdev = (void*)entry->key;
if (zdev->pdev == screen->pdev) {
zdev->refcount--;
if (!zdev->refcount) {
VKSCR(DestroyDevice)(zdev->dev, NULL);
_mesa_set_remove(&device_table, entry);
free(zdev);
break;
}
}
}
if (!device_table.entries) {
ralloc_free(device_table.table);
device_table.table = NULL;
}
simple_mtx_unlock(&device_lock);
}
if (screen->instance) simple_mtx_lock(&instance_lock);
VKSCR(DestroyInstance)(screen->instance, NULL); if (screen->instance && --instance_refcount == 0)
VKSCR(DestroyInstance)(instance, NULL);
simple_mtx_unlock(&instance_lock);
util_idalloc_mt_fini(&screen->buffer_ids); util_idalloc_mt_fini(&screen->buffer_ids);
@ -1705,7 +1740,7 @@ choose_pdev(struct zink_screen *screen, int64_t dev_major, int64_t dev_minor, ui
screen->info.device_version = screen->info.props.apiVersion; screen->info.device_version = screen->info.props.apiVersion;
/* runtime version is the lesser of the instance version and device version */ /* runtime version is the lesser of the instance version and device version */
screen->vk_version = MIN2(screen->info.device_version, screen->instance_info.loader_version); screen->vk_version = MIN2(screen->info.device_version, screen->instance_info->loader_version);
/* calculate SPIR-V version based on VK version */ /* calculate SPIR-V version based on VK version */
if (screen->vk_version >= VK_MAKE_VERSION(1, 3, 0)) if (screen->vk_version >= VK_MAKE_VERSION(1, 3, 0))
@ -2008,7 +2043,7 @@ zink_internal_setup_moltenvk(struct zink_screen *screen)
// disable unless we can get MoltenVK to confirm it is supported // disable unless we can get MoltenVK to confirm it is supported
screen->have_dynamic_state_vertex_input_binding_stride = false; screen->have_dynamic_state_vertex_input_binding_stride = false;
if (!screen->instance_info.have_MVK_moltenvk) if (!screen->instance_info->have_MVK_moltenvk)
return true; return true;
GET_PROC_ADDR_INSTANCE_LOCAL(screen, screen->instance, GetMoltenVKConfigurationMVK); GET_PROC_ADDR_INSTANCE_LOCAL(screen, screen->instance, GetMoltenVKConfigurationMVK);
@ -2648,10 +2683,40 @@ hack_it_up:
} }
static VkDevice static VkDevice
zink_create_logical_device(struct zink_screen *screen) get_device(struct zink_screen *screen, VkDeviceCreateInfo *dci)
{ {
VkDevice dev = VK_NULL_HANDLE; VkDevice dev = VK_NULL_HANDLE;
simple_mtx_lock(&device_lock);
if (!device_table.table)
_mesa_set_init(&device_table, NULL, _mesa_hash_pointer, _mesa_key_pointer_equal);
set_foreach(&device_table, entry) {
struct zink_device *zdev = (void*)entry->key;
if (zdev->pdev != screen->pdev)
continue;
zdev->refcount++;
simple_mtx_unlock(&device_lock);
return zdev->dev;
}
VkResult result = VKSCR(CreateDevice)(screen->pdev, dci, NULL, &dev);
if (result != VK_SUCCESS)
mesa_loge("ZINK: vkCreateDevice failed (%s)", vk_Result_to_str(result));
struct zink_device *zdev = malloc(sizeof(struct zink_device));
zdev->refcount = 1;
zdev->pdev = screen->pdev;
zdev->dev = dev;
_mesa_set_add(&device_table, zdev);
simple_mtx_unlock(&device_lock);
return dev;
}
static VkDevice
zink_create_logical_device(struct zink_screen *screen)
{
VkDeviceQueueCreateInfo qci[2] = {0}; VkDeviceQueueCreateInfo qci[2] = {0};
uint32_t queues[3] = { uint32_t queues[3] = {
screen->gfx_queue, screen->gfx_queue,
@ -2685,11 +2750,7 @@ zink_create_logical_device(struct zink_screen *screen)
dci.ppEnabledExtensionNames = screen->info.extensions; dci.ppEnabledExtensionNames = screen->info.extensions;
dci.enabledExtensionCount = screen->info.num_extensions; dci.enabledExtensionCount = screen->info.num_extensions;
VkResult result = VKSCR(CreateDevice)(screen->pdev, &dci, NULL, &dev); return get_device(screen, &dci);
if (result != VK_SUCCESS)
mesa_loge("ZINK: vkCreateDevice failed (%s)", vk_Result_to_str(result));
return dev;
} }
static void static void
@ -3258,7 +3319,6 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev
goto fail; goto fail;
} }
screen->instance_info.loader_version = zink_get_loader_version(screen);
if (config) { if (config) {
driParseConfigFiles(config->options, config->options_info, 0, "zink", driParseConfigFiles(config->options, config->options_info, 0, "zink",
NULL, NULL, NULL, 0, NULL, 0); NULL, NULL, NULL, 0, NULL, 0);
@ -3268,12 +3328,22 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev
screen->driconf.zink_shader_object_enable = driQueryOptionb(config->options, "zink_shader_object_enable"); screen->driconf.zink_shader_object_enable = driQueryOptionb(config->options, "zink_shader_object_enable");
} }
if (!zink_create_instance(screen)) simple_mtx_lock(&instance_lock);
if (++instance_refcount == 1) {
instance_info.loader_version = zink_get_loader_version(screen);
instance = zink_create_instance(screen, &instance_info);
if (!instance)
goto fail; goto fail;
} else {
assert(instance);
}
screen->instance = instance;
screen->instance_info = &instance_info;
simple_mtx_unlock(&instance_lock);
if (zink_debug & ZINK_DEBUG_VALIDATION) { if (zink_debug & ZINK_DEBUG_VALIDATION) {
if (!screen->instance_info.have_layer_KHRONOS_validation && if (!screen->instance_info->have_layer_KHRONOS_validation &&
!screen->instance_info.have_layer_LUNARG_standard_validation) { !screen->instance_info->have_layer_LUNARG_standard_validation) {
if (!screen->driver_name_is_inferred) if (!screen->driver_name_is_inferred)
mesa_loge("Failed to load validation layer"); mesa_loge("Failed to load validation layer");
goto fail; goto fail;
@ -3289,7 +3359,7 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev
zink_verify_instance_extensions(screen); zink_verify_instance_extensions(screen);
if (screen->instance_info.have_EXT_debug_utils && if (screen->instance_info->have_EXT_debug_utils &&
(zink_debug & ZINK_DEBUG_VALIDATION) && !create_debug(screen)) { (zink_debug & ZINK_DEBUG_VALIDATION) && !create_debug(screen)) {
if (!screen->driver_name_is_inferred) if (!screen->driver_name_is_inferred)
debug_printf("ZINK: failed to setup debug utils\n"); debug_printf("ZINK: failed to setup debug utils\n");
@ -3438,7 +3508,7 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev
util_live_shader_cache_init(&screen->shaders, zink_create_gfx_shader_state, zink_delete_shader_state); util_live_shader_cache_init(&screen->shaders, zink_create_gfx_shader_state, zink_delete_shader_state);
screen->base.get_name = zink_get_name; screen->base.get_name = zink_get_name;
if (screen->instance_info.have_KHR_external_memory_capabilities) { if (screen->instance_info->have_KHR_external_memory_capabilities) {
screen->base.get_device_uuid = zink_get_device_uuid; screen->base.get_device_uuid = zink_get_device_uuid;
screen->base.get_driver_uuid = zink_get_driver_uuid; screen->base.get_driver_uuid = zink_get_driver_uuid;
} }
@ -3650,7 +3720,7 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev
init_optimal_keys(screen); init_optimal_keys(screen);
screen->screen_id = p_atomic_inc_return(&num_screens); screen->screen_id = p_atomic_inc_return(&num_screens);
zink_tracing = screen->instance_info.have_EXT_debug_utils && zink_tracing = screen->instance_info->have_EXT_debug_utils &&
(u_trace_is_enabled(U_TRACE_TYPE_PERFETTO) || u_trace_is_enabled(U_TRACE_TYPE_MARKERS)); (u_trace_is_enabled(U_TRACE_TYPE_PERFETTO) || u_trace_is_enabled(U_TRACE_TYPE_MARKERS));
screen->frame_marker_emitted = zink_screen_debug_marker_begin(screen, "frame"); screen->frame_marker_emitted = zink_screen_debug_marker_begin(screen, "frame");

View file

@ -1461,7 +1461,7 @@ struct zink_screen {
uint64_t mapped_vram; uint64_t mapped_vram;
VkInstance instance; VkInstance instance;
struct zink_instance_info instance_info; const struct zink_instance_info *instance_info;
struct hash_table *debug_mem_sizes; struct hash_table *debug_mem_sizes;
simple_mtx_t debug_mem_lock; simple_mtx_t debug_mem_lock;