-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
macOS and iOS CPU ussage fix #5713
Description
What problem does this solve or what need does it fill?
increasing iOS and macOS game performance whilst saving battery live is a hard task but can be done quite easily, since macOS and iOS usually fix application framerate (with the exclusion to scrollviews or when programmatically demmanded). Currently a basic bevy app uses ~100% cpu on mac, which is a shame because it can be lower
What solution would you like?
Since application framerate is capped, using CADisplayLink on iOS and CVDisplayLink on macOS will give you a non-blocking 60 tick per second callback
What alternative(s) have you considered?
There's no other way on macOS , because the most common run loop [NSApp getevent.....] is really slow and CoreVideo bypasses all of the objc event system
Additional context
As someone who has implemented both CADisplayLink and CVDisplayLink once in the past. I can assure you it saves alot on cpu usage going from ~>100% to <20% which in turn saves on a lot of battery life. Also because apple ctr-alt-deleted there good old CoreVideo documention here’s a quick overview in obj-c (even though corevideo is mostly a c-api):
//create a display link
CVDisplayLinkRef displayLink;
CGDirectDisplayID displayID = CGMainDisplayID();
CVReturn error = kCVReturnSuccess;
error = CVDisplayLinkCreateWithCGDisplay(displayID, &displayLink);
if (error){
NSLog(@"error:%d", error);
displayLink = NULL;
}
//link callback
CVDisplayLinkSetOutputCallback(displayLink, renderCallback, (__bridge void *)self);
//start
CVDisplayLinkStart(displayLink);
//callback
CVReturn renderCallback(CVDisplayLinkRef displayLink,
const CVTimeStamp *inNow,
const CVTimeStamp *inOutputTime,
CVOptionFlags flagsIn,
CVOptionFlags *flagsOut,
void *displayLinkContext){
@autoreleasepool {
update();
//get access to the main thread when drawing to screen (this method is also blocking but way less demanding than the NSApp runloop)
dispatch_sync(dispatch_get_main_queue(), ^{
[gview setNeedsDisplay:YES];
});
}
return 0;
}