diff --git a/Makefile.common b/Makefile.common
index 0cec67afc1..ff13b416e8 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -1659,6 +1659,9 @@ endif
ifeq ($(WANT_WGL), 1)
OBJ += gfx/drivers_context/wgl_ctx.o
+ ifeq ($(HAVE_VULKAN),1)
+ OBJ += gfx/drivers_context/w_vk_ctx.o
+ endif
LIBS += -lcomctl32
endif
diff --git a/gfx/drivers_context/w_vk_ctx.c b/gfx/drivers_context/w_vk_ctx.c
new file mode 100644
index 0000000000..61dbf01423
--- /dev/null
+++ b/gfx/drivers_context/w_vk_ctx.c
@@ -0,0 +1,352 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2017 - Daniel De Matteis
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+#include
+
+/* Win32/WGL context. */
+
+/* necessary for mingw32 multimon defines: */
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0500 //_WIN32_WINNT_WIN2K
+#endif
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#ifdef HAVE_CONFIG_H
+#include "../../config.h"
+#endif
+
+#include "../../configuration.h"
+#include "../../dynamic.h"
+#include "../../retroarch.h"
+#include "../../verbosity.h"
+#include "../../frontend/frontend_driver.h"
+
+#include "../common/win32_common.h"
+
+#include "../common/vulkan_common.h"
+
+/* TODO/FIXME - static globals */
+static gfx_ctx_vulkan_data_t win32_vk;
+
+static void *dinput_vk_wgl = NULL;
+
+static int win32_vk_interval = 0;
+static enum gfx_ctx_api win32_vk_api = GFX_CTX_NONE;
+
+typedef struct gfx_ctx_cgl_data
+{
+ void *empty;
+} gfx_ctx_w_vk_data_t;
+
+void create_vk_context(HWND hwnd, bool *quit)
+{
+ RECT rect;
+ HINSTANCE instance;
+ unsigned width = 0;
+ unsigned height = 0;
+
+ GetClientRect(hwnd, &rect);
+
+ instance = GetModuleHandle(NULL);
+ width = rect.right - rect.left;
+ height = rect.bottom - rect.top;
+
+ if (!vulkan_surface_create(&win32_vk, VULKAN_WSI_WIN32,
+ &instance, &hwnd,
+ width, height, win32_vk_interval))
+ *quit = true;
+
+ g_win32_inited = true;
+}
+
+static void gfx_ctx_w_vk_swap_interval(void *data, int interval)
+{
+ if (win32_vk_interval != interval)
+ {
+ win32_vk_interval = interval;
+ if (win32_vk.swapchain)
+ win32_vk.need_new_swapchain = true;
+ }
+}
+
+static void gfx_ctx_w_vk_check_window(void *data, bool *quit,
+ bool *resize, unsigned *width, unsigned *height)
+{
+ win32_check_window(quit, resize, width, height);
+
+ if (win32_vk.need_new_swapchain)
+ *resize = true;
+}
+
+static void gfx_ctx_w_vk_swap_buffers(void *data)
+{
+ vulkan_present(&win32_vk, win32_vk.context.current_swapchain_index);
+ vulkan_acquire_next_image(&win32_vk);
+}
+
+static bool gfx_ctx_w_vk_set_resize(void *data,
+ unsigned width, unsigned height)
+{
+ if (!vulkan_create_swapchain(&win32_vk, width, height, win32_vk_interval))
+ {
+ RARCH_ERR("[Win32/Vulkan]: Failed to update swapchain.\n");
+ return false;
+ }
+
+ if (win32_vk.created_new_swapchain)
+ vulkan_acquire_next_image(&win32_vk);
+ win32_vk.context.invalid_swapchain = true;
+ win32_vk.need_new_swapchain = false;
+
+ return false;
+}
+
+static void gfx_ctx_w_vk_update_title(void *data)
+{
+ char title[128];
+
+ title[0] = '\0';
+
+ video_driver_get_window_title(title, sizeof(title));
+
+ if (title[0])
+ {
+ const ui_window_t *window = ui_companion_driver_get_window_ptr();
+
+ if (window)
+ window->set_title(&main_window, title);
+ }
+}
+
+static void gfx_ctx_w_vk_get_video_size(void *data,
+ unsigned *width, unsigned *height)
+{
+ HWND window = win32_get_window();
+
+ (void)data;
+
+ if (!window)
+ {
+ RECT mon_rect;
+ MONITORINFOEX current_mon;
+ unsigned mon_id = 0;
+ HMONITOR hm_to_use = NULL;
+
+ win32_monitor_info(¤t_mon, &hm_to_use, &mon_id);
+ mon_rect = current_mon.rcMonitor;
+ *width = mon_rect.right - mon_rect.left;
+ *height = mon_rect.bottom - mon_rect.top;
+ }
+ else
+ {
+ *width = g_win32_resize_width;
+ *height = g_win32_resize_height;
+ }
+}
+
+static void gfx_ctx_w_vk_destroy(void *data)
+{
+ HWND window = win32_get_window();
+ gfx_ctx_w_vk_data_t *wgl = (gfx_ctx_w_vk_data_t*)data;
+
+ vulkan_context_destroy(&win32_vk, win32_vk.vk_surface != VK_NULL_HANDLE);
+ if (win32_vk.context.queue_lock)
+ slock_free(win32_vk.context.queue_lock);
+ memset(&win32_vk, 0, sizeof(win32_vk));
+
+ if (window)
+ {
+ win32_monitor_from_window();
+ win32_destroy_window();
+ }
+
+ if (g_win32_restore_desktop)
+ {
+ win32_monitor_get_info();
+ g_win32_restore_desktop = false;
+ }
+
+ if (wgl)
+ free(wgl);
+
+ g_win32_inited = false;
+}
+
+static void *gfx_ctx_w_vk_init(void *video_driver)
+{
+ WNDCLASSEX wndclass = {0};
+ gfx_ctx_w_vk_data_t *wgl = (gfx_ctx_w_vk_data_t*)calloc(1, sizeof(*wgl));
+
+ if (!wgl)
+ return NULL;
+
+ if (g_win32_inited)
+ gfx_ctx_w_vk_destroy(NULL);
+
+ win32_window_reset();
+ win32_monitor_init();
+
+ wndclass.lpfnWndProc = WndProcVK;
+ if (!win32_window_init(&wndclass, true, NULL))
+ goto error;
+
+ if (!vulkan_context_init(&win32_vk, VULKAN_WSI_WIN32))
+ goto error;
+
+ return wgl;
+
+error:
+ if (wgl)
+ free(wgl);
+ return NULL;
+}
+
+static bool gfx_ctx_w_vk_set_video_mode(void *data,
+ unsigned width, unsigned height,
+ bool fullscreen)
+{
+ win32_vk.fullscreen = fullscreen;
+
+ if (!win32_set_video_mode(NULL, width, height, fullscreen))
+ {
+ RARCH_ERR("[WGL]: win32_set_video_mode failed.\n");
+ goto error;
+ }
+
+ gfx_ctx_w_vk_swap_interval(data, win32_vk_interval);
+ return true;
+
+error:
+ gfx_ctx_w_vk_destroy(data);
+ return false;
+}
+
+static void gfx_ctx_w_vk_input_driver(void *data,
+ const char *joypad_name,
+ input_driver_t **input, void **input_data)
+{
+ settings_t *settings = config_get_ptr();
+
+#if _WIN32_WINNT >= 0x0501
+#ifdef HAVE_WINRAWINPUT
+ const char *input_driver = settings->arrays.input_driver;
+
+ /* winraw only available since XP */
+ if (string_is_equal(input_driver, "raw"))
+ {
+ *input_data = input_winraw.init(joypad_name);
+ if (*input_data)
+ {
+ *input = &input_winraw;
+ dinput_vk_wgl = NULL;
+ return;
+ }
+ }
+#endif
+#endif
+
+#ifdef HAVE_DINPUT
+ dinput_vk_wgl = input_dinput.init(joypad_name);
+ *input = dinput_vk_wgl ? &input_dinput : NULL;
+ *input_data = dinput_vk_wgl;
+#endif
+}
+
+static enum gfx_ctx_api gfx_ctx_w_vk_get_api(void *data) { return win32_vk_api; }
+
+static bool gfx_ctx_w_vk_bind_api(void *data,
+ enum gfx_ctx_api api, unsigned major, unsigned minor)
+{
+ win32_vk_api = api;
+
+ if (api == GFX_CTX_VULKAN_API)
+ return true;
+ return false;
+}
+
+static void gfx_ctx_w_vk_bind_hw_render(void *data, bool enable) { }
+
+static void *gfx_ctx_w_vk_get_context_data(void *data)
+{
+ (void)data;
+ return &win32_vk.context;
+}
+
+static uint32_t gfx_ctx_w_vk_get_flags(void *data)
+{
+ uint32_t flags = 0;
+#if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS)
+ BIT32_SET(flags, GFX_CTX_FLAGS_SHADERS_SLANG);
+#endif
+ return flags;
+}
+
+static void gfx_ctx_w_vk_set_flags(void *data, uint32_t flags) { }
+
+static void gfx_ctx_w_vk_get_video_output_size(void *data,
+ unsigned *width, unsigned *height)
+{
+ win32_get_video_output_size(width, height);
+}
+
+static void gfx_ctx_w_vk_get_video_output_prev(void *data) { }
+
+static void gfx_ctx_w_vk_get_video_output_next(void *data) { }
+
+const gfx_ctx_driver_t gfx_ctx_w_vk = {
+ gfx_ctx_w_vk_init,
+ gfx_ctx_w_vk_destroy,
+ gfx_ctx_w_vk_get_api,
+ gfx_ctx_w_vk_bind_api,
+ gfx_ctx_w_vk_swap_interval,
+ gfx_ctx_w_vk_set_video_mode,
+ gfx_ctx_w_vk_get_video_size,
+ win32_get_refresh_rate,
+ gfx_ctx_w_vk_get_video_output_size,
+ gfx_ctx_w_vk_get_video_output_prev,
+ gfx_ctx_w_vk_get_video_output_next,
+ win32_get_metrics,
+ NULL,
+ gfx_ctx_w_vk_update_title,
+ gfx_ctx_w_vk_check_window,
+ gfx_ctx_w_vk_set_resize,
+ win32_has_focus,
+ win32_suppress_screensaver,
+ true, /* has_windowed */
+ gfx_ctx_w_vk_swap_buffers,
+ gfx_ctx_w_vk_input_driver,
+ NULL,
+ NULL,
+ NULL,
+ win32_show_cursor,
+ "w_vk",
+ gfx_ctx_w_vk_get_flags,
+ gfx_ctx_w_vk_set_flags,
+ gfx_ctx_w_vk_bind_hw_render,
+ gfx_ctx_w_vk_get_context_data,
+ NULL
+};
diff --git a/gfx/drivers_context/wgl_ctx.c b/gfx/drivers_context/wgl_ctx.c
index 91986778cd..1d7aa77db7 100644
--- a/gfx/drivers_context/wgl_ctx.c
+++ b/gfx/drivers_context/wgl_ctx.c
@@ -62,11 +62,7 @@
#include "../common/gl1_common.h"
#endif
-#ifdef HAVE_VULKAN
-#include "../common/vulkan_common.h"
-#endif
-
-#if defined(HAVE_OPENGL) || defined(HAVE_OPENGL1) || defined(HAVE_OPENGL_CORE) || defined(HAVE_VULKAN)
+#if defined(HAVE_OPENGL) || defined(HAVE_OPENGL1) || defined(HAVE_OPENGL_CORE)
#ifndef WGL_CONTEXT_MAJOR_VERSION_ARB
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#endif
@@ -102,9 +98,6 @@ static bool win32_use_hw_ctx = false;
static bool win32_core_hw_context_enable = false;
static bool wgl_adaptive_vsync = false;
-#ifdef HAVE_VULKAN
-static gfx_ctx_vulkan_data_t win32_vk;
-#endif
#ifdef HAVE_EGL
static egl_ctx_data_t win32_egl;
#endif
@@ -450,29 +443,6 @@ void create_graphics_context(HWND hwnd, bool *quit)
}
}
-void create_vk_context(HWND hwnd, bool *quit)
-{
-#ifdef HAVE_VULKAN
- RECT rect;
- HINSTANCE instance;
- unsigned width = 0;
- unsigned height = 0;
-
- GetClientRect(hwnd, &rect);
-
- instance = GetModuleHandle(NULL);
- width = rect.right - rect.left;
- height = rect.bottom - rect.top;
-
- if (!vulkan_surface_create(&win32_vk, VULKAN_WSI_WIN32,
- &instance, &hwnd,
- width, height, win32_interval))
- *quit = true;
-
- g_win32_inited = true;
-#endif
-}
-
static void gfx_ctx_wgl_swap_interval(void *data, int interval)
{
(void)data;
@@ -501,17 +471,6 @@ static void gfx_ctx_wgl_swap_interval(void *data, int interval)
#endif
break;
- case GFX_CTX_VULKAN_API:
-#ifdef HAVE_VULKAN
- if (win32_interval != interval)
- {
- win32_interval = interval;
- if (win32_vk.swapchain)
- win32_vk.need_new_swapchain = true;
- }
-#endif
- break;
-
case GFX_CTX_NONE:
default:
win32_interval = interval;
@@ -523,20 +482,6 @@ static void gfx_ctx_wgl_check_window(void *data, bool *quit,
bool *resize, unsigned *width, unsigned *height)
{
win32_check_window(quit, resize, width, height);
-
- switch (win32_api)
- {
- case GFX_CTX_VULKAN_API:
-#ifdef HAVE_VULKAN
- if (win32_vk.need_new_swapchain)
- *resize = true;
-#endif
- break;
-
- case GFX_CTX_NONE:
- default:
- break;
- }
}
static void gfx_ctx_wgl_swap_buffers(void *data)
@@ -548,12 +493,6 @@ static void gfx_ctx_wgl_swap_buffers(void *data)
case GFX_CTX_OPENGL_API:
SwapBuffers(win32_hdc);
break;
- case GFX_CTX_VULKAN_API:
-#ifdef HAVE_VULKAN
- vulkan_present(&win32_vk, win32_vk.context.current_swapchain_index);
- vulkan_acquire_next_image(&win32_vk);
-#endif
- break;
case GFX_CTX_OPENGL_ES_API:
#if defined(HAVE_EGL)
egl_swap_buffers(&win32_egl);
@@ -566,36 +505,7 @@ static void gfx_ctx_wgl_swap_buffers(void *data)
}
static bool gfx_ctx_wgl_set_resize(void *data,
- unsigned width, unsigned height)
-{
- (void)data;
- (void)width;
- (void)height;
-
- switch (win32_api)
- {
- case GFX_CTX_VULKAN_API:
-#ifdef HAVE_VULKAN
- if (!vulkan_create_swapchain(&win32_vk, width, height, win32_interval))
- {
- RARCH_ERR("[Win32/Vulkan]: Failed to update swapchain.\n");
- return false;
- }
-
- if (win32_vk.created_new_swapchain)
- vulkan_acquire_next_image(&win32_vk);
- win32_vk.context.invalid_swapchain = true;
- win32_vk.need_new_swapchain = false;
-#endif
- break;
-
- case GFX_CTX_NONE:
- default:
- break;
- }
-
- return false;
-}
+ unsigned width, unsigned height) { return false; }
static void gfx_ctx_wgl_update_title(void *data)
{
@@ -666,15 +576,6 @@ static void gfx_ctx_wgl_destroy(void *data)
#endif
break;
- case GFX_CTX_VULKAN_API:
-#ifdef HAVE_VULKAN
- vulkan_context_destroy(&win32_vk, win32_vk.vk_surface != VK_NULL_HANDLE);
- if (win32_vk.context.queue_lock)
- slock_free(win32_vk.context.queue_lock);
- memset(&win32_vk, 0, sizeof(win32_vk));
-#endif
- break;
-
case GFX_CTX_OPENGL_ES_API:
#ifdef HAVE_EGL
egl_destroy(&win32_egl);
@@ -742,32 +643,11 @@ static void *gfx_ctx_wgl_init(void *video_driver)
win32_window_reset();
win32_monitor_init();
- switch (win32_api)
- {
- case GFX_CTX_VULKAN_API:
- wndclass.lpfnWndProc = WndProcVK;
- break;
- default:
- wndclass.lpfnWndProc = WndProcWGL;
- break;
- }
+ wndclass.lpfnWndProc = WndProcWGL;
if (!win32_window_init(&wndclass, true, NULL))
goto error;
- switch (win32_api)
- {
- case GFX_CTX_VULKAN_API:
-#ifdef HAVE_VULKAN
- if (!vulkan_context_init(&win32_vk, VULKAN_WSI_WIN32))
- goto error;
-#endif
- break;
- case GFX_CTX_NONE:
- default:
- break;
- }
-
return wgl;
error:
@@ -780,10 +660,6 @@ static bool gfx_ctx_wgl_set_video_mode(void *data,
unsigned width, unsigned height,
bool fullscreen)
{
-#ifdef HAVE_VULKAN
- win32_vk.fullscreen = fullscreen;
-#endif
-
if (!win32_set_video_mode(NULL, width, height, fullscreen))
{
RARCH_ERR("[WGL]: win32_set_video_mode failed.\n");
@@ -861,10 +737,6 @@ static bool gfx_ctx_wgl_bind_api(void *data,
if (api == GFX_CTX_OPENGL_ES_API)
return true;
#endif
-#if defined(HAVE_VULKAN)
- if (api == GFX_CTX_VULKAN_API)
- return true;
-#endif
return false;
}
@@ -899,14 +771,6 @@ static void gfx_ctx_wgl_bind_hw_render(void *data, bool enable)
}
}
-#ifdef HAVE_VULKAN
-static void *gfx_ctx_wgl_get_context_data(void *data)
-{
- (void)data;
- return &win32_vk.context;
-}
-#endif
-
static uint32_t gfx_ctx_wgl_get_flags(void *data)
{
uint32_t flags = 0;
@@ -939,11 +803,6 @@ static uint32_t gfx_ctx_wgl_get_flags(void *data)
}
break;
- case GFX_CTX_VULKAN_API:
-#if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS)
- BIT32_SET(flags, GFX_CTX_FLAGS_SHADERS_SLANG);
-#endif
- break;
case GFX_CTX_OPENGL_ES_API:
#if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS)
@@ -1026,10 +885,6 @@ const gfx_ctx_driver_t gfx_ctx_wgl = {
gfx_ctx_wgl_get_flags,
gfx_ctx_wgl_set_flags,
gfx_ctx_wgl_bind_hw_render,
-#ifdef HAVE_VULKAN
- gfx_ctx_wgl_get_context_data,
-#else
NULL,
-#endif
NULL
};
diff --git a/griffin/griffin.c b/griffin/griffin.c
index a94a3db079..f5b538f2fc 100644
--- a/griffin/griffin.c
+++ b/griffin/griffin.c
@@ -230,6 +230,9 @@ VIDEO CONTEXT
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGL1) || defined(HAVE_VULKAN) || defined(HAVE_OPENGLES)
#include "../gfx/drivers_context/wgl_ctx.c"
#endif
+#if defined(HAVE_VULKAN)
+#include "../gfx/drivers_context/w_vk_ctx.c"
+#endif
#include "../gfx/display_servers/dispserv_win32.c"
diff --git a/retroarch.c b/retroarch.c
index c7123c2d4b..899b013b5b 100644
--- a/retroarch.c
+++ b/retroarch.c
@@ -575,6 +575,14 @@ static const video_driver_t *video_drivers[] = {
NULL,
};
+static const gfx_ctx_driver_t *gfx_ctx_vk_drivers[] = {
+#if defined(_WIN32) && !defined(__WINRT__) && (defined(HAVE_VULKAN))
+ &gfx_ctx_w_vk,
+#endif
+ &gfx_ctx_null,
+ NULL
+};
+
static const gfx_ctx_driver_t *gfx_ctx_gl_drivers[] = {
#if defined(ORBIS)
&orbis_ctx,
@@ -600,7 +608,7 @@ static const gfx_ctx_driver_t *gfx_ctx_gl_drivers[] = {
#if defined(HAVE_OPENDINGUX_FBDEV)
&gfx_ctx_opendingux_fbdev,
#endif
-#if defined(_WIN32) && !defined(__WINRT__) && (defined(HAVE_OPENGL) || defined(HAVE_OPENGL1) || defined(HAVE_OPENGL_CORE) || defined(HAVE_VULKAN))
+#if defined(_WIN32) && !defined(__WINRT__) && (defined(HAVE_OPENGL) || defined(HAVE_OPENGL1) || defined(HAVE_OPENGL_CORE))
&gfx_ctx_wgl,
#endif
#if defined(__WINRT__) && defined(HAVE_OPENGLES)
@@ -33031,6 +33039,51 @@ static const gfx_ctx_driver_t *video_context_driver_init(
return ctx;
}
+static const gfx_ctx_driver_t *vk_context_driver_init_first(void *data,
+ const char *ident, enum gfx_ctx_api api, unsigned major,
+ unsigned minor, bool hw_render_ctx, void **ctx_data)
+{
+ unsigned j;
+ struct rarch_state *p_rarch = &rarch_st;
+ int i = -1;
+
+ for (j = 0; gfx_ctx_vk_drivers[j]; j++)
+ {
+ if (string_is_equal_noncase(ident, gfx_ctx_vk_drivers[j]->ident))
+ {
+ i = j;
+ break;
+ }
+ }
+
+ if (i >= 0)
+ {
+ const gfx_ctx_driver_t *ctx = video_context_driver_init(data,
+ gfx_ctx_vk_drivers[i], ident,
+ api, major, minor, hw_render_ctx, ctx_data);
+ if (ctx)
+ {
+ p_rarch->video_context_data = *ctx_data;
+ return ctx;
+ }
+ }
+
+ for (i = 0; gfx_ctx_vk_drivers[i]; i++)
+ {
+ const gfx_ctx_driver_t *ctx =
+ video_context_driver_init(data, gfx_ctx_vk_drivers[i], ident,
+ api, major, minor, hw_render_ctx, ctx_data);
+
+ if (ctx)
+ {
+ p_rarch->video_context_data = *ctx_data;
+ return ctx;
+ }
+ }
+
+ return NULL;
+}
+
static const gfx_ctx_driver_t *gl_context_driver_init_first(void *data,
const char *ident, enum gfx_ctx_api api, unsigned major,
unsigned minor, bool hw_render_ctx, void **ctx_data)
@@ -33096,10 +33149,17 @@ const gfx_ctx_driver_t *video_context_driver_init_first(void *data,
{
switch (api)
{
+ case GFX_CTX_VULKAN_API:
+ {
+ const gfx_ctx_driver_t *ptr = vk_context_driver_init_first(
+ data, ident, api, major, minor, hw_render_ctx, ctx_data);
+ if (ptr && !string_is_equal(ptr->ident, "null"))
+ return ptr;
+ /* fall-through if no valid driver was found */
+ }
case GFX_CTX_OPENGL_API:
case GFX_CTX_OPENGL_ES_API:
case GFX_CTX_OPENVG_API:
- case GFX_CTX_VULKAN_API:
case GFX_CTX_METAL_API:
return gl_context_driver_init_first(data, ident, api, major, minor,
hw_render_ctx, ctx_data);
diff --git a/retroarch.h b/retroarch.h
index a7ab2972a3..a94a65fcc8 100644
--- a/retroarch.h
+++ b/retroarch.h
@@ -1893,6 +1893,7 @@ extern const gfx_ctx_driver_t gfx_ctx_mali_fbdev;
extern const gfx_ctx_driver_t gfx_ctx_vivante_fbdev;
extern const gfx_ctx_driver_t gfx_ctx_android;
extern const gfx_ctx_driver_t gfx_ctx_ps3;
+extern const gfx_ctx_driver_t gfx_ctx_w_vk;
extern const gfx_ctx_driver_t gfx_ctx_wgl;
extern const gfx_ctx_driver_t gfx_ctx_videocore;
extern const gfx_ctx_driver_t gfx_ctx_qnx;