【发布时间】: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