Merge branch 'sdl_platform' of https://github.com/GoaLitiuM/FlaxEngine into GoaLitiuM-sdl_platform

# Conflicts:
#	Source/Editor/GUI/Dialogs/ColorPickerDialog.cs
#	Source/Editor/Modules/UIModule.cs
This commit is contained in:
Wojtek Figat
2026-02-11 14:08:57 +01:00
267 changed files with 98532 additions and 2217 deletions

View File

@@ -4,6 +4,7 @@
#include "AndroidVulkanPlatform.h"
#include "../RenderToolsVulkan.h"
#include "Engine/Platform/Window.h"
void AndroidVulkanPlatform::GetInstanceExtensions(Array<const char*>& extensions, Array<const char*>& layers)
{
@@ -17,8 +18,10 @@ void AndroidVulkanPlatform::GetDeviceExtensions(Array<const char*>& extensions,
extensions.Add(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
}
void AndroidVulkanPlatform::CreateSurface(void* windowHandle, VkInstance instance, VkSurfaceKHR* surface)
void AndroidVulkanPlatform::CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* surface)
{
ASSERT(window);
void* windowHandle = window->GetNativePtr();
ASSERT(windowHandle);
VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
RenderToolsVulkan::ZeroStruct(surfaceCreateInfo, VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR);

View File

@@ -9,6 +9,8 @@
// Support more backbuffers in case driver decides to use more
#define VULKAN_BACK_BUFFERS_COUNT_MAX 8
class GPUDeviceVulkan;
/// <summary>
/// The implementation for the Vulkan API support for Android platform.
/// </summary>
@@ -17,7 +19,7 @@ class AndroidVulkanPlatform : public VulkanPlatformBase
public:
static void GetInstanceExtensions(Array<const char*>& extensions, Array<const char*>& layers);
static void GetDeviceExtensions(Array<const char*>& extensions, Array<const char*>& layers);
static void CreateSurface(void* windowHandle, VkInstance instance, VkSurfaceKHR* surface);
static void CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* surface);
};
typedef AndroidVulkanPlatform VulkanPlatform;

View File

@@ -217,7 +217,7 @@ bool GPUSwapChainVulkan::CreateSwapChain(int32 width, int32 height)
ASSERT_LOW_LAYER(_backBuffers.Count() == 0);
// Create platform-dependent surface
VulkanPlatform::CreateSurface(windowHandle, GPUDeviceVulkan::Instance, &_surface);
VulkanPlatform::CreateSurface(_window, _device, GPUDeviceVulkan::Instance, &_surface);
if (_surface == VK_NULL_HANDLE)
{
LOG(Warning, "Failed to create Vulkan surface.");
@@ -356,13 +356,22 @@ bool GPUSwapChainVulkan::CreateSwapChain(int32 width, int32 height)
LOG(Error, "Vulkan swapchain dimensions are invalid {}x{} (minImageExtent={}x{}, maxImageExtent={}x{})", width, height, surfProperties.minImageExtent.width, surfProperties.minImageExtent.height, surfProperties.maxImageExtent.width, surfProperties.maxImageExtent.height);
return true;
}
uint32_t backbuffersCount = VULKAN_BACK_BUFFERS_COUNT;
#if PLATFORM_SDL && PLATFORM_LINUX && USE_EDITOR
// Wayland compositor might block one of the backbuffers while the window is minimized or fully occluded,
// make sure we have at least 3 backbuffers available so double-buffering can be used while we are blocked.
if (Platform::UsesWayland())
backbuffersCount = Math::Max<uint32_t>(backbuffersCount, 3);
#endif
ASSERT(surfProperties.minImageCount <= VULKAN_BACK_BUFFERS_COUNT_MAX);
VkSwapchainCreateInfoKHR swapChainInfo;
RenderToolsVulkan::ZeroStruct(swapChainInfo, VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR);
swapChainInfo.surface = _surface;
swapChainInfo.minImageCount = surfProperties.maxImageCount > 0 // A value of 0 means that there is no limit on the number of image
? Math::Min<uint32_t>(VULKAN_BACK_BUFFERS_COUNT, surfProperties.maxImageCount)
: VULKAN_BACK_BUFFERS_COUNT;
? Math::Min<uint32_t>(backbuffersCount, surfProperties.maxImageCount)
: backbuffersCount;
swapChainInfo.minImageCount = Math::Max<uint32_t>(swapChainInfo.minImageCount, surfProperties.minImageCount);
swapChainInfo.minImageCount = Math::Min<uint32_t>(swapChainInfo.minImageCount, VULKAN_BACK_BUFFERS_COUNT_MAX);
swapChainInfo.imageFormat = result.format;
@@ -381,7 +390,9 @@ bool GPUSwapChainVulkan::CreateSwapChain(int32 width, int32 height)
swapChainInfo.presentMode = presentMode;
swapChainInfo.clipped = VK_TRUE;
swapChainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
if (surfProperties.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)
if (_window->GetSettings().SupportsTransparency && surfProperties.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR)
swapChainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
else if (surfProperties.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)
swapChainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
// Create swap chain

