diff options
author | RĂ©mi Verschelde <rverschelde@gmail.com> | 2019-07-29 20:44:14 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-11 11:57:40 +0100 |
commit | 6289e7d1479f6e7c9e55890c8c66d2e5e0a1481a (patch) | |
tree | 8223d907b1aa8184295240a7b6f63023da05c02f /platform/osx | |
parent | 6ecedd1e6ca7d8b10b13a3dab19074fd51b17bcf (diff) | |
parent | b456bfad5cee3922f55621bf7c133cc67337636a (diff) |
Merge pull request #29993 from bruvzg/vulkan
Initial Vulkan support for macOS (MoltenVK) and Windows
Diffstat (limited to 'platform/osx')
-rw-r--r-- | platform/osx/SCsub | 2 | ||||
-rw-r--r-- | platform/osx/context_gl_osx.h | 79 | ||||
-rw-r--r-- | platform/osx/context_gl_osx.mm | 216 | ||||
-rw-r--r-- | platform/osx/detect.py | 23 | ||||
-rw-r--r-- | platform/osx/godot_main_osx.mm | 6 | ||||
-rw-r--r-- | platform/osx/os_osx.h | 21 | ||||
-rw-r--r-- | platform/osx/os_osx.mm | 364 | ||||
-rw-r--r-- | platform/osx/vulkan_context_osx.h | 48 | ||||
-rw-r--r-- | platform/osx/vulkan_context_osx.mm | 56 |
9 files changed, 620 insertions, 195 deletions
diff --git a/platform/osx/SCsub b/platform/osx/SCsub index e15b4339a7..09f213cb0e 100644 --- a/platform/osx/SCsub +++ b/platform/osx/SCsub @@ -13,6 +13,8 @@ files = [ 'dir_access_osx.mm', 'joypad_osx.cpp', 'power_osx.cpp', + 'vulkan_context_osx.mm', + 'context_gl_osx.mm' ] prog = env.add_program('#bin/godot', files) diff --git a/platform/osx/context_gl_osx.h b/platform/osx/context_gl_osx.h new file mode 100644 index 0000000000..831a813fe9 --- /dev/null +++ b/platform/osx/context_gl_osx.h @@ -0,0 +1,79 @@ +/*************************************************************************/ +/* context_gl_osx.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CONTEXT_GL_OSX_H +#define CONTEXT_GL_OSX_H + +#if defined(OPENGL_ENABLED) || defined(GLES_ENABLED) + +#include "core/error_list.h" +#include "core/os/os.h" + +#include <AppKit/AppKit.h> +#include <ApplicationServices/ApplicationServices.h> +#include <CoreVideo/CoreVideo.h> + +class ContextGL_OSX { + + bool opengl_3_context; + bool use_vsync; + + void *framework; + id window_view; + NSOpenGLPixelFormat *pixelFormat; + NSOpenGLContext *context; + +public: + bool waiting_for_vsync; + NSCondition *vsync_condition; + CVDisplayLinkRef displayLink; + + void release_current(); + + void make_current(); + void update(); + + void set_opacity(GLint p_opacity); + + int get_window_width(); + int get_window_height(); + void swap_buffers(); + + Error initialize(); + + void set_use_vsync(bool p_use); + bool is_using_vsync() const; + + ContextGL_OSX(id p_view, bool p_opengl_3_context); + ~ContextGL_OSX(); +}; + +#endif +#endif
\ No newline at end of file diff --git a/platform/osx/context_gl_osx.mm b/platform/osx/context_gl_osx.mm new file mode 100644 index 0000000000..425c9b0ac4 --- /dev/null +++ b/platform/osx/context_gl_osx.mm @@ -0,0 +1,216 @@ +/*************************************************************************/ +/* context_gl_osx.mm */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "context_gl_osx.h" + +#if defined(OPENGL_ENABLED) || defined(GLES_ENABLED) + +// DisplayLinkCallback is called from our DisplayLink OS thread informing us right before +// a screen update is required. We can use it to work around the broken vsync. +static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *now, const CVTimeStamp *outputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext) { + ContextGL_OSX *gl_ctx = (ContextGL_OSX *)displayLinkContext; + + // Set flag so we know we can output our next frame and signal our conditional lock + // if we're not doing vsync this will be ignored + [gl_ctx->vsync_condition lock]; + gl_ctx->waiting_for_vsync = false; + [gl_ctx->vsync_condition signal]; + [gl_ctx->vsync_condition unlock]; + + return kCVReturnSuccess; +} + +void ContextGL_OSX::release_current() { + + [NSOpenGLContext clearCurrentContext]; +} + +void ContextGL_OSX::make_current() { + + [context makeCurrentContext]; +} + +void ContextGL_OSX::update() { + + [context update]; +} + +void ContextGL_OSX::set_opacity(GLint p_opacity) { + + [context setValues:&p_opacity forParameter:NSOpenGLCPSurfaceOpacity]; +} + +int ContextGL_OSX::get_window_width() { + + return OS::get_singleton()->get_video_mode().width; +} + +int ContextGL_OSX::get_window_height() { + + return OS::get_singleton()->get_video_mode().height; +} + +void ContextGL_OSX::swap_buffers() { + + if (use_vsync) { + // Wait until our DisplayLink callback unsets our flag... + [vsync_condition lock]; + while (waiting_for_vsync) + [vsync_condition wait]; + + // Make sure we wait again next frame around + waiting_for_vsync = true; + + [vsync_condition unlock]; + } + + [context flushBuffer]; +} + +void ContextGL_OSX::set_use_vsync(bool p_use) { + // CGLCPSwapInterval broke in OSX 10.14 and it seems Apple is not interested in fixing + // it as OpenGL is now deprecated and Metal solves this differently. + // Following SDLs example we're working around this using DisplayLink + // When vsync is enabled we set a flag "waiting_for_vsync" to true. + // This flag is set to false when DisplayLink informs us our display is about to refresh. + + ///TODO Maybe pause/unpause display link? + use_vsync = p_use; + waiting_for_vsync = p_use; +} + +bool ContextGL_OSX::is_using_vsync() const { + + return use_vsync; +} + +Error ContextGL_OSX::initialize() { + + framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")); + ERR_FAIL_COND_V(!framework, ERR_CANT_CREATE); + + unsigned int attributeCount = 0; + + // OS X needs non-zero color size, so set reasonable values + int colorBits = 32; + + // Fail if a robustness strategy was requested + +#define ADD_ATTR(x) \ + { attributes[attributeCount++] = x; } +#define ADD_ATTR2(x, y) \ + { \ + ADD_ATTR(x); \ + ADD_ATTR(y); \ + } + + // Arbitrary array size here + NSOpenGLPixelFormatAttribute attributes[40]; + + ADD_ATTR(NSOpenGLPFADoubleBuffer); + ADD_ATTR(NSOpenGLPFAClosestPolicy); + + if (!opengl_3_context) { + ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy); + } else { + //we now need OpenGL 3 or better, maybe even change this to 3_3Core ? + ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core); + } + + ADD_ATTR2(NSOpenGLPFAColorSize, colorBits); + + /* + if (fbconfig->alphaBits > 0) + ADD_ATTR2(NSOpenGLPFAAlphaSize, fbconfig->alphaBits); +*/ + + ADD_ATTR2(NSOpenGLPFADepthSize, 24); + + ADD_ATTR2(NSOpenGLPFAStencilSize, 8); + + /* + if (fbconfig->stereo) + ADD_ATTR(NSOpenGLPFAStereo); +*/ + + /* + if (fbconfig->samples > 0) { + ADD_ATTR2(NSOpenGLPFASampleBuffers, 1); + ADD_ATTR2(NSOpenGLPFASamples, fbconfig->samples); + } +*/ + + // NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB + // framebuffer, so there's no need (and no way) to request it + + ADD_ATTR(0); + +#undef ADD_ATTR +#undef ADD_ATTR2 + + pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; + ERR_FAIL_COND_V(pixelFormat == nil, ERR_CANT_CREATE); + + context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil]; + + ERR_FAIL_COND_V(context == nil, ERR_CANT_CREATE); + + [context setView:window_view]; + + [context makeCurrentContext]; + + // setup our display link, this will inform us when a refresh is needed + CVDisplayLinkCreateWithActiveCGDisplays(&displayLink); + CVDisplayLinkSetOutputCallback(displayLink, &DisplayLinkCallback, this); + CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, context.CGLContextObj, pixelFormat.CGLPixelFormatObj); + CVDisplayLinkStart(displayLink); + + // initialise a conditional lock object + vsync_condition = [[NSCondition alloc] init]; + + return OK; +} + +ContextGL_OSX::ContextGL_OSX(id p_view, bool p_opengl_3_context) { + + opengl_3_context = p_opengl_3_context; + window_view = p_view; + use_vsync = false; +} + +ContextGL_OSX::~ContextGL_OSX() { + + if (displayLink) { + CVDisplayLinkRelease(displayLink); + } + [vsync_condition release]; +} + +#endif diff --git a/platform/osx/detect.py b/platform/osx/detect.py index fe839199e8..c4e8779523 100644 --- a/platform/osx/detect.py +++ b/platform/osx/detect.py @@ -1,5 +1,6 @@ import os import sys +import subprocess from methods import detect_darwin_sdk_path @@ -25,6 +26,7 @@ def get_opts(): return [ ('osxcross_sdk', 'OSXCross SDK version', 'darwin14'), ('MACOS_SDK_PATH', 'Path to the macOS SDK', ''), + BoolVariable('use_static_mvk', 'Link MoltenVK statically as Level-0 driver (better portability) or use Vulkan ICD loader (enables validation layers)', False), EnumVariable('debug_symbols', 'Add debugging symbols to release builds', 'yes', ('yes', 'no', 'full')), BoolVariable('separate_debug_symbols', 'Create a separate file containing debugging symbols', False), BoolVariable('use_ubsan', 'Use LLVM/GCC compiler undefined behavior sanitizer (UBSAN)', False), @@ -148,9 +150,20 @@ def configure(env): ## Flags env.Prepend(CPPPATH=['#platform/osx']) - env.Append(CPPDEFINES=['OSX_ENABLED', 'UNIX_ENABLED', 'GLES_ENABLED', 'APPLE_STYLE_KEYS', 'COREAUDIO_ENABLED', 'COREMIDI_ENABLED']) - env.Append(LINKFLAGS=['-framework', 'Cocoa', '-framework', 'Carbon', '-framework', 'OpenGL', '-framework', 'AGL', '-framework', 'AudioUnit', '-framework', 'CoreAudio', '-framework', 'CoreMIDI', '-lz', '-framework', 'IOKit', '-framework', 'ForceFeedback', '-framework', 'AVFoundation', '-framework', 'CoreMedia', '-framework', 'CoreVideo']) - env.Append(LIBS=['pthread']) + env.Append(CPPDEFINES=['OSX_ENABLED', 'UNIX_ENABLED', 'APPLE_STYLE_KEYS', 'COREAUDIO_ENABLED', 'COREMIDI_ENABLED']) + env.Append(LINKFLAGS=['-framework', 'Cocoa', '-framework', 'Carbon', '-framework', 'AudioUnit', '-framework', 'CoreAudio', '-framework', 'CoreMIDI', '-framework', 'IOKit', '-framework', 'ForceFeedback', '-framework', 'CoreVideo', '-framework', 'AVFoundation', '-framework', 'CoreMedia']) + env.Append(LIBS=['pthread', 'z']) - env.Append(CCFLAGS=['-mmacosx-version-min=10.9']) - env.Append(LINKFLAGS=['-mmacosx-version-min=10.9']) + env.Prepend(CPPPATH=['#thirdparty/vulkan/include/', "#thirdparty/vulkan/registry/"]) + env.Append(CPPDEFINES=['VULKAN_ENABLED']) + + #env.Append(CPPDEFINES=['GLES_ENABLED', 'OPENGL_ENABLED']) + + env.Append(LINKFLAGS=['-framework', 'Metal', '-framework', 'QuartzCore', '-framework', 'IOSurface']) + if (env['use_static_mvk']): + env.Append(LINKFLAGS=['-framework', 'MoltenVK']) + elif not env["builtin_vulkan_loader"]: + env.Append(LIBS=['vulkan']) + + env.Append(CCFLAGS=['-mmacosx-version-min=10.11']) + env.Append(LINKFLAGS=['-mmacosx-version-min=10.11']) diff --git a/platform/osx/godot_main_osx.mm b/platform/osx/godot_main_osx.mm index e6f8cbecf1..eacd2b5cc6 100644 --- a/platform/osx/godot_main_osx.mm +++ b/platform/osx/godot_main_osx.mm @@ -36,6 +36,12 @@ #include <unistd.h> int main(int argc, char **argv) { + +#if defined(VULKAN_ENABLED) + //MoltenVK - enable full component swizzling support + setenv("MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE", "1", 1); +#endif + int first_arg = 1; const char *dbg_arg = "-NSDocumentRevisionsDebugMode"; printf("arguments\n"); diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index 190dbcf662..00fc56def6 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -46,6 +46,15 @@ #include "servers/visual/visual_server_wrap_mt.h" #include "servers/visual_server.h" +#if defined(OPENGL_ENABLED) +#include "context_gl_osx.h" +#endif + +#if defined(VULKAN_ENABLED) +#include "drivers/vulkan/rendering_device_vulkan.h" +#include "platform/osx/vulkan_context_osx.h" +#endif + #include <AppKit/AppKit.h> #include <AppKit/NSCursor.h> #include <ApplicationServices/ApplicationServices.h> @@ -93,7 +102,6 @@ public: void process_events(); void process_key_events(); - void *framework; // pthread_key_t current; bool mouse_grab; Point2 mouse_pos; @@ -104,8 +112,15 @@ public: id window_view; id autoreleasePool; id cursor; - NSOpenGLPixelFormat *pixelFormat; - NSOpenGLContext *context; + +#if defined(OPENGL_ENABLED) + ContextGL_OSX *context_gles2; +#endif + +#if defined(VULKAN_ENABLED) + VulkanContextOSX *context_vulkan; + RenderingDeviceVulkan *rendering_device_vulkan; +#endif bool layered_window; diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 43012220b6..5d2bc5172f 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -34,11 +34,19 @@ #include "core/print_string.h" #include "core/version_generated.gen.h" #include "dir_access_osx.h" + +#if defined(OPENGL_ENABLED) #include "drivers/gles2/rasterizer_gles2.h" -#include "drivers/gles3/rasterizer_gles3.h" +#endif + +#if defined(VULKAN_ENABLED) +#include "servers/visual/rasterizer_rd/rasterizer_rd.h" +#endif + #include "main/main.h" #include "semaphore_osx.h" #include "servers/visual/visual_server_raster.h" +#include "servers/visual/visual_server_wrap_mt.h" #include <mach-o/dyld.h> @@ -52,6 +60,9 @@ #include <os/log.h> #endif +#import <QuartzCore/CAMetalLayer.h> +#include <vulkan/vulkan_metal.h> + #include <dlfcn.h> #include <fcntl.h> #include <libproc.h> @@ -260,29 +271,6 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) { return NSTerminateCancel; } -- (void)applicationDidHide:(NSNotification *)notification { - /* - _Godotwindow* window; - for (window = _Godot.windowListHead; window; window = window->next) - _GodotInputWindowVisibility(window, GL_FALSE); -*/ -} - -- (void)applicationDidUnhide:(NSNotification *)notification { - /* - _Godotwindow* window; - - for (window = _Godot.windowListHead; window; window = window->next) { - if ([window_object isVisible]) - _GodotInputWindowVisibility(window, GL_TRUE); - } -*/ -} - -- (void)applicationDidChangeScreenParameters:(NSNotification *)notification { - //_GodotInputMonitorChange(); -} - - (void)showAbout:(id)sender { if (OS_OSX::singleton->get_main_loop()) OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_ABOUT); @@ -336,11 +324,16 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) { NSWindow *window = (NSWindow *)[notification object]; CGFloat newBackingScaleFactor = [window backingScaleFactor]; CGFloat oldBackingScaleFactor = [[[notification userInfo] objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue]; - if (OS_OSX::singleton->is_hidpi_allowed()) { - [OS_OSX::singleton->window_view setWantsBestResolutionOpenGLSurface:YES]; - } else { - [OS_OSX::singleton->window_view setWantsBestResolutionOpenGLSurface:NO]; + +#if defined(OPENGL_ENABLED) + if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_GLES2) { + if (OS_OSX::singleton->is_hidpi_allowed()) { + [OS_OSX::singleton->window_view setWantsBestResolutionOpenGLSurface:YES]; + } else { + [OS_OSX::singleton->window_view setWantsBestResolutionOpenGLSurface:NO]; + } } +#endif if (newBackingScaleFactor != oldBackingScaleFactor) { //Set new display scale and window size @@ -361,8 +354,12 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) { } - (void)windowDidResize:(NSNotification *)notification { - [OS_OSX::singleton->context update]; +#if defined(OPENGL_ENABLED) + if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_GLES2) { + OS_OSX::singleton->context_gles2->update(); + } +#endif const NSRect contentRect = [OS_OSX::singleton->window_view frame]; const NSRect fbRect = contentRect; @@ -370,6 +367,14 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) { OS_OSX::singleton->window_size.width = fbRect.size.width * displayScale; OS_OSX::singleton->window_size.height = fbRect.size.height * displayScale; +#if defined(VULKAN_ENABLED) + if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_VULKAN) { + CALayer* layer = [OS_OSX::singleton->window_view layer]; + layer.contentsScale = OS_OSX::singleton->_display_scale(); + OS_OSX::singleton->context_vulkan->window_resize(0, OS_OSX::singleton->window_size.width, OS_OSX::singleton->window_size.height); + } +#endif + if (OS_OSX::singleton->main_loop) { Main::force_redraw(); //Event retrieval blocks until resize is over. Call Main::iteration() directly. @@ -377,15 +382,6 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) { Main::iteration(); } } - - /* - _GodotInputFramebufferSize(window, fbRect.size.width, fbRect.size.height); - _GodotInputWindowSize(window, contentRect.size.width, contentRect.size.height); - _GodotInputWindowDamage(window); - - if (window->cursorMode == Godot_CURSOR_DISABLED) - centerCursor(window); -*/ } - (void)windowDidMove:(NSNotification *)notification { @@ -393,17 +389,6 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) { if (OS_OSX::singleton->get_main_loop()) { OS_OSX::singleton->input->release_pressed_events(); } - - /* - [window->nsgl.context update]; - - int x, y; - _GodotPlatformGetWindowPos(window, &x, &y); - _GodotInputWindowPos(window, x, y); - - if (window->cursorMode == Godot_CURSOR_DISABLED) - centerCursor(window); -*/ } - (void)windowDidBecomeKey:(NSNotification *)notification { @@ -450,8 +435,12 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) { bool imeInputEventInProgress; } - (void)cancelComposition; + +- (CALayer*)makeBackingLayer; + - (BOOL)wantsUpdateLayer; - (void)updateLayer; + @end @implementation GodotContentView @@ -462,12 +451,32 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) { } } -- (BOOL)wantsUpdateLayer { - return YES; +- (CALayer*)makeBackingLayer { +#if defined(VULKAN_ENABLED) + if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_VULKAN) { + CALayer* layer = [[CAMetalLayer class] layer]; + layer.contentsScale = OS_OSX::singleton->_display_scale(); + return layer; + } +#endif + return [super makeBackingLayer]; } - (void)updateLayer { - [OS_OSX::singleton->context update]; +#if defined(VULKAN_ENABLED) + if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_VULKAN) { + [super updateLayer]; + } +#endif +#if defined(OPENGL_ENABLED) + if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_GLES2) { + OS_OSX::singleton->context_gles2->update(); + } +#endif +} + +- (BOOL)wantsUpdateLayer { + return YES; } - (id)init { @@ -1458,6 +1467,14 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a // Register to be notified on displays arrangement changes CGDisplayRegisterReconfigurationCallback(displays_arrangement_changed, NULL); + //!!!!!!!!!!!!!!!!!!!!!!!!!! + //TODO - do Vulkan and GLES2 support checks, driver selection and fallback + video_driver_index = p_video_driver; + print_verbose("Driver: " + String(get_video_driver_name(video_driver_index)) + " [" + itos(video_driver_index) + "]"); + //!!!!!!!!!!!!!!!!!!!!!!!!!! + + //Create window + window_delegate = [[GodotWindowDelegate alloc] init]; // Don't use accumulation buffer support; it's not accelerated @@ -1498,14 +1515,16 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a window_size.height = p_desired.height * displayScale; if (displayScale > 1.0) { - [window_view setWantsBestResolutionOpenGLSurface:YES]; - //if (current_videomode.resizable) +#if defined(OPENGL_ENABLED) + if (video_driver_index == VIDEO_DRIVER_GLES2) { + [window_view setWantsBestResolutionOpenGLSurface:YES]; + } +#endif [window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; } else { [window_view setWantsBestResolutionOpenGLSurface:NO]; } - //[window_object setTitle:[NSString stringWithUTF8String:"GodotEnginies"]]; [window_object setContentView:window_view]; [window_object setDelegate:window_delegate]; [window_object setAcceptsMouseMovedEvents:YES]; @@ -1513,77 +1532,51 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a [window_object setRestorable:NO]; - unsigned int attributeCount = 0; - - // OS X needs non-zero color size, so set reasonable values - int colorBits = 32; + // Init context and rendering device +#if defined(OPENGL_ENABLED) + if (video_driver_index == VIDEO_DRIVER_GLES2) { - // Fail if a robustness strategy was requested - -#define ADD_ATTR(x) \ - { attributes[attributeCount++] = x; } -#define ADD_ATTR2(x, y) \ - { \ - ADD_ATTR(x); \ - ADD_ATTR(y); \ - } + context_gles2 = memnew(ContextGL_OSX(window_view, false)); - // Arbitrary array size here - NSOpenGLPixelFormatAttribute attributes[40]; + if (context_gles2->initialize() != OK) { + memdelete(context_gles2); + context_gles2 = NULL; + ERR_FAIL_V(ERR_UNAVAILABLE); + } - ADD_ATTR(NSOpenGLPFADoubleBuffer); - ADD_ATTR(NSOpenGLPFAClosestPolicy); + context_gles2->set_use_vsync(p_desired.use_vsync); - if (p_video_driver == VIDEO_DRIVER_GLES2) { - ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy); - } else { - //we now need OpenGL 3 or better, maybe even change this to 3_3Core ? - ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core); + if (RasterizerGLES2::is_viable() == OK) { + RasterizerGLES2::register_config(); + RasterizerGLES2::make_current(); + } else { + memdelete(context_gles2); + context_gles2 = NULL; + ERR_FAIL_V(ERR_UNAVAILABLE); + } } +#endif +#if defined(VULKAN_ENABLED) + if (video_driver_index == VIDEO_DRIVER_VULKAN) { + + context_vulkan = memnew(VulkanContextOSX); + if (context_vulkan->initialize() != OK) { + memdelete(context_vulkan); + context_vulkan = NULL; + ERR_FAIL_V(ERR_UNAVAILABLE); + } + if (context_vulkan->window_create(window_view, get_video_mode().width, get_video_mode().height) == -1) { + memdelete(context_vulkan); + context_vulkan = NULL; + ERR_FAIL_V(ERR_UNAVAILABLE); + } - ADD_ATTR2(NSOpenGLPFAColorSize, colorBits); - - /* - if (fbconfig->alphaBits > 0) - ADD_ATTR2(NSOpenGLPFAAlphaSize, fbconfig->alphaBits); -*/ - - ADD_ATTR2(NSOpenGLPFADepthSize, 24); - - ADD_ATTR2(NSOpenGLPFAStencilSize, 8); - - /* - if (fbconfig->stereo) - ADD_ATTR(NSOpenGLPFAStereo); -*/ + rendering_device_vulkan = memnew(RenderingDeviceVulkan); + rendering_device_vulkan->initialize(context_vulkan); - /* - if (fbconfig->samples > 0) { - ADD_ATTR2(NSOpenGLPFASampleBuffers, 1); - ADD_ATTR2(NSOpenGLPFASamples, fbconfig->samples); + RasterizerRD::make_current(); } -*/ - - // NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB - // framebuffer, so there's no need (and no way) to request it - - ADD_ATTR(0); - -#undef ADD_ATTR -#undef ADD_ATTR2 - - pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; - ERR_FAIL_COND_V(pixelFormat == nil, ERR_UNAVAILABLE); - - context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil]; - - ERR_FAIL_COND_V(context == nil, ERR_UNAVAILABLE); - - [context setView:window_view]; - - [context makeCurrentContext]; - - set_use_vsync(p_desired.use_vsync); +#endif [NSApp activateIgnoringOtherApps:YES]; @@ -1594,53 +1587,6 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a if (p_desired.fullscreen) zoomed = true; - /*** END OSX INITIALIZATION ***/ - - bool gles3 = true; - if (p_video_driver == VIDEO_DRIVER_GLES2) { - gles3 = false; - } - - bool editor = Engine::get_singleton()->is_editor_hint(); - bool gl_initialization_error = false; - - while (true) { - if (gles3) { - if (RasterizerGLES3::is_viable() == OK) { - RasterizerGLES3::register_config(); - RasterizerGLES3::make_current(); - break; - } else { - if (GLOBAL_GET("rendering/quality/driver/fallback_to_gles2") || editor) { - p_video_driver = VIDEO_DRIVER_GLES2; - gles3 = false; - continue; - } else { - gl_initialization_error = true; - break; - } - } - } else { - if (RasterizerGLES2::is_viable() == OK) { - RasterizerGLES2::register_config(); - RasterizerGLES2::make_current(); - break; - } else { - gl_initialization_error = true; - break; - } - } - } - - if (gl_initialization_error) { - OS::get_singleton()->alert("Your video card driver does not support any of the supported OpenGL versions.\n" - "Please update your drivers or if you have a very old or integrated GPU upgrade it.", - "Unable to initialize Video driver"); - return ERR_UNAVAILABLE; - } - - video_driver_index = p_video_driver; - visual_server = memnew(VisualServerRaster); if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD)); @@ -1673,6 +1619,27 @@ void OS_OSX::finalize() { midi_driver.close(); #endif +#if defined(OPENGL_ENABLED) + if (video_driver_index == VIDEO_DRIVER_GLES2) { + + if (context_gles2) + memdelete(context_gles2); + } +#endif +#if defined(VULKAN_ENABLED) + if (video_driver_index == VIDEO_DRIVER_VULKAN) { + + if (rendering_device_vulkan) { + rendering_device_vulkan->finalize(); + memdelete(rendering_device_vulkan); + } + + if (context_vulkan) + memdelete(context_vulkan); + + } +#endif + CFNotificationCenterRemoveObserver(CFNotificationCenterGetDistributedCenter(), NULL, kTISNotifySelectedKeyboardInputSourceChanged, NULL); CGDisplayRemoveReconfigurationCallback(displays_arrangement_changed, NULL); @@ -1684,7 +1651,6 @@ void OS_OSX::finalize() { cursors_cache.clear(); visual_server->finish(); memdelete(visual_server); - //memdelete(rasterizer); } void OS_OSX::set_main_loop(MainLoop *p_main_loop) { @@ -1916,7 +1882,6 @@ void OS_OSX::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, c image->lock(); - /* Premultiply the alpha channel */ for (int i = 0; i < len; i++) { int row_index = floor(i / texture_size.width) + atlas_rect.position.y; int column_index = (i % int(texture_size.width)) + atlas_rect.position.x; @@ -1971,6 +1936,7 @@ void OS_OSX::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, c cursors_cache.erase(p_shape); } + } void OS_OSX::set_mouse_show(bool p_show) { @@ -2228,13 +2194,19 @@ String OS_OSX::get_clipboard() const { } void OS_OSX::release_rendering_thread() { - - [NSOpenGLContext clearCurrentContext]; +#if defined(OPENGL_ENABLED) + if (video_driver_index == VIDEO_DRIVER_GLES2) { + context_gles2->release_current(); + } +#endif } void OS_OSX::make_rendering_thread() { - - [context makeCurrentContext]; +#if defined(OPENGL_ENABLED) + if (video_driver_index == VIDEO_DRIVER_GLES2) { + context_gles2->make_current(); + } +#endif } Error OS_OSX::shell_open(String p_uri) { @@ -2249,7 +2221,16 @@ String OS_OSX::get_locale() const { } void OS_OSX::swap_buffers() { - [context flushBuffer]; +#if defined(OPENGL_ENABLED) + if (video_driver_index == VIDEO_DRIVER_GLES2) { + context_gles2->swap_buffers(); + } +#endif +#if defined(VULKAN_ENABLED) + if (video_driver_index == VIDEO_DRIVER_VULKAN) { + context_vulkan->swap_buffers(); + } +#endif } void OS_OSX::wm_minimized(bool p_minimized) { @@ -2659,21 +2640,31 @@ void OS_OSX::set_window_per_pixel_transparency_enabled(bool p_enabled) { if (layered_window != p_enabled) { if (p_enabled) { set_borderless_window(true); - GLint opacity = 0; [window_object setBackgroundColor:[NSColor clearColor]]; [window_object setOpaque:NO]; [window_object setHasShadow:NO]; - [context setValues:&opacity forParameter:NSOpenGLCPSurfaceOpacity]; +#if defined(OPENGL_ENABLED) + if (video_driver_index == VIDEO_DRIVER_GLES2) { + context_gles2->set_opacity(0); + } +#endif layered_window = true; } else { - GLint opacity = 1; [window_object setBackgroundColor:[NSColor colorWithCalibratedWhite:1 alpha:1]]; [window_object setOpaque:YES]; [window_object setHasShadow:YES]; - [context setValues:&opacity forParameter:NSOpenGLCPSurfaceOpacity]; +#if defined(OPENGL_ENABLED) + if (video_driver_index == VIDEO_DRIVER_GLES2) { + context_gles2->set_opacity(1); + } +#endif layered_window = false; } - [context update]; +#if defined(OPENGL_ENABLED) + if (video_driver_index == VIDEO_DRIVER_GLES2) { + context_gles2->update(); + } +#endif NSRect frame = [window_object frame]; [window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, 1, 1) display:YES]; [window_object setFrame:frame display:YES]; @@ -2992,11 +2983,20 @@ Error OS_OSX::move_to_trash(const String &p_path) { } void OS_OSX::_set_use_vsync(bool p_enable) { + // FIXME: Commented out during rebase of vulkan branch on master. + /* CGLContextObj ctx = CGLGetCurrentContext(); if (ctx) { GLint swapInterval = p_enable ? 1 : 0; CGLSetParameter(ctx, kCGLCPSwapInterval, &swapInterval); } + */ +#if defined(OPENGL_ENABLED) + if (video_driver_index == VIDEO_DRIVER_GLES2) { + if (context_gles2) + context_gles2->set_use_vsync(p_enable); + } +#endif } OS_OSX *OS_OSX::singleton = NULL; @@ -3018,16 +3018,6 @@ OS_OSX::OS_OSX() { CGEventSourceSetLocalEventsSuppressionInterval(eventSource, 0.0); - /* - if (pthread_key_create(&_Godot.nsgl.current, NULL) != 0) { - _GodotInputError(Godot_PLATFORM_ERROR, "NSGL: Failed to create context TLS"); - return GL_FALSE; - } -*/ - - framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")); - ERR_FAIL_COND(!framework); - // Implicitly create shared NSApplication instance [GodotApplication sharedApplication]; diff --git a/platform/osx/vulkan_context_osx.h b/platform/osx/vulkan_context_osx.h new file mode 100644 index 0000000000..c048de509e --- /dev/null +++ b/platform/osx/vulkan_context_osx.h @@ -0,0 +1,48 @@ +/*************************************************************************/ +/* vulkan_context_osx.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef VULKAN_DEVICE_OSX_H +#define VULKAN_DEVICE_OSX_H + +#include "drivers/vulkan/vulkan_context.h" +#include <AppKit/AppKit.h> + +class VulkanContextOSX : public VulkanContext { + + virtual const char *_get_platform_surface_extension() const; + +public: + int window_create(id p_window, int p_width, int p_height); + + VulkanContextOSX(); + ~VulkanContextOSX(); +}; + +#endif // VULKAN_DEVICE_OSX_H diff --git a/platform/osx/vulkan_context_osx.mm b/platform/osx/vulkan_context_osx.mm new file mode 100644 index 0000000000..b4c663062c --- /dev/null +++ b/platform/osx/vulkan_context_osx.mm @@ -0,0 +1,56 @@ +/*************************************************************************/ +/* vulkan_context_osx.mm */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "vulkan_context_osx.h" +#include <vulkan/vulkan_macos.h> + +const char *VulkanContextOSX::_get_platform_surface_extension() const { + return VK_MVK_MACOS_SURFACE_EXTENSION_NAME; +} + +int VulkanContextOSX::window_create(id p_window, int p_width, int p_height) { + + VkMacOSSurfaceCreateInfoMVK createInfo; + createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK; + createInfo.pNext = NULL; + createInfo.flags = 0; + createInfo.pView = p_window; + + VkSurfaceKHR surface; + VkResult err = vkCreateMacOSSurfaceMVK(_get_instance(), &createInfo, NULL, &surface); + ERR_FAIL_COND_V(err, -1); + return _window_create(surface, p_width, p_height); +} + +VulkanContextOSX::VulkanContextOSX() { +} + +VulkanContextOSX::~VulkanContextOSX() { +} |