KhronosGroup / KhronosGroup/Vulkan-Docs

[Roadmap Feedback] VK_KHR_present_wait needs more return values

Open
#2,530 4 comments 0 reactions 0 assignees View on GitHub
System Integration
Dominant language
JavaScript
Stars
3.3k
Forks
549
Avg merge
5d 5h
Merged PRs (30d)
2

Description

## Problem statement:

`VK_KHR_present_wait` added `vkWaitForPresentKHR` to wait until a specific swapchain is presented.
This works fine for fullscreen games, but it has problems for non-game applications; such as a Game Engine Editor or other windowed scenarios.

The problem is that on Windows 11 on NVIDIA, a fully occluded window will timeout (or stall indefinitely if timeout is unlimited) and return `VK_TIMEOUT`. This is not a driver bug. The driver should not be returning from `vkWaitForPresentKHR` when the swapchain hasn't been presented. It's working as intended.

This happens because on Windows, drivers are using DXGI under the hood which follows this behavior.

More specifically, [IDXGISwapChain::Present](https://learn.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgiswapchain-present) method has a `DXGI_STATUS_OCCLUDED` return value to signal this scenario.

Furthermore DXGI provides `RegisterOcclusionStatusWindow` to signal when occluded status changes and we should probe again to see if we can present again.

A battery-friendly D3D11/12 loop is meant to be written like this (pseudo code):

```cpp
void main()
{
m_occluded = false;
while(true)
{
if( m_occluded )
{
Sleep(100);
}
else
{
render();
HRESULT hr = swapchain->Present();
if( hr == DXGI_STATUS_OCCLUDED )
{
m_occluded = true;
dxgi->RegisterOcclusionStatusWindow( hWnd, WM_USER, &m_occlusionCookie );
}
}

while (PeekMessage(&message, nullptr, 0, 0, PM_REMOVE) && (message.message != WM_QUIT))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
}
}

// Called in WM_USER. Unfortunately DXGI does not tell us if occlusion is now true or false.
// It only tells us it may have changed.
void OnOcclusion()
{
assert( m_occlusionCookie );

if (S_OK == swapchain->Present(0, DXGI_PRESENT_TEST))
{
dxgi->UnregisterOcclusionStatus(m_occlusionCookie);
m_occlusionCookie = 0;
m_occluded = true;
}
}
```

## Use Case Example(s):

Any app that isn't fullscreen (e.g. a Game Engine Editor) will run into this scenario as soon as the user Alt+Tabs to another window from a different process and the window happens to 100% occlude our window.

Ticket #2507 also makes an excellent point. On Linux, turning off the monitor should mean that Vulkan implementation should return `VK_SWAPCHAIN_OCCLUDED`.

## Suggested Solution(s) (via opening an MR on vulkan-docs repo and creating a Proposal Document) :

- Add a result value "VK_SWAPCHAIN_OCCLUDED" to `vkWaitForPresentKHR`, that returns as fast as possible, instead of returning VK_TIMEOUT (or deadlocking indefinitely). Other OSes who do not support this would simply never return this value.
- Of course there are details to this, since the app must opt-in to this new behavior otherwise old applications will get a return value that they're not expecting.
- Add a routine for testing for occlusion (i.e. analogous to `DXGI_PRESENT_TEST`). vkTestPresentOcclusion( swapchain ); which can return "VK_SWAPCHAIN_OCCLUDED" or `VK_SUCCESS`. Other OSes who do not support this would simply always return `VK_SUCCESS`.
- Add a routine where users can register a listener whenever occlusion changes, to avoid polling vkTestPresentOcclusion() continuously.

Contributor guide

Open the contributing guide

Research direction

No repository files or tests are named. Start by reviewing the VK_KHR_present_wait specification and the referenced issue #2507, then examine the Vulkan-Docs proposal process. Done means producing a decided proposal document and corresponding vulkan-docs MR covering the requested occlusion results, testing routine, and listener registration.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
backend-api-design, operating-systems
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.