View File

@@ -4,62 +4,61 @@
#include "LinuxVulkanPlatform.h"
#include "../RenderToolsVulkan.h"
#include "Engine/Platform/Window.h"
// Contents of vulkan\vulkan_xlib.h inlined here to prevent typename collisions with engine types due to X11 types
#include "Engine/Platform/Linux/IncludeX11.h"
#ifdef __cplusplus
extern "C" {
#endif
#define VK_KHR_xlib_surface 1
#define VK_KHR_XLIB_SURFACE_SPEC_VERSION 6
#define VK_KHR_XLIB_SURFACE_EXTENSION_NAME "VK_KHR_xlib_surface"
typedef VkFlags VkXlibSurfaceCreateFlagsKHR;
#define Display X11::Display
#define Window X11::Window
#define VisualID X11::VisualID
#include "vulkan/vulkan_xlib.h"
#undef Display
#undef Window
#undef VisualID
typedef struct VkXlibSurfaceCreateInfoKHR
{
VkStructureType sType;
const void* pNext;
VkXlibSurfaceCreateFlagsKHR flags;
X11::Display* dpy;
X11::Window window;
} VkXlibSurfaceCreateInfoKHR;
#include "vulkan/vulkan_wayland.h"
typedef VkResult (VKAPI_PTR *PFN_vkCreateXlibSurfaceKHR)(VkInstance instance, const VkXlibSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, X11::Display* dpy, X11::VisualID visualID);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR(
VkInstance instance,
const VkXlibSurfaceCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSurfaceKHR* pSurface);
VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXlibPresentationSupportKHR(
VkPhysicalDevice physicalDevice,
uint32_t queueFamilyIndex,
Display* dpy,
VisualID visualID);
#endif
#ifdef __cplusplus
}
#endif
//
// Export X11 surface extension from volk
// Export extension from volk
extern PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR;
extern PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR vkGetPhysicalDeviceXlibPresentationSupportKHR;
extern PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR;
extern PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR;
void LinuxVulkanPlatform::GetInstanceExtensions(Array<const char*>& extensions, Array<const char*>& layers)
{
extensions.Add(VK_KHR_SURFACE_EXTENSION_NAME);
extensions.Add(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
extensions.Add(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
}
void LinuxVulkanPlatform::CreateSurface(void* windowHandle, VkInstance instance, VkSurfaceKHR* surface)
void LinuxVulkanPlatform::CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* surface)
{
#if !PLATFORM_SDL
void* windowHandle = window->GetNativePtr();
VkXlibSurfaceCreateInfoKHR surfaceCreateInfo;
RenderToolsVulkan::ZeroStruct(surfaceCreateInfo, VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR);
surfaceCreateInfo.dpy = (X11::Display*)LinuxPlatform::GetXDisplay();
surfaceCreateInfo.dpy = (X11::Display*)Platform::GetXDisplay();
surfaceCreateInfo.window = (X11::Window)windowHandle;
VALIDATE_VULKAN_RESULT(vkCreateXlibSurfaceKHR(instance, &surfaceCreateInfo, nullptr, surface));
#else
SDLWindow* sdlWindow = static_cast<Window*>(window);
void* windowHandle = window->GetNativePtr();
if (SDLPlatform::UsesWayland())
{
VkWaylandSurfaceCreateInfoKHR surfaceCreateInfo;
RenderToolsVulkan::ZeroStruct(surfaceCreateInfo, VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR);
surfaceCreateInfo.display = (wl_display*)sdlWindow->GetWaylandDisplay();
surfaceCreateInfo.surface = (wl_surface*)windowHandle;
VALIDATE_VULKAN_RESULT(vkCreateWaylandSurfaceKHR(instance, &surfaceCreateInfo, nullptr, surface));
}
else if (SDLPlatform::UsesX11())
{
VkXlibSurfaceCreateInfoKHR surfaceCreateInfo;
RenderToolsVulkan::ZeroStruct(surfaceCreateInfo, VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR);
surfaceCreateInfo.dpy = (X11::Display*)sdlWindow->GetX11Display();
surfaceCreateInfo.window = (X11::Window)windowHandle;
VALIDATE_VULKAN_RESULT(vkCreateXlibSurfaceKHR(instance, &surfaceCreateInfo, nullptr, surface));
}
#endif
}
#endif

View File

@@ -12,6 +12,8 @@
// Prevent wierd error 'Invalid VkValidationCacheEXT Object'
#define VULKAN_USE_VALIDATION_CACHE 0
class GPUDeviceVulkan;
/// <summary>
/// The implementation for the Vulkan API support for Linux platform.
/// </summary>
@@ -19,7 +21,7 @@ class LinuxVulkanPlatform : public VulkanPlatformBase
{
public:
static void GetInstanceExtensions(Array<const char*>& extensions, Array<const char*>& layers);
static void CreateSurface(void* windowHandle, VkInstance instance, VkSurfaceKHR* outSurface);
static void CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* outSurface);
};
typedef LinuxVulkanPlatform VulkanPlatform;

