layers: Finish add support to validation for VK_KHR_display extension

Swapchain, object_tracker and unique_objects now intercept and perform
validation checks for this extension.
Change-Id: I2e78d1dc516103de165ef83b99665eaad05b73d9
diff --git a/layers/object_tracker.h b/layers/object_tracker.h
index ac62f03..a20760f 100644
--- a/layers/object_tracker.h
+++ b/layers/object_tracker.h
@@ -289,9 +289,11 @@
 static void create_device(VkDevice dispatchable_object, VkDevice object, VkDebugReportObjectTypeEXT objType);
 static void create_device(VkPhysicalDevice dispatchable_object, VkDevice object, VkDebugReportObjectTypeEXT objType);
 static void create_queue(VkDevice dispatchable_object, VkQueue vkObj, VkDebugReportObjectTypeEXT objType);
+static void create_display_khr(VkPhysicalDevice dispatchable_object, VkDisplayKHR vkObj, VkDebugReportObjectTypeEXT objType);
 static bool validate_image(VkQueue dispatchable_object, VkImage object, VkDebugReportObjectTypeEXT objType, bool null_allowed);
 static bool validate_instance(VkInstance dispatchable_object, VkInstance object, VkDebugReportObjectTypeEXT objType,
                                   bool null_allowed);
+static bool validate_physical_device(VkPhysicalDevice dispatchable_object, VkPhysicalDevice object, VkDebugReportObjectTypeEXT objType, bool null_allowed);
 static bool validate_device(VkDevice dispatchable_object, VkDevice object, VkDebugReportObjectTypeEXT objType,
                                 bool null_allowed);
 static bool validate_descriptor_pool(VkDevice dispatchable_object, VkDescriptorPool object, VkDebugReportObjectTypeEXT objType,
@@ -1025,6 +1027,27 @@
     return result;
 }
 
+VkResult VKAPI_CALL explicit_GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays)
+{
+    bool skipCall = false;
+    {
+        std::lock_guard<std::mutex> lock(global_lock);
+        skipCall |= validate_physical_device(physicalDevice, physicalDevice, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, false);
+    }
+    if (skipCall)
+        return VK_ERROR_VALIDATION_FAILED_EXT;
+    VkResult result = get_dispatch_table(object_tracker_instance_table_map, physicalDevice)->GetDisplayPlaneSupportedDisplaysKHR(physicalDevice, planeIndex, pDisplayCount, pDisplays);
+    {
+        std::lock_guard<std::mutex> lock(global_lock);
+        if (result == VK_SUCCESS) {
+            for (uint32_t idx=0; idx<*pDisplayCount; ++idx) {
+                create_display_khr(physicalDevice, pDisplays[idx], VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT);
+            }
+        }
+    }
+    return result;
+}
+
 // TODO: Add special case to codegen to cover validating all the pipelines instead of just the first
 VkResult explicit_CreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
                                           const VkGraphicsPipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator,
diff --git a/layers/swapchain.cpp b/layers/swapchain.cpp
index 1488feb..f120c7a 100644
--- a/layers/swapchain.cpp
+++ b/layers/swapchain.cpp
@@ -963,8 +963,6 @@
     return VK_ERROR_VALIDATION_FAILED_EXT;
 }
 
-static uint32_t gDisplayPlanePropertyCount = 0;
-static bool gDisplayPlanePropertyCountInit = false;
 VKAPI_ATTR VkResult VKAPI_CALL 
 GetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, VkDisplayPlanePropertiesKHR *pProperties) {
     VkResult result = VK_SUCCESS;
@@ -1028,7 +1026,7 @@
         skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pDisplayCount");
     }
 
-    if (!gDisplayPlanePropertyCountInit)
+    if (!pPhysicalDevice->gotDisplayPlanePropertyCount)
     {
         LOG_WARNING(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "planeIndex",
                 SWAPCHAIN_GET_SUPPORTED_DISPLAYS_WITHOUT_QUERY,
@@ -1036,14 +1034,14 @@
                 __FUNCTION__);
     }
 
-    if (gDisplayPlanePropertyCountInit && planeIndex >= gDisplayPlanePropertyCount)
+    if (pPhysicalDevice->gotDisplayPlanePropertyCount && planeIndex >= pPhysicalDevice->gotDisplayPlanePropertyCount)
     {
         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "planeIndex",
                 SWAPCHAIN_PLANE_INDEX_TOO_LARGE,
                 "%s(): %s must be in the range [0, %d] that was returned by vkGetPhysicalDeviceDisplayPlanePropertiesKHR. Do you have the plane index hardcoded?",
                 __FUNCTION__,
                 "planeIndex",
-                gDisplayPlanePropertyCount - 1);
+                pPhysicalDevice->displayPlanePropertyCount - 1);
     }
     lock.unlock();
 
@@ -1137,7 +1135,7 @@
                               VK_KHR_DISPLAY_EXTENSION_NAME);
     }
 
-    if (!gDisplayPlanePropertyCountInit)
+    if (!pPhysicalDevice->gotDisplayPlanePropertyCount)
     {
         LOG_WARNING(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "planeIndex",
                 SWAPCHAIN_GET_SUPPORTED_DISPLAYS_WITHOUT_QUERY,
@@ -1145,14 +1143,14 @@
                 __FUNCTION__);
     }
 
