From 108ea066f3eaaaa8cf636bf3eff3622e8f7e5198 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Wed, 6 Mar 2019 13:38:45 +0200 Subject: [PATCH] - added initial support of Vulkan to SDL backend Removed all platform-specific code from vulkan device --- src/CMakeLists.txt | 3 +- src/posix/cocoa/i_video.mm | 17 + src/posix/sdl/gl_sysfb.h | 45 +-- src/posix/sdl/sdlglvideo.cpp | 464 ++++++++++++++-------- src/rendering/vulkan/system/vk_device.cpp | 67 ++-- src/win32/win32vulkanvideo.cpp | 74 ++++ 6 files changed, 420 insertions(+), 250 deletions(-) create mode 100644 src/win32/win32vulkanvideo.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 16b4d1e514..78ca359651 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -504,7 +504,8 @@ set( PLAT_WIN32_SOURCES win32/gl_sysfb.cpp win32/base_sysfb.cpp win32/win32basevideo.cpp - win32/win32glvideo.cpp ) + win32/win32glvideo.cpp + win32/win32vulkanvideo.cpp ) set( PLAT_POSIX_SOURCES posix/i_cd.cpp posix/i_steam.cpp ) diff --git a/src/posix/cocoa/i_video.mm b/src/posix/cocoa/i_video.mm index 1f439669e3..6ca5496548 100644 --- a/src/posix/cocoa/i_video.mm +++ b/src/posix/cocoa/i_video.mm @@ -32,6 +32,7 @@ */ #include "gl_load/gl_load.h" +#include "volk/volk.h" #include "i_common.h" @@ -660,3 +661,19 @@ void I_SetWindowTitle(const char* title) { SystemBaseFrameBuffer::SetWindowTitle(title); } + + +void I_GetVulkanDrawableSize(int *width, int *height) +{ + assert(!"Not implemented"); +} + +bool I_GetVulkanPlatformExtensions(unsigned int *count, const char **names) +{ + assert(!"Not implemented"); +} + +bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface) +{ + assert(!"Not implemented"); +} diff --git a/src/posix/sdl/gl_sysfb.h b/src/posix/sdl/gl_sysfb.h index b241956735..e9491d098c 100644 --- a/src/posix/sdl/gl_sysfb.h +++ b/src/posix/sdl/gl_sysfb.h @@ -12,43 +12,17 @@ class SystemBaseFrameBuffer : public DFrameBuffer public: // this must have the same parameters as the Windows version, even if they are not used! SystemBaseFrameBuffer (void *hMonitor, bool fullscreen); - ~SystemBaseFrameBuffer (); - void ForceBuffering (bool force); - - bool IsFullscreen (); - - virtual void SetVSync( bool vsync ); - void SwapBuffers(); - - friend class SDLGLVideo; + bool IsFullscreen() override; int GetClientWidth() override; int GetClientHeight() override; + void ToggleFullscreen(bool yes) override; - void SetWindowSize(int client_w, int client_h); - - SDL_Window *GetSDLWindow() { return Screen; } - void GetWindowBordersSize(int &top, int &left); - - bool m_fsswitch; + void SetWindowSize(int client_w, int client_h) override; protected: - void SetGammaTable(uint16_t *tbl); - void ResetGammaTable(); - SystemBaseFrameBuffer () {} - uint8_t GammaTable[3][256]; - bool UpdatePending; - - SDL_Window *Screen; - - SDL_GLContext GLContext; - - void UpdateColors (); - - static const int MIN_WIDTH = 320; - static const int MIN_HEIGHT = 200; }; class SystemGLFrameBuffer : public SystemBaseFrameBuffer @@ -56,11 +30,18 @@ class SystemGLFrameBuffer : public SystemBaseFrameBuffer typedef SystemBaseFrameBuffer Super; public: - SystemGLFrameBuffer(void *hMonitor, bool fullscreen) - : SystemBaseFrameBuffer(hMonitor, fullscreen) - {} + SystemGLFrameBuffer(void *hMonitor, bool fullscreen); + ~SystemGLFrameBuffer(); + + int GetClientWidth() override; + int GetClientHeight() override; + + virtual void SetVSync(bool vsync) override; + void SwapBuffers(); protected: + SDL_GLContext GLContext; + SystemGLFrameBuffer() {} }; diff --git a/src/posix/sdl/sdlglvideo.cpp b/src/posix/sdl/sdlglvideo.cpp index 47684fd52f..2b261de438 100644 --- a/src/posix/sdl/sdlglvideo.cpp +++ b/src/posix/sdl/sdlglvideo.cpp @@ -53,6 +53,8 @@ #include "gl/system/gl_framebuffer.h" #include "gl/shaders/gl_shader.h" +#include "rendering/vulkan/system/vk_framebuffer.h" + // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- @@ -89,120 +91,297 @@ CVAR (Int, vid_adapter, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // PRIVATE DATA DEFINITIONS ------------------------------------------------ -class SDLGLVideo : public IVideo +namespace Priv +{ + FModule library("SDL2"); + +#define SDL2_OPTIONAL_FUNCTION(RESULT, NAME, ...) \ + static TOptProc NAME("SDL_" #NAME) + + SDL2_OPTIONAL_FUNCTION(int, GetWindowBordersSize, SDL_Window *window, int *top, int *left, int *bottom, int *right); + SDL2_OPTIONAL_FUNCTION(void, Vulkan_GetDrawableSize, SDL_Window *window, int *width, int *height); + SDL2_OPTIONAL_FUNCTION(SDL_bool, Vulkan_GetInstanceExtensions, SDL_Window *window, unsigned int *count, const char **names); + SDL2_OPTIONAL_FUNCTION(SDL_bool, Vulkan_CreateSurface, SDL_Window *window, VkInstance instance, VkSurfaceKHR *surface); + +#undef SDL2_OPTIONAL_FUNCTION + + static const uint32_t VulkanWindowFlag = 0x1000'0000; + + static const int MIN_WIDTH = 320; + static const int MIN_HEIGHT = 200; + + SDL_Window *window; + bool vulkanSupported; + bool fullscreenSwitch; + + void CreateWindow(uint32_t extraFlags) + { + assert(Priv::window == nullptr); + + // Set default size + SDL_Rect bounds; + SDL_GetDisplayBounds(vid_adapter, &bounds); + + if (win_w <= 0 || win_h <= 0) + { + win_w = bounds.w * 8 / 10; + win_h = bounds.h * 8 / 10; + } + + FString caption; + caption.Format(GAMESIG " %s (%s)", GetVersionString(), GetGitTime()); + + const uint32_t windowFlags = (win_maximized ? SDL_WINDOW_MAXIMIZED : 0) | SDL_WINDOW_RESIZABLE | extraFlags; + Priv::window = SDL_CreateWindow(caption, + (win_x <= 0) ? SDL_WINDOWPOS_CENTERED_DISPLAY(vid_adapter) : win_x, + (win_y <= 0) ? SDL_WINDOWPOS_CENTERED_DISPLAY(vid_adapter) : win_y, + win_w, win_h, windowFlags); + + if (Priv::window != nullptr) + { + // Enforce minimum size limit + SDL_SetWindowMinimumSize(Priv::window, Priv::MIN_WIDTH, Priv::MIN_HEIGHT); + } + } + + void SetupPixelFormat(int multisample, const int *glver) + { + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + if (multisample > 0) { + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, multisample); + } + if (gl_debug) + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); + + if (gl_es) + { + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + } + else if (glver[0] > 2) + { + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, glver[0]); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, glver[1]); + } + else + { + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + } + } +} + +class SDLVideo : public IVideo { public: - SDLGLVideo (int parm); - ~SDLGLVideo (); + SDLVideo (); + ~SDLVideo (); DFrameBuffer *CreateFrameBuffer (); - void SetupPixelFormat(bool allowsoftware, int multisample, const int *glver); +private: + VulkanDevice *device = nullptr; }; // CODE -------------------------------------------------------------------- -SDLGLVideo::SDLGLVideo (int parm) +void I_GetVulkanDrawableSize(int *width, int *height) { - if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { - fprintf( stderr, "Video initialization failed: %s\n", - SDL_GetError( ) ); - } + assert(Priv::vulkanSupported); + assert(Priv::window != nullptr); + assert(Priv::Vulkan_GetDrawableSize); + Priv::Vulkan_GetDrawableSize(Priv::window, width, height); } -SDLGLVideo::~SDLGLVideo () +bool I_GetVulkanPlatformExtensions(unsigned int *count, const char **names) { + assert(Priv::vulkanSupported); + assert(Priv::window != nullptr); + assert(Priv::Vulkan_GetInstanceExtensions); + return Priv::Vulkan_GetInstanceExtensions(Priv::window, count, names) == SDL_TRUE; } -DFrameBuffer *SDLGLVideo::CreateFrameBuffer () +bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface) { - SystemBaseFrameBuffer *fb = new OpenGLRenderer::OpenGLFrameBuffer(0, fullscreen); + assert(Priv::vulkanSupported); + assert(Priv::window != nullptr); + assert(Priv::Vulkan_CreateSurface); + return Priv::Vulkan_CreateSurface(Priv::window, instance, surface) == SDL_TRUE; +} + + +SDLVideo::SDLVideo () +{ + if (SDL_Init(SDL_INIT_VIDEO) < 0) + { + fprintf(stderr, "Video initialization failed: %s\n", SDL_GetError()); + return; + } + + // Load optional SDL functions + if (!Priv::library.IsLoaded()) + { + Priv::library.Load({ "libSDL2.so", "libSDL2-2.0.so" }); + } + + Priv::vulkanSupported = Priv::Vulkan_GetDrawableSize && Priv::Vulkan_GetInstanceExtensions && Priv::Vulkan_CreateSurface; + + if (Priv::vulkanSupported) + { + Priv::CreateWindow(Priv::VulkanWindowFlag | SDL_WINDOW_HIDDEN); + + if (Priv::window == nullptr) + { + Priv::vulkanSupported = false; + } + } +} + +SDLVideo::~SDLVideo () +{ + delete device; +} + +DFrameBuffer *SDLVideo::CreateFrameBuffer () +{ + SystemBaseFrameBuffer *fb = nullptr; + + // first try Vulkan, if that fails OpenGL + if (Priv::vulkanSupported) + { + try + { + assert(device == nullptr); + device = new VulkanDevice(); + fb = new VulkanFrameBuffer(nullptr, fullscreen, device); + } + catch (CRecoverableError const&) + { + Priv::vulkanSupported = false; + } + } + + if (fb == nullptr) + { + fb = new OpenGLRenderer::OpenGLFrameBuffer(0, fullscreen); + } return fb; } -//========================================================================== -// -// -// -//========================================================================== - -void SDLGLVideo::SetupPixelFormat(bool allowsoftware, int multisample, const int *glver) -{ - SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 ); - SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 ); - SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 ); - SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 ); - SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 24 ); - SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, 8 ); - SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); - if (multisample > 0) { - SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 1 ); - SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, multisample ); - } - if (gl_debug) - SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); - - if (gl_es) - { - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); - } - else if (glver[0] > 2) - { - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, glver[0]); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, glver[1]); - } - else - { - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); - } -} - IVideo *gl_CreateVideo() { - return new SDLGLVideo(0); + return new SDLVideo(); } -// FrameBuffer implementation ----------------------------------------------- - -FModule sdl_lib("SDL2"); - -typedef int (*SDL_GetWindowBordersSizePtr)(SDL_Window *, int *, int *, int *, int *); -static TOptProc SDL_GetWindowBordersSize_("SDL_GetWindowBordersSize"); +// FrameBuffer Implementation ----------------------------------------------- SystemBaseFrameBuffer::SystemBaseFrameBuffer (void *, bool fullscreen) - : DFrameBuffer (vid_defwidth, vid_defheight) +: DFrameBuffer (vid_defwidth, vid_defheight) { - m_fsswitch = false; - - // SDL_GetWindowBorderSize() is only available since 2.0.5, but because - // GZDoom supports platforms with older SDL2 versions, this function - // has to be dynamically loaded - if (!sdl_lib.IsLoaded()) + if (Priv::window != nullptr) { - sdl_lib.Load({ "libSDL2.so", "libSDL2-2.0.so" }); + SDL_SetWindowFullscreen(Priv::window, fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); + SDL_ShowWindow(Priv::window); } +} +int SystemBaseFrameBuffer::GetClientWidth() +{ + int width = 0; + + assert(Priv::vulkanSupported); + Priv::Vulkan_GetDrawableSize(Priv::window, &width, nullptr); + + return width; +} + +int SystemBaseFrameBuffer::GetClientHeight() +{ + int height = 0; + + assert(Priv::vulkanSupported); + Priv::Vulkan_GetDrawableSize(Priv::window, nullptr, &height); + + return height; +} + +bool SystemBaseFrameBuffer::IsFullscreen () +{ + return (SDL_GetWindowFlags(Priv::window) & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0; +} + +void SystemBaseFrameBuffer::ToggleFullscreen(bool yes) +{ + SDL_SetWindowFullscreen(Priv::window, yes ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); + if ( !yes ) + { + if ( !Priv::fullscreenSwitch ) + { + Priv::fullscreenSwitch = true; + fullscreen = false; + } + else + { + Priv::fullscreenSwitch = false; + SetWindowSize(win_w, win_h); + } + } +} + +void SystemBaseFrameBuffer::SetWindowSize(int w, int h) +{ + if (w < Priv::MIN_WIDTH || h < Priv::MIN_HEIGHT) + { + w = Priv::MIN_WIDTH; + h = Priv::MIN_HEIGHT; + } + win_w = w; + win_h = h; + if ( fullscreen ) + { + fullscreen = false; + } + else + { + win_maximized = false; + SDL_SetWindowSize(Priv::window, w, h); + SDL_SetWindowPosition(Priv::window, SDL_WINDOWPOS_CENTERED_DISPLAY(vid_adapter), SDL_WINDOWPOS_CENTERED_DISPLAY(vid_adapter)); + SetSize(GetClientWidth(), GetClientHeight()); + int x, y; + SDL_GetWindowPosition(Priv::window, &x, &y); + win_x = x; + win_y = y; + } +} + + +SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool fullscreen) +: SystemBaseFrameBuffer(hMonitor, fullscreen) +{ // NOTE: Core profiles were added with GL 3.2, so there's no sense trying // to set core 3.1 or 3.0. We could try a forward-compatible context // instead, but that would be too restrictive (w.r.t. shaders). static const int glvers[][2] = { - { 4, 5 }, { 4, 4 }, { 4, 3 }, { 4, 2 }, { 4, 1 }, { 4, 0 }, + { 4, 6 }, { 4, 5 }, { 4, 4 }, { 4, 3 }, { 4, 2 }, { 4, 1 }, { 4, 0 }, { 3, 3 }, { 3, 2 }, { 2, 0 }, { 0, 0 }, }; int glveridx = 0; int i; - UpdatePending = false; - const char *version = Args->CheckValue("-glversion"); if (version != NULL) { @@ -222,61 +401,58 @@ SystemBaseFrameBuffer::SystemBaseFrameBuffer (void *, bool fullscreen) } } - FString caption; - caption.Format(GAMESIG " %s (%s)", GetVersionString(), GetGitTime()); - for ( ; glvers[glveridx][0] > 0; ++glveridx) { - static_cast(Video)->SetupPixelFormat(false, 0, glvers[glveridx]); + Priv::SetupPixelFormat(0, glvers[glveridx]); + Priv::CreateWindow(SDL_WINDOW_OPENGL | (fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)); - SDL_Rect bounds; - SDL_GetDisplayBounds(vid_adapter,&bounds); - // set default size - if ( win_w <= 0 || win_h <= 0 ) + if (Priv::window == nullptr) { - win_w = bounds.w * 8 / 10; - win_h = bounds.h * 8 / 10; + continue; } - Screen = SDL_CreateWindow(caption, - (win_x <= 0) ? SDL_WINDOWPOS_CENTERED_DISPLAY(vid_adapter) : win_x, - (win_y <= 0) ? SDL_WINDOWPOS_CENTERED_DISPLAY(vid_adapter) : win_y, - win_w, win_h, (fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0) | (win_maximized ? SDL_WINDOW_MAXIMIZED : 0) | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); - if (Screen != NULL) + GLContext = SDL_GL_CreateContext(Priv::window); + if (GLContext == nullptr) { - // enforce minimum size limit - SDL_SetWindowMinimumSize(Screen, MIN_WIDTH, MIN_HEIGHT); - - GLContext = SDL_GL_CreateContext(Screen); - if (GLContext != NULL) - return; - - SDL_DestroyWindow(Screen); - Screen = NULL; + SDL_DestroyWindow(Priv::window); + Priv::window = nullptr; + } + else + { + break; } } } -SystemBaseFrameBuffer::~SystemBaseFrameBuffer () +SystemGLFrameBuffer::~SystemGLFrameBuffer () { - if (Screen) + if (Priv::window) { if (GLContext) { SDL_GL_DeleteContext(GLContext); } - SDL_DestroyWindow(Screen); + SDL_DestroyWindow(Priv::window); + Priv::window = nullptr; } } - -bool SystemBaseFrameBuffer::IsFullscreen () +int SystemGLFrameBuffer::GetClientWidth() { - return (SDL_GetWindowFlags (Screen) & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0; + int width = 0; + SDL_GL_GetDrawableSize(Priv::window, &width, nullptr); + return width; } -void SystemBaseFrameBuffer::SetVSync( bool vsync ) +int SystemGLFrameBuffer::GetClientHeight() +{ + int height = 0; + SDL_GL_GetDrawableSize(Priv::window, nullptr, &height); + return height; +} + +void SystemGLFrameBuffer::SetVSync( bool vsync ) { #if defined (__APPLE__) const GLint value = vsync ? 1 : 0; @@ -294,7 +470,7 @@ void SystemBaseFrameBuffer::SetVSync( bool vsync ) #endif } -void SystemBaseFrameBuffer::SwapBuffers() +void SystemGLFrameBuffer::SwapBuffers() { #if !defined(__APPLE__) && !defined(__OpenBSD__) if (vid_maxfps && !cl_capfps) @@ -303,74 +479,9 @@ void SystemBaseFrameBuffer::SwapBuffers() } #endif - SDL_GL_SwapWindow (Screen); + SDL_GL_SwapWindow(Priv::window); } -void SystemBaseFrameBuffer::ToggleFullscreen(bool yes) -{ - SDL_SetWindowFullscreen(Screen, yes ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); - if ( !yes ) - { - if ( !m_fsswitch ) - { - m_fsswitch = true; - fullscreen = false; - } - else - { - m_fsswitch = false; - SetWindowSize(win_w, win_h); - } - } -} - -int SystemBaseFrameBuffer::GetClientWidth() -{ - int width = 0; - SDL_GL_GetDrawableSize(Screen, &width, nullptr); - return width; -} - -int SystemBaseFrameBuffer::GetClientHeight() -{ - int height = 0; - SDL_GL_GetDrawableSize(Screen, nullptr, &height); - return height; -} - -void SystemBaseFrameBuffer::SetWindowSize(int w, int h) -{ - if (w < MIN_WIDTH || h < MIN_HEIGHT) - { - w = MIN_WIDTH; - h = MIN_HEIGHT; - } - win_w = w; - win_h = h; - if ( fullscreen ) - { - fullscreen = false; - } - else - { - win_maximized = false; - SDL_SetWindowSize(Screen, w, h); - SDL_SetWindowPosition(Screen, SDL_WINDOWPOS_CENTERED_DISPLAY(vid_adapter), SDL_WINDOWPOS_CENTERED_DISPLAY(vid_adapter)); - SetSize(GetClientWidth(), GetClientHeight()); - int x, y; - SDL_GetWindowPosition(Screen, &x, &y); - win_x = x; - win_y = y; - } -} - -void SystemBaseFrameBuffer::GetWindowBordersSize(int &top, int &left) -{ - if (SDL_GetWindowBordersSize_) - { - SDL_GetWindowBordersSize_(Screen, &top, &left, nullptr, nullptr); - } -} void ProcessSDLWindowEvent(const SDL_WindowEvent &event) { @@ -389,17 +500,17 @@ void ProcessSDLWindowEvent(const SDL_WindowEvent &event) break; case SDL_WINDOWEVENT_MOVED: - if (!fullscreen) + if (!fullscreen && Priv::GetWindowBordersSize) { int top = 0, left = 0; - static_cast(screen)->GetWindowBordersSize(top,left); + Priv::GetWindowBordersSize(Priv::window, &top, &left, nullptr, nullptr); win_x = event.data1-left; win_y = event.data2-top; } break; case SDL_WINDOWEVENT_RESIZED: - if (!fullscreen && !(static_cast(screen)->m_fsswitch)) + if (!fullscreen && !Priv::fullscreenSwitch) { win_w = event.data1; win_h = event.data2; @@ -420,14 +531,15 @@ void ProcessSDLWindowEvent(const SDL_WindowEvent &event) // each platform has its own specific version of this function. void I_SetWindowTitle(const char* caption) { - auto window = static_cast(screen)->GetSDLWindow(); if (caption) - SDL_SetWindowTitle(window, caption); + { + SDL_SetWindowTitle(Priv::window, caption); + } else { FString default_caption; default_caption.Format(GAMESIG " %s (%s)", GetVersionString(), GetGitTime()); - SDL_SetWindowTitle(window, default_caption); + SDL_SetWindowTitle(Priv::window, default_caption); } } diff --git a/src/rendering/vulkan/system/vk_device.cpp b/src/rendering/vulkan/system/vk_device.cpp index ecbf68b39e..2ef0a63c90 100644 --- a/src/rendering/vulkan/system/vk_device.cpp +++ b/src/rendering/vulkan/system/vk_device.cpp @@ -21,17 +21,11 @@ //-------------------------------------------------------------------------- // -#ifdef _WIN32 -#define VK_USE_PLATFORM_WIN32_KHR -#endif - #include "volk/volk.h" #ifdef _WIN32 #undef max #undef min - -extern HWND Window; #endif #include @@ -48,6 +42,10 @@ extern HWND Window; #include "doomerrors.h" #include "gamedata/fonts/v_text.h" +void I_GetVulkanDrawableSize(int *width, int *height); +bool I_GetVulkanPlatformExtensions(unsigned int *count, const char **names); +bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface); + EXTERN_CVAR(Bool, vid_vsync); CUSTOM_CVAR(Bool, vk_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) @@ -75,13 +73,9 @@ VulkanDevice::VulkanDevice() createDevice(); createAllocator(); -#ifdef _WIN32 - RECT clientRect = { 0 }; - GetClientRect(Window, &clientRect); - swapChain = std::make_unique(this, clientRect.right, clientRect.bottom, vid_vsync); -#else - assert(!"Implement platform-specific swapchain size getter"); -#endif + int width, height; + I_GetVulkanDrawableSize(&width, &height); + swapChain = std::make_unique(this, width, height, vid_vsync); createSemaphores(); } @@ -99,15 +93,11 @@ VulkanDevice::~VulkanDevice() void VulkanDevice::windowResized() { -#ifdef _WIN32 - RECT clientRect = { 0 }; - GetClientRect(Window, &clientRect); + int width, height; + I_GetVulkanDrawableSize(&width, &height); swapChain.reset(); - swapChain = std::make_unique(this, clientRect.right, clientRect.bottom, vid_vsync); -#else - assert(!"Implement platform-specific swapchain resize"); -#endif + swapChain = std::make_unique(this, width, height, vid_vsync); } void VulkanDevice::waitPresent() @@ -211,12 +201,19 @@ void VulkanDevice::createInstance() appInfo.engineVersion = VK_MAKE_VERSION(ENG_MAJOR, ENG_MINOR, ENG_REVISION); appInfo.apiVersion = VK_API_VERSION_1_0; - std::vector enabledExtensions = { VK_KHR_SURFACE_EXTENSION_NAME }; -#ifdef _WIN32 - enabledExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); -#else - assert(!"Add platform-specific surface extension"); -#endif + std::vector enabledExtensions; + + if (!I_GetVulkanPlatformExtensions(&extensionCount, nullptr)) + { + throw std::runtime_error("Cannot obtain number of Vulkan extensions"); + } + + enabledExtensions.resize(extensionCount); + + if (!I_GetVulkanPlatformExtensions(&extensionCount, &enabledExtensions[0])) + { + throw std::runtime_error("Cannot obtain list of Vulkan extensions"); + } std::vector validationLayers; std::string debugLayer = "VK_LAYER_LUNARG_standard_validation"; @@ -269,22 +266,10 @@ void VulkanDevice::createInstance() void VulkanDevice::createSurface() { -#ifdef _WIN32 - VkWin32SurfaceCreateInfoKHR windowCreateInfo; - windowCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; - windowCreateInfo.pNext = nullptr; - windowCreateInfo.flags = 0; - windowCreateInfo.hwnd = Window; - windowCreateInfo.hinstance = GetModuleHandle(nullptr); - - VkResult result = vkCreateWin32SurfaceKHR(instance, &windowCreateInfo, nullptr, &surface); - if (result != VK_SUCCESS) + if (!I_CreateVulkanSurface(instance, &surface)) + { throw std::runtime_error("Could not create vulkan surface"); -#elif defined __APPLE__ - // todo -#else - // todo -#endif + } } void VulkanDevice::selectPhysicalDevice() diff --git a/src/win32/win32vulkanvideo.cpp b/src/win32/win32vulkanvideo.cpp new file mode 100644 index 0000000000..7abb338617 --- /dev/null +++ b/src/win32/win32vulkanvideo.cpp @@ -0,0 +1,74 @@ + +#include + +#ifdef _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#endif + +#include "volk/volk.h" + + +extern HWND Window; + +void I_GetVulkanDrawableSize(int *width, int *height) +{ + assert(Window); + + RECT clientRect = { 0 }; + GetClientRect(Window, &clientRect); + + if (width != nullptr) + { + *width = clientRect.right; + } + + if (height != nullptr) + { + *height = clientRect.bottom; + } +} + +bool I_GetVulkanPlatformExtensions(unsigned int *count, const char **names) +{ + static const char* extensions[] = + { + VK_KHR_SURFACE_EXTENSION_NAME, + VK_KHR_WIN32_SURFACE_EXTENSION_NAME + }; + static const unsigned int extensionCount = static_cast(sizeof extensions / sizeof extensions[0]); + + if (count == nullptr && names == nullptr) + { + return false; + } + else if (names == nullptr) + { + *count = extensionCount; + return true; + } + else + { + const bool result = *count >= extensionCount; + *count = min(*count, extensionCount); + + for (unsigned int i = 0; i < *count; ++i) + { + names[i] = extensions[i]; + } + + return result; + } +} + +bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface) +{ + VkWin32SurfaceCreateInfoKHR windowCreateInfo; + windowCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; + windowCreateInfo.pNext = nullptr; + windowCreateInfo.flags = 0; + windowCreateInfo.hwnd = Window; + windowCreateInfo.hinstance = GetModuleHandle(nullptr); + + const VkResult result = vkCreateWin32SurfaceKHR(instance, &windowCreateInfo, nullptr, surface); + return result == VK_SUCCESS; +}