loader: Add checks for usage of wsi extensions
authorMark Young <marky@lunarg.com>
Thu, 8 Sep 2016 18:28:38 +0000 (12:28 -0600)
committerMark Young <marky@lunarg.com>
Thu, 8 Sep 2016 21:10:40 +0000 (15:10 -0600)
The loader really should validate that the WSI extensions are
enabled before being called.  Additionally, I needed to add
more checks for the KHR_display_swapchain extension in the
parameter_validation and object_tracker layers.

Change-Id: I3d07d46baf551be6f5f07e5374d6c683e3f52e7e

layers/object_tracker.cpp
layers/object_tracker.h
layers/parameter_validation.cpp
loader/loader.c
loader/loader.h
loader/wsi.c
loader/wsi.h

index e3d49b5..3c906ac 100644 (file)
@@ -2940,6 +2940,40 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateAndroidSurfaceKHR(VkInstance instance, cons
 }
 #endif // VK_USE_PLATFORM_ANDROID_KHR
 
+VKAPI_ATTR VkResult VKAPI_CALL CreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCount,
+                                                         const VkSwapchainCreateInfoKHR *pCreateInfos,
+                                                         const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchains) {
+    bool skip_call = false;
+    uint32_t i = 0;
+    {
+        std::lock_guard<std::mutex> lock(global_lock);
+        skip_call |= ValidateDispatchableObject(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
+        if (NULL != pCreateInfos) {
+            for (i = 0; i < swapchainCount; i++) {
+                skip_call |= ValidateNonDispatchableObject(device, pCreateInfos[i].oldSwapchain,
+                                                           VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, true);
+                layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+                skip_call |= ValidateNonDispatchableObject(device_data->physical_device, pCreateInfos[i].surface,
+                                                           VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT, false);
+            }
+        }
+    }
+    if (skip_call) {
+        return VK_ERROR_VALIDATION_FAILED_EXT;
+    }
+    VkResult result =
+        get_dispatch_table(ot_device_table_map, device)->CreateSharedSwapchainsKHR(device, swapchainCount, pCreateInfos, pAllocator, pSwapchains);
+    {
+        std::lock_guard<std::mutex> lock(global_lock);
+        if (result == VK_SUCCESS) {
+            for (i = 0; i < swapchainCount; i++) {
+                CreateNonDispatchableObject(device, pSwapchains[i], VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT);
+            }
+        }
+    }
+    return result;
+}
+
 VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
                                                             const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
                                                             const VkAllocationCallbacks *pAllocator,
@@ -3066,11 +3100,16 @@ static inline PFN_vkVoidFunction InterceptWsiEnabledCommand(const char *name, Vk
 static void CheckDeviceRegisterExtensions(const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
     layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
     device_data->wsi_enabled = false;
+    device_data->wsi_display_swapchain_enabled = false;
+    device_data->objtrack_extensions_enabled = false;
 
     for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) {
             device_data->wsi_enabled = true;
         }
+        if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME) == 0) {
+            device_data->wsi_display_swapchain_enabled = true;
+        }
         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], "OBJTRACK_EXTENSIONS") == 0) {
             device_data->objtrack_extensions_enabled = true;
         }
@@ -3885,19 +3924,26 @@ static inline PFN_vkVoidFunction InterceptCoreInstanceCommand(const char *name)
 static inline PFN_vkVoidFunction InterceptWsiEnabledCommand(const char *name, VkDevice device) {
     if (device) {
         layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
-        if (!device_data->wsi_enabled)
-            return nullptr;
-    }
-    if (!strcmp("vkCreateSwapchainKHR", name))
-        return reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR);
-    if (!strcmp("vkDestroySwapchainKHR", name))
-        return reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR);
-    if (!strcmp("vkGetSwapchainImagesKHR", name))
-        return reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR);
-    if (!strcmp("vkAcquireNextImageKHR", name))
-        return reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR);
-    if (!strcmp("vkQueuePresentKHR", name))
-        return reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR);
+
+        if (device_data->wsi_enabled) {
+            if (!strcmp("vkCreateSwapchainKHR", name))
+                return reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR);
+            if (!strcmp("vkDestroySwapchainKHR", name))
+                return reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR);
+            if (!strcmp("vkGetSwapchainImagesKHR", name))
+                return reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR);
+            if (!strcmp("vkAcquireNextImageKHR", name))
+                return reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR);
+            if (!strcmp("vkQueuePresentKHR", name))
+                return reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR);
+        }
+
+        if (device_data->wsi_display_swapchain_enabled) {
+            if (!strcmp("vkCreateSharedSwapchainsKHR", name)) {
+                return reinterpret_cast<PFN_vkVoidFunction>(CreateSharedSwapchainsKHR);
+            }
+        }
+    }
 
     return nullptr;
 }
