【问题标题】:(Vulkan) vkAcquireNextImageKHR takes so long when VK_PRESENT_MODE_FIFO_KHR choosen for present mode(Vulkan) 当 VK_PRESENT_MODE_FIFO_KHR 选择当前模式时,vkAcquireNextImageKHR 需要很长时间
【发布时间】:2021-03-26 14:17:51
【问题描述】:

我按照https://vulkan-tutorial.com/ 上的教程尝试使用 Vulkan 绘制一个简单的三角形,但我得到了大约 70 fps。 (对于类似的场景,比如使用 directx11 绘制三角形,我得到 10000 fps 和 opengl:9000fps)

我做了一些分析,发现 vkAcquireNextImageKHR 需要很长时间。

原因大概是我的显卡不支持VK_PRESENT_MODE_MAILBOX_KHR,根据教程我选择了VK_PRESENT_MODE_FIFO_KHR

( 我的显卡仅支持 PresentMode 的 2 种模式: VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR )

是的,我唯一能想到的本教程是为 VK_PRESENT_MODE_MAILBOX_KHR 设计的,但我使用的是 VK_PRESENT_MODE_FIFO_KHR 模式。

如果我切换到 VK_PRESENT_MODE_IMMEDIATE_KHR 模式,我会得到 4000 fps(仍然是 direct3D11 和 opengl 比 vulkan 快)

我从 vulkan-tutorial.com 复制粘贴几乎所有内容,代码如下: https://vulkan-tutorial.com/code/16_swap_chain_recreation.cpp

我正在做的唯一不同的部分是,在教程中,他使用 glfw 库创建窗口,我创建自己的.. 这些是不同的部分(我没有复制粘贴其余代码,因为一切都与上面的链接,问题vkAcquireNextImageKHR调用在drawFrame方法中,请从上面的链接中检查)

void Graphics_Vulkan::recreateSwapChain()
{
    uint w = 0, h = 0;
    while (!MainWindow->GetClientSize(w, h) || w == 0 || h == 0) 
        ProcessMessageForAllWindows();

    vkDeviceWaitIdle(device);

    cleanupSwapChain();

    createSwapChain();
    createImageViews();
    createRenderPass();
    createGraphicsPipeline();
    createFramebuffers();
    createCommandBuffers();

    imagesInFlight.resize(swapChainImages.size(), VK_NULL_HANDLE);
}

void Graphics_Vulkan::createSurface()
{
    VkWin32SurfaceCreateInfoKHR createInfo{};
    createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
    createInfo.hwnd = MainWindow->hwnd;
    createInfo.hinstance = hInstance;

    if (vkCreateWin32SurfaceKHR(instance, &createInfo, nullptr, &surface) != VK_SUCCESS)
        throw std::runtime_error("failed to create window surface!");
}

VkExtent2D Graphics_Vulkan::chooseSwapExtent(const VkSurfaceCapabilitiesKHR & capabilities)
{
    if (capabilities.currentExtent.width != UINT32_MAX) {
        return capabilities.currentExtent;
    }
    else {

        uint width = 0, height = 0;
        MainWindow->GetClientSize(width, height);

        VkExtent2D actualExtent = {
            static_cast<uint32_t>(width),
            static_cast<uint32_t>(height)
        };

        actualExtent.width = max(capabilities.minImageExtent.width, min(capabilities.maxImageExtent.width, actualExtent.width));
        actualExtent.height = max(capabilities.minImageExtent.height, min(capabilities.maxImageExtent.height, actualExtent.height));

        return actualExtent;
    }
}

std::vector<const char*> Graphics_Vulkan::getRequiredExtensions()
{
    std::vector<const char*> enabledExtensions = { VK_KHR_SURFACE_EXTENSION_NAME };

#if defined(OSWINDOWS)
    enabledExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
#elif defined(__ANDROID__)
    enabledExtensions.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
#elif defined(__linux__)
    enabledExtensions.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
#endif

    enabledExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);

    /*on my pc, there were 2 more extensions. i wasnt sure to add those to in the list:
    VK_KHR_get_physical_device_properties2
    VK_EXT_debug_report
    */

    return enabledExtensions;
}

还有另一个人也有这个问题,但在那个页面上没有得到任何答案 https://community.khronos.org/t/tearing-with-present-mode-fifo-enabled-vulkan-tutorial/106298

编辑: 我认为如果我在 64 位发布测试后分享以下值会有所帮助:

64位发布模式:

Vulkan 74fps(使用 VK_PRESENT_MODE_FIFO_KHR) Vulkan 9930fps(使用 VK_PRESENT_MODE_IMMEDIATE_KHR) Direct3D11 13100fps OpenGL 9600fps

【问题讨论】:

  • 您应该知道,分析琐碎的渲染并不代表您在分析实际渲染时将获得的性能。
  • 即使没有分析,它也给出了其他 api 之间的荒谬差异: 64 位发布模式:Vulkan 74fps(使用 VK_PRESENT_MODE_FIFO_KHR) Vulkan 9930fps(使用 VK_PRESENT_MODE_IMMEDIATE_KHR) Direct3D11 13100fps OpenGL 9600fps 我认为 vsync 存在问题(双缓冲)顺便说一句,我进行分析的方式是:在 drawFrame 方法上,就在 vkAcquireNextImageKHR 之前,我使用“std::chrono::high_resolution_clock::now()”获取当前时间,在 vkAcquireNextImageKHR 之后,再次获取时间并subtruct .. 即使我的分析错误,vsync 也存在问题
  • 我不明白有问题的问题应该是什么。 FIFO呈现意味着将呈现锁定到vsync。这就是发生的事情。 Vulkan 的行为符合预期。问题似乎是您认为它不应该表现得那样。那么为什么你认为同步的演示模式应该是非同步的呢?

标签: c++ frame-rate vulkan


【解决方案1】:

你所描述的一切本质上都是应该发生的。

如果您超出显示引擎的速度(即:渲染内容比显示速度快),有两种选择。您可以减慢渲染速度,也可以强制显示引擎在显示不同图像的过程中显示图像(通常会导致撕裂)。

在 Vulkan 中,这两个选项拼写为 PRESENT_MODE_FIFOPRESENT_MODE_IMMEDIATE。因此,FIFO 会导致您的代码与显示引擎同步,而 IMMEDIATE 不会,这是完全正常的。这实际上是您要求的

【讨论】:

  • 我不知道垂直同步对性能的影响那么差。你是对的,我找到了其他示例集,启用/禁用 vsync,禁用时示例约为 700fps,启用后,同样为 70fps.. 内容无关紧要,70 已修复,这表明 vsync 是瓶颈.. 谢谢你的帮助
猜你喜欢
  • 2020-01-02
  • 1970-01-01
  • 1970-01-01
  • 2014-09-24
  • 2018-12-07
  • 2013-04-15
  • 1970-01-01
  • 2019-07-27
相关资源
最近更新 更多