-    if (gDisplayPlanePropertyCountInit && planeIndex >= gDisplayPlanePropertyCount)
+    if (pPhysicalDevice->gotDisplayPlanePropertyCount && planeIndex >= pPhysicalDevice->displayPlanePropertyCount)
     {
         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "planeIndex",
                 SWAPCHAIN_PLANE_INDEX_TOO_LARGE,
                 "%s(): %s must be in the range [0, %d] that was returned by vkGetPhysicalDeviceDisplayPlanePropertiesKHR. Do you have the plane index hardcoded?",
                 __FUNCTION__,
                 "planeIndex",
-                gDisplayPlanePropertyCount - 1);
+                pPhysicalDevice->displayPlanePropertyCount - 1);
     }
 
     if (!pCapabilities) {
diff --git a/layers/unique_objects.h b/layers/unique_objects.h
index 5cadf2e..5323006 100644
--- a/layers/unique_objects.h
+++ b/layers/unique_objects.h
@@ -62,6 +62,7 @@
     bool mir_enabled;
     bool android_enabled;
     bool win32_enabled;
+    bool display_enabled;
 };
 
 static std::unordered_map<void *, struct instance_extension_enables> instanceExtMap;
@@ -76,6 +77,7 @@
     VkLayerInstanceDispatchTable *pDisp = get_dispatch_table(unique_objects_instance_table_map, instance);
     PFN_vkGetInstanceProcAddr gpa = pDisp->GetInstanceProcAddr;
 
+    //KHR_surface
     pDisp->DestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)gpa(instance, "vkDestroySurfaceKHR");
     pDisp->GetPhysicalDeviceSurfaceSupportKHR =
         (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)gpa(instance, "vkGetPhysicalDeviceSurfaceSupportKHR");
@@ -85,7 +87,16 @@
         (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)gpa(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR");
     pDisp->GetPhysicalDeviceSurfacePresentModesKHR =
         (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)gpa(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR");
+
+    // KHR_display
+    pDisp->GetPhysicalDeviceDisplayPropertiesKHR = (PFN_vkGetPhysicalDeviceDisplayPropertiesKHR)gpa(instance, "vkGetPhysicalDeviceDisplayPropertiesKHR");
+    pDisp->GetPhysicalDeviceDisplayPlanePropertiesKHR = (PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR)gpa(instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR");
+    pDisp->GetDisplayPlaneSupportedDisplaysKHR = (PFN_vkGetDisplayPlaneSupportedDisplaysKHR)gpa(instance, "vkGetDisplayPlaneSupportedDisplaysKHR");
+    pDisp->GetDisplayModePropertiesKHR = (PFN_vkGetDisplayModePropertiesKHR)gpa(instance, "vkGetDisplayModePropertiesKHR");
+    pDisp->CreateDisplayModeKHR = (PFN_vkCreateDisplayModeKHR)gpa(instance, "vkCreateDisplayModeKHR");
+    pDisp->GetDisplayPlaneCapabilitiesKHR = (PFN_vkGetDisplayPlaneCapabilitiesKHR)gpa(instance, "vkGetDisplayPlaneCapabilitiesKHR");
     pDisp->CreateDisplayPlaneSurfaceKHR = (PFN_vkCreateDisplayPlaneSurfaceKHR)gpa(instance, "vkCreateDisplayPlaneSurfaceKHR");
+
 #ifdef VK_USE_PLATFORM_WIN32_KHR
     pDisp->CreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)gpa(instance, "vkCreateWin32SurfaceKHR");
     pDisp->GetPhysicalDeviceWin32PresentationSupportKHR =
@@ -120,6 +131,8 @@
     for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0)
             instanceExtMap[pDisp].wsi_enabled = true;
+        if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_EXTENSION_NAME) == 0)
+            instanceExtMap[pDisp].display_enabled = true;
 #ifdef VK_USE_PLATFORM_XLIB_KHR
         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XLIB_SURFACE_EXTENSION_NAME) == 0)
             instanceExtMap[pDisp].xlib_enabled = true;
@@ -179,6 +192,8 @@
     dispatch_key key = get_dispatch_key(instance);
     get_dispatch_table(unique_objects_instance_table_map, instance)->DestroyInstance(instance, pAllocator);
     layer_data_map.erase(key);
+    VkLayerInstanceDispatchTable *pDisp = get_dispatch_table(unique_objects_instance_table_map, instance);
+    instanceExtMap.erase(pDisp);
 }
 
 // Handle CreateDevice
@@ -403,4 +418,21 @@
     return result;
 }
 
+VkResult explicit_GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays)
+{
+    layer_data *my_map_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
+    VkResult result = get_dispatch_table(unique_objects_instance_table_map, physicalDevice)->GetDisplayPlaneSupportedDisplaysKHR(physicalDevice, planeIndex, pDisplayCount, pDisplays);
+    if (VK_SUCCESS == result) {
+        if ((*pDisplayCount > 0) && pDisplays) {
+            std::lock_guard<std::mutex> lock(global_lock);
+            uint64_t unique_id;
+            for (uint32_t i = 0; i < *pDisplayCount; i++) {
+                unique_id = global_unique_id++;
+                my_map_data->unique_id_mapping[unique_id] = reinterpret_cast<uint64_t &>(*pDisplays);
+                pDisplays[i] = reinterpret_cast<VkDisplayKHR&>(unique_id);
+            }
+        }
+    }
+    return result;
+}
 } // namespace unique_objects