Kha icon indicating copy to clipboard operation
Kha copied to clipboard

macOS Mojave fullscreen freezing

Open linuslindell opened this issue 6 years ago • 4 comments
trafficstars

  • Using XCode Version 10.1 (10B61) on macOS Version 10.14.3 (18D109).
  • Using https://github.com/Kha-Samples/Empty.git with below change
diff --git a/Sources/Main.hx b/Sources/Main.hx
index 3976b7f..595f20f 100644
--- a/Sources/Main.hx
+++ b/Sources/Main.hx
@@ -11,7 +11,9 @@ class Main {
 	}
 
 	static function render(framebuffer: Framebuffer): Void {
-
+		framebuffer.g2.begin();
+		framebuffer.g2.fillRect(100, 100, 32, 32);
+		framebuffer.g2.end();
 	}
 
 	public static function main() {
  • Kha updated to latest version.
  • Using node Kha/make --compile to create build

Steps to reproduce Start build Make app fullscreen using macOS fullscreen function that place the app on its own screen Trigger Mission Control using keyboard shortcut control+↑ Keep pressing control+↑ to go between app and Mission Control, also pressing during Mission Control animation Eventually app becomes unresponsive with spinning pinwheel cursor.

Notes Above example is simplest code where issue happens, but issue seems to happen faster and with less aggressive interaction when code is more complex with more drawing to screen. Unable to reproduce using same build on another macbook that has older macOS than Mojave Not seeing any errors, system just says that app is unresponsive and it must be force quit because the window controls for the app will no longer slide down when moving the cursor to the top of the fullscreen app. There is no spike in processor usage. I tried the build on a third macbook with an even older version of macOS, but build would not start at all instead, closing with error segmentation fault 11, probably a different issue.

linuslindell avatar Feb 17 '19 21:02 linuslindell

This might be related to metal. If I create a build using node Kha/make osx --graphics metal --compile then I am able to reproduce the issue, but if I create a build using node Kha/make osx --graphics opengl --compile then the issue doesn't seem to happen even when using a more complex project and constantly toggling between Mission Control and fullscreen app.

I'm guessing that metal is used by default when --graphics is not used. Is there a recommendation for using one over the other? My understanding is that metal is a pretty new technology, is the implementation used by Kha considered to be stable and generally work well?

linuslindell avatar Feb 24 '19 22:02 linuslindell

There's currently two issues with Metal I know of (clear not working and no way to switch between point and bilinear filtering). I strongly recommend using Metal and reporting any issues you find. OpenGL on macOS is deprecated and starts doing weird things on new macOS versions (like Mojave doesn't seem to support vsyncing OpenGL applications). I also recommend avoiding --compile for development. Kha has excellent Xcode support which makes it much easier to see what's going on when your application starts acting weirdly.

RobDangerous avatar Feb 24 '19 23:02 RobDangerous

I think I noticed the clear issue too, and I was wondering regarding image quality when using drawScaledSubImage which I guess is related to filtering?

The opengl build also seemed to run at 100+ fps according to my rudimentary fps counter. I noticed that verticalSync defaults to true, but didn't investigate that more, so I guess I don't need to if it is a known issue.

I also recommend avoiding --compile for development. Kha has excellent Xcode support which makes it much easier to see what's going on when your application starts acting weirdly.

I don't see any errors when running through xcode either. There doesn't seem to be an error or crash, the app is just frozen. I tried to do some debugging, and trying to understand assembly is a bit over my head, but it seems like the code gets stuck in some kind of loop.

If I run the test app without reproducing the issue and pause execution it stops at

* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
  * frame #0: 0x00007fff76dde1ce libsystem_kernel.dylib`semaphore_timedwait_trap + 10
    frame #1: 0x0000000101063f36 libdispatch.dylib`_dispatch_sema4_timedwait + 76
    frame #2: 0x0000000101064627 libdispatch.dylib`_dispatch_semaphore_wait_slow + 58
    frame #3: 0x00007fff54a7360c QuartzCore`-[CAMetalLayer nextDrawable] + 1202
    frame #4: 0x0000000100e7a05e libMTLInterpose.dylib`CAMetalLayer_nextDrawable(CAMetalLayer*, objc_selector*) + 53
    frame #5: 0x00000001004dd82a Empty`::-[BasicOpenGLView begin](self=0x0000000101608300, _cmd="begin") at BasicOpenGLView.mm:353
    frame #6: 0x00000001004e01eb Empty`beginGL() at System.mm:87
    frame #7: 0x00000001004d2e74 Empty`Kore::Graphics5::begin(renderTarget=0x0000600000c57420, windowId=0) at Metal.mm:52
    frame #8: 0x00000001004cd9c0 Empty`Kore::Graphics4::begin(window=0) at G4.cpp:109
    frame #9: 0x000000010023691f Empty`kha::kore::graphics4::Graphics_obj::begin(this=0x00000001142dbaf8, additionalRenderTargets=Array<Dynamic> @ 0x00007ffeefbfe4e8) at Graphics.cpp:1083
    frame #10: 0x00000001001c8039 Empty`kha::graphics4::Graphics_obj::begin(_hx_=<unavailable>, additionalRenderTargets=Array<Dynamic> @ 0x00007ffeefbfe540) at Graphics.h:39
    frame #11: 0x00000001001c7eb2 Empty`kha::graphics4::Graphics2_obj::begin(this=0x00000001142dbb90, __o_clear=<unavailable>, clearColor=Dynamic @ 0x00007ffeefbfe628) at Graphics2.cpp:948
    frame #12: 0x0000000100006273 Empty`Main_obj::render(framebuffer=kha::Framebuffer @ 0x00007ffeefbfe6b8) at Main.cpp:71
    frame #13: 0x0000000100007a26 Empty`Main_obj::main(this=0x00000001142ddc1c, framebuffers=Array<Dynamic> @ 0x00007ffeefbfe718)::_hx_Closure_3::_hx_run(hx::ObjectPtr<kha::Window_obj>)::_hx_Closure_2::_hx_run()::_hx_Closure_1::_hx_run(Array<Dynamic>) at Main.cpp:94
    frame #14: 0x0000000100007980 Empty`Main_obj::main(this=0x00000001142ddc1c, inArg0=0x00007ffeefbfe7b8)::_hx_Closure_3::_hx_run(hx::ObjectPtr<kha::Window_obj>)::_hx_Closure_2::_hx_run()::_hx_Closure_1::__run(Dynamic const&) at Main.cpp:96
    frame #15: 0x000000010000a31d Empty`Dynamic::operator(this=0x00007ffeefbfe7c0, inArg0=0x00007ffeefbfe7b8)(Dynamic const&) at Dynamic.h:305
    frame #16: 0x0000000100092381 Empty`kha::System_obj::render(framebuffers=Array<Dynamic> @ 0x00007ffeefbfe820) at System.cpp:260
    frame #17: 0x000000010009bb1e Empty`kha::SystemImpl_obj::frame() at SystemImpl.cpp:509
    frame #18: 0x0000000100284e90 Empty`(anonymous namespace)::update() at main.cpp:145
    frame #19: 0x00000001004e4498 Empty`Kore::System::_callback() at System.cpp:104
    frame #20: 0x00000001004e474d Empty`Kore::System::frame() at System.cpp:230
    frame #21: 0x00000001004e0048 Empty`::withAutoreleasepool(f=(Empty`Kore::System::frame() at System.cpp:229))()) at System.mm:24
    frame #22: 0x00000001004e4787 Empty`Kore::System::start() at System.cpp:242
    frame #23: 0x00000001002854a1 Empty`run_kore() at main.cpp:331
    frame #24: 0x000000010009a5cd Empty`kha::SystemImpl_obj::postInit(callback=Dynamic @ 0x00007ffeefbfeb70) at SystemImpl.cpp:382
    frame #25: 0x0000000100099ec0 Empty`kha::SystemImpl_obj::init(options=kha::SystemOptions @ 0x00007ffeefbfece0, callback=Dynamic @ 0x00007ffeefbfecd8) at SystemImpl.cpp:345
    frame #26: 0x00000001000914b7 Empty`kha::System_obj::start(options=kha::SystemOptions @ 0x00007ffeefbfedb0, callback=Dynamic @ 0x00007ffeefbfed58) at System.cpp:157
    frame #27: 0x0000000100006695 Empty`Main_obj::main() at Main.cpp:110
    frame #28: 0x00000001000124ad Empty`::__hxcpp_main() at __lib__.cpp:19
    frame #29: 0x00000001002855c2 Empty`kore(argc=3, argv=0x00007ffeefbff118) at main.cpp:349
    frame #30: 0x00000001004e15c7 Empty`::-[MyApplication run](self=0x0000600003300c80, _cmd="run") at System.mm:273
    frame #31: 0x00007fff4be490c5 Foundation`-[NSObject(NSThreadPerformAdditions) performSelector:onThread:withObject:waitUntilDone:modes:] + 1123
    frame #32: 0x00007fff4be50c6a Foundation`-[NSObject(NSThreadPerformAdditions) performSelectorOnMainThread:withObject:waitUntilDone:] + 131
    frame #33: 0x00000001004e11a4 Empty`main(argc=3, argv=0x00007ffeefbff118) at System.mm:235
    frame #34: 0x00007fff76ca4ed9 libdyld.dylib`start + 1
    frame #35: 0x00007fff76ca4ed9 libdyld.dylib`start + 1

