layers: Add mutex for each validation object
Give each validation object its own mutex, instead of having a single
uber-mutex. SHOULD help with concurrency.
diff --git a/scripts/layer_chassis_generator.py b/scripts/layer_chassis_generator.py
index 1106eeb..c2b6e28 100644
--- a/scripts/layer_chassis_generator.py
+++ b/scripts/layer_chassis_generator.py
@@ -173,8 +173,6 @@
using std::unordered_map;
-static std::mutex global_lock;
-
static const VkLayerProperties global_layer = {
"VK_LAYER_KHRONOS_validation", VK_LAYER_API_VERSION, 1, "LunarG validation Layer",
};
@@ -284,16 +282,18 @@
dispatch_key key = get_dispatch_key(instance);
instance_layer_data *instance_data = GetLayerDataPtr(key, instance_layer_data_map);
for (auto intercept : global_interceptor_list) {
+ std::lock_guard<std::mutex> lock(intercept->layer_mutex);
intercept->PreCallValidateDestroyInstance(instance, pAllocator);
}
for (auto intercept : global_interceptor_list) {
+ std::lock_guard<std::mutex> lock(intercept->layer_mutex);
intercept->PreCallRecordDestroyInstance(instance, pAllocator);
}
instance_data->dispatch_table.DestroyInstance(instance, pAllocator);
- std::lock_guard<std::mutex> lock(global_lock);
for (auto intercept : global_interceptor_list) {
+ std::lock_guard<std::mutex> lock(intercept->layer_mutex);
intercept->PostCallRecordDestroyInstance(instance, pAllocator);
}
// Clean up logging callback, if any
@@ -318,7 +318,6 @@
const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(gpu), instance_layer_data_map);
- std::unique_lock <std::mutex> lock(global_lock);
VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
@@ -326,17 +325,18 @@
chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
for (auto intercept : global_interceptor_list) {
+ std::lock_guard<std::mutex> lock(intercept->layer_mutex);
intercept->PreCallValidateCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
}
for (auto intercept : global_interceptor_list) {
+ std::lock_guard<std::mutex> lock(intercept->layer_mutex);
intercept->PreCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
}
- lock.unlock();
VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
- lock.lock();
for (auto intercept : global_interceptor_list) {
+ std::lock_guard<std::mutex> lock(intercept->layer_mutex);
intercept->PostCallRecordCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
}
layer_data *device_data = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
@@ -348,7 +348,6 @@
VkPhysicalDeviceProperties physical_device_properties{};
instance_data->dispatch_table.GetPhysicalDeviceProperties(gpu, &physical_device_properties);
device_data->extensions.InitFromDeviceCreateInfo(&instance_data->extensions, physical_device_properties.apiVersion, pCreateInfo);
- lock.unlock();
return result;
}
@@ -357,20 +356,20 @@
dispatch_key key = get_dispatch_key(device);
layer_data *device_data = GetLayerDataPtr(key, layer_data_map);
- std::unique_lock <std::mutex> lock(global_lock);
for (auto intercept : global_interceptor_list) {
+ std::lock_guard<std::mutex> lock(intercept->layer_mutex);
intercept->PreCallValidateDestroyDevice(device, pAllocator);
}
for (auto intercept : global_interceptor_list) {
+ std::lock_guard<std::mutex> lock(intercept->layer_mutex);
intercept->PreCallRecordDestroyDevice(device, pAllocator);
}
layer_debug_utils_destroy_device(device);
- lock.unlock();
device_data->dispatch_table.DestroyDevice(device, pAllocator);
- lock.lock();
for (auto intercept : global_interceptor_list) {
+ std::lock_guard<std::mutex> lock(intercept->layer_mutex);
intercept->PostCallRecordDestroyDevice(device, pAllocator);
}
@@ -383,14 +382,17 @@
VkDebugReportCallbackEXT *pCallback) {
instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
for (auto intercept : global_interceptor_list) {
+ std::lock_guard<std::mutex> lock(intercept->layer_mutex);
intercept->PreCallValidateCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
}
for (auto intercept : global_interceptor_list) {
+ std::lock_guard<std::mutex> lock(intercept->layer_mutex);
intercept->PreCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
}
VkResult result = instance_data->dispatch_table.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
result = layer_create_report_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pCallback);
for (auto intercept : global_interceptor_list) {
+ std::lock_guard<std::mutex> lock(intercept->layer_mutex);
intercept->PostCallRecordCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
}
return result;
@@ -400,14 +402,17 @@
const VkAllocationCallbacks *pAllocator) {
instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
for (auto intercept : global_interceptor_list) {
+ std::lock_guard<std::mutex> lock(intercept->layer_mutex);
intercept->PreCallValidateDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
}
for (auto intercept : global_interceptor_list) {
+ std::lock_guard<std::mutex> lock(intercept->layer_mutex);
intercept->PreCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
}
instance_data->dispatch_table.DestroyDebugReportCallbackEXT(instance, callback, pAllocator);
layer_destroy_report_callback(instance_data->report_data, callback, pAllocator);
for (auto intercept : global_interceptor_list) {
+ std::lock_guard<std::mutex> lock(intercept->layer_mutex);
intercept->PostCallRecordDestroyDebugReportCallbackEXT(instance, callback, pAllocator);
}
}
@@ -594,6 +599,8 @@
self.layer_factory += ' global_interceptor_list.emplace_back(this);\n'
self.layer_factory += ' };\n'
self.layer_factory += '\n'
+ self.layer_factory += ' std::mutex layer_mutex;\n'
+ self.layer_factory += '\n'
self.layer_factory += ' std::string layer_name = "CHASSIS";\n'
self.layer_factory += '\n'
self.layer_factory += ' // Pre/post hook point declarations\n'
@@ -780,34 +787,34 @@
assignresult = resulttype.text + ' result = '
# Set up skip and locking
- self.appendSection('command', ' {')
- self.appendSection('command', ' bool skip = false;')
- self.appendSection('command', ' std::lock_guard<std::mutex> lock(global_lock);')
+ self.appendSection('command', ' bool skip = false;')
# Generate pre-call validation source code
- self.appendSection('command', ' for (auto intercept : global_interceptor_list) {')
- self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
- self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
- self.appendSection('command', ' }')
+ self.appendSection('command', ' for (auto intercept : global_interceptor_list) {')
+ self.appendSection('command', ' std::lock_guard<std::mutex> lock(intercept->layer_mutex);')
+ self.appendSection('command', ' skip |= intercept->PreCallValidate%s(%s);' % (api_function_name[2:], paramstext))
+ self.appendSection('command', ' if (skip) %s' % return_map[resulttype.text])
+ self.appendSection('command', ' }')
# Generate pre-call state recording source code
- self.appendSection('command', ' for (auto intercept : global_interceptor_list) {')
- self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
- self.appendSection('command', ' }')
+ self.appendSection('command', ' for (auto intercept : global_interceptor_list) {')
+ self.appendSection('command', ' std::lock_guard<std::mutex> lock(intercept->layer_mutex);')
+ self.appendSection('command', ' intercept->PreCallRecord%s(%s);' % (api_function_name[2:], paramstext))
self.appendSection('command', ' }')
self.appendSection('command', ' ' + assignresult + API + '(' + paramstext + ');')
# Generate post-call object processing source code
- return_check = ''
+ return_type_indent = ''
if (resulttype.text == 'VkResult'):
- return_check = 'if (VK_SUCCESS == result) '
- self.appendSection('command', ' %s{' % return_check)
- self.appendSection('command', ' std::lock_guard<std::mutex> lock(global_lock);')
- self.appendSection('command', ' for (auto intercept : global_interceptor_list) {')
- self.appendSection('command', ' intercept->PostCallRecord%s(%s);' % (api_function_name[2:], paramstext))
- self.appendSection('command', ' }')
- self.appendSection('command', ' }')
+ return_type_indent = ' '
+ self.appendSection('command', ' if (VK_SUCCESS == result) {')
+ self.appendSection('command', '%s for (auto intercept : global_interceptor_list) {' % return_type_indent)
+ self.appendSection('command', '%s std::lock_guard<std::mutex> lock(intercept->layer_mutex);' % return_type_indent)
+ self.appendSection('command', '%s intercept->PostCallRecord%s(%s);' % (return_type_indent,api_function_name[2:], paramstext))
+ self.appendSection('command', '%s }' % return_type_indent)
+ if (resulttype.text == 'VkResult'):
+ self.appendSection('command', ' }')
# Return result variable, if any.
if (resulttype.text != 'void'):