From ff03ef66919c17ffbf46292783fe64fe51af41f1 Mon Sep 17 00:00:00 2001 From: SupinePandora43 Date: Wed, 21 Jul 2021 12:56:34 +0500 Subject: [PATCH 1/4] initial --- .gitignore | 2 + src/linux/AppGLFW.cpp | 9 ++- src/linux/WindowGLFW.cpp | 4 +- src/linux/vulkan/GPUContextVK.cpp | 96 +++++++++++++++++++++++++++++++ src/linux/vulkan/GPUContextVK.h | 48 ++++++++++++++++ src/linux/vulkan/GPUDriverVK.cpp | 0 src/linux/vulkan/GPUDriverVK.h | 0 7 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 src/linux/vulkan/GPUContextVK.cpp create mode 100644 src/linux/vulkan/GPUContextVK.h create mode 100644 src/linux/vulkan/GPUDriverVK.cpp create mode 100644 src/linux/vulkan/GPUDriverVK.h diff --git a/.gitignore b/.gitignore index 276f347..a16fda7 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ build_*/ .DS_Store /deps/ .directory +.cache +CMakeFiles diff --git a/src/linux/AppGLFW.cpp b/src/linux/AppGLFW.cpp index a5ea9df..4a5eac2 100644 --- a/src/linux/AppGLFW.cpp +++ b/src/linux/AppGLFW.cpp @@ -1,4 +1,6 @@ #include "AppGLFW.h" +#include "vulkan/GPUContextVK.h" +#include "vulkan/GPUDriverVK.h" #include "gl/GPUContextGL.h" #include "gl/GPUDriverGL.h" #include @@ -100,8 +102,11 @@ AppGLFW::AppGLFW(Settings settings, Config config) : settings_(settings) { clipboard_.reset(new ClipboardGLFW()); Platform::instance().set_clipboard(clipboard_.get()); - - gpu_context_.reset(new GPUContextGL(true, false)); + if (glfwVulkanSupported()){ + gpu_context_.reset((GPUContextGL*)new GPUContextVK(true, false)); + }else { + gpu_context_.reset(new GPUContextGL(true, false)); + } Platform::instance().set_gpu_driver(gpu_context_->driver()); // We use the GPUContext's global offscreen window to maintain diff --git a/src/linux/WindowGLFW.cpp b/src/linux/WindowGLFW.cpp index 0d97a75..d6eabd3 100644 --- a/src/linux/WindowGLFW.cpp +++ b/src/linux/WindowGLFW.cpp @@ -149,7 +149,9 @@ WindowGLFW::WindowGLFW(Monitor* monitor, uint32_t width, uint32_t height, glfwTerminate(); exit(EXIT_FAILURE); } - + if (glfwVulkanSupported()){ + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); // do not create GL context + } // This window will share the GL context of GPUContextGL's offscreen window GLFWwindow* win = glfwCreateWindow(ScreenToPixels(width), ScreenToPixels(height), "", NULL, gpu_context->window()); diff --git a/src/linux/vulkan/GPUContextVK.cpp b/src/linux/vulkan/GPUContextVK.cpp new file mode 100644 index 0000000..eb5632c --- /dev/null +++ b/src/linux/vulkan/GPUContextVK.cpp @@ -0,0 +1,96 @@ +#include "GPUContextVK.h" +#include "GPUDriverVK.h" +#include +#include +#include + +namespace ultralight { + +GPUContextVK::GPUContextVK(bool enable_vsync, bool enable_msaa) : msaa_enabled_(enable_msaa) { + + std::vector instance_layers; + std::vector instance_extensions; + std::vector device_extensions; + + // SUPINE for debug + instance_layers.push_back("VK_LAYER_LUNARG_standard_validation"); + instance_extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); + + device_extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); // make sure we can display anything + + uint32_t instance_extension_count = 0; + const char** instance_extensions_buffer = glfwGetRequiredInstanceExtensions(&instance_extension_count); + for (uint32_t i = 0; i < instance_extension_count; ++i) { + instance_extensions.push_back(instance_extensions_buffer[i]); + } + + VkApplicationInfo application_info {}; + application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + application_info.apiVersion = VK_MAKE_VERSION(1, 0, 2); + application_info.applicationVersion = VK_MAKE_VERSION(0, 0, 1); + application_info.engineVersion = VK_MAKE_VERSION(0, 0, 1); + application_info.pApplicationName = "GLFW with Vulkan"; + application_info.pEngineName = "GLFW with Vulkan"; + + VkInstanceCreateInfo instance_create_info {}; + instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + instance_create_info.pApplicationInfo = &application_info; + instance_create_info.enabledLayerCount = instance_layers.size(); + instance_create_info.ppEnabledLayerNames = instance_layers.data(); + instance_create_info.enabledExtensionCount = instance_extensions.size(); + instance_create_info.ppEnabledExtensionNames = instance_extensions.data(); + + VkInstance instance = VK_NULL_HANDLE; + vkCreateInstance(&instance_create_info, nullptr, &instance); + this->instance = instance; + + // Get GPUs + uint32_t GPU_count; + vkEnumeratePhysicalDevices(instance, &GPU_count, nullptr); + std::vector GPUs(GPU_count); + vkEnumeratePhysicalDevices(instance, &GPU_count, GPUs.data()); + + uint32_t queue_family_count; + vkGetPhysicalDeviceQueueFamilyProperties(GPUs[0], &queue_family_count, nullptr); + std::vector family_properties(queue_family_count); + vkGetPhysicalDeviceQueueFamilyProperties(GPUs[0], &queue_family_count, family_properties.data()); + + uint32_t graphics_queue_family = UINT32_MAX; + for (uint32_t i = 0; i < queue_family_count; ++i) { + if (family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { + graphics_queue_family = i; + } + } + if (graphics_queue_family == UINT32_MAX) { + // queue family not found + glfwTerminate(); + } + // graphics_queue_family now contains queue family ID which supports graphics + + // Create Vulkan device + const float priorities[] { 1.0f }; + VkDeviceQueueCreateInfo queue_create_info {}; + queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queue_create_info.queueCount = 1; + queue_create_info.queueFamilyIndex = graphics_queue_family; + queue_create_info.pQueuePriorities = priorities; + + VkDeviceCreateInfo device_create_info {}; + device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + device_create_info.queueCreateInfoCount = 1; + device_create_info.pQueueCreateInfos = &queue_create_info; + device_create_info.enabledLayerCount = device_extensions.size(); + device_create_info.ppEnabledExtensionNames = device_extensions.data(); + + VkDevice device = VK_NULL_HANDLE; + vkCreateDevice(GPUs[0], &device_create_info, nullptr, &device); + + this->device = device; +} + +GPUContextVK::~GPUContextVK(){ + vkDestroyDevice( device, nullptr ); + vkDestroyInstance( instance, nullptr ); +} + +} // namespace ultralight \ No newline at end of file diff --git a/src/linux/vulkan/GPUContextVK.h b/src/linux/vulkan/GPUContextVK.h new file mode 100644 index 0000000..e7ecb45 --- /dev/null +++ b/src/linux/vulkan/GPUContextVK.h @@ -0,0 +1,48 @@ +#pragma once +#include +#include +#include "GPUDriverImpl.h" +#include +#include + +typedef struct GLFWwindow GLFWwindow; + +namespace ultralight { + +class GPUContextVK { +protected: + std::unique_ptr driver_; + GLFWwindow* window_; + GLFWwindow* active_window_ = nullptr; + bool msaa_enabled_; +public: + GPUContextVK(bool enable_vsync, bool enable_msaa); + + virtual ~GPUContextVK() {} + + virtual ultralight::GPUDriverImpl* driver() const { return driver_.get(); } + + virtual ultralight::FaceWinding face_winding() const { return ultralight::kFaceWinding_CounterClockwise; } + + virtual void BeginDrawing() {} + + virtual void EndDrawing() {} + + virtual bool msaa_enabled() const { return msaa_enabled_; } + + // An offscreen window dedicated to maintaining the OpenGL context. + // All other windows created during lifetime of the app share this context. + virtual GLFWwindow* window() { return window_; } + + // FBOs are not shared across contexts in OpenGL 3.2 (AFAIK), we luckily + // don't need to share them across multiple windows anyways so we temporarily + // set the active GL context to the "active window" when creating FBOs. + virtual void set_active_window(GLFWwindow* win) { active_window_ = win; } + + virtual GLFWwindow* active_window() { return active_window_; } + + VkInstance instance; + VkDevice device; +}; + +} // namespace ultralight \ No newline at end of file diff --git a/src/linux/vulkan/GPUDriverVK.cpp b/src/linux/vulkan/GPUDriverVK.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/linux/vulkan/GPUDriverVK.h b/src/linux/vulkan/GPUDriverVK.h new file mode 100644 index 0000000..e69de29 From c50fade430fe54b3bca5ff4e8f0c47b4856108c6 Mon Sep 17 00:00:00 2001 From: SupinePandora43 Date: Wed, 21 Jul 2021 13:33:26 +0500 Subject: [PATCH 2/4] VkSurfaceKHR --- src/linux/AppGLFW.h | 1 + src/linux/WindowGLFW.cpp | 10 ++++++++++ src/linux/WindowGLFW.h | 4 ++++ src/linux/vulkan/GPUContextVK.h | 2 +- 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/linux/AppGLFW.h b/src/linux/AppGLFW.h index fb3cdac..a5079f2 100644 --- a/src/linux/AppGLFW.h +++ b/src/linux/AppGLFW.h @@ -1,6 +1,7 @@ #pragma once #include #include "gl/GPUContextGL.h" +#include "vulkan/GPUContextVK.h" #include #include "RefCountedImpl.h" #include "MonitorGLFW.h" diff --git a/src/linux/WindowGLFW.cpp b/src/linux/WindowGLFW.cpp index d6eabd3..e475c55 100644 --- a/src/linux/WindowGLFW.cpp +++ b/src/linux/WindowGLFW.cpp @@ -163,6 +163,16 @@ WindowGLFW::WindowGLFW(Monitor* monitor, uint32_t width, uint32_t height, exit(EXIT_FAILURE); } + if (glfwVulkanSupported()){ + VkSurfaceKHR surface = VK_NULL_HANDLE; + VkResult ret = glfwCreateWindowSurface(((GPUContextVK*)gpu_context)->instance, window_, nullptr, &surface); + if(ret != VK_SUCCESS) { + glfwTerminate(); + exit(EXIT_FAILURE); + } + this->surface = surface; + } + glfwSetWindowUserPointer(window_, this); // Bind callbacks diff --git a/src/linux/WindowGLFW.h b/src/linux/WindowGLFW.h index eaba826..f6268de 100644 --- a/src/linux/WindowGLFW.h +++ b/src/linux/WindowGLFW.h @@ -4,6 +4,7 @@ #include "RefCountedImpl.h" #include "OverlayManager.h" #include +#include typedef struct GLFWwindow GLFWwindow; typedef struct GLFWcursor GLFWcursor; @@ -100,6 +101,9 @@ class WindowGLFW : public Window, GLFWcursor* cursor_hresize_; GLFWcursor* cursor_vresize_; bool window_needs_repaint_ = false; + + // Vulkan + VkSurfaceKHR surface = VK_NULL_HANDLE; }; } // namespace ultralight diff --git a/src/linux/vulkan/GPUContextVK.h b/src/linux/vulkan/GPUContextVK.h index e7ecb45..627da90 100644 --- a/src/linux/vulkan/GPUContextVK.h +++ b/src/linux/vulkan/GPUContextVK.h @@ -18,7 +18,7 @@ class GPUContextVK { public: GPUContextVK(bool enable_vsync, bool enable_msaa); - virtual ~GPUContextVK() {} + virtual ~GPUContextVK(); virtual ultralight::GPUDriverImpl* driver() const { return driver_.get(); } From 8df8228e398188d06c4e458c22d322a03a71d053 Mon Sep 17 00:00:00 2001 From: SupinePandora43 Date: Wed, 21 Jul 2021 13:44:44 +0500 Subject: [PATCH 3/4] destroy vksurface on window destruction --- src/linux/WindowGLFW.cpp | 5 +++++ src/linux/vulkan/GPUContextVK.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/linux/WindowGLFW.cpp b/src/linux/WindowGLFW.cpp index e475c55..305d6d0 100644 --- a/src/linux/WindowGLFW.cpp +++ b/src/linux/WindowGLFW.cpp @@ -213,6 +213,11 @@ WindowGLFW::~WindowGLFW() { glfwDestroyCursor(cursor_hresize_); glfwDestroyCursor(cursor_vresize_); + if(glfwVulkanSupported()){ + GPUContextVK* gpu_context = (GPUContextVK*)static_cast(App::instance())->gpu_context(); + vkDestroySurfaceKHR(gpu_context->instance, this->surface, nullptr); + } + glfwDestroyWindow(window_); static_cast(App::instance())->RemoveWindow(this); } diff --git a/src/linux/vulkan/GPUContextVK.h b/src/linux/vulkan/GPUContextVK.h index 627da90..15ae44d 100644 --- a/src/linux/vulkan/GPUContextVK.h +++ b/src/linux/vulkan/GPUContextVK.h @@ -41,6 +41,7 @@ class GPUContextVK { virtual GLFWwindow* active_window() { return active_window_; } + // Vulkan VkInstance instance; VkDevice device; }; From 683dc8a477e9761a57bf309fe5d6af1e0db1d7af Mon Sep 17 00:00:00 2001 From: SupinePandora43 Date: Wed, 21 Jul 2021 16:10:18 +0500 Subject: [PATCH 4/4] link against vulkan --- CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 29b8a35..24e4cba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,10 @@ if (PORT MATCHES "UltralightLinux") option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF) option(GLFW_INSTALL "Generate installation target" OFF) + option(GLFW_VULKAN_STATIC "Use the Vulkan loader statically linked into application" ON) + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGLFW_VULKAN_STATIC=1") + set(GLFW_DIR "src/glfw") add_subdirectory(${GLFW_DIR}) @@ -74,7 +78,7 @@ if (PORT MATCHES "UltralightLinux") include_directories("${GLFW_DIR}/include") include_directories("${GLFW_DIR}/deps") - link_libraries(glfw fontconfig) + link_libraries(glfw fontconfig vulkan) elseif (PORT MATCHES "UltralightMac") link_directories("${ULTRALIGHTCORE_DIR}/bin" "${WEBCORE_DIR}/bin"