From here I am able to step up through the stack and end up at the kore graphics code.

If I reproduce the issue and pause execution it stops at

* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
  * frame #0: 0x00007fff76de17de libsystem_kernel.dylib`__psynch_cvwait + 10
    frame #1: 0x00000001010e21eb libsystem_pthread.dylib`_pthread_cond_wait + 724
    frame #2: 0x00007fff4e67c93b Metal`-[_MTLCommandBuffer waitUntilCompleted] + 67
    frame #3: 0x00000001004de9b8 Empty`::-[BasicOpenGLView newRenderPass:wait:](self=0x0000000101608300, _cmd="newRenderPass:wait:", renderTarget=0x0000000000000000, wait=true) at BasicOpenGLView.mm:416
    frame #4: 0x00000001004e0244 Empty`newRenderPass(renderTarget=0x0000000000000000, wait=true) at System.mm:95
    frame #5: 0x00000001004d083d Empty`Kore::Graphics5::CommandList::executeAndWait(this=0x0000600000009740) at CommandList5Impl.mm:99
    frame #6: 0x00000001004cd7e9 Empty`(anonymous namespace)::endDraw() at G4.cpp:62
    frame #7: 0x00000001004cd86a Empty`Kore::Graphics4::drawIndexedVertices(start=0, count=6) at G4.cpp:80
    frame #8: 0x00000001002357dd Empty`kha::kore::graphics4::Graphics_obj::drawSomeIndexedVertices(this=0x00000001142dbaf8, start=0, count=6) at Graphics.cpp:989
    frame #9: 0x0000000100235722 Empty`kha::kore::graphics4::Graphics_obj::drawIndexedVertices(this=0x00000001142dbaf8, __o_start=<unavailable>, __o_count=(isNull = false, value = 6)) at Graphics.cpp:968
    frame #10: 0x00000001001ad745 Empty`kha::graphics4::Graphics_obj::drawIndexedVertices(_hx_=<unavailable>, start=(isNull = false, value = 0), count=(isNull = false, value = 6)) at Graphics.h:199
    frame #11: 0x00000001001ace09 Empty`kha::graphics4::ColoredShaderPainter_obj::drawBuffer(this=0x00000001142dc1bc, trisDone=false) at ColoredShaderPainter.cpp:280
    frame #12: 0x00000001001c83ec Empty`kha::graphics4::Graphics2_obj::flush(this=0x00000001142dbb90) at Graphics2.cpp:980
    frame #13: 0x00000001001c8454 Empty`kha::graphics4::Graphics2_obj::end(this=0x00000001142dbb90) at Graphics2.cpp:988
    frame #14: 0x0000000100006370 Empty`Main_obj::render(framebuffer=kha::Framebuffer @ 0x00007ffeefbfe6b8) at Main.cpp:73
    frame #15: 0x0000000100007a26 Empty`Main_obj::main(this=0x00000001142ddc1c, framebuffers=Array<Dynamic> @ 0x00007ffeefbfe718)::_hx_Closure_3::_hx_run(hx::ObjectPtr<kha::Window_obj>)::_hx_Closure_2::_hx_run()::_hx_Closure_1::_hx_run(Array<Dynamic>) at Main.cpp:94
    frame #16: 0x0000000100007980 Empty`Main_obj::main(this=0x00000001142ddc1c, inArg0=0x00007ffeefbfe7b8)::_hx_Closure_3::_hx_run(hx::ObjectPtr<kha::Window_obj>)::_hx_Closure_2::_hx_run()::_hx_Closure_1::__run(Dynamic const&) at Main.cpp:96
    frame #17: 0x000000010000a31d Empty`Dynamic::operator(this=0x00007ffeefbfe7c0, inArg0=0x00007ffeefbfe7b8)(Dynamic const&) at Dynamic.h:305
    frame #18: 0x0000000100092381 Empty`kha::System_obj::render(framebuffers=Array<Dynamic> @ 0x00007ffeefbfe820) at System.cpp:260
    frame #19: 0x000000010009bb1e Empty`kha::SystemImpl_obj::frame() at SystemImpl.cpp:509
    frame #20: 0x0000000100284e90 Empty`(anonymous namespace)::update() at main.cpp:145
    frame #21: 0x00000001004e4498 Empty`Kore::System::_callback() at System.cpp:104
    frame #22: 0x00000001004e474d Empty`Kore::System::frame() at System.cpp:230
    frame #23: 0x00000001004e0048 Empty`::withAutoreleasepool(f=(Empty`Kore::System::frame() at System.cpp:229))()) at System.mm:24
    frame #24: 0x00000001004e4787 Empty`Kore::System::start() at System.cpp:242
    frame #25: 0x00000001002854a1 Empty`run_kore() at main.cpp:331
    frame #26: 0x000000010009a5cd Empty`kha::SystemImpl_obj::postInit(callback=Dynamic @ 0x00007ffeefbfeb70) at SystemImpl.cpp:382
    frame #27: 0x0000000100099ec0 Empty`kha::SystemImpl_obj::init(options=kha::SystemOptions @ 0x00007ffeefbfece0, callback=Dynamic @ 0x00007ffeefbfecd8) at SystemImpl.cpp:345
    frame #28: 0x00000001000914b7 Empty`kha::System_obj::start(options=kha::SystemOptions @ 0x00007ffeefbfedb0, callback=Dynamic @ 0x00007ffeefbfed58) at System.cpp:157
    frame #29: 0x0000000100006695 Empty`Main_obj::main() at Main.cpp:110
    frame #30: 0x00000001000124ad Empty`::__hxcpp_main() at __lib__.cpp:19
    frame #31: 0x00000001002855c2 Empty`kore(argc=3, argv=0x00007ffeefbff118) at main.cpp:349
    frame #32: 0x00000001004e15c7 Empty`::-[MyApplication run](self=0x0000600003300c80, _cmd="run") at System.mm:273
    frame #33: 0x00007fff4be490c5 Foundation`-[NSObject(NSThreadPerformAdditions) performSelector:onThread:withObject:waitUntilDone:modes:] + 1123
    frame #34: 0x00007fff4be50c6a Foundation`-[NSObject(NSThreadPerformAdditions) performSelectorOnMainThread:withObject:waitUntilDone:] + 131
    frame #35: 0x00000001004e11a4 Empty`main(argc=3, argv=0x00007ffeefbff118) at System.mm:235
    frame #36: 0x00007fff76ca4ed9 libdyld.dylib`start + 1
    frame #37: 0x00007fff76ca4ed9 libdyld.dylib`start + 1

If I try to step up from here, the execution just resumes. The stack is inside _pthread_cond_wait, and trying to step through the code, it ends up jumping back into pthread_cond_wait from _MTLCommandBuffer waitUntilCompleted

Metal`-[_MTLCommandBuffer waitUntilCompleted]:
    ; […]
    0x7fff4e67c930 <+56>: movq   %rbx, %rdi
    0x7fff4e67c933 <+59>: movq   %r15, %rsi
    0x7fff4e67c936 <+62>: callq  0x7fff4e6cecc0            ; symbol stub for: pthread_cond_wait
->  0x7fff4e67c93b <+67>: cmpb   $0x0, (%r14,%r12)
    0x7fff4e67c940 <+72>: je     0x7fff4e67c930            ; <+56>
    ; […]

I don't know any more assembly than I am able to google, so I'm just stepping through the code to see what it's doing.

linuslindell avatar Feb 25 '19 12:02 linuslindell

Thanks, now we know what's happening (Metal is waiting for the GPU to finish some work). Will try to find out more about that next time I boot my Mac.

RobDangerous avatar Feb 25 '19 12:02 RobDangerous