Selaa lähdekoodia

Merge pull request #3150 from jpark37/vulkan-dynamic-arrays

win-capture: Remove fixed-size Vulkan arrays
Jim 5 vuotta sitten
vanhempi
sitoutus
cd865a0be8
1 muutettua tiedostoa jossa 244 lisäystä ja 208 poistoa
  1. 244 208
      plugins/win-capture/graphics-hook/vulkan-capture.c

+ 244 - 208
plugins/win-capture/graphics-hook/vulkan-capture.c

@@ -30,18 +30,27 @@
 #define VkFunc PFN_vkVoidFunction
 #define EXPORT VK_LAYER_EXPORT
 
-#define OBJ_MAX 16
-
 /* use the loader's dispatch table pointer as a key for internal data maps */
 #define GET_LDT(x) (*(void **)x)
 
 static bool vulkan_seen = false;
-static SRWLOCK mutex = SRWLOCK_INIT; // Faster CRITICAL_SECTION
 
 /* ======================================================================== */
 /* hook data                                                                */
 
+struct vk_obj_node {
+	uint64_t obj;
+	struct vk_obj_node *next;
+};
+
+struct vk_obj_list {
+	struct vk_obj_node *root;
+	SRWLOCK mutex;
+};
+
 struct vk_swap_data {
+	struct vk_obj_node node;
+
 	VkSwapchainKHR sc;
 	VkExtent2D image_extent;
 	VkFormat format;
@@ -49,7 +58,7 @@ struct vk_swap_data {
 	VkImage export_image;
 	bool layout_initialized;
 	VkDeviceMemory export_mem;
-	VkImage swap_images[OBJ_MAX];
+	VkImage *swap_images;
 	uint32_t image_count;
 
 	HANDLE handle;
@@ -71,25 +80,42 @@ struct vk_frame_data {
 };
 
 struct vk_family_data {
-	struct vk_frame_data frames[OBJ_MAX];
+	struct vk_frame_data *frames;
 	uint32_t frame_index;
 	uint32_t frame_count;
 };
 
+struct vk_surf_data {
+	struct vk_obj_node node;
+
+	HWND hwnd;
+};
+
+struct vk_inst_data {
+	struct vk_obj_node node;
+
+	bool valid;
+
+	struct vk_inst_funcs funcs;
+	struct vk_obj_list surfaces;
+};
+
 struct vk_data {
+	struct vk_obj_node node;
+
 	bool valid;
 
 	struct vk_device_funcs funcs;
 	VkPhysicalDevice phy_device;
 	VkDevice device;
-	struct vk_swap_data swaps[OBJ_MAX];
+	struct vk_obj_list swaps;
 	struct vk_swap_data *cur_swap;
-	uint32_t swap_idx;
 
-	struct vk_queue_data queues[OBJ_MAX];
+	struct vk_queue_data *queues;
 	uint32_t queue_count;
 
-	struct vk_family_data families[OBJ_MAX];
+	struct vk_family_data *families;
+	uint32_t family_capacity;
 	VkExternalMemoryProperties external_mem_props;
 
 	struct vk_inst_data *inst_data;
@@ -101,83 +127,130 @@ struct vk_data {
 	ID3D11DeviceContext *d3d11_context;
 };
 
-static struct vk_swap_data *get_swap_data(struct vk_data *data,
-					  VkSwapchainKHR sc)
+/* ------------------------------------------------------------------------- */
+
+static void *vk_alloc(const VkAllocationCallbacks *ac, size_t size,
+		      size_t alignment, enum VkSystemAllocationScope scope)
 {
-	for (int i = 0; i < OBJ_MAX; i++) {
-		if (data->swaps[i].sc == sc) {
-			return &data->swaps[i];
-		}
-	}
+	return ac ? ac->pfnAllocation(ac->pUserData, size, alignment, scope)
+		  : _aligned_malloc(size, alignment);
+}
 
-	debug("get_swap_data failed, swapchain not found");
-	return NULL;
+static void vk_free(const VkAllocationCallbacks *ac, void *memory)
+{
+	if (ac)
+		ac->pfnFree(ac->pUserData, memory);
+	else
+		_aligned_free(memory);
 }
 
-static struct vk_swap_data *get_new_swap_data(struct vk_data *data)
+static void add_obj_data(struct vk_obj_list *list, uint64_t obj, void *data)
 {
-	for (int i = 0; i < OBJ_MAX; i++) {
-		if (data->swaps[i].sc == VK_NULL_HANDLE) {
-			return &data->swaps[i];
-		}
-	}
+	AcquireSRWLockExclusive(&list->mutex);
 
-	debug("get_new_swap_data failed, no more free slot");
-	return NULL;
-}
+	struct vk_obj_node *const node = data;
+	node->obj = obj;
+	node->next = list->root;
+	list->root = node;
 
-/* ------------------------------------------------------------------------- */
+	ReleaseSRWLockExclusive(&list->mutex);
+}
 
-static inline size_t find_obj_idx(void *objs[], void *obj)
+static struct vk_obj_node *get_obj_data(struct vk_obj_list *list, uint64_t obj)
 {
-	size_t idx = SIZE_MAX;
+	struct vk_obj_node *data = NULL;
+
+	AcquireSRWLockExclusive(&list->mutex);
 
-	AcquireSRWLockExclusive(&mutex);
-	for (size_t i = 0; i < OBJ_MAX; i++) {
-		if (objs[i] == obj) {
-			idx = i;
+	struct vk_obj_node *node = list->root;
+	while (node) {
+		if (node->obj == obj) {
+			data = node;
 			break;
 		}
+
+		node = node->next;
 	}
-	ReleaseSRWLockExclusive(&mutex);
 
-	return idx;
+	ReleaseSRWLockExclusive(&list->mutex);
+
+	return data;
 }
 
-static size_t get_obj_idx(void *objs[], void *obj)
+static struct vk_obj_node *remove_obj_data(struct vk_obj_list *list,
+					   uint64_t obj)
 {
-	size_t idx = SIZE_MAX;
-
-	AcquireSRWLockExclusive(&mutex);
-	for (size_t i = 0; i < OBJ_MAX; i++) {
-		if (objs[i] == obj) {
-			idx = i;
+	struct vk_obj_node *data = NULL;
+
+	AcquireSRWLockExclusive(&list->mutex);
+
+	struct vk_obj_node *prev = NULL;
+	struct vk_obj_node *node = list->root;
+	while (node) {
+		if (node->obj == obj) {
+			data = node;
+			if (prev)
+				prev->next = node->next;
+			else
+				list->root = node->next;
 			break;
 		}
-		if (!objs[i] && idx == SIZE_MAX) {
-			idx = i;
-		}
+
+		prev = node;
+		node = node->next;
 	}
-	ReleaseSRWLockExclusive(&mutex);
-	return idx;
+
+	ReleaseSRWLockExclusive(&list->mutex);
+
+	return data;
+}
+
+static void init_obj_list(struct vk_obj_list *list)
+{
+	list->root = NULL;
+	InitializeSRWLock(&list->mutex);
 }
 
 /* ------------------------------------------------------------------------- */
 
-static struct vk_data device_data[OBJ_MAX] = {0};
-static void *devices[OBJ_MAX] = {0};
+static struct vk_obj_list devices;
 
-static inline struct vk_data *get_device_data(void *dev)
+static struct vk_data *add_device_data(VkDevice device,
+				       const VkAllocationCallbacks *ac)
 {
-	size_t idx = get_obj_idx(devices, GET_LDT(dev));
-	if (idx == SIZE_MAX) {
-		debug("out of device slots");
-		return NULL;
-	}
+	struct vk_data *data = vk_alloc(ac, sizeof(struct vk_data),
+					_Alignof(struct vk_data),
+					VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+	add_obj_data(&devices, (uint64_t)GET_LDT(device), data);
+	return data;
+}
+
+static struct vk_data *get_device_data(void *obj)
+{
+	return (struct vk_data *)get_obj_data(&devices, (uint64_t)GET_LDT(obj));
+}
+
+/* ------------------------------------------------------------------------- */
+
+static struct vk_swap_data *add_swap_data(struct vk_data *data,
+					  VkSwapchainKHR sc)
+{
+	struct vk_swap_data *swap = vk_alloc(data->ac,
+					     sizeof(struct vk_swap_data),
+					     _Alignof(struct vk_swap_data),
+					     VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+	add_obj_data(&data->swaps, (uint64_t)sc, swap);
+	return swap;
+}
 
-	return &device_data[idx];
+static struct vk_swap_data *get_swap_data(struct vk_data *data,
+					  VkSwapchainKHR sc)
+{
+	return (struct vk_swap_data *)get_obj_data(&data->swaps, (uint64_t)sc);
 }
 
+/* ------------------------------------------------------------------------- */
+
 static void vk_shtex_clear_fence(const struct vk_data *data,
 				 struct vk_frame_data *frame_data)
 {
@@ -205,8 +278,7 @@ static void vk_shtex_wait_until_pool_idle(struct vk_data *data,
 
 static void vk_shtex_wait_until_idle(struct vk_data *data)
 {
-	for (uint32_t fam_idx = 0; fam_idx < _countof(data->families);
-	     fam_idx++) {
+	for (uint32_t fam_idx = 0; fam_idx < data->family_capacity; fam_idx++) {
 		struct vk_family_data *family_data = &data->families[fam_idx];
 		vk_shtex_wait_until_pool_idle(data, family_data);
 	}
@@ -218,9 +290,8 @@ static void vk_shtex_free(struct vk_data *data)
 
 	vk_shtex_wait_until_idle(data);
 
-	for (int swap_idx = 0; swap_idx < OBJ_MAX; swap_idx++) {
-		struct vk_swap_data *swap = &data->swaps[swap_idx];
-
+	struct vk_swap_data *swap = (struct vk_swap_data *)data->swaps.root;
+	while (swap) {
 		if (swap->export_image)
 			data->funcs.DestroyImage(data->device,
 						 swap->export_image, data->ac);
@@ -239,6 +310,8 @@ static void vk_shtex_free(struct vk_data *data)
 		swap->export_image = VK_NULL_HANDLE;
 
 		swap->captured = false;
+
+		swap = (struct vk_swap_data *)swap->node.next;
 	}
 
 	if (data->d3d11_context) {
@@ -255,148 +328,54 @@ static void vk_shtex_free(struct vk_data *data)
 	hlog("------------------ vulkan capture freed ------------------");
 }
 
-static void vk_remove_device(void *dev)
-{
-	size_t idx = find_obj_idx(devices, GET_LDT(dev));
-	if (idx == SIZE_MAX) {
-		return;
-	}
-
-	struct vk_data *data = &device_data[idx];
-
-	memset(data, 0, sizeof(*data));
-
-	AcquireSRWLockExclusive(&mutex);
-	devices[idx] = NULL;
-	ReleaseSRWLockExclusive(&mutex);
-}
-
 /* ------------------------------------------------------------------------- */
 
-struct vk_surf_data {
-	VkSurfaceKHR surf;
-	HWND hwnd;
-	struct vk_surf_data *next;
-};
-
-struct vk_inst_data {
-	bool valid;
-
-	struct vk_inst_funcs funcs;
-	struct vk_surf_data *surfaces;
-};
-
-static void *object_malloc(const VkAllocationCallbacks *ac, size_t size,
-			   size_t alignment)
-{
-	return ac ? ac->pfnAllocation(ac->pUserData, size, alignment,
-				      VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)
-		  : _aligned_malloc(size, alignment);
-}
-
-static void object_free(const VkAllocationCallbacks *ac, void *memory)
-{
-	if (ac)
-		ac->pfnFree(ac->pUserData, memory);
-	else
-		_aligned_free(memory);
-}
-
 static void insert_surf_data(struct vk_inst_data *data, VkSurfaceKHR surf,
 			     HWND hwnd, const VkAllocationCallbacks *ac)
 {
-	struct vk_surf_data *surf_data = object_malloc(
-		ac, sizeof(struct vk_surf_data), _Alignof(struct vk_surf_data));
+	struct vk_surf_data *surf_data = vk_alloc(
+		ac, sizeof(struct vk_surf_data), _Alignof(struct vk_surf_data),
+		VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
 	if (surf_data) {
-		surf_data->surf = surf;
 		surf_data->hwnd = hwnd;
 
-		AcquireSRWLockExclusive(&mutex);
-		struct vk_surf_data *next = data->surfaces;
-		surf_data->next = next;
-		data->surfaces = surf_data;
-		ReleaseSRWLockExclusive(&mutex);
+		add_obj_data(&data->surfaces, (uint64_t)surf, surf_data);
 	}
 }
 
 static HWND find_surf_hwnd(struct vk_inst_data *data, VkSurfaceKHR surf)
 {
-	HWND hwnd = NULL;
-
-	AcquireSRWLockExclusive(&mutex);
-	struct vk_surf_data *surf_data = data->surfaces;
-	while (surf_data) {
-		if (surf_data->surf == surf) {
-			hwnd = surf_data->hwnd;
-			break;
-		}
-		surf_data = surf_data->next;
-	}
-	ReleaseSRWLockExclusive(&mutex);
-
-	return hwnd;
+	struct vk_surf_data *surf_data = (struct vk_surf_data *)get_obj_data(
+		&data->surfaces, (uint64_t)surf);
+	return surf_data->hwnd;
 }
 
-static void erase_surf_data(struct vk_inst_data *data, VkSurfaceKHR surf,
-			    const VkAllocationCallbacks *ac)
-{
-	AcquireSRWLockExclusive(&mutex);
-	struct vk_surf_data *current = data->surfaces;
-	if (current->surf == surf) {
-		data->surfaces = current->next;
-	} else {
-		struct vk_surf_data *previous;
-		do {
-			previous = current;
-			current = current->next;
-		} while (current && current->surf != surf);
+/* ------------------------------------------------------------------------- */
 
-		if (current)
-			previous->next = current->next;
-	}
-	ReleaseSRWLockExclusive(&mutex);
+static struct vk_obj_list instances;
 
-	object_free(ac, current);
+static struct vk_inst_data *add_inst_data(void *inst,
+					  const VkAllocationCallbacks *ac)
+{
+	struct vk_inst_data *data = vk_alloc(
+		ac, sizeof(struct vk_inst_data), _Alignof(struct vk_inst_data),
+		VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+	add_obj_data(&instances, (uint64_t)GET_LDT(inst), data);
+	return data;
 }
 
-/* ------------------------------------------------------------------------- */
-
-static struct vk_inst_data inst_data[OBJ_MAX] = {0};
-static void *instances[OBJ_MAX] = {0};
-
 static struct vk_inst_data *get_inst_data(void *inst)
 {
-	size_t idx = get_obj_idx(instances, GET_LDT(inst));
-	if (idx == SIZE_MAX) {
-		debug("out of instance slots");
-		return NULL;
-	}
-
-	vulkan_seen = true;
-	return &inst_data[idx];
+	return (struct vk_inst_data *)get_obj_data(&instances,
+						   (uint64_t)GET_LDT(inst));
 }
 
 static inline struct vk_inst_funcs *get_inst_funcs(void *inst)
 {
-	struct vk_inst_data *data = get_inst_data(inst);
+	struct vk_inst_data *data = (struct vk_inst_data *)get_inst_data(inst);
 	return &data->funcs;
 }
 
-static void remove_instance(void *inst)
-{
-	size_t idx = find_obj_idx(instances, inst);
-	if (idx == SIZE_MAX) {
-		return;
-	}
-
-	struct vk_inst_data *data = &inst_data[idx];
-	memset(data, 0, sizeof(*data));
-
-	AcquireSRWLockExclusive(&mutex);
-	instances[idx] = NULL;
-	ReleaseSRWLockExclusive(&mutex);
-}
-
 /* ======================================================================== */
 /* capture                                                                  */
 
@@ -712,17 +691,16 @@ static bool vk_shtex_init(struct vk_data *data, HWND window,
 					    (uint32_t)swap->format, false,
 					    (uintptr_t)swap->handle);
 
-	if (swap->captured) {
-		if (global_hook_info->force_shmem) {
-			flog("shared memory capture currently "
-			     "unsupported; ignoring");
-		}
+	if (!swap->captured)
+		return false;
 
-		hlog("vulkan shared texture capture successful");
-		return true;
+	if (global_hook_info->force_shmem) {
+		flog("shared memory capture currently "
+		     "unsupported; ignoring");
 	}
 
-	return false;
+	hlog("vulkan shared texture capture successful");
+	return true;
 }
 
 static void vk_shtex_create_family_objects(struct vk_data *data,
@@ -730,6 +708,14 @@ static void vk_shtex_create_family_objects(struct vk_data *data,
 					   uint32_t image_count)
 {
 	struct vk_family_data *family_data = &data->families[fam_idx];
+	family_data->frames =
+		vk_alloc(data->ac, image_count * sizeof(struct vk_frame_data),
+			 _Alignof(struct vk_frame_data),
+			 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+	memset(family_data->frames, 0,
+	       image_count * sizeof(struct vk_frame_data));
+	family_data->frame_index = 0;
+	family_data->frame_count = image_count;
 
 	for (uint32_t image_index = 0; image_index < image_count;
 	     image_index++) {
@@ -766,9 +752,6 @@ static void vk_shtex_create_family_objects(struct vk_data *data,
 					      &frame_data->fence);
 		debug_res("CreateFence", res);
 	}
-
-	family_data->frame_index = 0;
-	family_data->frame_count = image_count;
 }
 
 static void vk_shtex_destroy_fence(struct vk_data *data, bool *cmd_buffer_busy,
@@ -801,6 +784,8 @@ static void vk_shtex_destroy_family_objects(struct vk_data *data,
 		frame_data->cmd_pool = VK_NULL_HANDLE;
 	}
 
+	vk_free(data->ac, family_data->frames);
+	family_data->frames = NULL;
 	family_data->frame_count = 0;
 }
 
@@ -833,9 +818,6 @@ static void vk_shtex_capture(struct vk_data *data,
 			fam_idx = data->queues[i].fam_idx;
 	}
 
-	if (fam_idx >= _countof(data->families))
-		return;
-
 	struct vk_family_data *family_data = &data->families[fam_idx];
 	const uint32_t image_count = swap->image_count;
 	if (family_data->frame_count < image_count) {
@@ -1139,7 +1121,7 @@ static VkResult VKAPI OBS_CreateInstance(const VkInstanceCreateInfo *cinfo,
 	/* -------------------------------------------------------- */
 	/* fetch the functions we need                              */
 
-	struct vk_inst_data *data = get_inst_data(inst);
+	struct vk_inst_data *data = add_inst_data(inst, ac);
 	struct vk_inst_funcs *funcs = &data->funcs;
 
 #define GETADDR(x)                                     \
@@ -1162,6 +1144,8 @@ static VkResult VKAPI OBS_CreateInstance(const VkInstanceCreateInfo *cinfo,
 	GETADDR(EnumerateDeviceExtensionProperties);
 #undef GETADDR
 
+	init_obj_list(&data->surfaces);
+
 	data->valid = !funcs_not_found;
 	return res;
 }
@@ -1170,8 +1154,11 @@ static VkResult VKAPI OBS_DestroyInstance(VkInstance instance,
 					  const VkAllocationCallbacks *ac)
 {
 	struct vk_inst_funcs *funcs = get_inst_funcs(instance);
+	const uint64_t obj = (uint64_t)GET_LDT(instance);
+	struct vk_inst_data *data =
+		(struct vk_inst_data *)remove_obj_data(&instances, obj);
 	funcs->DestroyInstance(instance, ac);
-	remove_instance(instance);
+	vk_free(ac, data);
 	return VK_SUCCESS;
 }
 
@@ -1273,7 +1260,7 @@ static VkResult VKAPI OBS_CreateDevice(VkPhysicalDevice phy_device,
 
 	VkDevice device = *p_device;
 
-	data = get_device_data(*p_device);
+	data = add_device_data(*p_device, ac);
 	struct vk_device_funcs *dfuncs = &data->funcs;
 
 	data->valid = false; /* set true below if it doesn't go to fail */
@@ -1399,6 +1386,33 @@ static VkResult VKAPI OBS_CreateDevice(VkPhysicalDevice phy_device,
 		data->ac = &data->ac_storage;
 	}
 
+	uint32_t queue_capacity = 0;
+	uint32_t family_capacity = 1;
+	for (uint32_t i = 0, count = info->queueCreateInfoCount; i < count;
+	     ++i) {
+		const VkDeviceQueueCreateInfo *queue_info =
+			&info->pQueueCreateInfos[i];
+		queue_capacity += queue_info->queueCount;
+		family_capacity =
+			max(family_capacity, queue_info->queueFamilyIndex + 1);
+	}
+
+	data->queues = vk_alloc(ac,
+				queue_capacity * sizeof(struct vk_queue_data),
+				_Alignof(struct vk_queue_data),
+				VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+	data->queue_count = 0;
+
+	data->families =
+		vk_alloc(ac, family_capacity * sizeof(struct vk_family_data),
+			 _Alignof(struct vk_family_data),
+			 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+	memset(data->families, 0,
+	       family_capacity * sizeof(struct vk_family_data));
+	data->family_capacity = family_capacity;
+
+	init_obj_list(&data->swaps);
+
 	data->valid = true;
 
 fail:
@@ -1413,21 +1427,26 @@ static void VKAPI OBS_DestroyDevice(VkDevice device,
 		return;
 
 	if (data->valid) {
-		for (uint32_t fam_idx = 0; fam_idx < _countof(data->families);
+		for (uint32_t fam_idx = 0; fam_idx < data->family_capacity;
 		     fam_idx++) {
 			struct vk_family_data *family_data =
 				&data->families[fam_idx];
-			if (family_data->frame_count > 0) {
-				vk_shtex_destroy_family_objects(data,
-								family_data);
-			}
+			vk_shtex_destroy_family_objects(data, family_data);
 		}
-	}
 
-	data->queue_count = 0;
+		vk_free(ac, data->queues);
+		data->queues = NULL;
+		data->queue_count = 0;
 
-	vk_remove_device(device);
+		vk_free(ac, data->families);
+		data->families = NULL;
+		data->family_capacity = 0;
+	}
+
+	const uint64_t obj = (uint64_t)GET_LDT(device);
+	remove_obj_data(&devices, obj);
 	data->funcs.DestroyDevice(device, ac);
+	vk_free(ac, data);
 }
 
 static VkResult VKAPI
@@ -1452,11 +1471,11 @@ OBS_CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *cinfo,
 	res = funcs->GetSwapchainImagesKHR(data->device, sc, &count, NULL);
 	debug_res("GetSwapchainImagesKHR", res);
 
-	struct vk_swap_data *swap = get_new_swap_data(data);
+	struct vk_swap_data *swap = add_swap_data(data, sc);
 	if (count > 0) {
-		if (count > OBJ_MAX)
-			count = OBJ_MAX;
-
+		swap->swap_images = vk_alloc(ac, count * sizeof(VkImage),
+					     _Alignof(VkImage),
+					     VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
 		res = funcs->GetSwapchainImagesKHR(data->device, sc, &count,
 						   swap->swap_images);
 		debug_res("GetSwapchainImagesKHR", res);
@@ -1487,10 +1506,17 @@ static void VKAPI OBS_DestroySwapchainKHR(VkDevice device, VkSwapchainKHR sc,
 
 			swap->sc = VK_NULL_HANDLE;
 			swap->hwnd = NULL;
+
+			vk_free(ac, swap->swap_images);
+			swap->swap_images = NULL;
+			swap->image_count = 0;
 		}
-	}
 
-	funcs->DestroySwapchainKHR(device, sc, ac);
+		const uint64_t obj = swap->node.obj;
+		remove_obj_data(&data->swaps, obj);
+		funcs->DestroySwapchainKHR(device, sc, ac);
+		vk_free(data->ac, swap);
+	}
 }
 
 static void VKAPI OBS_GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex,
@@ -1532,8 +1558,11 @@ static void VKAPI OBS_DestroySurfaceKHR(VkInstance inst, VkSurfaceKHR surf,
 	struct vk_inst_data *data = get_inst_data(inst);
 	struct vk_inst_funcs *funcs = &data->funcs;
 
-	erase_surf_data(data, surf, ac);
+	const uint64_t obj = (uint64_t)surf;
+	struct vk_surf_data *surf_data =
+		(struct vk_surf_data *)remove_obj_data(&data->surfaces, obj);
 	funcs->DestroySurfaceKHR(inst, surf, ac);
+	vk_free(ac, surf_data);
 }
 
 #define GETPROCADDR(func)              \
@@ -1604,6 +1633,13 @@ EXPORT VkResult VKAPI OBS_Negotiate(VkNegotiateLayerInterface *nli)
 		nli->loaderLayerInterfaceVersion = cur_ver;
 	}
 
+	if (!vulkan_seen) {
+		init_obj_list(&instances);
+		init_obj_list(&devices);
+
+		vulkan_seen = true;
+	}
+
 	return VK_SUCCESS;
 }