Skip to content

Commit 84fe074

Browse files
committed
vulkan+windows: tell the driver we don't want exclusive fullscreen, when in desktop-fullscreen mode.
1 parent 52c6b88 commit 84fe074

3 files changed

Lines changed: 70 additions & 0 deletions

File tree

src/modules/graphics/vulkan/Graphics.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,24 @@ VmaAllocator Graphics::getVmaAllocator() const
7474
return vmaAllocator;
7575
}
7676

77+
// Calling Window::getSettings is the correct abstracted way to do this, but
78+
// it also does a bunch more work which we want to avoid.
79+
static bool isWindowFullscreenExclusive()
80+
{
81+
auto window = Module::getInstance<love::window::Window>(Module::M_WINDOW);
82+
if (window == nullptr)
83+
return false;
84+
85+
SDL_Window *handle = (SDL_Window *)window->getHandle();
86+
if (handle == nullptr)
87+
return false;
88+
89+
if ((SDL_GetWindowFlags(handle) & SDL_WINDOW_FULLSCREEN) != SDL_WINDOW_FULLSCREEN)
90+
return false;
91+
92+
return SDL_GetWindowFullscreenMode(handle) != nullptr;
93+
}
94+
7795
static void checkOptionalInstanceExtensions(OptionalInstanceExtensions& ext)
7896
{
7997
uint32_t count;
@@ -592,6 +610,21 @@ void Graphics::present(void *screenshotCallbackdata)
592610
}
593611
}
594612

613+
#ifdef VK_EXT_full_screen_exclusive
614+
if (optionalDeviceExtensions.fullscreenExclusive)
615+
{
616+
// TODO: We really don't want to query this every frame, it has performance
617+
// costs including calling into system code. But SDL doesn't yet provide an
618+
// event for it: https://github.com/libsdl-org/SDL/issues/15850
619+
bool fullscreenExclusive = isWindowFullscreenExclusive();
620+
if (windowIsFullscreenExclusive != fullscreenExclusive)
621+
{
622+
windowIsFullscreenExclusive = fullscreenExclusive;
623+
requestSwapchainRecreation();
624+
}
625+
}
626+
#endif
627+
595628
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || swapChainRecreationRequested)
596629
{
597630
swapChainRecreationRequested = false;
@@ -1783,6 +1816,10 @@ static void findOptionalDeviceExtensions(VkPhysicalDevice physicalDevice, Option
17831816
optionalDeviceExtensions.shaderFloatControls = true;
17841817
if (strcmp(extension.extensionName, VK_KHR_SPIRV_1_4_EXTENSION_NAME) == 0)
17851818
optionalDeviceExtensions.spirv14 = true;
1819+
#ifdef VK_EXT_full_screen_exclusive
1820+
if (strcmp(extension.extensionName, VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME) == 0)
1821+
optionalDeviceExtensions.fullscreenExclusive = true;
1822+
#endif
17861823
}
17871824
}
17881825

@@ -1845,6 +1882,10 @@ void Graphics::createLogicalDevice()
18451882
enabledExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
18461883
if (optionalDeviceExtensions.spirv14)
18471884
enabledExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME);
1885+
#ifdef VK_EXT_full_screen_exclusive
1886+
if (optionalDeviceExtensions.fullscreenExclusive)
1887+
enabledExtensions.push_back(VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME);
1888+
#endif
18481889
if (deviceApiVersion >= VK_API_VERSION_1_1)
18491890
enabledExtensions.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME);
18501891

@@ -2023,6 +2064,25 @@ void Graphics::createSwapChain()
20232064
createInfo.clipped = VK_TRUE;
20242065
createInfo.oldSwapchain = swapChain;
20252066

2067+
#ifdef VK_EXT_full_screen_exclusive
2068+
VkSurfaceFullScreenExclusiveInfoEXT exclusiveInfo = {};
2069+
exclusiveInfo.sType = VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT;
2070+
2071+
if (optionalDeviceExtensions.fullscreenExclusive)
2072+
{
2073+
// This should in theory help Windows graphics drivers avoid treating
2074+
// desktop-fullscreen like exclusive-fullscreen, which should reduce
2075+
// issues with programs that interact with the window (e.g. screen recorders).
2076+
windowIsFullscreenExclusive = isWindowFullscreenExclusive();
2077+
if (windowIsFullscreenExclusive)
2078+
exclusiveInfo.fullScreenExclusive = VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT;
2079+
else
2080+
exclusiveInfo.fullScreenExclusive = VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT;
2081+
2082+
createInfo.pNext = &exclusiveInfo;
2083+
}
2084+
#endif
2085+
20262086
VkSwapchainKHR newSwapChain = VK_NULL_HANDLE;
20272087
VkResult result = vkCreateSwapchainKHR(device, &createInfo, nullptr, &newSwapChain);
20282088

src/modules/graphics/vulkan/Graphics.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,9 @@ struct OptionalDeviceExtensions
175175

176176
// VK_KHR_spirv_1_4
177177
bool spirv14 = false;
178+
179+
// VK_EXT_full_screen_exclusive
180+
bool fullscreenExclusive = false;
178181
};
179182

180183
struct QueueFamilyIndices
@@ -403,6 +406,7 @@ class Graphics final : public love::graphics::Graphics
403406
uint32_t imageIndex = 0;
404407
uint64 realFrameIndex = 0;
405408
bool swapChainRecreationRequested = false;
409+
bool windowIsFullscreenExclusive = false;
406410
bool transitionColorDepthLayouts = false;
407411
VmaAllocator vmaAllocator = VK_NULL_HANDLE;
408412
StrongRef<love::graphics::Buffer> defaultVertexBuffer;

src/modules/graphics/vulkan/VulkanWrapper.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,13 @@
2020

2121
#pragma once
2222

23+
#include "common/config.h"
24+
2325
#define VK_NO_PROTOTYPES
26+
#ifdef LOVE_WINDOWS
27+
#define VK_USE_PLATFORM_WIN32_KHR
28+
#define WIN32_LEAN_AND_MEAN
29+
#endif
2430
#include "libraries/vulkanheaders/vulkan.h"
2531

2632
#include "libraries/volk/volk.h"

0 commit comments

Comments
 (0)