diff options
author | Jeff Bolz <jbolz@nvidia.com> | 2019-08-20 08:58:51 -0500 |
---|---|---|
committer | Mark Lobodzinski <mark@lunarg.com> | 2019-08-20 14:29:37 -0600 |
commit | 89b9a5030ae96c9a5e3df95833baf1fbf1ab7b8a (patch) | |
tree | 983fd7a1f2ba2489e9fd56c700f6499541d83472 /scripts | |
parent | 2711f53975317e8ec10e26ee3556722556b789ba (diff) | |
download | vulkan-validation-layers-89b9a5030ae96c9a5e3df95833baf1fbf1ab7b8a.tar.gz |
layers: Use concurrent_unordered_map in dispatcher
Use a concurrent_unordered_map for object tracking in dispatch.
Add a vl_concurrent_unordered_map class that acts like an unordered_map but
internally synchronizes concurrent accesses, and split the locks into 2^N
buckets.
Change-Id: If639feb0c53315888e057b1d91ad5da10a9d65c1
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/layer_chassis_dispatch_generator.py | 162 | ||||
-rw-r--r-- | scripts/layer_chassis_generator.py | 36 |
2 files changed, 107 insertions, 91 deletions
diff --git a/scripts/layer_chassis_dispatch_generator.py b/scripts/layer_chassis_dispatch_generator.py index b49f77e0b..977824b2d 100644 --- a/scripts/layer_chassis_dispatch_generator.py +++ b/scripts/layer_chassis_dispatch_generator.py @@ -148,7 +148,6 @@ VkResult DispatchCreateComputePipelines(VkDevice device, VkPipelineCache pipelin pCreateInfos, pAllocator, pPipelines); safe_VkComputePipelineCreateInfo *local_pCreateInfos = NULL; if (pCreateInfos) { - std::lock_guard<std::mutex> lock(dispatch_lock); local_pCreateInfos = new safe_VkComputePipelineCreateInfo[createInfoCount]; for (uint32_t idx0 = 0; idx0 < createInfoCount; ++idx0) { local_pCreateInfos[idx0].initialize(&pCreateInfos[idx0]); @@ -164,7 +163,6 @@ VkResult DispatchCreateComputePipelines(VkDevice device, VkPipelineCache pipelin } } if (pipelineCache) { - std::lock_guard<std::mutex> lock(dispatch_lock); pipelineCache = layer_data->Unwrap(pipelineCache); } @@ -172,7 +170,6 @@ VkResult DispatchCreateComputePipelines(VkDevice device, VkPipelineCache pipelin local_pCreateInfos->ptr(), pAllocator, pPipelines); delete[] local_pCreateInfos; { - std::lock_guard<std::mutex> lock(dispatch_lock); for (uint32_t i = 0; i < createInfoCount; ++i) { if (pPipelines[i] != VK_NULL_HANDLE) { pPipelines[i] = layer_data->WrapNew(pPipelines[i]); @@ -191,7 +188,7 @@ VkResult DispatchCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipeli safe_VkGraphicsPipelineCreateInfo *local_pCreateInfos = nullptr; if (pCreateInfos) { local_pCreateInfos = new safe_VkGraphicsPipelineCreateInfo[createInfoCount]; - std::lock_guard<std::mutex> lock(dispatch_lock); + read_dispatch_lock_guard_t lock(dispatch_lock); for (uint32_t idx0 = 0; idx0 < createInfoCount; ++idx0) { bool uses_color_attachment = false; bool uses_depthstencil_attachment = false; @@ -227,7 +224,6 @@ VkResult DispatchCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipeli } } if (pipelineCache) { - std::lock_guard<std::mutex> lock(dispatch_lock); pipelineCache = layer_data->Unwrap(pipelineCache); } @@ -235,7 +231,6 @@ VkResult DispatchCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipeli local_pCreateInfos->ptr(), pAllocator, pPipelines); delete[] local_pCreateInfos; { - std::lock_guard<std::mutex> lock(dispatch_lock); for (uint32_t i = 0; i < createInfoCount; ++i) { if (pPipelines[i] != VK_NULL_HANDLE) { pPipelines[i] = layer_data->WrapNew(pPipelines[i]); @@ -270,7 +265,7 @@ VkResult DispatchCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo VkResult result = layer_data->device_dispatch_table.CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass); if (!wrap_handles) return result; if (VK_SUCCESS == result) { - std::lock_guard<std::mutex> lock(dispatch_lock); + write_dispatch_lock_guard_t lock(dispatch_lock); UpdateCreateRenderPassState(layer_data, pCreateInfo, *pRenderPass); *pRenderPass = layer_data->WrapNew(*pRenderPass); } @@ -283,7 +278,7 @@ VkResult DispatchCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateI VkResult result = layer_data->device_dispatch_table.CreateRenderPass2KHR(device, pCreateInfo, pAllocator, pRenderPass); if (!wrap_handles) return result; if (VK_SUCCESS == result) { - std::lock_guard<std::mutex> lock(dispatch_lock); + write_dispatch_lock_guard_t lock(dispatch_lock); UpdateCreateRenderPassState(layer_data, pCreateInfo, *pRenderPass); *pRenderPass = layer_data->WrapNew(*pRenderPass); } @@ -293,14 +288,18 @@ VkResult DispatchCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateI void DispatchDestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks *pAllocator) { auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); if (!wrap_handles) return layer_data->device_dispatch_table.DestroyRenderPass(device, renderPass, pAllocator); - std::unique_lock<std::mutex> lock(dispatch_lock); uint64_t renderPass_id = reinterpret_cast<uint64_t &>(renderPass); - renderPass = (VkRenderPass)unique_id_mapping[renderPass_id]; - unique_id_mapping.erase(renderPass_id); - lock.unlock(); + + auto iter = unique_id_mapping.pop(renderPass_id); + if (iter != unique_id_mapping.end()) { + renderPass = (VkRenderPass)iter->second; + } else { + renderPass = (VkRenderPass)0; + } + layer_data->device_dispatch_table.DestroyRenderPass(device, renderPass, pAllocator); - lock.lock(); + write_dispatch_lock_guard_t lock(dispatch_lock); layer_data->renderpasses_states.erase(renderPass); } @@ -310,7 +309,6 @@ VkResult DispatchCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfo if (!wrap_handles) return layer_data->device_dispatch_table.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain); safe_VkSwapchainCreateInfoKHR *local_pCreateInfo = NULL; if (pCreateInfo) { - std::lock_guard<std::mutex> lock(dispatch_lock); local_pCreateInfo = new safe_VkSwapchainCreateInfoKHR(pCreateInfo); local_pCreateInfo->oldSwapchain = layer_data->Unwrap(pCreateInfo->oldSwapchain); // Surface is instance-level object @@ -321,7 +319,6 @@ VkResult DispatchCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfo delete local_pCreateInfo; if (VK_SUCCESS == result) { - std::lock_guard<std::mutex> lock(dispatch_lock); *pSwapchain = layer_data->WrapNew(*pSwapchain); } return result; @@ -335,7 +332,6 @@ VkResult DispatchCreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCo pSwapchains); safe_VkSwapchainCreateInfoKHR *local_pCreateInfos = NULL; { - std::lock_guard<std::mutex> lock(dispatch_lock); if (pCreateInfos) { local_pCreateInfos = new safe_VkSwapchainCreateInfoKHR[swapchainCount]; for (uint32_t i = 0; i < swapchainCount; ++i) { @@ -354,7 +350,6 @@ VkResult DispatchCreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCo pAllocator, pSwapchains); delete[] local_pCreateInfos; if (VK_SUCCESS == result) { - std::lock_guard<std::mutex> lock(dispatch_lock); for (uint32_t i = 0; i < swapchainCount; i++) { pSwapchains[i] = layer_data->WrapNew(pSwapchains[i]); } @@ -369,14 +364,13 @@ VkResult DispatchGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain return layer_data->device_dispatch_table.GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages); VkSwapchainKHR wrapped_swapchain_handle = swapchain; if (VK_NULL_HANDLE != swapchain) { - std::lock_guard<std::mutex> lock(dispatch_lock); swapchain = layer_data->Unwrap(swapchain); } VkResult result = layer_data->device_dispatch_table.GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages); if ((VK_SUCCESS == result) || (VK_INCOMPLETE == result)) { if ((*pSwapchainImageCount > 0) && pSwapchainImages) { - std::lock_guard<std::mutex> lock(dispatch_lock); + write_dispatch_lock_guard_t lock(dispatch_lock); auto &wrapped_swapchain_image_handles = layer_data->swapchain_wrapped_image_handle_map[wrapped_swapchain_handle]; for (uint32_t i = static_cast<uint32_t>(wrapped_swapchain_image_handles.size()); i < *pSwapchainImageCount; i++) { wrapped_swapchain_image_handles.emplace_back(layer_data->WrapNew(pSwapchainImages[i])); @@ -392,18 +386,24 @@ VkResult DispatchGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain void DispatchDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) { auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); if (!wrap_handles) return layer_data->device_dispatch_table.DestroySwapchainKHR(device, swapchain, pAllocator); - std::unique_lock<std::mutex> lock(dispatch_lock); + write_dispatch_lock_guard_t lock(dispatch_lock); auto &image_array = layer_data->swapchain_wrapped_image_handle_map[swapchain]; for (auto &image_handle : image_array) { unique_id_mapping.erase(HandleToUint64(image_handle)); } layer_data->swapchain_wrapped_image_handle_map.erase(swapchain); + lock.unlock(); uint64_t swapchain_id = HandleToUint64(swapchain); - swapchain = (VkSwapchainKHR)unique_id_mapping[swapchain_id]; - unique_id_mapping.erase(swapchain_id); - lock.unlock(); + + auto iter = unique_id_mapping.pop(swapchain_id); + if (iter != unique_id_mapping.end()) { + swapchain = (VkSwapchainKHR)iter->second; + } else { + swapchain = (VkSwapchainKHR)0; + } + layer_data->device_dispatch_table.DestroySwapchainKHR(device, swapchain, pAllocator); } @@ -412,7 +412,6 @@ VkResult DispatchQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresent if (!wrap_handles) return layer_data->device_dispatch_table.QueuePresentKHR(queue, pPresentInfo); safe_VkPresentInfoKHR *local_pPresentInfo = NULL; { - std::lock_guard<std::mutex> lock(dispatch_lock); if (pPresentInfo) { local_pPresentInfo = new safe_VkPresentInfoKHR(pPresentInfo); if (local_pPresentInfo->pWaitSemaphores) { @@ -443,18 +442,24 @@ VkResult DispatchQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresent void DispatchDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks *pAllocator) { auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); if (!wrap_handles) return layer_data->device_dispatch_table.DestroyDescriptorPool(device, descriptorPool, pAllocator); - std::unique_lock<std::mutex> lock(dispatch_lock); + write_dispatch_lock_guard_t lock(dispatch_lock); // remove references to implicitly freed descriptor sets for(auto descriptor_set : layer_data->pool_descriptor_sets_map[descriptorPool]) { unique_id_mapping.erase(reinterpret_cast<uint64_t &>(descriptor_set)); } layer_data->pool_descriptor_sets_map.erase(descriptorPool); + lock.unlock(); uint64_t descriptorPool_id = reinterpret_cast<uint64_t &>(descriptorPool); - descriptorPool = (VkDescriptorPool)unique_id_mapping[descriptorPool_id]; - unique_id_mapping.erase(descriptorPool_id); - lock.unlock(); + + auto iter = unique_id_mapping.pop(descriptorPool_id); + if (iter != unique_id_mapping.end()) { + descriptorPool = (VkDescriptorPool)iter->second; + } else { + descriptorPool = (VkDescriptorPool)0; + } + layer_data->device_dispatch_table.DestroyDescriptorPool(device, descriptorPool, pAllocator); } @@ -463,12 +468,11 @@ VkResult DispatchResetDescriptorPool(VkDevice device, VkDescriptorPool descripto if (!wrap_handles) return layer_data->device_dispatch_table.ResetDescriptorPool(device, descriptorPool, flags); VkDescriptorPool local_descriptor_pool = VK_NULL_HANDLE; { - std::lock_guard<std::mutex> lock(dispatch_lock); local_descriptor_pool = layer_data->Unwrap(descriptorPool); } VkResult result = layer_data->device_dispatch_table.ResetDescriptorPool(device, local_descriptor_pool, flags); if (VK_SUCCESS == result) { - std::lock_guard<std::mutex> lock(dispatch_lock); + write_dispatch_lock_guard_t lock(dispatch_lock); // remove references to implicitly freed descriptor sets for(auto descriptor_set : layer_data->pool_descriptor_sets_map[descriptorPool]) { unique_id_mapping.erase(reinterpret_cast<uint64_t &>(descriptor_set)); @@ -485,7 +489,6 @@ VkResult DispatchAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAl if (!wrap_handles) return layer_data->device_dispatch_table.AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets); safe_VkDescriptorSetAllocateInfo *local_pAllocateInfo = NULL; { - std::lock_guard<std::mutex> lock(dispatch_lock); if (pAllocateInfo) { local_pAllocateInfo = new safe_VkDescriptorSetAllocateInfo(pAllocateInfo); if (pAllocateInfo->descriptorPool) { @@ -504,7 +507,7 @@ VkResult DispatchAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAl delete local_pAllocateInfo; } if (VK_SUCCESS == result) { - std::lock_guard<std::mutex> lock(dispatch_lock); + write_dispatch_lock_guard_t lock(dispatch_lock); auto &pool_descriptor_sets = layer_data->pool_descriptor_sets_map[pAllocateInfo->descriptorPool]; for (uint32_t index0 = 0; index0 < pAllocateInfo->descriptorSetCount; index0++) { pDescriptorSets[index0] = layer_data->WrapNew(pDescriptorSets[index0]); @@ -522,7 +525,6 @@ VkResult DispatchFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptor VkDescriptorSet *local_pDescriptorSets = NULL; VkDescriptorPool local_descriptor_pool = VK_NULL_HANDLE; { - std::lock_guard<std::mutex> lock(dispatch_lock); local_descriptor_pool = layer_data->Unwrap(descriptorPool); if (pDescriptorSets) { local_pDescriptorSets = new VkDescriptorSet[descriptorSetCount]; @@ -535,7 +537,7 @@ VkResult DispatchFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptor (const VkDescriptorSet *)local_pDescriptorSets); if (local_pDescriptorSets) delete[] local_pDescriptorSets; if ((VK_SUCCESS == result) && (pDescriptorSets)) { - std::unique_lock<std::mutex> lock(dispatch_lock); + write_dispatch_lock_guard_t lock(dispatch_lock); auto &pool_descriptor_sets = layer_data->pool_descriptor_sets_map[descriptorPool]; for (uint32_t index0 = 0; index0 < descriptorSetCount; index0++) { VkDescriptorSet handle = pDescriptorSets[index0]; @@ -557,7 +559,6 @@ VkResult DispatchCreateDescriptorUpdateTemplate(VkDevice device, const VkDescrip pDescriptorUpdateTemplate); safe_VkDescriptorUpdateTemplateCreateInfo *local_create_info = NULL; { - std::lock_guard<std::mutex> lock(dispatch_lock); if (pCreateInfo) { local_create_info = new safe_VkDescriptorUpdateTemplateCreateInfo(pCreateInfo); if (pCreateInfo->descriptorSetLayout) { @@ -571,7 +572,7 @@ VkResult DispatchCreateDescriptorUpdateTemplate(VkDevice device, const VkDescrip VkResult result = layer_data->device_dispatch_table.CreateDescriptorUpdateTemplate(device, local_create_info->ptr(), pAllocator, pDescriptorUpdateTemplate); if (VK_SUCCESS == result) { - std::lock_guard<std::mutex> lock(dispatch_lock); + write_dispatch_lock_guard_t lock(dispatch_lock); *pDescriptorUpdateTemplate = layer_data->WrapNew(*pDescriptorUpdateTemplate); // Shadow template createInfo for later updates @@ -591,7 +592,6 @@ VkResult DispatchCreateDescriptorUpdateTemplateKHR(VkDevice device, const VkDesc pDescriptorUpdateTemplate); safe_VkDescriptorUpdateTemplateCreateInfo *local_create_info = NULL; { - std::lock_guard<std::mutex> lock(dispatch_lock); if (pCreateInfo) { local_create_info = new safe_VkDescriptorUpdateTemplateCreateInfo(pCreateInfo); if (pCreateInfo->descriptorSetLayout) { @@ -605,7 +605,7 @@ VkResult DispatchCreateDescriptorUpdateTemplateKHR(VkDevice device, const VkDesc VkResult result = layer_data->device_dispatch_table.CreateDescriptorUpdateTemplateKHR(device, local_create_info->ptr(), pAllocator, pDescriptorUpdateTemplate); if (VK_SUCCESS == result) { - std::lock_guard<std::mutex> lock(dispatch_lock); + write_dispatch_lock_guard_t lock(dispatch_lock); *pDescriptorUpdateTemplate = layer_data->WrapNew(*pDescriptorUpdateTemplate); // Shadow template createInfo for later updates @@ -621,12 +621,18 @@ void DispatchDestroyDescriptorUpdateTemplate(VkDevice device, VkDescriptorUpdate auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); if (!wrap_handles) return layer_data->device_dispatch_table.DestroyDescriptorUpdateTemplate(device, descriptorUpdateTemplate, pAllocator); - std::unique_lock<std::mutex> lock(dispatch_lock); + write_dispatch_lock_guard_t lock(dispatch_lock); uint64_t descriptor_update_template_id = reinterpret_cast<uint64_t &>(descriptorUpdateTemplate); layer_data->desc_template_createinfo_map.erase(descriptor_update_template_id); - descriptorUpdateTemplate = (VkDescriptorUpdateTemplate)unique_id_mapping[descriptor_update_template_id]; - unique_id_mapping.erase(descriptor_update_template_id); lock.unlock(); + + auto iter = unique_id_mapping.pop(descriptor_update_template_id); + if (iter != unique_id_mapping.end()) { + descriptorUpdateTemplate = (VkDescriptorUpdateTemplate)iter->second; + } else { + descriptorUpdateTemplate = (VkDescriptorUpdateTemplate)0; + } + layer_data->device_dispatch_table.DestroyDescriptorUpdateTemplate(device, descriptorUpdateTemplate, pAllocator); } @@ -636,12 +642,18 @@ void DispatchDestroyDescriptorUpdateTemplateKHR(VkDevice device, VkDescriptorUpd auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); if (!wrap_handles) return layer_data->device_dispatch_table.DestroyDescriptorUpdateTemplateKHR(device, descriptorUpdateTemplate, pAllocator); - std::unique_lock<std::mutex> lock(dispatch_lock); + write_dispatch_lock_guard_t lock(dispatch_lock); uint64_t descriptor_update_template_id = reinterpret_cast<uint64_t &>(descriptorUpdateTemplate); layer_data->desc_template_createinfo_map.erase(descriptor_update_template_id); - descriptorUpdateTemplate = (VkDescriptorUpdateTemplate)unique_id_mapping[descriptor_update_template_id]; - unique_id_mapping.erase(descriptor_update_template_id); lock.unlock(); + + auto iter = unique_id_mapping.pop(descriptor_update_template_id); + if (iter != unique_id_mapping.end()) { + descriptorUpdateTemplate = (VkDescriptorUpdateTemplate)iter->second; + } else { + descriptorUpdateTemplate = (VkDescriptorUpdateTemplate)0; + } + layer_data->device_dispatch_table.DestroyDescriptorUpdateTemplateKHR(device, descriptorUpdateTemplate, pAllocator); } @@ -751,12 +763,13 @@ void DispatchUpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet de return layer_data->device_dispatch_table.UpdateDescriptorSetWithTemplate(device, descriptorSet, descriptorUpdateTemplate, pData); uint64_t template_handle = reinterpret_cast<uint64_t &>(descriptorUpdateTemplate); + void *unwrapped_buffer = nullptr; { - std::lock_guard<std::mutex> lock(dispatch_lock); + read_dispatch_lock_guard_t lock(dispatch_lock); descriptorSet = layer_data->Unwrap(descriptorSet); - descriptorUpdateTemplate = (VkDescriptorUpdateTemplate)unique_id_mapping[template_handle]; + descriptorUpdateTemplate = (VkDescriptorUpdateTemplate)layer_data->Unwrap(descriptorUpdateTemplate); + unwrapped_buffer = BuildUnwrappedUpdateTemplateBuffer(layer_data, template_handle, pData); } - void *unwrapped_buffer = BuildUnwrappedUpdateTemplateBuffer(layer_data, template_handle, pData); layer_data->device_dispatch_table.UpdateDescriptorSetWithTemplate(device, descriptorSet, descriptorUpdateTemplate, unwrapped_buffer); free(unwrapped_buffer); } @@ -770,9 +783,9 @@ void DispatchUpdateDescriptorSetWithTemplateKHR(VkDevice device, VkDescriptorSet uint64_t template_handle = reinterpret_cast<uint64_t &>(descriptorUpdateTemplate); void *unwrapped_buffer = nullptr; { - std::lock_guard<std::mutex> lock(dispatch_lock); + read_dispatch_lock_guard_t lock(dispatch_lock); descriptorSet = layer_data->Unwrap(descriptorSet); - descriptorUpdateTemplate = (VkDescriptorUpdateTemplate)unique_id_mapping[template_handle]; + descriptorUpdateTemplate = layer_data->Unwrap(descriptorUpdateTemplate); unwrapped_buffer = BuildUnwrappedUpdateTemplateBuffer(layer_data, template_handle, pData); } layer_data->device_dispatch_table.UpdateDescriptorSetWithTemplateKHR(device, descriptorSet, descriptorUpdateTemplate, unwrapped_buffer); @@ -789,7 +802,7 @@ void DispatchCmdPushDescriptorSetWithTemplateKHR(VkCommandBuffer commandBuffer, uint64_t template_handle = reinterpret_cast<uint64_t &>(descriptorUpdateTemplate); void *unwrapped_buffer = nullptr; { - std::lock_guard<std::mutex> lock(dispatch_lock); + read_dispatch_lock_guard_t lock(dispatch_lock); descriptorUpdateTemplate = layer_data->Unwrap(descriptorUpdateTemplate); layout = layer_data->Unwrap(layout); unwrapped_buffer = BuildUnwrappedUpdateTemplateBuffer(layer_data, template_handle, pData); @@ -806,7 +819,6 @@ VkResult DispatchGetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physical layer_data->instance_dispatch_table.GetPhysicalDeviceDisplayPropertiesKHR(physicalDevice, pPropertyCount, pProperties); if (!wrap_handles) return result; if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pProperties) { - std::lock_guard<std::mutex> lock(dispatch_lock); for (uint32_t idx0 = 0; idx0 < *pPropertyCount; ++idx0) { pProperties[idx0].display = layer_data->MaybeWrapDisplay(pProperties[idx0].display, layer_data); } @@ -821,7 +833,6 @@ VkResult DispatchGetPhysicalDeviceDisplayProperties2KHR(VkPhysicalDevice physica layer_data->instance_dispatch_table.GetPhysicalDeviceDisplayProperties2KHR(physicalDevice, pPropertyCount, pProperties); if (!wrap_handles) return result; if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pProperties) { - std::lock_guard<std::mutex> lock(dispatch_lock); for (uint32_t idx0 = 0; idx0 < *pPropertyCount; ++idx0) { pProperties[idx0].displayProperties.display = layer_data->MaybeWrapDisplay(pProperties[idx0].displayProperties.display, layer_data); @@ -837,7 +848,6 @@ VkResult DispatchGetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice phy layer_data->instance_dispatch_table.GetPhysicalDeviceDisplayPlanePropertiesKHR(physicalDevice, pPropertyCount, pProperties); if (!wrap_handles) return result; if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pProperties) { - std::lock_guard<std::mutex> lock(dispatch_lock); for (uint32_t idx0 = 0; idx0 < *pPropertyCount; ++idx0) { VkDisplayKHR &opt_display = pProperties[idx0].currentDisplay; if (opt_display) opt_display = layer_data->MaybeWrapDisplay(opt_display, layer_data); @@ -853,7 +863,6 @@ VkResult DispatchGetPhysicalDeviceDisplayPlaneProperties2KHR(VkPhysicalDevice ph pPropertyCount, pProperties); if (!wrap_handles) return result; if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pProperties) { - std::lock_guard<std::mutex> lock(dispatch_lock); for (uint32_t idx0 = 0; idx0 < *pPropertyCount; ++idx0) { VkDisplayKHR &opt_display = pProperties[idx0].displayPlaneProperties.currentDisplay; if (opt_display) opt_display = layer_data->MaybeWrapDisplay(opt_display, layer_data); @@ -869,7 +878,6 @@ VkResult DispatchGetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDe pDisplayCount, pDisplays); if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pDisplays) { if (!wrap_handles) return result; - std::lock_guard<std::mutex> lock(dispatch_lock); for (uint32_t i = 0; i < *pDisplayCount; ++i) { if (pDisplays[i]) pDisplays[i] = layer_data->MaybeWrapDisplay(pDisplays[i], layer_data); } @@ -884,13 +892,11 @@ VkResult DispatchGetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice, Vk return layer_data->instance_dispatch_table.GetDisplayModePropertiesKHR(physicalDevice, display, pPropertyCount, pProperties); { - std::lock_guard<std::mutex> lock(dispatch_lock); display = layer_data->Unwrap(display); } VkResult result = layer_data->instance_dispatch_table.GetDisplayModePropertiesKHR(physicalDevice, display, pPropertyCount, pProperties); if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pProperties) { - std::lock_guard<std::mutex> lock(dispatch_lock); for (uint32_t idx0 = 0; idx0 < *pPropertyCount; ++idx0) { pProperties[idx0].displayMode = layer_data->WrapNew(pProperties[idx0].displayMode); } @@ -905,14 +911,12 @@ VkResult DispatchGetDisplayModeProperties2KHR(VkPhysicalDevice physicalDevice, V return layer_data->instance_dispatch_table.GetDisplayModeProperties2KHR(physicalDevice, display, pPropertyCount, pProperties); { - std::lock_guard<std::mutex> lock(dispatch_lock); display = layer_data->Unwrap(display); } VkResult result = layer_data->instance_dispatch_table.GetDisplayModeProperties2KHR(physicalDevice, display, pPropertyCount, pProperties); if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pProperties) { - std::lock_guard<std::mutex> lock(dispatch_lock); for (uint32_t idx0 = 0; idx0 < *pPropertyCount; ++idx0) { pProperties[idx0].displayModeProperties.displayMode = layer_data->WrapNew(pProperties[idx0].displayModeProperties.displayMode); } @@ -925,7 +929,6 @@ VkResult DispatchDebugMarkerSetObjectTagEXT(VkDevice device, const VkDebugMarker if (!wrap_handles) return layer_data->device_dispatch_table.DebugMarkerSetObjectTagEXT(device, pTagInfo); safe_VkDebugMarkerObjectTagInfoEXT local_tag_info(pTagInfo); { - std::lock_guard<std::mutex> lock(dispatch_lock); auto it = unique_id_mapping.find(reinterpret_cast<uint64_t &>(local_tag_info.object)); if (it != unique_id_mapping.end()) { local_tag_info.object = it->second; @@ -941,7 +944,6 @@ VkResult DispatchDebugMarkerSetObjectNameEXT(VkDevice device, const VkDebugMarke if (!wrap_handles) return layer_data->device_dispatch_table.DebugMarkerSetObjectNameEXT(device, pNameInfo); safe_VkDebugMarkerObjectNameInfoEXT local_name_info(pNameInfo); { - std::lock_guard<std::mutex> lock(dispatch_lock); auto it = unique_id_mapping.find(reinterpret_cast<uint64_t &>(local_name_info.object)); if (it != unique_id_mapping.end()) { local_name_info.object = it->second; @@ -958,7 +960,6 @@ VkResult DispatchSetDebugUtilsObjectTagEXT(VkDevice device, const VkDebugUtilsOb if (!wrap_handles) return layer_data->device_dispatch_table.SetDebugUtilsObjectTagEXT(device, pTagInfo); safe_VkDebugUtilsObjectTagInfoEXT local_tag_info(pTagInfo); { - std::lock_guard<std::mutex> lock(dispatch_lock); auto it = unique_id_mapping.find(reinterpret_cast<uint64_t &>(local_tag_info.objectHandle)); if (it != unique_id_mapping.end()) { local_tag_info.objectHandle = it->second; @@ -974,7 +975,6 @@ VkResult DispatchSetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsO if (!wrap_handles) return layer_data->device_dispatch_table.SetDebugUtilsObjectNameEXT(device, pNameInfo); safe_VkDebugUtilsObjectNameInfoEXT local_name_info(pNameInfo); { - std::lock_guard<std::mutex> lock(dispatch_lock); auto it = unique_id_mapping.find(reinterpret_cast<uint64_t &>(local_name_info.objectHandle)); if (it != unique_id_mapping.end()) { local_name_info.objectHandle = it->second; @@ -1121,7 +1121,18 @@ VkResult DispatchSetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsO write('// This intentionally includes a cpp file', file=self.outFile) write('#include "vk_safe_struct.cpp"', file=self.outFile) self.newline() - write('std::mutex dispatch_lock;', file=self.outFile) + write('// shared_mutex support added in MSVC 2015 update 2', file=self.outFile) + write('#if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023918', file=self.outFile) + write(' #include <shared_mutex>', file=self.outFile) + write(' typedef std::shared_mutex dispatch_lock_t;', file=self.outFile) + write(' typedef std::shared_lock<dispatch_lock_t> read_dispatch_lock_guard_t;', file=self.outFile) + write(' typedef std::unique_lock<dispatch_lock_t> write_dispatch_lock_guard_t;', file=self.outFile) + write('#else', file=self.outFile) + write(' typedef std::mutex dispatch_lock_t;', file=self.outFile) + write(' typedef std::unique_lock<dispatch_lock_t> read_dispatch_lock_guard_t;', file=self.outFile) + write(' typedef std::unique_lock<dispatch_lock_t> write_dispatch_lock_guard_t;', file=self.outFile) + write('#endif', file=self.outFile) + write('dispatch_lock_t dispatch_lock;', file=self.outFile) self.newline() write('// Unique Objects pNext extension handling function', file=self.outFile) write('%s' % extension_proc, file=self.outFile) @@ -1270,10 +1281,6 @@ VkResult DispatchSetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsO self.structMembers.append(self.StructMemberData(name=typeName, members=membersInfo)) # - # Insert a lock_guard line - def lock_guard(self, indent): - return '%sstd::lock_guard<std::mutex> lock(dispatch_lock);\n' % indent - # # Determine if a struct has an NDO as a member or an embedded member def struct_contains_ndo(self, struct_item): struct_member_dict = dict(self.structMembers) @@ -1386,7 +1393,6 @@ VkResult DispatchSetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsO handle_name = params[-1].find('name') create_ndo_code += '%sif (VK_SUCCESS == result) {\n' % (indent) indent = self.incIndent(indent) - create_ndo_code += '%sstd::lock_guard<std::mutex> lock(dispatch_lock);\n' % (indent) ndo_dest = '*%s' % handle_name.text if ndo_array == True: create_ndo_code += '%sfor (uint32_t index0 = 0; index0 < %s; index0++) {\n' % (indent, cmd_info[-1].len) @@ -1416,7 +1422,6 @@ VkResult DispatchSetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsO # This API is freeing an array of handles. Remove them from the unique_id map. destroy_ndo_code += '%sif ((VK_SUCCESS == result) && (%s)) {\n' % (indent, cmd_info[param].name) indent = self.incIndent(indent) - destroy_ndo_code += '%sstd::unique_lock<std::mutex> lock(dispatch_lock);\n' % (indent) destroy_ndo_code += '%sfor (uint32_t index0 = 0; index0 < %s; index0++) {\n' % (indent, cmd_info[param].len) indent = self.incIndent(indent) destroy_ndo_code += '%s%s handle = %s[index0];\n' % (indent, cmd_info[param].type, cmd_info[param].name) @@ -1428,11 +1433,18 @@ VkResult DispatchSetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsO destroy_ndo_code += '%s}\n' % indent else: # Remove a single handle from the map - destroy_ndo_code += '%sstd::unique_lock<std::mutex> lock(dispatch_lock);\n' % (indent) destroy_ndo_code += '%suint64_t %s_id = reinterpret_cast<uint64_t &>(%s);\n' % (indent, cmd_info[param].name, cmd_info[param].name) - destroy_ndo_code += '%s%s = (%s)unique_id_mapping[%s_id];\n' % (indent, cmd_info[param].name, cmd_info[param].type, cmd_info[param].name) - destroy_ndo_code += '%sunique_id_mapping.erase(%s_id);\n' % (indent, cmd_info[param].name) - destroy_ndo_code += '%slock.unlock();\n' % (indent) + destroy_ndo_code += '%sauto iter = unique_id_mapping.pop(%s_id);\n' % (indent, cmd_info[param].name) + destroy_ndo_code += '%sif (iter != unique_id_mapping.end()) {\n' % (indent) + indent = self.incIndent(indent) + destroy_ndo_code += '%s%s = (%s)iter->second;\n' % (indent, cmd_info[param].name, cmd_info[param].type) + indent = self.decIndent(indent); + destroy_ndo_code += '%s} else {\n' % (indent) + indent = self.incIndent(indent) + destroy_ndo_code += '%s%s = (%s)0;\n' % (indent, cmd_info[param].name, cmd_info[param].type) + indent = self.decIndent(indent); + destroy_ndo_code += '%s}\n' % (indent) + return ndo_array, destroy_ndo_code # @@ -1624,7 +1636,7 @@ VkResult DispatchSetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsO param_pre_code += destroy_ndo_code if param_pre_code: if (not destroy_func) or (destroy_array): - param_pre_code = '%s{\n%s%s%s%s}\n' % (' ', indent, self.lock_guard(indent), param_pre_code, indent) + param_pre_code = '%s{\n%s%s}\n' % (' ', param_pre_code, indent) return paramdecl, param_pre_code, param_post_code # # Capture command parameter info needed to wrap NDOs as well as handling some boilerplate code diff --git a/scripts/layer_chassis_generator.py b/scripts/layer_chassis_generator.py index 332363f80..c1c7f3dc5 100644 --- a/scripts/layer_chassis_generator.py +++ b/scripts/layer_chassis_generator.py @@ -198,6 +198,7 @@ class LayerChassisOutputGenerator(OutputGenerator): inline_custom_header_preamble = """ #define NOMINMAX +#include <atomic> #include <mutex> #include <cinttypes> #include <stdio.h> @@ -225,8 +226,8 @@ class LayerChassisOutputGenerator(OutputGenerator): #include "vk_typemap_helper.h" -extern uint64_t global_unique_id; -extern std::unordered_map<uint64_t, uint64_t> unique_id_mapping; +extern std::atomic<uint64_t> global_unique_id; +extern vl_concurrent_unordered_map<uint64_t, uint64_t, 4> unique_id_mapping; """ inline_custom_header_class_definition = """ @@ -346,7 +347,7 @@ class ValidationObject { // Handle Wrapping Data // Reverse map display handles - std::unordered_map<VkDisplayKHR, uint64_t> display_id_reverse_mapping; + vl_concurrent_unordered_map<VkDisplayKHR, uint64_t, 0> display_id_reverse_mapping; // Wrapping Descriptor Template Update structures requires access to the template createinfo structs std::unordered_map<uint64_t, std::unique_ptr<TEMPLATE_STATE>> desc_template_createinfo_map; struct SubpassesUsageStates { @@ -362,31 +363,33 @@ class ValidationObject { std::unordered_map<VkDescriptorPool, std::unordered_set<VkDescriptorSet>> pool_descriptor_sets_map; - // Unwrap a handle. Must hold lock. + // Unwrap a handle. template <typename HandleType> HandleType Unwrap(HandleType wrappedHandle) { - // TODO: don't use operator[] here. - return (HandleType)unique_id_mapping[reinterpret_cast<uint64_t const &>(wrappedHandle)]; + auto iter = unique_id_mapping.find(reinterpret_cast<uint64_t const &>(wrappedHandle)); + if (iter == unique_id_mapping.end()) + return (HandleType)0; + return (HandleType)iter->second; } - // Wrap a newly created handle with a new unique ID, and return the new ID -- must hold lock. + // Wrap a newly created handle with a new unique ID, and return the new ID. template <typename HandleType> HandleType WrapNew(HandleType newlyCreatedHandle) { auto unique_id = global_unique_id++; - unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle); + unique_id_mapping.insert_or_assign(unique_id, reinterpret_cast<uint64_t const &>(newlyCreatedHandle)); return (HandleType)unique_id; } - // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. Must hold lock. + // Specialized handling for VkDisplayKHR. Adds an entry to enable reverse-lookup. VkDisplayKHR WrapDisplay(VkDisplayKHR newlyCreatedHandle, ValidationObject *map_data) { auto unique_id = global_unique_id++; - unique_id_mapping[unique_id] = reinterpret_cast<uint64_t const &>(newlyCreatedHandle); - map_data->display_id_reverse_mapping[newlyCreatedHandle] = unique_id; + unique_id_mapping.insert_or_assign(unique_id, reinterpret_cast<uint64_t const &>(newlyCreatedHandle)); + map_data->display_id_reverse_mapping.insert_or_assign(newlyCreatedHandle, unique_id); return (VkDisplayKHR)unique_id; } // VkDisplayKHR objects don't have a single point of creation, so we need to see if one already exists in the map before - // creating another. Must hold lock. + // creating another. VkDisplayKHR MaybeWrapDisplay(VkDisplayKHR handle, ValidationObject *map_data) { // See if this display is already known auto it = map_data->display_id_reverse_mapping.find(handle); @@ -434,10 +437,11 @@ class ValidationObject { std::unordered_map<void*, ValidationObject*> layer_data_map; -// Global unique object identifier. All increments must be guarded by a lock. -uint64_t global_unique_id = 1; -// Map uniqueID to actual object handle -std::unordered_map<uint64_t, uint64_t> unique_id_mapping; +// Global unique object identifier. +std::atomic<uint64_t> global_unique_id(1ULL); +// Map uniqueID to actual object handle. Accesses to the map itself are +// internally synchronized. +vl_concurrent_unordered_map<uint64_t, uint64_t, 4> unique_id_mapping; // TODO: This variable controls handle wrapping -- in the future it should be hooked // up to the new VALIDATION_FEATURES extension. Temporarily, control with a compile-time flag. |