diff --git a/Makefile.common b/Makefile.common index 9050d0f349..2780dedd24 100644 --- a/Makefile.common +++ b/Makefile.common @@ -741,11 +741,12 @@ ifeq ($(HAVE_SDL2), 1) endif ifeq ($(HAVE_VULKAN), 1) - ifeq ($(platform), win) + ifneq ($(findstring Win32,$(OS)),) GLSLANG_PLATFORM := Windows else GLSLANG_PLATFORM := Unix endif + GLSLANG_SOURCES := \ $(wildcard deps/glslang/*.cpp) \ $(wildcard deps/glslang/glslang/SPIRV/*.cpp) \ @@ -756,9 +757,14 @@ ifeq ($(HAVE_VULKAN), 1) $(wildcard deps/glslang/glslang/glslang/OSDependent/$(GLSLANG_PLATFORM)/*.cpp) SPIRV_CROSS_SOURCES := deps/SPIRV-Cross/spirv_cross.cpp + ifneq ($(findstring Win32,$(OS)),) + # Trivial temporary workaround for MinGW and glslang. + CXXFLAGS += -fpermissive + endif DEFINES += \ -Ideps/glslang/glslang/glslang/OSDependent/$(GLSLANG_PLATFORM) \ + -Ideps/glslang/glslang/OGLCompilersDLL \ -Ideps/glslang/glslang \ -Ideps/glslang/glslang/glslang/MachineIndependent \ -Ideps/glslang/glslang/glslang/Public \ @@ -766,8 +772,8 @@ ifeq ($(HAVE_VULKAN), 1) -Ideps/glslang \ -Ideps/SPIRV-Cross - CXXFLAGS += -Wno-switch -Wno-sign-compare -fno-strict-aliasing -Wno-maybe-uninitialized -Wno-reorder -I./gfx/include/vulkan - CFLAGS += -I./gfx/include/vulkan + CXXFLAGS += -Wno-switch -Wno-sign-compare -fno-strict-aliasing -Wno-maybe-uninitialized -Wno-reorder -Igfx/include + CFLAGS += -Igfx/include GLSLANG_OBJ := $(GLSLANG_SOURCES:.cpp=.o) SPIRV_CROSS_OBJ := $(SPIRV_CROSS_SOURCES:.cpp=.o) diff --git a/gfx/common/vulkan_common.c b/gfx/common/vulkan_common.c index 6a205c6638..5d86fa9c74 100644 --- a/gfx/common/vulkan_common.c +++ b/gfx/common/vulkan_common.c @@ -1261,7 +1261,10 @@ bool vulkan_context_init(gfx_ctx_vulkan_data_t *vk, #endif if (!vulkan_library) + { + RARCH_ERR("[Vulkan]: Failed to open Vulkan loader.\n"); return false; + } RARCH_LOG("Vulkan dynamic library loaded.\n"); @@ -1306,19 +1309,31 @@ bool vulkan_context_init(gfx_ctx_vulkan_data_t *vk, } if (!vulkan_load_instance_symbols(vk)) + { + RARCH_ERR("[Vulkan]: Failed to load instance symbols.\n"); return false; + } if (VKFUNC(vkEnumeratePhysicalDevices)(vk->context.instance, &gpu_count, NULL) != VK_SUCCESS) + { + RARCH_ERR("[Vulkan]: Failed to enumerate physical devices.\n"); return false; + } gpus = (VkPhysicalDevice*)calloc(gpu_count, sizeof(*gpus)); if (!gpus) + { + RARCH_ERR("[Vulkan]: Failed to enumerate physical devices.\n"); return false; + } if (VKFUNC(vkEnumeratePhysicalDevices)(vk->context.instance, &gpu_count, gpus) != VK_SUCCESS) + { + RARCH_ERR("[Vulkan]: Failed to enumerate physical devices.\n"); return false; + } if (gpu_count < 1) { @@ -1338,7 +1353,10 @@ bool vulkan_context_init(gfx_ctx_vulkan_data_t *vk, &queue_count, NULL); if (queue_count < 1 || queue_count > 32) + { + RARCH_ERR("[Vulkan]: Invalid number of queues detected.\n"); return false; + } VKFUNC(vkGetPhysicalDeviceQueueFamilyProperties)(vk->context.gpu, &queue_count, queue_properties); @@ -1382,10 +1400,16 @@ bool vulkan_context_init(gfx_ctx_vulkan_data_t *vk, } else if (VKFUNC(vkCreateDevice)(vk->context.gpu, &device_info, NULL, &vk->context.device) != VK_SUCCESS) + { + RARCH_ERR("[Vulkan]: Failed to create device.\n"); return false; + } if (!vulkan_load_device_symbols(vk)) + { + RARCH_ERR("[Vulkan]: Failed to load device symbols.\n"); return false; + } VKFUNC(vkGetDeviceQueue)(vk->context.device, vk->context.graphics_queue_index, 0, &vk->context.queue); @@ -1430,7 +1454,10 @@ bool vulkan_context_init(gfx_ctx_vulkan_data_t *vk, #ifdef HAVE_THREADS vk->context.queue_lock = slock_new(); if (!vk->context.queue_lock) + { + RARCH_ERR("[Vulkan]: Failed to create queue lock.\n"); return false; + } #endif return true; @@ -1489,8 +1516,8 @@ bool vulkan_surface_create(gfx_ctx_vulkan_data_t *vk, surf_info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; surf_info.flags = 0; - surf_info.hinstance = display; - surf_info.hwnd = surface; + surf_info.hinstance = *(const HINSTANCE*)display; + surf_info.hwnd = *(const HWND*)surface; if (VKFUNC(vkCreateWin32SurfaceKHR)(vk->context.instance, &surf_info, NULL, &vk->vk_surface) != VK_SUCCESS) @@ -1776,10 +1803,17 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - VKFUNC(vkCreateSwapchainKHR)(vk->context.device, &info, NULL, &vk->swapchain); + if (VKFUNC(vkCreateSwapchainKHR)(vk->context.device, &info, NULL, &vk->swapchain) != VK_SUCCESS) + { + RARCH_ERR("[Vulkan]: Failed to create swapchain.\n"); + return false; + } if (old_swapchain != VK_NULL_HANDLE) + { + RARCH_LOG("[Vulkan]: Recycled old swapchain.\n"); VKFUNC(vkDestroySwapchainKHR)(vk->context.device, old_swapchain, NULL); + } vk->context.swapchain_width = swapchain_size.width; vk->context.swapchain_height = swapchain_size.height; diff --git a/gfx/common/vulkan_common.h b/gfx/common/vulkan_common.h index 13d0f0b6d9..0bfc9c4d17 100644 --- a/gfx/common/vulkan_common.h +++ b/gfx/common/vulkan_common.h @@ -48,6 +48,10 @@ #include "../video_context_driver.h" #include "../drivers_shader/shader_vulkan.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct vulkan_filter_chain vulkan_filter_chain_t; enum vk_texture_type @@ -505,5 +509,9 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, unsigned width, unsigned height, unsigned swap_interval); +#ifdef __cplusplus +} +#endif + #endif diff --git a/gfx/common/win32_common.cpp b/gfx/common/win32_common.cpp index 3110071eff..d257521408 100644 --- a/gfx/common/win32_common.cpp +++ b/gfx/common/win32_common.cpp @@ -228,7 +228,7 @@ LRESULT CALLBACK WndProcD3D(HWND hwnd, UINT message, return 0; } - if (dinput_handle_message(dinput, message, wparam, lparam)) + if (dinput && dinput_handle_message(dinput, message, wparam, lparam)) return 0; return DefWindowProc(hwnd, message, wparam, lparam); } @@ -258,11 +258,11 @@ LRESULT CALLBACK WndProcGL(HWND hwnd, UINT message, return ret; break; case WM_CREATE: - create_gl_context(hwnd, &g_quit); + create_graphics_context(hwnd, &g_quit); return 0; } - if (dinput_handle_message(dinput_wgl, message, wparam, lparam)) + if (dinput_wgl && dinput_handle_message(dinput_wgl, message, wparam, lparam)) return 0; return DefWindowProc(hwnd, message, wparam, lparam); } diff --git a/gfx/common/win32_common.h b/gfx/common/win32_common.h index 99661115c2..741e70e506 100644 --- a/gfx/common/win32_common.h +++ b/gfx/common/win32_common.h @@ -47,7 +47,7 @@ void win32_monitor_get_info(void); void win32_monitor_info(void *data, void *hm_data, unsigned *mon_id); -void create_gl_context(HWND hwnd, bool *quit); +void create_graphics_context(HWND hwnd, bool *quit); bool win32_shader_dlg_init(void); void shader_dlg_show(HWND parent_hwnd); diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index c46ea440e5..d19ac54d01 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -983,7 +983,10 @@ static void *vulkan_init(const video_info_t *video, ctx_driver = vulkan_get_context(vk); if (!ctx_driver) + { + RARCH_ERR("[Vulkan]: Failed to get Vulkan context.\n"); goto error; + } video_context_driver_set((const gfx_ctx_driver_t*)ctx_driver); @@ -1009,8 +1012,12 @@ static void *vulkan_init(const video_info_t *video, mode.width = win_width; mode.height = win_height; mode.fullscreen = video->fullscreen; + if (!video_context_driver_set_video_mode(&mode)) + { + RARCH_ERR("[Vulkan]: Failed to set video mode.\n"); goto error; + } video_context_driver_get_video_size(&mode); temp_width = mode.width; @@ -1042,7 +1049,10 @@ static void *vulkan_init(const video_info_t *video, vulkan_init_resources(vk); if (!vulkan_init_filter_chain(vk)) + { + RARCH_ERR("[Vulkan]: Failed to init filter chain.\n"); goto error; + } inp.input = input; inp.input_data = input_data; diff --git a/gfx/drivers_context/wgl_ctx.cpp b/gfx/drivers_context/wgl_ctx.cpp index d8b687b7f1..71ef8df06e 100644 --- a/gfx/drivers_context/wgl_ctx.cpp +++ b/gfx/drivers_context/wgl_ctx.cpp @@ -39,6 +39,10 @@ #include "../common/gl_common.h" #include "../common/win32_common.h" +#ifdef HAVE_VULKAN +#include "../common/vulkan_common.h" +#endif + #ifndef WGL_CONTEXT_MAJOR_VERSION_ARB #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 #endif @@ -72,8 +76,13 @@ static HGLRC g_hw_hrc; static HDC g_hdc; static bool g_core_hw_context_enable; +#ifdef HAVE_VULKAN +static gfx_ctx_vulkan_data_t g_vk; +#endif + static unsigned g_major; static unsigned g_minor; +static enum gfx_ctx_api g_api; static unsigned g_interval; @@ -96,7 +105,7 @@ static void setup_pixel_format(HDC hdc) SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd); } -void create_gl_context(HWND hwnd, bool *quit) +static void create_gl_context(HWND hwnd, bool *quit) { bool core_context; struct retro_hw_render_callback *hwr = NULL; @@ -220,6 +229,37 @@ void create_gl_context(HWND hwnd, bool *quit) } } +void create_graphics_context(HWND hwnd, bool *quit) +{ + switch (g_api) + { + case GFX_CTX_OPENGL_API: + create_gl_context(hwnd, quit); + break; + + case GFX_CTX_VULKAN_API: + { +#ifdef HAVE_VULKAN + RECT rect; + unsigned width = rect.right - rect.left; + unsigned height = rect.bottom - rect.top; + GetClientRect(hwnd, &rect); + HINSTANCE instance = GetModuleHandle(NULL); + if (!vulkan_surface_create(&g_vk, VULKAN_WSI_WIN32, + &instance, &hwnd, + width, height, g_interval)) + *quit = true; + g_inited = true; + break; +#endif + } + + case GFX_CTX_NONE: + default: + break; + } +} + void *dinput_wgl; static void gfx_ctx_wgl_swap_interval(void *data, unsigned interval) @@ -227,26 +267,81 @@ static void gfx_ctx_wgl_swap_interval(void *data, unsigned interval) (void)data; g_interval = interval; - if (!g_hrc) - return; - if (!p_swap_interval) - return; + switch (g_api) + { + case GFX_CTX_OPENGL_API: +#ifdef HAVE_OPENGL + if (!g_hrc) + return; + if (!p_swap_interval) + return; - RARCH_LOG("[WGL]: wglSwapInterval(%u)\n", g_interval); - if (!p_swap_interval(g_interval)) - RARCH_WARN("[WGL]: wglSwapInterval() failed.\n"); + RARCH_LOG("[WGL]: wglSwapInterval(%u)\n", g_interval); + if (!p_swap_interval(g_interval)) + RARCH_WARN("[WGL]: wglSwapInterval() failed.\n"); +#endif + break; + + case GFX_CTX_VULKAN_API: +#ifdef HAVE_VULKAN + if (g_interval != interval) + { + g_interval = interval; + if (g_vk.swapchain) + g_vk.need_new_swapchain = true; + } +#endif + break; + + case GFX_CTX_NONE: + default: + break; + } } static void gfx_ctx_wgl_check_window(void *data, bool *quit, bool *resize, unsigned *width, unsigned *height, unsigned frame_count) { win32_check_window(quit, resize, width, height); + + switch (g_api) + { + case GFX_CTX_VULKAN_API: +#ifdef HAVE_VULKAN + if (g_vk.need_new_swapchain) + *resize = true; +#endif + break; + + case GFX_CTX_NONE: + default: + break; + } } static void gfx_ctx_wgl_swap_buffers(void *data) { (void)data; - SwapBuffers(g_hdc); + + switch (g_api) + { + case GFX_CTX_OPENGL_API: +#ifdef HAVE_OPENGL + SwapBuffers(g_hdc); + break; +#endif + + case GFX_CTX_VULKAN_API: +#ifdef HAVE_VULKAN + vulkan_present(&g_vk, g_vk.context.current_swapchain_index); + vulkan_acquire_next_image(&g_vk); +#endif + break; + + case GFX_CTX_NONE: + default: + break; + } } static bool gfx_ctx_wgl_set_resize(void *data, @@ -255,6 +350,27 @@ static bool gfx_ctx_wgl_set_resize(void *data, (void)data; (void)width; (void)height; + + switch (g_api) + { + case GFX_CTX_VULKAN_API: +#ifdef HAVE_VULKAN + if (!vulkan_create_swapchain(&g_vk, width, height, g_interval)) + { + RARCH_ERR("[Win32/Vulkan]: Failed to update swapchain.\n"); + return false; + } + + g_vk.context.invalid_swapchain = true; + g_vk.need_new_swapchain = false; +#endif + break; + + case GFX_CTX_NONE: + default: + break; + } + return false; } @@ -315,6 +431,16 @@ static void *gfx_ctx_wgl_init(void *video_driver) if (!win32_window_init(&wndclass, true, NULL)) return NULL; + switch (g_api) + { + case GFX_CTX_VULKAN_API: +#ifdef HAVE_VULKAN + if (!vulkan_context_init(&g_vk, VULKAN_WSI_WIN32)) + return NULL; +#endif + break; + } + return (void*)"wgl"; } @@ -324,19 +450,39 @@ static void gfx_ctx_wgl_destroy(void *data) (void)data; - if (g_hrc) + switch (g_api) { - glFinish(); - wglMakeCurrent(NULL, NULL); + case GFX_CTX_OPENGL_API: +#ifdef HAVE_OPENGL + if (g_hrc) + { + glFinish(); + wglMakeCurrent(NULL, NULL); - if (!video_driver_is_video_cache_context()) - { - if (g_hw_hrc) - wglDeleteContext(g_hw_hrc); - wglDeleteContext(g_hrc); - g_hrc = NULL; - g_hw_hrc = NULL; - } + if (!video_driver_is_video_cache_context()) + { + if (g_hw_hrc) + wglDeleteContext(g_hw_hrc); + wglDeleteContext(g_hrc); + g_hrc = NULL; + g_hw_hrc = NULL; + } + } +#endif + break; + + case GFX_CTX_VULKAN_API: +#ifdef HAVE_VULKAN + vulkan_context_destroy(&g_vk, g_vk.vk_surface != VK_NULL_HANDLE); + if (g_vk.context.queue_lock) + slock_free(g_vk.context.queue_lock); + memset(&g_vk, 0, sizeof(g_vk)); +#endif + break; + + case GFX_CTX_NONE: + default: + break; } if (window && g_hdc) @@ -369,13 +515,26 @@ static bool gfx_ctx_wgl_set_video_mode(void *data, bool fullscreen) { if (!win32_set_video_mode(NULL, width, height, fullscreen)) + { + RARCH_ERR("[WGL]: win32_set_video_mode failed.\n"); goto error; + } - p_swap_interval = (BOOL (APIENTRY *)(int)) - wglGetProcAddress("wglSwapIntervalEXT"); + switch (g_api) + { + case GFX_CTX_OPENGL_API: +#ifdef HAVE_OPENGL + p_swap_interval = (BOOL (APIENTRY *)(int)) + wglGetProcAddress("wglSwapIntervalEXT"); +#endif + break; + + case GFX_CTX_NONE: + default: + break; + } gfx_ctx_wgl_swap_interval(data, g_interval); - return true; error: @@ -433,8 +592,9 @@ static bool gfx_ctx_wgl_bind_api(void *data, g_major = major; g_minor = minor; + g_api = api; - return api == GFX_CTX_OPENGL_API; + return api == GFX_CTX_OPENGL_API || api == GFX_CTX_VULKAN_API; } static void gfx_ctx_wgl_show_mouse(void *data, bool state) @@ -445,12 +605,31 @@ static void gfx_ctx_wgl_show_mouse(void *data, bool state) static void gfx_ctx_wgl_bind_hw_render(void *data, bool enable) { - g_use_hw_ctx = enable; + switch (g_api) + { + case GFX_CTX_OPENGL_API: +#ifdef HAVE_OPENGL + g_use_hw_ctx = enable; - if (g_hdc) - wglMakeCurrent(g_hdc, enable ? g_hw_hrc : g_hrc); + if (g_hdc) + wglMakeCurrent(g_hdc, enable ? g_hw_hrc : g_hrc); +#endif + break; + + case GFX_CTX_NONE: + default: + break; + } } +#ifdef HAVE_VULKAN +static void *gfx_ctx_wgl_get_context_data(void *data) +{ + (void)data; + return &g_vk.context; +} +#endif + static uint32_t gfx_ctx_wgl_get_flags(void *data) { uint32_t flags = 0; @@ -498,6 +677,11 @@ const gfx_ctx_driver_t gfx_ctx_wgl = { "wgl", gfx_ctx_wgl_get_flags, gfx_ctx_wgl_set_flags, - gfx_ctx_wgl_bind_hw_render + gfx_ctx_wgl_bind_hw_render, +#ifdef HAVE_VULKAN + gfx_ctx_wgl_get_context_data, +#else + NULL, +#endif }; diff --git a/libretro-common/net/net_ifinfo.c b/libretro-common/net/net_ifinfo.c index 806032978b..63bbb90413 100644 --- a/libretro-common/net/net_ifinfo.c +++ b/libretro-common/net/net_ifinfo.c @@ -28,8 +28,8 @@ #if defined(_WIN32) && !defined(_XBOX) #include -#include -#include +#include +#include #else #include #include diff --git a/qb/config.libs.sh b/qb/config.libs.sh index 01859e8ede..d4501becbb 100644 --- a/qb/config.libs.sh +++ b/qb/config.libs.sh @@ -395,7 +395,6 @@ if [ "$OS" != 'Win32' ]; then fi check_lib STRCASESTR "$CLIB" strcasestr check_lib MMAP "$CLIB" mmap -check_lib VULKAN -lvulkan vkCreateInstance if [ "$HAVE_VULKAN" != 'no' ] && [ ! -e deps/glslang/glslang/README.md ]; then echo "Warning: glslang submodule not loaded, can't use Vulkan." diff --git a/qb/config.params.sh b/qb/config.params.sh index 7f89043a61..fa0f741b78 100644 --- a/qb/config.params.sh +++ b/qb/config.params.sh @@ -75,7 +75,7 @@ HAVE_MMAP=auto # MMAP support HAVE_QT=no # QT companion support HAVE_XSHM=no # XShm video driver support (disabled because it's just a dummied out stub) HAVE_CHEEVOS=yes # Retro Achievements -HAVE_VULKAN=auto # Vulkan support +HAVE_VULKAN=no # Vulkan support C89_VULKAN=no HAVE_RPNG=yes # RPNG support HAVE_RJPEG=yes # RJPEG support