mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-12-01 16:32:17 +00:00
- added initial support of Vulkan to SDL backend
Removed all platform-specific code from vulkan device
This commit is contained in:
parent
08d8ea5d31
commit
108ea066f3
6 changed files with 420 additions and 250 deletions
|
@ -504,7 +504,8 @@ set( PLAT_WIN32_SOURCES
|
||||||
win32/gl_sysfb.cpp
|
win32/gl_sysfb.cpp
|
||||||
win32/base_sysfb.cpp
|
win32/base_sysfb.cpp
|
||||||
win32/win32basevideo.cpp
|
win32/win32basevideo.cpp
|
||||||
win32/win32glvideo.cpp )
|
win32/win32glvideo.cpp
|
||||||
|
win32/win32vulkanvideo.cpp )
|
||||||
set( PLAT_POSIX_SOURCES
|
set( PLAT_POSIX_SOURCES
|
||||||
posix/i_cd.cpp
|
posix/i_cd.cpp
|
||||||
posix/i_steam.cpp )
|
posix/i_steam.cpp )
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "gl_load/gl_load.h"
|
#include "gl_load/gl_load.h"
|
||||||
|
#include "volk/volk.h"
|
||||||
|
|
||||||
#include "i_common.h"
|
#include "i_common.h"
|
||||||
|
|
||||||
|
@ -660,3 +661,19 @@ void I_SetWindowTitle(const char* title)
|
||||||
{
|
{
|
||||||
SystemBaseFrameBuffer::SetWindowTitle(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");
|
||||||
|
}
|
||||||
|
|
|
@ -12,43 +12,17 @@ class SystemBaseFrameBuffer : public DFrameBuffer
|
||||||
public:
|
public:
|
||||||
// this must have the same parameters as the Windows version, even if they are not used!
|
// this must have the same parameters as the Windows version, even if they are not used!
|
||||||
SystemBaseFrameBuffer (void *hMonitor, bool fullscreen);
|
SystemBaseFrameBuffer (void *hMonitor, bool fullscreen);
|
||||||
~SystemBaseFrameBuffer ();
|
|
||||||
|
|
||||||
void ForceBuffering (bool force);
|
bool IsFullscreen() override;
|
||||||
|
|
||||||
bool IsFullscreen ();
|
|
||||||
|
|
||||||
virtual void SetVSync( bool vsync );
|
|
||||||
void SwapBuffers();
|
|
||||||
|
|
||||||
friend class SDLGLVideo;
|
|
||||||
|
|
||||||
int GetClientWidth() override;
|
int GetClientWidth() override;
|
||||||
int GetClientHeight() override;
|
int GetClientHeight() override;
|
||||||
|
|
||||||
void ToggleFullscreen(bool yes) override;
|
void ToggleFullscreen(bool yes) override;
|
||||||
void SetWindowSize(int client_w, int client_h);
|
void SetWindowSize(int client_w, int client_h) override;
|
||||||
|
|
||||||
SDL_Window *GetSDLWindow() { return Screen; }
|
|
||||||
void GetWindowBordersSize(int &top, int &left);
|
|
||||||
|
|
||||||
bool m_fsswitch;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void SetGammaTable(uint16_t *tbl);
|
|
||||||
void ResetGammaTable();
|
|
||||||
|
|
||||||
SystemBaseFrameBuffer () {}
|
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
|
class SystemGLFrameBuffer : public SystemBaseFrameBuffer
|
||||||
|
@ -56,11 +30,18 @@ class SystemGLFrameBuffer : public SystemBaseFrameBuffer
|
||||||
typedef SystemBaseFrameBuffer Super;
|
typedef SystemBaseFrameBuffer Super;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SystemGLFrameBuffer(void *hMonitor, bool fullscreen)
|
SystemGLFrameBuffer(void *hMonitor, bool fullscreen);
|
||||||
: SystemBaseFrameBuffer(hMonitor, fullscreen)
|
~SystemGLFrameBuffer();
|
||||||
{}
|
|
||||||
|
int GetClientWidth() override;
|
||||||
|
int GetClientHeight() override;
|
||||||
|
|
||||||
|
virtual void SetVSync(bool vsync) override;
|
||||||
|
void SwapBuffers();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
SDL_GLContext GLContext;
|
||||||
|
|
||||||
SystemGLFrameBuffer() {}
|
SystemGLFrameBuffer() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,8 @@
|
||||||
#include "gl/system/gl_framebuffer.h"
|
#include "gl/system/gl_framebuffer.h"
|
||||||
#include "gl/shaders/gl_shader.h"
|
#include "gl/shaders/gl_shader.h"
|
||||||
|
|
||||||
|
#include "rendering/vulkan/system/vk_framebuffer.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
// TYPES -------------------------------------------------------------------
|
// TYPES -------------------------------------------------------------------
|
||||||
|
@ -89,56 +91,71 @@ CVAR (Int, vid_adapter, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
|
||||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
|
|
||||||
class SDLGLVideo : public IVideo
|
namespace Priv
|
||||||
{
|
{
|
||||||
public:
|
FModule library("SDL2");
|
||||||
SDLGLVideo (int parm);
|
|
||||||
~SDLGLVideo ();
|
|
||||||
|
|
||||||
DFrameBuffer *CreateFrameBuffer ();
|
#define SDL2_OPTIONAL_FUNCTION(RESULT, NAME, ...) \
|
||||||
|
static TOptProc<library, RESULT(*)(__VA_ARGS__)> NAME("SDL_" #NAME)
|
||||||
|
|
||||||
void SetupPixelFormat(bool allowsoftware, int multisample, const int *glver);
|
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);
|
||||||
|
|
||||||
// CODE --------------------------------------------------------------------
|
#undef SDL2_OPTIONAL_FUNCTION
|
||||||
|
|
||||||
SDLGLVideo::SDLGLVideo (int parm)
|
static const uint32_t VulkanWindowFlag = 0x1000'0000;
|
||||||
{
|
|
||||||
if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
|
static const int MIN_WIDTH = 320;
|
||||||
fprintf( stderr, "Video initialization failed: %s\n",
|
static const int MIN_HEIGHT = 200;
|
||||||
SDL_GetError( ) );
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
SDLGLVideo::~SDLGLVideo ()
|
FString caption;
|
||||||
{
|
caption.Format(GAMESIG " %s (%s)", GetVersionString(), GetGitTime());
|
||||||
}
|
|
||||||
|
|
||||||
DFrameBuffer *SDLGLVideo::CreateFrameBuffer ()
|
const uint32_t windowFlags = (win_maximized ? SDL_WINDOW_MAXIMIZED : 0) | SDL_WINDOW_RESIZABLE | extraFlags;
|
||||||
{
|
Priv::window = SDL_CreateWindow(caption,
|
||||||
SystemBaseFrameBuffer *fb = new OpenGLRenderer::OpenGLFrameBuffer(0, fullscreen);
|
(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);
|
||||||
|
|
||||||
return fb;
|
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);
|
||||||
void SDLGLVideo::SetupPixelFormat(bool allowsoftware, int multisample, const int *glver)
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||||
{
|
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
|
||||||
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||||
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) {
|
if (multisample > 0) {
|
||||||
SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 1 );
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
|
||||||
SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, multisample );
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, multisample);
|
||||||
}
|
}
|
||||||
if (gl_debug)
|
if (gl_debug)
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
|
||||||
|
@ -161,48 +178,210 @@ void SDLGLVideo::SetupPixelFormat(bool allowsoftware, int multisample, const int
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SDLVideo : public IVideo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SDLVideo ();
|
||||||
|
~SDLVideo ();
|
||||||
|
|
||||||
|
DFrameBuffer *CreateFrameBuffer ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
VulkanDevice *device = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// CODE --------------------------------------------------------------------
|
||||||
|
|
||||||
|
void I_GetVulkanDrawableSize(int *width, int *height)
|
||||||
|
{
|
||||||
|
assert(Priv::vulkanSupported);
|
||||||
|
assert(Priv::window != nullptr);
|
||||||
|
assert(Priv::Vulkan_GetDrawableSize);
|
||||||
|
Priv::Vulkan_GetDrawableSize(Priv::window, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface)
|
||||||
|
{
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
IVideo *gl_CreateVideo()
|
IVideo *gl_CreateVideo()
|
||||||
{
|
{
|
||||||
return new SDLGLVideo(0);
|
return new SDLVideo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// FrameBuffer implementation -----------------------------------------------
|
// 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");
|
|
||||||
|
|
||||||
SystemBaseFrameBuffer::SystemBaseFrameBuffer (void *, bool fullscreen)
|
SystemBaseFrameBuffer::SystemBaseFrameBuffer (void *, bool fullscreen)
|
||||||
: DFrameBuffer (vid_defwidth, vid_defheight)
|
: DFrameBuffer (vid_defwidth, vid_defheight)
|
||||||
{
|
{
|
||||||
m_fsswitch = false;
|
if (Priv::window != nullptr)
|
||||||
|
|
||||||
// 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())
|
|
||||||
{
|
{
|
||||||
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
|
// 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
|
// 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).
|
// instead, but that would be too restrictive (w.r.t. shaders).
|
||||||
static const int glvers[][2] = {
|
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 },
|
{ 3, 3 }, { 3, 2 }, { 2, 0 },
|
||||||
{ 0, 0 },
|
{ 0, 0 },
|
||||||
};
|
};
|
||||||
int glveridx = 0;
|
int glveridx = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
UpdatePending = false;
|
|
||||||
|
|
||||||
const char *version = Args->CheckValue("-glversion");
|
const char *version = Args->CheckValue("-glversion");
|
||||||
if (version != NULL)
|
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)
|
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;
|
if (Priv::window == nullptr)
|
||||||
SDL_GetDisplayBounds(vid_adapter,&bounds);
|
|
||||||
// set default size
|
|
||||||
if ( win_w <= 0 || win_h <= 0 )
|
|
||||||
{
|
{
|
||||||
win_w = bounds.w * 8 / 10;
|
continue;
|
||||||
win_h = bounds.h * 8 / 10;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Screen = SDL_CreateWindow(caption,
|
GLContext = SDL_GL_CreateContext(Priv::window);
|
||||||
(win_x <= 0) ? SDL_WINDOWPOS_CENTERED_DISPLAY(vid_adapter) : win_x,
|
if (GLContext == nullptr)
|
||||||
(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)
|
|
||||||
{
|
{
|
||||||
// enforce minimum size limit
|
SDL_DestroyWindow(Priv::window);
|
||||||
SDL_SetWindowMinimumSize(Screen, MIN_WIDTH, MIN_HEIGHT);
|
Priv::window = nullptr;
|
||||||
|
}
|
||||||
GLContext = SDL_GL_CreateContext(Screen);
|
else
|
||||||
if (GLContext != NULL)
|
{
|
||||||
return;
|
break;
|
||||||
|
|
||||||
SDL_DestroyWindow(Screen);
|
|
||||||
Screen = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemBaseFrameBuffer::~SystemBaseFrameBuffer ()
|
SystemGLFrameBuffer::~SystemGLFrameBuffer ()
|
||||||
{
|
{
|
||||||
if (Screen)
|
if (Priv::window)
|
||||||
{
|
{
|
||||||
if (GLContext)
|
if (GLContext)
|
||||||
{
|
{
|
||||||
SDL_GL_DeleteContext(GLContext);
|
SDL_GL_DeleteContext(GLContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_DestroyWindow(Screen);
|
SDL_DestroyWindow(Priv::window);
|
||||||
|
Priv::window = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SystemGLFrameBuffer::GetClientWidth()
|
||||||
bool SystemBaseFrameBuffer::IsFullscreen ()
|
|
||||||
{
|
{
|
||||||
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__)
|
#if defined (__APPLE__)
|
||||||
const GLint value = vsync ? 1 : 0;
|
const GLint value = vsync ? 1 : 0;
|
||||||
|
@ -294,7 +470,7 @@ void SystemBaseFrameBuffer::SetVSync( bool vsync )
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemBaseFrameBuffer::SwapBuffers()
|
void SystemGLFrameBuffer::SwapBuffers()
|
||||||
{
|
{
|
||||||
#if !defined(__APPLE__) && !defined(__OpenBSD__)
|
#if !defined(__APPLE__) && !defined(__OpenBSD__)
|
||||||
if (vid_maxfps && !cl_capfps)
|
if (vid_maxfps && !cl_capfps)
|
||||||
|
@ -303,74 +479,9 @@ void SystemBaseFrameBuffer::SwapBuffers()
|
||||||
}
|
}
|
||||||
#endif
|
#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)
|
void ProcessSDLWindowEvent(const SDL_WindowEvent &event)
|
||||||
{
|
{
|
||||||
|
@ -389,17 +500,17 @@ void ProcessSDLWindowEvent(const SDL_WindowEvent &event)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_WINDOWEVENT_MOVED:
|
case SDL_WINDOWEVENT_MOVED:
|
||||||
if (!fullscreen)
|
if (!fullscreen && Priv::GetWindowBordersSize)
|
||||||
{
|
{
|
||||||
int top = 0, left = 0;
|
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_x = event.data1-left;
|
||||||
win_y = event.data2-top;
|
win_y = event.data2-top;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_WINDOWEVENT_RESIZED:
|
case SDL_WINDOWEVENT_RESIZED:
|
||||||
if (!fullscreen && !(static_cast<SystemBaseFrameBuffer *>(screen)->m_fsswitch))
|
if (!fullscreen && !Priv::fullscreenSwitch)
|
||||||
{
|
{
|
||||||
win_w = event.data1;
|
win_w = event.data1;
|
||||||
win_h = event.data2;
|
win_h = event.data2;
|
||||||
|
@ -420,14 +531,15 @@ void ProcessSDLWindowEvent(const SDL_WindowEvent &event)
|
||||||
// each platform has its own specific version of this function.
|
// each platform has its own specific version of this function.
|
||||||
void I_SetWindowTitle(const char* caption)
|
void I_SetWindowTitle(const char* caption)
|
||||||
{
|
{
|
||||||
auto window = static_cast<SystemBaseFrameBuffer *>(screen)->GetSDLWindow();
|
|
||||||
if (caption)
|
if (caption)
|
||||||
SDL_SetWindowTitle(window, caption);
|
{
|
||||||
|
SDL_SetWindowTitle(Priv::window, caption);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FString default_caption;
|
FString default_caption;
|
||||||
default_caption.Format(GAMESIG " %s (%s)", GetVersionString(), GetGitTime());
|
default_caption.Format(GAMESIG " %s (%s)", GetVersionString(), GetGitTime());
|
||||||
SDL_SetWindowTitle(window, default_caption);
|
SDL_SetWindowTitle(Priv::window, default_caption);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,17 +21,11 @@
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define VK_USE_PLATFORM_WIN32_KHR
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "volk/volk.h"
|
#include "volk/volk.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#undef max
|
#undef max
|
||||||
#undef min
|
#undef min
|
||||||
|
|
||||||
extern HWND Window;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -48,6 +42,10 @@ extern HWND Window;
|
||||||
#include "doomerrors.h"
|
#include "doomerrors.h"
|
||||||
#include "gamedata/fonts/v_text.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);
|
EXTERN_CVAR(Bool, vid_vsync);
|
||||||
|
|
||||||
CUSTOM_CVAR(Bool, vk_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
CUSTOM_CVAR(Bool, vk_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
||||||
|
@ -75,13 +73,9 @@ VulkanDevice::VulkanDevice()
|
||||||
createDevice();
|
createDevice();
|
||||||
createAllocator();
|
createAllocator();
|
||||||
|
|
||||||
#ifdef _WIN32
|
int width, height;
|
||||||
RECT clientRect = { 0 };
|
I_GetVulkanDrawableSize(&width, &height);
|
||||||
GetClientRect(Window, &clientRect);
|
swapChain = std::make_unique<VulkanSwapChain>(this, width, height, vid_vsync);
|
||||||
swapChain = std::make_unique<VulkanSwapChain>(this, clientRect.right, clientRect.bottom, vid_vsync);
|
|
||||||
#else
|
|
||||||
assert(!"Implement platform-specific swapchain size getter");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
createSemaphores();
|
createSemaphores();
|
||||||
}
|
}
|
||||||
|
@ -99,15 +93,11 @@ VulkanDevice::~VulkanDevice()
|
||||||
|
|
||||||
void VulkanDevice::windowResized()
|
void VulkanDevice::windowResized()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
int width, height;
|
||||||
RECT clientRect = { 0 };
|
I_GetVulkanDrawableSize(&width, &height);
|
||||||
GetClientRect(Window, &clientRect);
|
|
||||||
|
|
||||||
swapChain.reset();
|
swapChain.reset();
|
||||||
swapChain = std::make_unique<VulkanSwapChain>(this, clientRect.right, clientRect.bottom, vid_vsync);
|
swapChain = std::make_unique<VulkanSwapChain>(this, width, height, vid_vsync);
|
||||||
#else
|
|
||||||
assert(!"Implement platform-specific swapchain resize");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanDevice::waitPresent()
|
void VulkanDevice::waitPresent()
|
||||||
|
@ -211,12 +201,19 @@ void VulkanDevice::createInstance()
|
||||||
appInfo.engineVersion = VK_MAKE_VERSION(ENG_MAJOR, ENG_MINOR, ENG_REVISION);
|
appInfo.engineVersion = VK_MAKE_VERSION(ENG_MAJOR, ENG_MINOR, ENG_REVISION);
|
||||||
appInfo.apiVersion = VK_API_VERSION_1_0;
|
appInfo.apiVersion = VK_API_VERSION_1_0;
|
||||||
|
|
||||||
std::vector<const char *> enabledExtensions = { VK_KHR_SURFACE_EXTENSION_NAME };
|
std::vector<const char *> enabledExtensions;
|
||||||
#ifdef _WIN32
|
|
||||||
enabledExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
if (!I_GetVulkanPlatformExtensions(&extensionCount, nullptr))
|
||||||
#else
|
{
|
||||||
assert(!"Add platform-specific surface extension");
|
throw std::runtime_error("Cannot obtain number of Vulkan extensions");
|
||||||
#endif
|
}
|
||||||
|
|
||||||
|
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::vector<const char*> validationLayers;
|
||||||
std::string debugLayer = "VK_LAYER_LUNARG_standard_validation";
|
std::string debugLayer = "VK_LAYER_LUNARG_standard_validation";
|
||||||
|
@ -269,22 +266,10 @@ void VulkanDevice::createInstance()
|
||||||
|
|
||||||
void VulkanDevice::createSurface()
|
void VulkanDevice::createSurface()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
if (!I_CreateVulkanSurface(instance, &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);
|
|
||||||
|
|
||||||
VkResult result = vkCreateWin32SurfaceKHR(instance, &windowCreateInfo, nullptr, &surface);
|
|
||||||
if (result != VK_SUCCESS)
|
|
||||||
throw std::runtime_error("Could not create vulkan surface");
|
throw std::runtime_error("Could not create vulkan surface");
|
||||||
#elif defined __APPLE__
|
}
|
||||||
// todo
|
|
||||||
#else
|
|
||||||
// todo
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanDevice::selectPhysicalDevice()
|
void VulkanDevice::selectPhysicalDevice()
|
||||||
|
|
74
src/win32/win32vulkanvideo.cpp
Normal file
74
src/win32/win32vulkanvideo.cpp
Normal 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;
|
||||||
|
}
|
Loading…
Reference in a new issue