View File

@@ -4,21 +4,40 @@
#include "MacVulkanPlatform.h"
#include "../RenderToolsVulkan.h"
#include "Engine/Platform/Window.h"
#include "Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h"
#include <Cocoa/Cocoa.h>
#include <QuartzCore/CAMetalLayer.h>
void MacVulkanPlatform::GetInstanceExtensions(Array<const char*>& extensions, Array<const char*>& layers)
{
extensions.Add(VK_KHR_SURFACE_EXTENSION_NAME);
extensions.Add(VK_MVK_MACOS_SURFACE_EXTENSION_NAME);
extensions.Add(VK_MVK_MACOS_SURFACE_EXTENSION_NAME);
extensions.Add(VK_EXT_METAL_SURFACE_EXTENSION_NAME);
}
void MacVulkanPlatform::CreateSurface(void* windowHandle, VkInstance instance, VkSurfaceKHR* surface)
void MacVulkanPlatform::CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* surface)
{
NSWindow* window = (NSWindow*)windowHandle;
VkMacOSSurfaceCreateInfoMVK surfaceCreateInfo;
RenderToolsVulkan::ZeroStruct(surfaceCreateInfo, VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK);
surfaceCreateInfo.pView = (void*)window.contentView;
VALIDATE_VULKAN_RESULT(vkCreateMacOSSurfaceMVK(instance, &surfaceCreateInfo, nullptr, surface));
void* windowHandle = window->GetNativePtr();
NSWindow* nswindow = (NSWindow*)windowHandle;
#if PLATFORM_SDL
nswindow.contentView.wantsLayer = YES;
nswindow.contentView.layer = [CAMetalLayer layer];
#endif
if (device->InstanceExtensions.Contains(VK_EXT_METAL_SURFACE_EXTENSION_NAME))
{
VkMetalSurfaceCreateInfoEXT surfaceCreateInfo;
RenderToolsVulkan::ZeroStruct(surfaceCreateInfo, VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT);
surfaceCreateInfo.pLayer = (CAMetalLayer*)nswindow.contentView.layer;
VALIDATE_VULKAN_RESULT(vkCreateMetalSurfaceEXT(instance, &surfaceCreateInfo, nullptr, surface));
}
else
{
VkMacOSSurfaceCreateInfoMVK surfaceCreateInfo;
RenderToolsVulkan::ZeroStruct(surfaceCreateInfo, VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK);
surfaceCreateInfo.pView = (void*)nswindow.contentView;
VALIDATE_VULKAN_RESULT(vkCreateMacOSSurfaceMVK(instance, &surfaceCreateInfo, nullptr, surface));
}
}
#endif

View File

