Skip to content

Commit

Permalink
Refactor instance level objects to not use icd_index
Browse files Browse the repository at this point in the history
The previous way per-ICD instance level objects were accessed was
using the ICD's index into an array that was allocated with the object.
This solution worked while the indexes were static, but with the
recent change to remove unused ICD's that is no longer the case.

This commit replaces an array per object with object arrays, one for each
type (surface, debug messenger, & debug report) and per ICD. That flips
where the index comes from, with the instance storing an array indication
which indices are used and which are free.

Whenever an instance level object is created, the loader checks if there
is a free index available, reusing it if available. Otherwise it resizes
its own store as well as each ICD's array for that object.
  • Loading branch information
charles-lunarg committed Mar 27, 2024
1 parent c2bbc84 commit 6d3a915
Show file tree
Hide file tree
Showing 12 changed files with 669 additions and 638 deletions.
195 changes: 110 additions & 85 deletions loader/debug_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ VkBool32 util_SubmitDebugUtilsMessageEXT(const struct loader_instance *inst, VkD
if (0 < pCallbackData->objectCount) {
debug_utils_AnnotObjectToDebugReportObject(pCallbackData->pObjects, &object_type, &object_handle);
}

while (pTrav) {
if (pTrav->is_messenger && (pTrav->messenger.messageSeverity & messageSeverity) &&
(pTrav->messenger.messageType & messageTypes)) {
Expand All @@ -106,7 +105,6 @@ VkBool32 util_SubmitDebugUtilsMessageEXT(const struct loader_instance *inst, VkD
bail = true;
}
}

pTrav = pTrav->pNext;
}
}
Expand Down Expand Up @@ -175,33 +173,44 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugUtilsMessengerEXT(VkInstanc
const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkDebugUtilsMessengerEXT *pMessenger) {
VkDebugUtilsMessengerEXT *icd_info = NULL;
const struct loader_icd_term *icd_term;
struct loader_instance *inst = (struct loader_instance *)instance;
VkResult res = VK_SUCCESS;
uint32_t storage_idx;
VkLayerDbgFunctionNode *new_dbg_func_node = NULL;
uint32_t next_index = 0;

icd_info = (VkDebugUtilsMessengerEXT *)loader_calloc_with_instance_fallback(
pAllocator, inst, inst->icd_terms_count * sizeof(VkDebugUtilsMessengerEXT), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);

if (!icd_info) {
uint32_t *pNextIndex = loader_instance_heap_alloc(inst, sizeof(uint32_t), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (NULL == pNextIndex) {
res = VK_ERROR_OUT_OF_HOST_MEMORY;
goto out;
}

storage_idx = 0;
for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
if (!icd_term->dispatch.CreateDebugUtilsMessengerEXT) {
continue;
res = loader_get_next_available_entry(inst, &inst->debug_utils_messengers_list, &next_index);
if (res != VK_SUCCESS) {
goto out;
}

for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
if (icd_term->debug_utils_messenger_list.list == NULL) {
res = loader_init_generic_list(inst, (struct loader_generic_list *)&icd_term->debug_utils_messenger_list,
sizeof(VkDebugUtilsMessengerEXT));
if (res != VK_SUCCESS) {
goto out;
}
} else if (icd_term->debug_utils_messenger_list.capacity <= next_index * sizeof(VkDebugUtilsMessengerEXT)) {
res = loader_resize_generic_list(inst, (struct loader_generic_list *)&icd_term->debug_utils_messenger_list);
if (res != VK_SUCCESS) {
goto out;
}
}

res = icd_term->dispatch.CreateDebugUtilsMessengerEXT(icd_term->instance, pCreateInfo, pAllocator, &icd_info[storage_idx]);
if (icd_term->dispatch.CreateDebugUtilsMessengerEXT) {
res = icd_term->dispatch.CreateDebugUtilsMessengerEXT(icd_term->instance, pCreateInfo, pAllocator,
&icd_term->debug_utils_messenger_list.list[next_index]);

if (res != VK_SUCCESS) {
goto out;
if (res != VK_SUCCESS) {
goto out;
}
}
storage_idx++;
}

// Setup the debug report callback in the terminator since a layer may want
Expand All @@ -221,27 +230,29 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugUtilsMessengerEXT(VkInstanc
new_dbg_func_node->pUserData = pCreateInfo->pUserData;
new_dbg_func_node->pNext = inst->current_dbg_function_head;
inst->current_dbg_function_head = new_dbg_func_node;

*pMessenger = (VkDebugUtilsMessengerEXT)(uintptr_t)icd_info;
*pNextIndex = next_index;
*pMessenger = (VkDebugUtilsMessengerEXT)(uintptr_t)pNextIndex;
new_dbg_func_node->messenger.messenger = *pMessenger;

out:

// Roll back on errors
if (VK_SUCCESS != res) {
storage_idx = 0;
for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
if (NULL == icd_term->dispatch.DestroyDebugUtilsMessengerEXT) {
continue;
}

if (icd_info && icd_info[storage_idx]) {
icd_term->dispatch.DestroyDebugUtilsMessengerEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
if (pNextIndex) {
for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
if (icd_term->debug_utils_messenger_list.list && icd_term->debug_utils_messenger_list.list[next_index] &&
NULL != icd_term->dispatch.DestroyDebugUtilsMessengerEXT) {
icd_term->dispatch.DestroyDebugUtilsMessengerEXT(
icd_term->instance, icd_term->debug_utils_messenger_list.list[next_index], pAllocator);
}
}
storage_idx++;
}
if (inst->debug_utils_messengers_list.list &&
inst->debug_utils_messengers_list.capacity > (*pNextIndex) * sizeof(VkBool32)) {
inst->debug_utils_messengers_list.list[*pNextIndex] = VK_FALSE;
}
loader_free_with_instance_fallback(pAllocator, inst, new_dbg_func_node);
loader_free_with_instance_fallback(pAllocator, inst, icd_info);
loader_free_with_instance_fallback(pAllocator, inst, pNextIndex);
}

return res;
Expand All @@ -250,27 +261,28 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugUtilsMessengerEXT(VkInstanc
// This is the instance chain terminator function for DestroyDebugUtilsMessenger
VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
const VkAllocationCallbacks *pAllocator) {
uint32_t storage_idx;
VkDebugUtilsMessengerEXT *icd_info;
const struct loader_icd_term *icd_term;

struct loader_instance *inst = (struct loader_instance *)instance;
icd_info = (VkDebugUtilsMessengerEXT *)(uintptr_t)messenger;
storage_idx = 0;
for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
if (NULL == icd_term->dispatch.DestroyDebugUtilsMessengerEXT) {
continue;
}
uint32_t *debug_messenger_index = (uint32_t *)(uintptr_t)messenger;
// Make sure that messenger actually points to anything
if (NULL == debug_messenger_index) {
return;
}

if (icd_info && icd_info[storage_idx]) {
icd_term->dispatch.DestroyDebugUtilsMessengerEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
if (icd_term->debug_utils_messenger_list.list && icd_term->debug_utils_messenger_list.list[*debug_messenger_index] &&
NULL != icd_term->dispatch.DestroyDebugUtilsMessengerEXT) {
icd_term->dispatch.DestroyDebugUtilsMessengerEXT(
icd_term->instance, icd_term->debug_utils_messenger_list.list[*debug_messenger_index], pAllocator);
}
storage_idx++;
}

util_DestroyDebugUtilsMessenger(inst, messenger, pAllocator);
if (inst->debug_utils_messengers_list.list &&
inst->debug_utils_messengers_list.capacity > (*debug_messenger_index) * sizeof(VkBool32)) {
inst->debug_utils_messengers_list.list[*debug_messenger_index] = VK_FALSE;
}

loader_free_with_instance_fallback(pAllocator, inst, icd_info);
loader_free_with_instance_fallback(pAllocator, inst, debug_messenger_index);
}

// This is the instance chain terminator function for SubmitDebugUtilsMessageEXT
Expand Down Expand Up @@ -431,32 +443,44 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstanc
const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkDebugReportCallbackEXT *pCallback) {
VkDebugReportCallbackEXT *icd_info = NULL;
const struct loader_icd_term *icd_term;
struct loader_instance *inst = (struct loader_instance *)instance;
VkResult res = VK_SUCCESS;
uint32_t storage_idx;
VkLayerDbgFunctionNode *new_dbg_func_node = NULL;
uint32_t next_index = 0;

icd_info = ((VkDebugReportCallbackEXT *)loader_calloc_with_instance_fallback(
pAllocator, inst, inst->icd_terms_count * sizeof(VkDebugReportCallbackEXT), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
if (!icd_info) {
uint32_t *pNextIndex = loader_instance_heap_alloc(inst, sizeof(uint32_t), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (NULL == pNextIndex) {
res = VK_ERROR_OUT_OF_HOST_MEMORY;
goto out;
}

storage_idx = 0;
for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
if (!icd_term->dispatch.CreateDebugReportCallbackEXT) {
continue;
res = loader_get_next_available_entry(inst, &inst->debug_report_callbacks_list, &next_index);
if (res != VK_SUCCESS) {
goto out;
}

for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
if (icd_term->debug_report_callback_list.list == NULL) {
res = loader_init_generic_list(inst, (struct loader_generic_list *)&icd_term->debug_report_callback_list,
sizeof(VkDebugUtilsMessengerEXT));
if (res != VK_SUCCESS) {
goto out;
}
} else if (icd_term->debug_report_callback_list.capacity <= next_index * sizeof(VkDebugReportCallbackEXT)) {
res = loader_resize_generic_list(inst, (struct loader_generic_list *)&icd_term->debug_report_callback_list);
if (res != VK_SUCCESS) {
goto out;
}
}

res = icd_term->dispatch.CreateDebugReportCallbackEXT(icd_term->instance, pCreateInfo, pAllocator, &icd_info[storage_idx]);
if (icd_term->dispatch.CreateDebugReportCallbackEXT) {
res = icd_term->dispatch.CreateDebugReportCallbackEXT(icd_term->instance, pCreateInfo, pAllocator,
&icd_term->debug_report_callback_list.list[next_index]);

if (res != VK_SUCCESS) {
goto out;
if (res != VK_SUCCESS) {
goto out;
}
}
storage_idx++;
}

// Setup the debug report callback in the terminator since a layer may want
Expand All @@ -476,27 +500,29 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstanc
new_dbg_func_node->pUserData = pCreateInfo->pUserData;
new_dbg_func_node->pNext = inst->current_dbg_function_head;
inst->current_dbg_function_head = new_dbg_func_node;

*pCallback = (VkDebugReportCallbackEXT)(uintptr_t)icd_info;
*pNextIndex = next_index;
*pCallback = (VkDebugReportCallbackEXT)(uintptr_t)pNextIndex;
new_dbg_func_node->report.msgCallback = *pCallback;

out:

// Roll back on errors
if (VK_SUCCESS != res) {
storage_idx = 0;
for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) {
continue;
}

if (icd_info && icd_info[storage_idx]) {
icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
if (pNextIndex) {
for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
if (icd_term->debug_report_callback_list.list && icd_term->debug_report_callback_list.list[next_index] &&
NULL != icd_term->dispatch.DestroyDebugReportCallbackEXT) {
icd_term->dispatch.DestroyDebugReportCallbackEXT(
icd_term->instance, icd_term->debug_report_callback_list.list[next_index], pAllocator);
}
}
storage_idx++;
}
if (inst->debug_report_callbacks_list.list &&
inst->debug_report_callbacks_list.capacity > (*pNextIndex) * sizeof(VkBool32)) {
inst->debug_report_callbacks_list.list[*pNextIndex] = VK_FALSE;
}
loader_free_with_instance_fallback(pAllocator, inst, new_dbg_func_node);
loader_free_with_instance_fallback(pAllocator, inst, icd_info);
loader_free_with_instance_fallback(pAllocator, inst, pNextIndex);
}

return res;
Expand All @@ -505,27 +531,26 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstanc
// This is the instance chain terminator function for DestroyDebugReportCallback
VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
const VkAllocationCallbacks *pAllocator) {
uint32_t storage_idx;
VkDebugReportCallbackEXT *icd_info;
const struct loader_icd_term *icd_term;

struct loader_instance *inst = (struct loader_instance *)instance;
icd_info = (VkDebugReportCallbackEXT *)(uintptr_t)callback;
storage_idx = 0;
for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) {
continue;
}

if (icd_info[storage_idx]) {
icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
uint32_t *debug_report_index = (uint32_t *)(uintptr_t)callback;
// Make sure that callback actually points to anything
if (NULL == debug_report_index) {
return;
}
for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
if (icd_term->debug_report_callback_list.list && icd_term->debug_report_callback_list.list[*debug_report_index] &&
NULL != icd_term->dispatch.DestroyDebugReportCallbackEXT) {
icd_term->dispatch.DestroyDebugReportCallbackEXT(
icd_term->instance, icd_term->debug_report_callback_list.list[*debug_report_index], pAllocator);
}
storage_idx++;
}

util_DestroyDebugReportCallback(inst, callback, pAllocator);

loader_free_with_instance_fallback(pAllocator, inst, icd_info);
if (inst->debug_report_callbacks_list.list &&
inst->debug_report_callbacks_list.capacity > (*debug_report_index) * sizeof(VkBool32)) {
inst->debug_report_callbacks_list.list[*debug_report_index] = VK_FALSE;
}
loader_free_with_instance_fallback(pAllocator, inst, debug_report_index);
}

// This is the instance chain terminator function for DebugReportMessage
Expand Down
25 changes: 14 additions & 11 deletions loader/extension_manual.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,13 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2E
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;

VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(surface);
uint8_t icd_index = phys_dev_term->icd_index;

// Unwrap the surface if needed
VkSurfaceKHR unwrapped_surface = surface;
if (NULL != icd_surface->real_icd_surfaces && NULL != (void *)(uintptr_t)(icd_surface->real_icd_surfaces[icd_index])) {
unwrapped_surface = icd_surface->real_icd_surfaces[icd_index];
if (NULL != phys_dev_term->this_icd_term->surface_list.list &&
phys_dev_term->this_icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index]) {
unwrapped_surface = phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index];
}

if (NULL != icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2EXT) {
Expand Down Expand Up @@ -275,12 +276,13 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfacePresentModes2E
abort();
}
VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface);
uint8_t icd_index = phys_dev_term->icd_index;
if (NULL != icd_surface->real_icd_surfaces && NULL != (void *)(uintptr_t)icd_surface->real_icd_surfaces[icd_index]) {
if (NULL != icd_term->surface_list.list &&
icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
icd_term->surface_list.list[icd_surface->surface_index]) {
VkPhysicalDeviceSurfaceInfo2KHR surface_info_copy;
surface_info_copy.sType = pSurfaceInfo->sType;
surface_info_copy.pNext = pSurfaceInfo->pNext;
surface_info_copy.surface = icd_surface->real_icd_surfaces[icd_index];
surface_info_copy.surface = icd_term->surface_list.list[icd_surface->surface_index];
return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModes2EXT(phys_dev_term->phys_dev, &surface_info_copy,
pPresentModeCount, pPresentModes);
}
Expand All @@ -304,9 +306,8 @@ VKAPI_ATTR VkResult VKAPI_CALL GetDeviceGroupSurfacePresentModes2EXT(VkDevice de
VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDeviceGroupSurfacePresentModes2EXT(VkDevice device,
const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
VkDeviceGroupPresentModeFlagsKHR *pModes) {
uint32_t icd_index = 0;
struct loader_device *dev;
struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);
struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev);
if (NULL == icd_term || NULL == dev ||
NULL == dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModes2EXT) {
loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
Expand All @@ -321,12 +322,14 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDeviceGroupSurfacePresentModes2EXT(
"[VUID-vkGetDeviceGroupSurfacePresentModes2EXT-pSurfaceInfo-parameter]");
abort(); /* Intentionally fail so user can correct issue. */
}
VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pSurfaceInfo->surface;
if (NULL != icd_surface->real_icd_surfaces && NULL != (void *)(uintptr_t)icd_surface->real_icd_surfaces[icd_index]) {
VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface);
if (NULL != icd_term->surface_list.list &&
icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
icd_term->surface_list.list[icd_surface->surface_index]) {
VkPhysicalDeviceSurfaceInfo2KHR surface_info_copy;
surface_info_copy.sType = pSurfaceInfo->sType;
surface_info_copy.pNext = pSurfaceInfo->pNext;
surface_info_copy.surface = icd_surface->real_icd_surfaces[icd_index];
surface_info_copy.surface = icd_term->surface_list.list[icd_surface->surface_index];
return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModes2EXT(device, &surface_info_copy,
pModes);
}
Expand Down
Loading

0 comments on commit 6d3a915

Please sign in to comment.