index 8f514a6..c4088a9 100644 (file)
@@ -92,6 +92,7 @@ struct layer_data {
     debug_report_data *report_data;
     std::vector<VkDebugReportCallbackEXT> logging_callback;
     bool wsi_enabled;
+    bool wsi_display_swapchain_enabled;
     bool objtrack_extensions_enabled;
 
     // The following are for keeping track of the temporary callbacks that can
@@ -112,8 +113,8 @@ struct layer_data {
     // Default constructor
     layer_data()
         : instance(nullptr), physical_device(nullptr), num_objects{}, num_total_objects(0), report_data(nullptr),
-          wsi_enabled(false), objtrack_extensions_enabled(false), num_tmp_callbacks(0), tmp_dbg_create_infos(nullptr),
-                 tmp_callbacks(nullptr), object_map{} {
+          wsi_enabled(false), wsi_display_swapchain_enabled(false), objtrack_extensions_enabled(false), num_tmp_callbacks(0),
+          tmp_dbg_create_infos(nullptr), tmp_callbacks(nullptr), object_map{} {
         object_map.resize(VK_DEBUG_REPORT_OBJECT_TYPE_RANGE_SIZE_EXT + 1);
     }
 };
index bf45285..2bc8d38 100644 (file)
@@ -73,10 +73,11 @@ struct layer_data {
     VkPhysicalDevice physical_device;
 
     bool wsi_enabled;
+    bool wsi_display_swapchain_enabled;
 
     layer_data()
         : report_data(nullptr), num_tmp_callbacks(0), tmp_dbg_create_infos(nullptr), tmp_callbacks(nullptr), device_limits{},
-          physical_device_features{}, physical_device{}, wsi_enabled(false){};
+          physical_device_features{}, physical_device{}, wsi_enabled(false), wsi_display_swapchain_enabled(false) {};
 };
 
 static std::unordered_map<void *, struct instance_extension_enables> instance_extension_map;
@@ -1633,11 +1634,15 @@ static void CheckInstanceRegisterExtensions(const VkInstanceCreateInfo *pCreateI
 static void CheckDeviceRegisterExtensions(const VkDeviceCreateInfo *pCreateInfo, VkDevice device) {
     layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
     device_data->wsi_enabled = false;
+    device_data->wsi_display_swapchain_enabled = false;
 
     for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) {
             device_data->wsi_enabled = true;
         }
+        if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME) == 0) {
+            device_data->wsi_display_swapchain_enabled = true;
+        }
     }
 }
 
@@ -5051,6 +5056,27 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateAndroidSurfaceKHR(VkInstance instance, cons
 }
 #endif // VK_USE_PLATFORM_ANDROID_KHR
 
+VKAPI_ATTR VkResult VKAPI_CALL CreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCount,
+                                                         const VkSwapchainCreateInfoKHR *pCreateInfos,
+                                                         const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchains) {
+    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
+    bool skip_call = false;
+    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+    assert(my_data != NULL);
+
+    skip_call |= parameter_validation_vkCreateSharedSwapchainsKHR(my_data->report_data, swapchainCount, pCreateInfos, pAllocator,
+                                                                  pSwapchains);
+
+    if (!skip_call) {
+        result = get_dispatch_table(pc_device_table_map, device)
+                     ->CreateSharedSwapchainsKHR(device, swapchainCount, pCreateInfos, pAllocator, pSwapchains);
+
+        validate_result(my_data->report_data, "vkCreateSharedSwapchainsKHR", result);
+    }
+
+    return result;
+}
+
 static PFN_vkVoidFunction intercept_core_instance_command(const char *name);
 
 static PFN_vkVoidFunction intercept_core_device_command(const char *name);
@@ -5285,13 +5311,19 @@ static PFN_vkVoidFunction InterceptWsiEnabledCommand(const char *name, VkDevice
 
     if (device) {
         layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
-        if (!device_data->wsi_enabled)
-            return nullptr;
-    }
 
-    for (size_t i = 0; i < ARRAY_SIZE(wsi_device_commands); i++) {
-        if (!strcmp(wsi_device_commands[i].name, name))
-            return wsi_device_commands[i].proc;
+        if (device_data->wsi_enabled) {
+            for (size_t i = 0; i < ARRAY_SIZE(wsi_device_commands); i++) {
+                if (!strcmp(wsi_device_commands[i].name, name))
+                    return wsi_device_commands[i].proc;
+            }
+        }
+
+        if (device_data->wsi_display_swapchain_enabled) {
+            if (!strcmp("vkCreateSharedSwapchainsKHR", name)) {
+                return reinterpret_cast<PFN_vkVoidFunction>(CreateSharedSwapchainsKHR);
+            }
+        }
     }
 
     return nullptr;
index ac8f4fc..5a347db 100644 (file)
@@ -4324,6 +4324,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDevice(
         }
     }
 
