diff --git a/layers/core_checks/cc_wsi.cpp b/layers/core_checks/cc_wsi.cpp index 1bc03c21c02..055422f7fb0 100644 --- a/layers/core_checks/cc_wsi.cpp +++ b/layers/core_checks/cc_wsi.cpp @@ -68,61 +68,50 @@ static VkImageCreateInfo GetSwapchainImpliedImageCreateInfo(const VkSwapchainCre return result; } +// Validate VkSwapchainPresentModesCreateInfoEXT data bool CoreChecks::ValidateSwapchainPresentModesCreateInfo(VkPresentModeKHR present_mode, const Location &create_info_loc, const VkSwapchainCreateInfoKHR &create_info, + const std::vector &present_modes, const vvl::Surface *surface_state) const { bool skip = false; - std::vector present_modes{}; - if (surface_state) { - present_modes = surface_state->GetPresentModes(physical_device, create_info_loc, this); - } else if (IsExtEnabled(instance_extensions.vk_google_surfaceless_query)) { - present_modes = physical_device_state->surfaceless_query_state.present_modes; - } - - if (std::find(present_modes.begin(), present_modes.end(), present_mode) == present_modes.end()) { - skip |= LogError("VUID-VkSwapchainCreateInfoKHR-presentMode-01281", device, create_info_loc, - "called with a non-supported presentMode (%s).", string_VkPresentModeKHR(present_mode)); - } - - // Validate VkSwapchainPresentModesCreateInfoEXT data auto swapchain_present_modes_ci = vku::FindStructInPNextChain(create_info.pNext); - if (swapchain_present_modes_ci) { - ASSERT_AND_RETURN_SKIP(surface_state); + if (!swapchain_present_modes_ci) { + return skip; + } + ASSERT_AND_RETURN_SKIP(surface_state); - bool found_swapchain_modes_ci_present_mode = false; - const std::vector compatible_present_modes = - surface_state->GetCompatibleModes(physical_device, present_mode); - for (uint32_t i = 0; i < swapchain_present_modes_ci->presentModeCount; i++) { - VkPresentModeKHR swapchain_present_mode = swapchain_present_modes_ci->pPresentModes[i]; - - if (std::find(present_modes.begin(), present_modes.end(), swapchain_present_mode) == present_modes.end()) { - if (LogError("VUID-VkSwapchainPresentModesCreateInfoEXT-None-07762", device, - create_info_loc.pNext(Struct::VkSwapchainPresentModesCreateInfoEXT, Field::pPresentModes, i), - "%s is a non-supported presentMode.", string_VkPresentModeKHR(swapchain_present_mode))) { - skip |= true; - } - } + bool found_swapchain_modes_ci_present_mode = false; + const std::vector compatible_present_modes = surface_state->GetCompatibleModes(physical_device, present_mode); + for (uint32_t i = 0; i < swapchain_present_modes_ci->presentModeCount; i++) { + VkPresentModeKHR swapchain_present_mode = swapchain_present_modes_ci->pPresentModes[i]; - if (std::find(compatible_present_modes.begin(), compatible_present_modes.end(), swapchain_present_mode) == - compatible_present_modes.end()) { - if (LogError("VUID-VkSwapchainPresentModesCreateInfoEXT-pPresentModes-07763", device, - create_info_loc.pNext(Struct::VkSwapchainPresentModesCreateInfoEXT, Field::pPresentModes, i), - "%s is a non-compatible presentMode.", string_VkPresentModeKHR(swapchain_present_mode))) { - skip |= true; - } + if (std::find(present_modes.begin(), present_modes.end(), swapchain_present_mode) == present_modes.end()) { + if (LogError("VUID-VkSwapchainPresentModesCreateInfoEXT-None-07762", device, + create_info_loc.pNext(Struct::VkSwapchainPresentModesCreateInfoEXT, Field::pPresentModes, i), + "%s is a non-supported presentMode.", string_VkPresentModeKHR(swapchain_present_mode))) { + skip |= true; } - - const bool has_present_mode = (swapchain_present_modes_ci->pPresentModes[i] == present_mode); - found_swapchain_modes_ci_present_mode |= has_present_mode; } - if (!found_swapchain_modes_ci_present_mode) { - if (LogError("VUID-VkSwapchainPresentModesCreateInfoEXT-presentMode-07764", device, create_info_loc, - "was called with a present mode (%s) that was not included in the set of present modes specified in " - "the vkSwapchainPresentModesCreateInfoEXT structure included in its pNext chain.", - string_VkPresentModeKHR(present_mode))) { + + if (std::find(compatible_present_modes.begin(), compatible_present_modes.end(), swapchain_present_mode) == + compatible_present_modes.end()) { + if (LogError("VUID-VkSwapchainPresentModesCreateInfoEXT-pPresentModes-07763", device, + create_info_loc.pNext(Struct::VkSwapchainPresentModesCreateInfoEXT, Field::pPresentModes, i), + "%s is a non-compatible presentMode.", string_VkPresentModeKHR(swapchain_present_mode))) { skip |= true; } } + + const bool has_present_mode = (swapchain_present_modes_ci->pPresentModes[i] == present_mode); + found_swapchain_modes_ci_present_mode |= has_present_mode; + } + if (!found_swapchain_modes_ci_present_mode) { + if (LogError("VUID-VkSwapchainPresentModesCreateInfoEXT-presentMode-07764", device, create_info_loc, + "was called with a present mode (%s) that was not included in the set of present modes specified in " + "the vkSwapchainPresentModesCreateInfoEXT structure included in its pNext chain.", + string_VkPresentModeKHR(present_mode))) { + skip |= true; + } } return skip; } @@ -527,6 +516,23 @@ bool CoreChecks::ValidateCreateSwapchain(const VkSwapchainCreateInfoKHR &create_ } } + std::vector present_modes{}; + if (surface_state) { + present_modes = surface_state->GetPresentModes(physical_device, create_info_loc, this); + } else if (IsExtEnabled(instance_extensions.vk_google_surfaceless_query)) { + present_modes = physical_device_state->surfaceless_query_state.present_modes; + } + + if (std::find(present_modes.begin(), present_modes.end(), present_mode) == present_modes.end()) { + std::stringstream ss; + for (auto mode : present_modes) { + ss << string_VkPresentModeKHR(mode) << " "; + } + skip |= LogError("VUID-VkSwapchainCreateInfoKHR-presentMode-01281", device, create_info_loc.dot(Field::presentMode), + "(%s) is not supported (the following are supported %s).", string_VkPresentModeKHR(present_mode), + ss.str().c_str()); + } + if (!IsExtEnabled(device_extensions.vk_ext_swapchain_maintenance1)) { // Validate pCreateInfo->imageExtent against VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent: if (!IsExtentInsideBounds(create_info.imageExtent, surface_caps.minImageExtent, surface_caps.maxImageExtent)) { @@ -549,7 +555,7 @@ bool CoreChecks::ValidateCreateSwapchain(const VkSwapchainCreateInfoKHR &create_ } } } else { - skip |= ValidateSwapchainPresentModesCreateInfo(present_mode, create_info_loc, create_info, surface_state); + skip |= ValidateSwapchainPresentModesCreateInfo(present_mode, create_info_loc, create_info, present_modes, surface_state); skip |= ValidateSwapchainPresentScalingCreateInfo(present_mode, create_info_loc, surface_caps, create_info, surface_state); } // Validate state for shared presentable case diff --git a/layers/core_checks/core_validation.h b/layers/core_checks/core_validation.h index 33a9f6bc47b..e931b28e3b5 100644 --- a/layers/core_checks/core_validation.h +++ b/layers/core_checks/core_validation.h @@ -219,6 +219,7 @@ class CoreChecks : public ValidationStateTracker { VkSharingMode sharing_mode) const; bool ValidateSwapchainPresentModesCreateInfo(VkPresentModeKHR present_mode, const Location& create_info_loc, const VkSwapchainCreateInfoKHR& create_info, + const std::vector& present_modes, const vvl::Surface* surface_state) const; bool ValidateSwapchainPresentScalingCreateInfo(VkPresentModeKHR present_mode, const Location& create_info_loc, const VkSurfaceCapabilitiesKHR& capabilities, diff --git a/tests/unit/wsi.cpp b/tests/unit/wsi.cpp index 634b05419f0..40af99d5319 100644 --- a/tests/unit/wsi.cpp +++ b/tests/unit/wsi.cpp @@ -3468,4 +3468,51 @@ TEST_F(NegativeWsi, SwapchainPresentModeInfoImplicit) { m_errorMonitor->SetDesiredError("VUID-VkSwapchainPresentModeInfoEXT-pPresentModes-parameter"); vk::QueuePresentKHR(m_default_queue->handle(), &present); m_errorMonitor->VerifyFound(); -} \ No newline at end of file +} + +TEST_F(NegativeWsi, NonSupportedPresentMode) { + TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8204"); + AddSurfaceExtension(); + RETURN_IF_SKIP(Init()); + RETURN_IF_SKIP(InitSurface()); + + uint32_t count; + vk::GetPhysicalDeviceSurfacePresentModesKHR(gpu(), m_surface, &count, nullptr); + std::vector present_modes(count); + vk::GetPhysicalDeviceSurfacePresentModesKHR(gpu(), m_surface, &count, present_modes.data()); + for (auto present_mode : present_modes) { + if (present_mode == VK_PRESENT_MODE_IMMEDIATE_KHR) { + GTEST_SKIP() << "Need no support for VK_PRESENT_MODE_IMMEDIATE_KHR"; + } + } + + VkBool32 supported; + vk::GetPhysicalDeviceSurfaceSupportKHR(gpu(), m_device->graphics_queue_node_index_, m_surface, &supported); + if (!supported) { + GTEST_SKIP() << "Surface not supported."; + } + + SurfaceInformation info = GetSwapchainInfo(m_surface); + InitSwapchainInfo(); + + VkSwapchainCreateInfoKHR swapchain_create_info = vku::InitStructHelper(); + swapchain_create_info.surface = m_surface; + swapchain_create_info.minImageCount = info.surface_capabilities.minImageCount; + swapchain_create_info.imageFormat = info.surface_formats[0].format; + swapchain_create_info.imageColorSpace = info.surface_formats[0].colorSpace; + swapchain_create_info.imageExtent = {info.surface_capabilities.minImageExtent.width, + info.surface_capabilities.minImageExtent.height}; + swapchain_create_info.imageArrayLayers = 1; + swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + swapchain_create_info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + swapchain_create_info.compositeAlpha = info.surface_composite_alpha; + swapchain_create_info.presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; + swapchain_create_info.clipped = VK_FALSE; + swapchain_create_info.oldSwapchain = VK_NULL_HANDLE; + + VkSwapchainKHR swapchain; + m_errorMonitor->SetDesiredError("VUID-VkSwapchainCreateInfoKHR-presentMode-01281"); + vk::CreateSwapchainKHR(device(), &swapchain_create_info, nullptr, &swapchain); + m_errorMonitor->VerifyFound(); +}