@@ -11,6 +11,8 @@
// General/Validation Error:0 VK_ERROR_INITIALIZATION_FAILED: Could not create MTLCounterSampleBuffer for query pool of type VK_QUERY_TYPE_TIMESTAMP. Reverting to emulated behavior. (Error code 0): Cannot allocate sample buffer
#define VULKAN_USE_TIMER_QUERIES 0
class GPUDeviceVulkan;
/// <summary>
/// The implementation for the Vulkan API support for Mac platform.
/// </summary>
@@ -18,7 +20,7 @@ class MacVulkanPlatform : public VulkanPlatformBase
{
public:
static void GetInstanceExtensions(Array<const char*>& extensions, Array<const char*>& layers);
static void CreateSurface(void* windowHandle, VkInstance instance, VkSurfaceKHR* outSurface);
static void CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* outSurface);
};
typedef MacVulkanPlatform VulkanPlatform;

View File

@@ -6,6 +6,7 @@
#include "../RenderToolsVulkan.h"
#include "Engine/Graphics/GPUDevice.h"
#include "Engine/Platform/Window.h"
void Win32VulkanPlatform::GetInstanceExtensions(Array<const char*>& extensions, Array<const char*>& layers)
{
@@ -13,8 +14,9 @@ void Win32VulkanPlatform::GetInstanceExtensions(Array<const char*>& extensions,
extensions.Add(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
}
void Win32VulkanPlatform::CreateSurface(void* windowHandle, VkInstance instance, VkSurfaceKHR* surface)
void Win32VulkanPlatform::CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* surface)
{
void* windowHandle = window->GetNativePtr();
VkWin32SurfaceCreateInfoKHR surfaceCreateInfo;
RenderToolsVulkan::ZeroStruct(surfaceCreateInfo, VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR);
surfaceCreateInfo.hinstance = GetModuleHandle(nullptr);

View File

@@ -10,6 +10,8 @@
#define VULKAN_USE_PLATFORM_WIN32_KHX 1
#define VULKAN_USE_CREATE_WIN32_SURFACE 1
class GPUDeviceVulkan;
/// <summary>
/// The implementation for the Vulkan API support for Win32 platform.
/// </summary>
@@ -17,7 +19,7 @@ class Win32VulkanPlatform : public VulkanPlatformBase
{
public:
static void GetInstanceExtensions(Array<const char*>& extensions, Array<const char*>& layers);
static void CreateSurface(void* windowHandle, VkInstance instance, VkSurfaceKHR* surface);
static void CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* surface);
};
typedef Win32VulkanPlatform VulkanPlatform;

View File

@@ -5,6 +5,7 @@
#include "iOSVulkanPlatform.h"
#include "../RenderToolsVulkan.h"
#include "Engine/Core/Delegate.h"
#include "Engine/Platform/Window.h"
#include <UIKit/UIKit.h>
void iOSVulkanPlatform::GetInstanceExtensions(Array<const char*>& extensions, Array<const char*>& layers)
@@ -13,8 +14,9 @@ void iOSVulkanPlatform::GetInstanceExtensions(Array<const char*>& extensions, Ar
extensions.Add(VK_MVK_IOS_SURFACE_EXTENSION_NAME);
}
void iOSVulkanPlatform::CreateSurface(void* windowHandle, VkInstance instance, VkSurfaceKHR* surface)
void iOSVulkanPlatform::CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* surface)
{
void* windowHandle = window->GetNativePtr();
// Create surface on a main UI Thread
Function<void()> func = [&windowHandle, &instance, &surface]()
{

View File

@@ -11,6 +11,8 @@
// General/Validation Error:0 VK_ERROR_INITIALIZATION_FAILED: Could not create MTLCounterSampleBuffer for query pool of type VK_QUERY_TYPE_TIMESTAMP. Reverting to emulated behavior. (Error code 0): Cannot allocate sample buffer
#define VULKAN_USE_TIMER_QUERIES 0
class GPUDeviceVulkan;
/// <summary>
/// The implementation for the Vulkan API support for iOS platform.
/// </summary>
@@ -18,7 +20,7 @@ class iOSVulkanPlatform : public VulkanPlatformBase
{
public:
static void GetInstanceExtensions(Array<const char*>& extensions, Array<const char*>& layers);
static void CreateSurface(void* windowHandle, VkInstance instance, VkSurfaceKHR* outSurface);
static void CreateSurface(Window* window, GPUDeviceVulkan* device, VkInstance instance, VkSurfaceKHR* outSurface);
};
typedef iOSVulkanPlatform VulkanPlatform;