Add core validation for VK_KHR_get_display_properties2
This adds core validation for VK_KHR_get_display_properties2, which is
based on the existing validation for the corresponding functions in
VK_KHR_display. The VK_KHR_get_display_properties2 has no explicit VUs,
only implicit ones that correct generated in the param validation
layer.
This MR also adds object tracking for VkDisplayKHR and
VkDisplayModeKHR for both VK_KHR_display and
VK_KHR_get_display_properties2. Note that the lifetime of these objects
is tied to the physical device. They aren't "created" just queried by
the application. Similar to how VkQueue objects are with respect to a
VkDevice.
This has been tested with the Vulkan CTS
VK_KHR_get_display_properties2 tests and showed some valid usage
violations in the test. These violations are reported here
Tracker/vk-gl-cts#1155 (closed) and fixed here
https://gerrit.khronos.org/#/c/2507/.
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index 2eb37ce..6509ed6 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -12561,23 +12561,41 @@
return result;
}
+VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceDisplayPlaneProperties2KHR(VkPhysicalDevice physicalDevice,
+ uint32_t *pPropertyCount,
+ VkDisplayPlaneProperties2KHR *pProperties) {
+ VkResult result = VK_SUCCESS;
+ instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
+
+ result = instance_data->dispatch_table.GetPhysicalDeviceDisplayPlaneProperties2KHR(physicalDevice, pPropertyCount, pProperties);
+
+ if (result == VK_SUCCESS || result == VK_INCOMPLETE) {
+ PostCallRecordGetPhysicalDeviceDisplayPlanePropertiesKHR(instance_data, physicalDevice, pPropertyCount,
+ (pProperties) ? &pProperties->displayPlaneProperties : 0);
+ }
+
+ return result;
+}
+
static bool ValidateGetPhysicalDeviceDisplayPlanePropertiesKHRQuery(instance_layer_data *instance_data,
VkPhysicalDevice physicalDevice, uint32_t planeIndex,
const char *api_name) {
bool skip = false;
auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice);
if (physical_device_state->vkGetPhysicalDeviceDisplayPlanePropertiesKHRState == UNCALLED) {
- skip |= log_msg(
- instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
- HandleToUint64(physicalDevice), SWAPCHAIN_GET_SUPPORTED_DISPLAYS_WITHOUT_QUERY,
- "Potential problem with calling %s() without first querying vkGetPhysicalDeviceDisplayPlanePropertiesKHR.", api_name);
+ skip |=
+ log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
+ HandleToUint64(physicalDevice), SWAPCHAIN_GET_SUPPORTED_DISPLAYS_WITHOUT_QUERY,
+ "Potential problem with calling %s() without first querying vkGetPhysicalDeviceDisplayPlanePropertiesKHR "
+ "or vkGetPhysicalDeviceDisplayPlaneProperties2KHR.",
+ api_name);
} else {
if (planeIndex >= physical_device_state->display_plane_property_count) {
skip |= log_msg(
instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
HandleToUint64(physicalDevice), "VUID-vkGetDisplayPlaneSupportedDisplaysKHR-planeIndex-01249",
- "%s(): planeIndex must be in the range [0, %d] that was returned by vkGetPhysicalDeviceDisplayPlanePropertiesKHR. "
- "Do you have the plane index hardcoded?",
+ "%s(): planeIndex must be in the range [0, %d] that was returned by vkGetPhysicalDeviceDisplayPlanePropertiesKHR "
+ "or vkGetPhysicalDeviceDisplayPlaneProperties2KHR. Do you have the plane index hardcoded?",
api_name, physical_device_state->display_plane_property_count - 1);
}
}
@@ -12627,6 +12645,20 @@
return result;
}
+VKAPI_ATTR VkResult VKAPI_CALL GetDisplayPlaneCapabilities2KHR(VkPhysicalDevice physicalDevice,
+ const VkDisplayPlaneInfo2KHR *pDisplayPlaneInfo,
+ VkDisplayPlaneCapabilities2KHR *pCapabilities) {
+ VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
+ instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
+ bool skip = PreCallValidateGetDisplayPlaneCapabilitiesKHR(instance_data, physicalDevice, pDisplayPlaneInfo->planeIndex);
+
+ if (!skip) {
+ result = instance_data->dispatch_table.GetDisplayPlaneCapabilities2KHR(physicalDevice, pDisplayPlaneInfo, pCapabilities);
+ }
+
+ return result;
+}
+
VKAPI_ATTR VkResult VKAPI_CALL DebugMarkerSetObjectNameEXT(VkDevice device, const VkDebugMarkerObjectNameInfoEXT *pNameInfo) {
unique_lock_t lock(global_lock);
layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
@@ -13073,8 +13105,10 @@
{"vkDestroyDebugReportCallbackEXT", (void *)DestroyDebugReportCallbackEXT},
{"vkDebugReportMessageEXT", (void *)DebugReportMessageEXT},
{"vkGetPhysicalDeviceDisplayPlanePropertiesKHR", (void *)GetPhysicalDeviceDisplayPlanePropertiesKHR},
+ {"vkGetPhysicalDeviceDisplayPlaneProperties2KHR", (void *)GetPhysicalDeviceDisplayPlaneProperties2KHR},
{"vkGetDisplayPlaneSupportedDisplaysKHR", (void *)GetDisplayPlaneSupportedDisplaysKHR},
{"vkGetDisplayPlaneCapabilitiesKHR", (void *)GetDisplayPlaneCapabilitiesKHR},
+ {"vkGetDisplayPlaneCapabilities2KHR", (void *)GetDisplayPlaneCapabilities2KHR},
{"vkImportSemaphoreFdKHR", (void *)ImportSemaphoreFdKHR},
{"vkGetSemaphoreFdKHR", (void *)GetSemaphoreFdKHR},
{"vkImportFenceFdKHR", (void *)ImportFenceFdKHR},
diff --git a/layers/object_tracker_utils.cpp b/layers/object_tracker_utils.cpp
index 5e96e81..e9b1796 100644
--- a/layers/object_tracker_utils.cpp
+++ b/layers/object_tracker_utils.cpp
@@ -1363,6 +1363,71 @@
return instance_data->instance_dispatch_table.GetInstanceProcAddr(instance, funcName);
}
+VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceDisplayProperties2KHR(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount,
+ VkDisplayProperties2KHR *pProperties) {
+ bool skip = false;
+ {
+ std::lock_guard<std::mutex> lock(global_lock);
+ skip |=
+ ValidateObject(physicalDevice, physicalDevice, kVulkanObjectTypePhysicalDevice, false, kVUIDUndefined, kVUIDUndefined);
+ }
+ if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
+ VkResult result = get_dispatch_table(ot_instance_table_map, physicalDevice)
+ ->GetPhysicalDeviceDisplayProperties2KHR(physicalDevice, pPropertyCount, pProperties);
+ if (pProperties && (VK_SUCCESS == result || VK_INCOMPLETE == result)) {
+ std::lock_guard<std::mutex> lock(global_lock);
+ for (uint32_t index = 0; index < *pPropertyCount; ++index) {
+ CreateObject(physicalDevice, pProperties[index].displayProperties.display, kVulkanObjectTypeDisplayKHR, nullptr);
+ }
+ }
+
+ return result;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice, uint32_t planeIndex,
+ uint32_t *pDisplayCount, VkDisplayKHR *pDisplays) {
+ bool skip = false;
+ {
+ std::lock_guard<std::mutex> lock(global_lock);
+ skip |= ValidateObject(physicalDevice, physicalDevice, kVulkanObjectTypePhysicalDevice, false,
+ "VUID-vkGetDisplayPlaneSupportedDisplaysKHR-physicalDevice-parameter", kVUIDUndefined);
+ }
+ if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
+ VkResult result = get_dispatch_table(ot_instance_table_map, physicalDevice)
+ ->GetDisplayPlaneSupportedDisplaysKHR(physicalDevice, planeIndex, pDisplayCount, pDisplays);
+ if (pDisplays && (VK_SUCCESS == result || VK_INCOMPLETE == result)) {
+ std::lock_guard<std::mutex> lock(global_lock);
+ for (uint32_t index = 0; index < *pDisplayCount; ++index) {
+ CreateObject(physicalDevice, pDisplays[index], kVulkanObjectTypeDisplayKHR, nullptr);
+ }
+ }
+
+ return result;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL GetDisplayModeProperties2KHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
+ uint32_t *pPropertyCount, VkDisplayModeProperties2KHR *pProperties) {
+ bool skip = false;
+ {
+ std::lock_guard<std::mutex> lock(global_lock);
+ skip |=
+ ValidateObject(physicalDevice, physicalDevice, kVulkanObjectTypePhysicalDevice, false, kVUIDUndefined, kVUIDUndefined);
+ skip |= ValidateObject(physicalDevice, display, kVulkanObjectTypeDisplayKHR, false, kVUIDUndefined, kVUIDUndefined);
+ }
+ if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
+ VkResult result = get_dispatch_table(ot_instance_table_map, physicalDevice)
+ ->GetDisplayModeProperties2KHR(physicalDevice, display, pPropertyCount, pProperties);
+ if (pProperties && (VK_SUCCESS == result || VK_INCOMPLETE == result)) {
+ std::lock_guard<std::mutex> lock(global_lock);
+ for (uint32_t index = 0; index < *pPropertyCount; ++index) {
+ CreateObject(physicalDevice, pProperties[index].displayModeProperties.displayMode, kVulkanObjectTypeDisplayModeKHR,
+ nullptr);
+ }
+ }
+
+ return result;
+}
+
} // namespace object_tracker
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
diff --git a/scripts/object_tracker_generator.py b/scripts/object_tracker_generator.py
index 710d1e9..0a6626a 100644
--- a/scripts/object_tracker_generator.py
+++ b/scripts/object_tracker_generator.py
@@ -188,6 +188,9 @@
'vkCmdInsertDebugUtilsLabelEXT',
'vkGetDisplayModePropertiesKHR',
'vkGetPhysicalDeviceDisplayPropertiesKHR',
+ 'vkGetPhysicalDeviceDisplayProperties2KHR',
+ 'vkGetDisplayPlaneSupportedDisplaysKHR',
+ 'vkGetDisplayModeProperties2KHR',
]
# These VUIDS are not implicit, but are best handled in this layer. Codegen for vkDestroy calls will generate a key
# which is translated here into a good VU. Saves ~40 checks.