Browse Source

Examples: SDL,GLFW,Vulkan: The Platform<>Renderer link is handled by SDL/GLFW platforms, both can compile without Vulkan headers, SDL+Vulkan is now on part with GLFW+Vulkan (aka broken the same way!). (#1542)

omar 7 years ago
parent
commit
d0e0b106f0

+ 34 - 3
examples/imgui_impl_glfw.cpp

@@ -34,6 +34,12 @@
 #define GLFW_EXPOSE_NATIVE_WIN32
 #include <GLFW/glfw3native.h> // for glfwGetWin32Window
 #endif
+#ifdef GLFW_HOVERED
+#define GLFW_HAS_GLFW_HOVERED   1
+#else
+#define GLFW_HAS_GLFW_HOVERED   0
+#endif
+#define GLFW_HAS_VULKAN         (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+
 
 // Data
 enum GlfwClientApi
@@ -437,6 +443,31 @@ static void ImGui_ImplGlfw_SwapBuffers(ImGuiViewport* viewport)
         glfwSwapBuffers(data->Window);
 }
 
+// Vulkan support (the Vulkan renderer needs to call a platform-side support function to create the surface)
+// Avoid including <vulkan.h> so we can build without it
+#if GLFW_HAS_VULKAN
+#ifndef VULKAN_H_
+#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
+#if defined(__LP64__) || defined(_WIN64) || defined(__x86_64__) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
+#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;
+#else
+#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
+#endif
+VK_DEFINE_HANDLE(VkInstance)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR)
+struct VkAllocationCallbacks;
+enum VkResult { VK_RESULT_MAX_ENUM = 0x7FFFFFFF };
+#endif // VULKAN_H_
+extern "C" { extern GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); }
+static int ImGui_ImplGlfw_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_instance, const void* vk_allocator, ImU64* out_vk_surface)
+{
+    ImGuiPlatformDataGlfw* data = (ImGuiPlatformDataGlfw*)viewport->PlatformUserData;
+    IM_ASSERT(g_ClientApi == GlfwClientApi_Vulkan);
+    VkResult err = glfwCreateWindowSurface((VkInstance)vk_instance, data->Window, (const VkAllocationCallbacks*)vk_allocator, (VkSurfaceKHR*)out_vk_surface);
+    return (int)err;
+}
+#endif // GLFW_HAS_VULKAN
+
 static void ImGui_ImplGlfw_InitPlatformInterface()
 {
     // Register platform interface (will be coupled with a renderer interface)
@@ -451,9 +482,9 @@ static void ImGui_ImplGlfw_InitPlatformInterface()
     io.PlatformInterface.SetWindowTitle = ImGui_ImplGlfw_SetWindowTitle;
     io.PlatformInterface.RenderViewport = ImGui_ImplGlfw_RenderViewport;
     io.PlatformInterface.SwapBuffers = ImGui_ImplGlfw_SwapBuffers;
-
-    // We let the user set up the link to glfwCreateWindowSurface() here, so this binding can work with old GLFW and without Vulkan headers
-    io.PlatformInterface.CreateVkSurface = NULL;
+#if GLFW_HAS_VULKAN
+    io.PlatformInterface.CreateVkSurface = ImGui_ImplGlfw_CreateVkSurface;
+#endif
 
     // Register main window handle
     ImGuiViewport* main_viewport = ImGui::GetMainViewport();

+ 31 - 9
examples/imgui_impl_sdl2.cpp

@@ -32,6 +32,9 @@
 // SDL
 #include <SDL.h>
 #include <SDL_syswm.h>
+#define SDL_HAS_CAPTURE_MOUSE   SDL_VERSION_ATLEAST(2,0,4)
+#define SDL_HAS_WINDOW_OPACITY  SDL_VERSION_ATLEAST(2,0,5)
+#define SDL_HAS_VULKAN          SDL_VERSION_ATLEAST(2,0,6)
 
 // Data
 static SDL_Window*  g_Window = NULL;
@@ -151,7 +154,7 @@ bool    ImGui_ImplSDL2_Init(SDL_Window* window, void* sdl_gl_context)
 
     // We need SDL_CaptureMouse(), SDL_GetGlobalMouseState() from SDL 2.0.4+ to support multiple viewports.
     // We left the call to ImGui_ImplSDL2_InitPlatformInterface() outside of #ifdef to avoid unused-function warnings.
-#if SDL_VERSION_ATLEAST(2,0,4)
+#if SDL_HAS_CAPTURE_MOUSE
     io.ConfigFlags |= ImGuiConfigFlags_PlatformHasViewports;
 #endif
     if ((io.ConfigFlags & ImGuiConfigFlags_EnableViewports) && (io.ConfigFlags & ImGuiConfigFlags_PlatformHasViewports))
@@ -185,7 +188,7 @@ static void ImGui_ImplSDL2_UpdateMouse()
     io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
     g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false;
 
-#if SDL_VERSION_ATLEAST(2,0,4)
+#if SDL_HAS_CAPTURE_MOUSE
     SDL_Window* focused_window = SDL_GetKeyboardFocus();
     if (focused_window)
     {
@@ -254,8 +257,6 @@ void ImGui_ImplSDL2_NewFrame(SDL_Window* window)
 // Platform Windows
 // --------------------------------------------------------------------------------------------------------
 
-#define SDL_HAS_WINDOW_OPACITY      SDL_VERSION_ATLEAST(2,0,5)
-
 struct ImGuiPlatformDataSDL2
 {
     SDL_Window*     Window;
@@ -280,12 +281,13 @@ static void ImGui_ImplSDL2_CreateViewport(ImGuiViewport* viewport)
 
     // We don't enable SDL_WINDOW_RESIZABLE because it enforce windows decorations
     Uint32 sdl_flags = 0;
-    sdl_flags |= SDL_WINDOW_OPENGL; // FIXME-PLATFORM
+    sdl_flags |= main_viewport_data->GLContext ? SDL_WINDOW_OPENGL : SDL_WINDOW_VULKAN;
     sdl_flags |= SDL_WINDOW_HIDDEN;
     sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? SDL_WINDOW_BORDERLESS : 0;
     sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? 0 : SDL_WINDOW_RESIZABLE;
     data->Window = SDL_CreateWindow("No Title Yet", 0, 0, (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags);
-    data->GLContext = SDL_GL_CreateContext(data->Window);
+    if (main_viewport_data->GLContext)
+        data->GLContext = SDL_GL_CreateContext(data->Window);
     viewport->PlatformHandle = (void*)data->Window;
 }
 
@@ -374,15 +376,32 @@ static void ImGui_ImplSDL2_SetWindowTitle(ImGuiViewport* viewport, const char* t
 static void ImGui_ImplSDL2_RenderViewport(ImGuiViewport* viewport)
 {
     ImGuiPlatformDataSDL2* data = (ImGuiPlatformDataSDL2*)viewport->PlatformUserData;
-    SDL_GL_MakeCurrent(data->Window, data->GLContext);
+    if (data->GLContext)
+        SDL_GL_MakeCurrent(data->Window, data->GLContext);
 }
 
 static void ImGui_ImplSDL2_SwapBuffers(ImGuiViewport* viewport)
 {
     ImGuiPlatformDataSDL2* data = (ImGuiPlatformDataSDL2*)viewport->PlatformUserData;
-    SDL_GL_MakeCurrent(data->Window, data->GLContext);  // FIXME-PLATFORM2
-    SDL_GL_SwapWindow(data->Window);
+    if (data->GLContext)
+    {
+        SDL_GL_MakeCurrent(data->Window, data->GLContext);  // FIXME-PLATFORM2
+        SDL_GL_SwapWindow(data->Window);
+    }
+}
+
+// Vulkan support (the Vulkan renderer needs to call a platform-side support function to create the surface)
+// SDL is graceful enough to _not_ need <vulkan/vulkan.h> so we can safely include this.
+#if SDL_HAS_VULKAN
+#include <SDL_vulkan.h>
+static int ImGui_ImplSDL2_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_instance, const void* vk_allocator, ImU64* out_vk_surface)
+{
+    ImGuiPlatformDataSDL2* data = (ImGuiPlatformDataSDL2*)viewport->PlatformUserData;
+    (void)vk_allocator;
+    SDL_bool ret = SDL_Vulkan_CreateSurface(data->Window, (VkInstance)vk_instance, (VkSurfaceKHR*)out_vk_surface);
+    return ret ? 0 : 1; // ret ? VK_SUCCESS : VK_NOT_READY 
 }
+#endif // SDL_HAS_VULKAN
 
 static void ImGui_ImplSDL2_InitPlatformInterface(SDL_Window* window, void* sdl_gl_context)
 {
@@ -398,6 +417,9 @@ static void ImGui_ImplSDL2_InitPlatformInterface(SDL_Window* window, void* sdl_g
     io.PlatformInterface.SetWindowTitle = ImGui_ImplSDL2_SetWindowTitle;
     io.PlatformInterface.RenderViewport = ImGui_ImplSDL2_RenderViewport;
     io.PlatformInterface.SwapBuffers = ImGui_ImplSDL2_SwapBuffers;
+#if SDL_HAS_VULKAN
+    io.PlatformInterface.CreateVkSurface = ImGui_ImplSDL2_CreateVkSurface;
+#endif
 
     io.ConfigFlags |= SDL_HAS_WINDOW_OPACITY ? ImGuiConfigFlags_PlatformHasWindowAlpha : 0;
 

+ 1 - 2
examples/imgui_impl_vulkan.cpp

@@ -199,7 +199,6 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory
 void ImGui_ImplVulkan_RenderDrawData(VkCommandBuffer command_buffer, ImDrawData* draw_data)
 {
     VkResult err;
-    ImGuiIO& io = ImGui::GetIO();
     if (draw_data->TotalVtxCount == 0)
         return;
 
@@ -1070,7 +1069,7 @@ static void ImGui_ImplVulkan_CreateViewport(ImGuiViewport* viewport)
 
     // Create surface
     ImGuiIO& io = ImGui::GetIO();
-    VkResult err = (VkResult)io.PlatformInterface.CreateVkSurface(viewport->PlatformHandle, (ImU64)g_Instance, (const void*)g_Allocator, (ImU64*)&wd->Surface);
+    VkResult err = (VkResult)io.PlatformInterface.CreateVkSurface(viewport, (ImU64)g_Instance, (const void*)g_Allocator, (ImU64*)&wd->Surface);
     check_vk_result(err);
 
     // Check for WSI support

+ 0 - 12
examples/vulkan_example/main.cpp

@@ -311,17 +311,6 @@ static void glfw_resize_callback(GLFWwindow*, int w, int h)
 	g_ResizeHeight = h;
 }
 
-static int glfw_create_vk_surface(void* platform_handle, ImU64 vk_instance, const void* vk_allocator, ImU64* out_vk_surface)
-{
-    GLFWwindow* window = (GLFWwindow*)platform_handle;
-    VkInstance instance = (VkInstance)vk_instance;
-    const VkAllocationCallbacks* allocator = (const VkAllocationCallbacks*)vk_allocator;
-    VkSurfaceKHR* surface = (VkSurfaceKHR*)out_vk_surface;
-    VkResult err = glfwCreateWindowSurface(instance, window, allocator, surface);
-    check_vk_result(err);
-    return (int)err;
-}
-
 int main(int, char**)
 {
 	// Setup window
@@ -363,7 +352,6 @@ int main(int, char**)
 
     // Setup GLFW binding
     ImGui_ImplGlfw_InitForVulkan(window, true);
-    io.PlatformInterface.CreateVkSurface = glfw_create_vk_surface;
 
     // Setup Vulkan binding
     ImGui_ImplVulkan_InitInfo init_info = {};

+ 1 - 1
imgui.h

@@ -963,7 +963,7 @@ struct ImGuiPlatformInterface
     void    (*SwapBuffers)(ImGuiViewport* viewport);
 
     // FIXME-VIEWPORT: Experimenting with back-end abstraction. This probably shouldn't stay as is.
-    int     (*CreateVkSurface)(void* platform_handle, ImU64 vk_instance, const void* vk_allocator, ImU64* out_vk_surface);
+    int     (*CreateVkSurface)(ImGuiViewport* viewport, ImU64 vk_instance, const void* vk_allocator, ImU64* out_vk_surface);
 
     // FIXME-DPI
     float   (*GetWindowDpiScale)(ImGuiViewport* viewport);  // (Optional)