- added initial support of Vulkan to SDL backend

Removed all platform-specific code from vulkan device
This commit is contained in:
alexey.lysiuk 2019-03-06 13:38:45 +02:00
parent 08d8ea5d31
commit 108ea066f3
6 changed files with 420 additions and 250 deletions

View file

@ -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 )

View file

@ -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");
}

View file

@ -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() {}
};

View file

@ -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<library, RESULT(*)(__VA_ARGS__)> 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_lib, SDL_GetWindowBordersSizePtr> 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<SDLGLVideo*>(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<SystemBaseFrameBuffer *>(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<SystemBaseFrameBuffer *>(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<SystemBaseFrameBuffer *>(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);
}
}

View file

@ -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 <vector>
@ -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<VulkanSwapChain>(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<VulkanSwapChain>(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<VulkanSwapChain>(this, clientRect.right, clientRect.bottom, vid_vsync);
#else
assert(!"Implement platform-specific swapchain resize");
#endif
swapChain = std::make_unique<VulkanSwapChain>(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<const char *> 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<const char *> 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<const char*> 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()

View file

@ -0,0 +1,74 @@
#include <assert.h>
#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<unsigned int>(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;
}