diff --git a/include/layer.hpp b/include/layer.hpp index 8cb3163..ce12818 100644 --- a/include/layer.hpp +++ b/include/layer.hpp @@ -53,6 +53,11 @@ namespace Layer { void ovkGetPhysicalDeviceProperties( VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties); + /// Call to the original vkGetPhysicalDeviceSurfaceCapabilitiesKHR function. + VkResult ovkGetPhysicalDeviceSurfaceCapabilitiesKHR( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + VkSurfaceCapabilitiesKHR* pSurfaceCapabilities); /// Call to the original vkCreateSwapchainKHR function. VkResult ovkCreateSwapchainKHR( diff --git a/include/utils/utils.hpp b/include/utils/utils.hpp index 7094cbe..138eb00 100644 --- a/include/utils/utils.hpp +++ b/include/utils/utils.hpp @@ -31,6 +31,15 @@ namespace Utils { /// uint64_t getDeviceUUID(VkPhysicalDevice physicalDevice); + /// + /// Get the max image count for a swapchain. + /// + /// @param physicalDevice The physical device to query. + /// @param surface The surface to query the capabilities for. + /// @return The maximum image count for the swapchain. + /// + uint32_t getMaxImageCount(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface); + /// /// Ensure a list of extensions is present in the given array. /// diff --git a/src/hooks.cpp b/src/hooks.cpp index a7afc26..6f7c12b 100644 --- a/src/hooks.cpp +++ b/src/hooks.cpp @@ -151,13 +151,21 @@ namespace { // update swapchain create info VkSwapchainCreateInfoKHR createInfo = *pCreateInfo; - createInfo.minImageCount += 1 + deviceInfo.frameGen; // 1 deferred + N framegen, FIXME: check hardware max + const uint32_t maxImageCount = Utils::getMaxImageCount(deviceInfo.physicalDevice, pCreateInfo->surface); + const uint32_t imageCount = createInfo.minImageCount + 1 + static_cast(deviceInfo.frameGen); + Log::debug("hooks", "Creating swapchain with max image count: {}/{}", imageCount, maxImageCount); + if (imageCount > maxImageCount) { + Log::warn("hooks", "LSFG_MULTIPLIER is set very high. This might lead to performance degradation"); + createInfo.minImageCount = maxImageCount; // limit to max possible + } else { + createInfo.minImageCount = imageCount; // set to frameGen + 1 + } createInfo.imageUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; // allow copy from/to images createInfo.imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; createInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR; // force vsync auto res = Layer::ovkCreateSwapchainKHR(device, &createInfo, pAllocator, pSwapchain); if (res != VK_SUCCESS) { - Log::error("hooks", "Failed to create swapchain: {:x}", static_cast(res)); + Log::error("hooks", "Failed to create swapchain: {}", static_cast(res)); return res; } Log::info("hooks", "Swapchain created successfully: {:x}", @@ -235,6 +243,8 @@ namespace { auto& swapchain = it3->second; // patch vsync NOLINTBEGIN + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" const VkSwapchainPresentModeInfoEXT* presentModeInfo = reinterpret_cast(pPresentInfo->pNext); while (presentModeInfo) { @@ -246,6 +256,7 @@ namespace { presentModeInfo = reinterpret_cast(presentModeInfo->pNext); } // NOLINTEND +#pragma clang diagnostic pop // present the next frame Log::debug("hooks2", "Presenting swapchain: {:x} on queue: {:x}", diff --git a/src/layer.cpp b/src/layer.cpp index 6a5e915..bc8bb9d 100644 --- a/src/layer.cpp +++ b/src/layer.cpp @@ -23,6 +23,7 @@ namespace { PFN_vkGetPhysicalDeviceQueueFamilyProperties next_vkGetPhysicalDeviceQueueFamilyProperties{}; PFN_vkGetPhysicalDeviceMemoryProperties next_vkGetPhysicalDeviceMemoryProperties{}; PFN_vkGetPhysicalDeviceProperties next_vkGetPhysicalDeviceProperties{}; + PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR next_vkGetPhysicalDeviceSurfaceCapabilitiesKHR{}; PFN_vkCreateSwapchainKHR next_vkCreateSwapchainKHR{}; PFN_vkQueuePresentKHR next_vkQueuePresentKHR{}; @@ -122,6 +123,8 @@ namespace { "vkGetPhysicalDeviceMemoryProperties", &next_vkGetPhysicalDeviceMemoryProperties); success &= initInstanceFunc(*pInstance, "vkGetPhysicalDeviceProperties", &next_vkGetPhysicalDeviceProperties); + success &= initInstanceFunc(*pInstance, + "vkGetPhysicalDeviceSurfaceCapabilitiesKHR", &next_vkGetPhysicalDeviceSurfaceCapabilitiesKHR); if (!success) { Log::error("layer", "Failed to get instance function pointers"); return VK_ERROR_INITIALIZATION_FAILED; @@ -374,6 +377,15 @@ void Layer::ovkGetPhysicalDeviceProperties( reinterpret_cast(physicalDevice)); next_vkGetPhysicalDeviceProperties(physicalDevice, pProperties); } +VkResult Layer::ovkGetPhysicalDeviceSurfaceCapabilitiesKHR( + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + VkSurfaceCapabilitiesKHR* pSurfaceCapabilities) { + Log::debug("vulkan", "vkGetPhysicalDeviceSurfaceCapabilitiesKHR called for physical device {:x} and surface {:x}", + reinterpret_cast(physicalDevice), + reinterpret_cast(surface)); + return next_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, pSurfaceCapabilities); +} VkResult Layer::ovkCreateSwapchainKHR( VkDevice device, diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index a36bae3..d09de7f 100644 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -53,6 +53,17 @@ uint64_t Utils::getDeviceUUID(VkPhysicalDevice physicalDevice) { return static_cast(properties.vendorID) << 32 | properties.deviceID; } +uint32_t Utils::getMaxImageCount(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface) { + VkSurfaceCapabilitiesKHR capabilities{}; + auto res = Layer::ovkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, + surface, &capabilities); + if (res != VK_SUCCESS) + throw LSFG::vulkan_error(res, "Failed to get surface capabilities"); + if (capabilities.maxImageCount == 0) + return 999; // :3 + return capabilities.maxImageCount; +} + std::vector Utils::addExtensions(const char* const* extensions, size_t count, const std::vector& requiredExtensions) { std::vector ext(count);