mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
[Feat] (MG_Test/Backend/DirectVulkan): add support on macOS
This commit is contained in:
@@ -450,11 +450,18 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
VK_KHR_ANDROID_SURFACE_EXTENSION_NAME
|
||||
#elif defined VK_USE_PLATFORM_WIN32_KHR
|
||||
VK_KHR_WIN32_SURFACE_EXTENSION_NAME
|
||||
#elif defined VK_USE_PLATFORM_METAL_EXT
|
||||
VK_EXT_METAL_SURFACE_EXTENSION_NAME
|
||||
#else
|
||||
#warning "VulkanContext::CreateInstance: VK_KHR_*_surface extension not defined on this platform"
|
||||
#endif
|
||||
}; // TODO: support more platforms
|
||||
|
||||
#if defined(VK_USE_PLATFORM_METAL_EXT)
|
||||
exts.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
|
||||
instanceInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
|
||||
#endif
|
||||
|
||||
if (m_validationLayersEnabled) {
|
||||
exts.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||
}
|
||||
@@ -740,8 +747,31 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
} else {
|
||||
deviceCreateInfo.enabledLayerCount = 0;
|
||||
}
|
||||
deviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(std::size(s_deviceExtensionNames));
|
||||
deviceCreateInfo.ppEnabledExtensionNames = s_deviceExtensionNames;
|
||||
|
||||
Vector<const char*> enabledDeviceExtensions;
|
||||
enabledDeviceExtensions.reserve(std::size(s_deviceExtensionNames) + 1);
|
||||
for (const char* extensionName : s_deviceExtensionNames) {
|
||||
enabledDeviceExtensions.push_back(extensionName);
|
||||
}
|
||||
|
||||
#ifdef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME
|
||||
Uint32 extensionCount = 0;
|
||||
VK_VERIFY(vkEnumerateDeviceExtensionProperties(m_physicalDevice.handle, nullptr, &extensionCount, nullptr));
|
||||
Vector<VkExtensionProperties> availableExtensions(extensionCount);
|
||||
VK_VERIFY(vkEnumerateDeviceExtensionProperties(
|
||||
m_physicalDevice.handle, nullptr, &extensionCount, availableExtensions.data()));
|
||||
|
||||
for (const auto& extension : availableExtensions) {
|
||||
if (strcmp(extension.extensionName, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME) == 0) {
|
||||
enabledDeviceExtensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME);
|
||||
MGLOG_I("Enabled optional device extension: %s", VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
deviceCreateInfo.enabledExtensionCount = static_cast<Uint32>(enabledDeviceExtensions.size());
|
||||
deviceCreateInfo.ppEnabledExtensionNames = enabledDeviceExtensions.data();
|
||||
VK_VERIFY(vkCreateDevice(m_physicalDevice.handle, &deviceCreateInfo, nullptr, &m_device), "vkCreateDevice");
|
||||
MGLOG_I("Logical device created.");
|
||||
|
||||
@@ -1215,6 +1245,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
VkWin32SurfaceCreateInfoKHR sci{VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR};
|
||||
sci.hwnd = hwnd;
|
||||
VK_VERIFY(vkCreateWin32SurfaceKHR(m_instance, &sci, nullptr, &m_surface), "vkCreateWin32SurfaceKHR failed");
|
||||
#elif defined VK_USE_PLATFORM_METAL_EXT
|
||||
MOBILEGL_ASSERT(m_window, "CAMetalLayer is null");
|
||||
|
||||
VkMetalSurfaceCreateInfoEXT sci{VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT};
|
||||
sci.pLayer = reinterpret_cast<const void*>(m_window);
|
||||
VK_VERIFY(vkCreateMetalSurfaceEXT(m_instance, &sci, nullptr, &m_surface), "vkCreateMetalSurfaceEXT failed");
|
||||
#else
|
||||
//#warning "VulkanRenderer::Initialize called on a platform which is not supported yet"
|
||||
MGLOG_W("VulkanRenderer::Initialize called on a platform which is not supported yet"); // TODO: support more
|
||||
|
||||
@@ -46,8 +46,15 @@ TEST(DirectVulkanSanity, WindowCreation) {
|
||||
#include <EGL/egl.h>
|
||||
#ifdef _WIN32
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#elif defined(__APPLE__)
|
||||
#define GLFW_EXPOSE_NATIVE_COCOA
|
||||
#endif
|
||||
#include <GLFW/glfw3native.h>
|
||||
#ifdef __APPLE__
|
||||
#include <objc/message.h>
|
||||
#include <objc/objc.h>
|
||||
#include <objc/runtime.h>
|
||||
#endif
|
||||
TEST(DirectVulkanSanity, ContextCreation) {
|
||||
glfwInit();
|
||||
|
||||
@@ -67,8 +74,26 @@ TEST(DirectVulkanSanity, ContextCreation) {
|
||||
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
GLFWwindow* window = glfwCreateWindow(800, 600, "MobileGL ContextCreation", nullptr, nullptr);
|
||||
EGLNativeWindowType nativewindow = nullptr;
|
||||
#ifdef _WIN32
|
||||
EGLNativeWindowType nativewindow = glfwGetWin32Window(window);
|
||||
nativewindow = glfwGetWin32Window(window);
|
||||
#elif defined(__APPLE__)
|
||||
void* cocoaWindow = glfwGetCocoaWindow(window);
|
||||
ASSERT_NE(cocoaWindow, nullptr);
|
||||
auto msgSendObj = reinterpret_cast<id (*)(id, SEL)>(objc_msgSend);
|
||||
auto msgSendVoidObj = reinterpret_cast<void (*)(id, SEL, id)>(objc_msgSend);
|
||||
auto msgSendVoidBool = reinterpret_cast<void (*)(id, SEL, bool)>(objc_msgSend);
|
||||
id contentView = msgSendObj(static_cast<id>(cocoaWindow), sel_registerName("contentView"));
|
||||
ASSERT_NE(contentView, nullptr);
|
||||
msgSendVoidBool(contentView, sel_registerName("setWantsLayer:"), true);
|
||||
|
||||
id metalLayerClass = reinterpret_cast<id>(objc_getClass("CAMetalLayer"));
|
||||
ASSERT_NE(metalLayerClass, nullptr);
|
||||
id metalLayer = msgSendObj(metalLayerClass, sel_registerName("layer"));
|
||||
ASSERT_NE(metalLayer, nullptr);
|
||||
|
||||
msgSendVoidObj(contentView, sel_registerName("setLayer:"), metalLayer);
|
||||
nativewindow = reinterpret_cast<EGLNativeWindowType>(metalLayer);
|
||||
#endif
|
||||
EGLSurface surface = eglCreateWindowSurface(display, config, nativewindow, nullptr);
|
||||
eglMakeCurrent(display, surface, surface, context);
|
||||
|
||||
@@ -16,11 +16,18 @@
|
||||
#include <EGL/egl.h>
|
||||
#ifdef _WIN32
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#elif defined(__APPLE__)
|
||||
#define GLFW_EXPOSE_NATIVE_COCOA
|
||||
#endif
|
||||
#include "MG_Backend/DirectVulkan/DirectVulkan.h"
|
||||
#include "MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h"
|
||||
|
||||
#include <GLFW/glfw3native.h>
|
||||
#ifdef __APPLE__
|
||||
#include <objc/message.h>
|
||||
#include <objc/objc.h>
|
||||
#include <objc/runtime.h>
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
glfwInit();
|
||||
@@ -41,8 +48,26 @@ int main() {
|
||||
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
GLFWwindow* window = glfwCreateWindow(800, 600, "MobileGL ContextCreation", nullptr, nullptr);
|
||||
EGLNativeWindowType nativewindow = nullptr;
|
||||
#ifdef _WIN32
|
||||
EGLNativeWindowType nativewindow = glfwGetWin32Window(window);
|
||||
nativewindow = glfwGetWin32Window(window);
|
||||
#elif defined(__APPLE__)
|
||||
void* cocoaWindow = glfwGetCocoaWindow(window);
|
||||
MOBILEGL_ASSERT(cocoaWindow, "glfwGetCocoaWindow returned null");
|
||||
auto msgSendObj = reinterpret_cast<id (*)(id, SEL)>(objc_msgSend);
|
||||
auto msgSendVoidObj = reinterpret_cast<void (*)(id, SEL, id)>(objc_msgSend);
|
||||
auto msgSendVoidBool = reinterpret_cast<void (*)(id, SEL, bool)>(objc_msgSend);
|
||||
id contentView = msgSendObj(static_cast<id>(cocoaWindow), sel_registerName("contentView"));
|
||||
MOBILEGL_ASSERT(contentView, "Failed to query NSWindow.contentView");
|
||||
msgSendVoidBool(contentView, sel_registerName("setWantsLayer:"), true);
|
||||
|
||||
id metalLayerClass = reinterpret_cast<id>(objc_getClass("CAMetalLayer"));
|
||||
MOBILEGL_ASSERT(metalLayerClass, "Failed to lookup CAMetalLayer class");
|
||||
id metalLayer = msgSendObj(metalLayerClass, sel_registerName("layer"));
|
||||
MOBILEGL_ASSERT(metalLayer, "Failed to create CAMetalLayer");
|
||||
|
||||
msgSendVoidObj(contentView, sel_registerName("setLayer:"), metalLayer);
|
||||
nativewindow = reinterpret_cast<EGLNativeWindowType>(metalLayer);
|
||||
#endif
|
||||
EGLSurface surface = eglCreateWindowSurface(display, config, nativewindow, nullptr);
|
||||
eglMakeCurrent(display, surface, surface, context);
|
||||
|
||||
Reference in New Issue
Block a user