+    wsi_create_device(dev, pCreateInfo);
     extensions_create_device(dev, pCreateInfo);
 
     // TODO: Why does fpCreateDevice behave differently than
index 9b57372..651d507 100644 (file)
@@ -160,6 +160,7 @@ struct loader_dev_ext_dispatch_table {
 
 union loader_device_extension_enables {
     struct {
+        uint8_t khr_display_swapchain       : 1;
         uint8_t ext_debug_marker            : 1;
         uint8_t amd_draw_indirect_count     : 1;
         uint8_t nv_external_memory_win32    : 1;
index 10c5260..13d3004 100644 (file)
@@ -158,6 +158,20 @@ void wsi_create_instance(struct loader_instance *ptr_instance,
     }
 }
 
+void wsi_create_device(struct loader_device *dev,
+    const VkDeviceCreateInfo *pCreateInfo) {
+    dev->loader_dispatch.enabled_known_extensions.khr_display_swapchain = 0;
+
+    for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+        if (strcmp(pCreateInfo->ppEnabledExtensionNames[i],
+                   VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME) == 0) {
+            dev->loader_dispatch.enabled_known_extensions
+                .khr_display_swapchain = 1;
+            return;
+        }
+    }
+}
+
 // Linux WSI surface extensions are not always compiled into the loader. (Assume
 // for Windows the KHR_win32_surface is always compiled into loader). A given
 // Linux build environment might not have the headers required for building one
@@ -403,9 +417,8 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(
     const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) {
     const VkLayerDispatchTable *disp;
     disp = loader_get_dispatch(device);
-    VkResult res =
-        disp->CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
-    return res;
+    return disp->CreateSwapchainKHR(device, pCreateInfo, pAllocator,
+                                    pSwapchain);
 }
 
 // This is the trampoline entrypoint for DestroySwapchainKHR
@@ -424,9 +437,8 @@ vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain,
                         VkImage *pSwapchainImages) {
     const VkLayerDispatchTable *disp;
     disp = loader_get_dispatch(device);
-    VkResult res = disp->GetSwapchainImagesKHR(
+    return disp->GetSwapchainImagesKHR(
         device, swapchain, pSwapchainImageCount, pSwapchainImages);
-    return res;
 }
 
 // This is the trampoline entrypoint for AcquireNextImageKHR
@@ -436,9 +448,8 @@ vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain,
                       uint32_t *pImageIndex) {
     const VkLayerDispatchTable *disp;
     disp = loader_get_dispatch(device);
-    VkResult res = disp->AcquireNextImageKHR(device, swapchain, timeout,
-                                             semaphore, fence, pImageIndex);
-    return res;
+    return disp->AcquireNextImageKHR(device, swapchain, timeout,
+        semaphore, fence, pImageIndex);
 }
 
 // This is the trampoline entrypoint for QueuePresentKHR
@@ -446,8 +457,7 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
 vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) {
     const VkLayerDispatchTable *disp;
     disp = loader_get_dispatch(queue);
-    VkResult res = disp->QueuePresentKHR(queue, pPresentInfo);
-    return res;
+    return disp->QueuePresentKHR(queue, pPresentInfo);
 }
 
 #ifdef VK_USE_PLATFORM_WIN32_KHR
@@ -1268,10 +1278,14 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR(
     VkDevice device, uint32_t swapchainCount,
     const VkSwapchainCreateInfoKHR *pCreateInfos,
     const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchains) {
-    const VkLayerDispatchTable *disp;
-    disp = loader_get_dispatch(device);
-    return disp->CreateSharedSwapchainsKHR(
-        device, swapchainCount, pCreateInfos, pAllocator, pSwapchains);
+    struct loader_dev_dispatch_table *disp = loader_get_dev_dispatch(device);
+    if (0 == disp->enabled_known_extensions.khr_display_swapchain ||
+        NULL == disp->core_dispatch.CreateSharedSwapchainsKHR) {
+        return VK_ERROR_EXTENSION_NOT_PRESENT;
+    } else {
+        return disp->core_dispatch.CreateSharedSwapchainsKHR(
+            device, swapchainCount, pCreateInfos, pAllocator, pSwapchains);
+    }
 }
 
 bool wsi_swapchain_instance_gpa(struct loader_instance *ptr_instance,
index fa60088..7409e7d 100644 (file)
@@ -27,6 +27,8 @@ bool wsi_swapchain_instance_gpa(struct loader_instance *ptr_instance,
 
 void wsi_create_instance(struct loader_instance *ptr_instance,
                          const VkInstanceCreateInfo *pCreateInfo);
+void wsi_create_device(struct loader_device *dev,
+                       const VkDeviceCreateInfo *pCreateInfo);
 bool wsi_unsupported_instance_extension(const VkExtensionProperties *ext_prop);
 
 VKAPI_ATTR void VKAPI_CALL