From f885c1f9faa95a8aa68becc1047171e8373d6f5f Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sun, 11 Oct 2026 10:11:57 -0700
Subject: [PATCH] Fixed transparent windows using the Vulkan renderer
This uses the same logic as the SDL GPU API
Fixes https://github.com/libsdl-org/SDL/issues/16497
---
src/render/vulkan/SDL_render_vulkan.c | 41 ++++++++++++++-------------
1 file changed, 22 insertions(+), 19 deletions(-)
diff --git a/src/render/vulkan/SDL_render_vulkan.c b/src/render/vulkan/SDL_render_vulkan.c
index 01e3f04971f0d..a2583f1e9f0fb 100644
--- a/src/render/vulkan/SDL_render_vulkan.c
+++ b/src/render/vulkan/SDL_render_vulkan.c
@@ -2554,6 +2554,27 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
}
}
+ VkCompositeAlphaFlagsKHR compositeAlphaFlag = 0;
+
+ // Default to opaque, if available, followed by inherit, and overwrite with a value that supports transparency, if necessary.
+ if (rendererData->surfaceCapabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) {
+ compositeAlphaFlag = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+ } else if (rendererData->surfaceCapabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) {
+ compositeAlphaFlag = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
+ }
+
+ if ((renderer->window->flags & SDL_WINDOW_TRANSPARENT) || !compositeAlphaFlag) {
+ if (rendererData->surfaceCapabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR) {
+ compositeAlphaFlag = VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
+ } else if (rendererData->surfaceCapabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR) {
+ compositeAlphaFlag = VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR;
+ } else if (rendererData->surfaceCapabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) {
+ compositeAlphaFlag = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
+ } else {
+ SDL_LogWarn(SDL_LOG_CATEGORY_RENDER, "SDL_WINDOW_TRANSPARENT flag set, but no suitable swapchain composite alpha value supported!");
+ }
+ }
+
VkSwapchainCreateInfoKHR swapchainCreateInfo = { 0 };
swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapchainCreateInfo.surface = rendererData->surface;
@@ -2569,28 +2590,10 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
}
swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
swapchainCreateInfo.preTransform = rendererData->swapChainPreTransform;
- swapchainCreateInfo.compositeAlpha = (renderer->window->flags & SDL_WINDOW_TRANSPARENT) ? (VkCompositeAlphaFlagBitsKHR)0 : VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+ swapchainCreateInfo.compositeAlpha = compositeAlphaFlag;
swapchainCreateInfo.presentMode = presentMode;
swapchainCreateInfo.clipped = VK_TRUE;
swapchainCreateInfo.oldSwapchain = rendererData->swapchain;
- if (!(renderer->window->flags & SDL_WINDOW_TRANSPARENT)) {
- // Set the first supported swap chain composite mode
- // Android doesn't support VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, for example
- const VkCompositeAlphaFlagBitsKHR compositeAlphaFlags[] = {
- VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
- VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR
- };
- for (uint32_t i = 0; i < SDL_arraysize(compositeAlphaFlags); ++i) {
- if (rendererData->surfaceCapabilities.supportedCompositeAlpha & compositeAlphaFlags[i]) {
- swapchainCreateInfo.compositeAlpha = compositeAlphaFlags[i];
- break;
- }
- }
- if (!swapchainCreateInfo.compositeAlpha) {
- // Fall back to VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, unsupported but better than nothing
- swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
- }
- }
result = vkCreateSwapchainKHR(rendererData->device, &swapchainCreateInfo, NULL, &rendererData->swapchain);
if (swapchainCreateInfo.oldSwapchain != VK_NULL_HANDLE) {