Skip to content

Commit 31122c3

Browse files
committed
Add a CADisplayLink to the metal viewcontroller as well
1 parent 6c84cfd commit 31122c3

File tree

3 files changed

+46
-19
lines changed

3 files changed

+46
-19
lines changed

ios/ViewController.mm

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,11 +283,12 @@ - (void)displayLinkFired:(CADisplayLink *)dl {
283283
NSTimeInterval timestamp = dl.timestamp;
284284
NSTimeInterval targetTimestamp = dl.targetTimestamp;
285285

286+
// Probably don't need to call this, we handle it ourselves below.
287+
NativeVSync(presentId, from_mach_time_interval(timestamp), from_mach_time_interval(targetTimestamp));
288+
286289
// Ensure context is current before drawing
287290
[EAGLContext setCurrentContext:self.glContext];
288291

289-
NativeVSync(presentId, from_mach_time_interval(timestamp), from_mach_time_interval(targetTimestamp));
290-
291292
// Trigger GLKView draw, which in turn calls glkView:drawInRect.
292293
[self.glView display];
293294
}

ios/ViewControllerMetal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,7 @@
1111

1212
/** The Metal-compatibile view. */
1313
@interface PPSSPPMetalView : UIView
14+
@property (nonatomic, strong) CADisplayLink *displayLink;
15+
- (void)startDisplayLink;
16+
- (void)stopDisplayLink;
1417
@end

ios/ViewControllerMetal.mm

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
#import <QuartzCore/CADisplayLink.h>
2+
#import <Metal/Metal.h>
3+
14
#import "AppDelegate.h"
25
#import "ViewControllerMetal.h"
36
#import "DisplayManager.h"
@@ -35,6 +38,8 @@ @interface PPSSPPViewControllerMetal () {
3538

3639
@implementation PPSSPPViewControllerMetal {}
3740

41+
PPSSPPMetalView *metalView;
42+
3843
- (id)init {
3944
self = [super init];
4045
return self;
@@ -66,11 +71,7 @@ void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLaye
6671
int desiredBackbufferSizeX = g_display.pixel_xres;
6772
int desiredBackbufferSizeY = g_display.pixel_yres;
6873

69-
//WARN_LOG(G3D, "runVulkanRenderLoop. desiredBackbufferSizeX=%d desiredBackbufferSizeY=%d",
70-
// desiredBackbufferSizeX, desiredBackbufferSizeY);
71-
7274
if (!graphicsContext->InitFromRenderThread(metalLayer, desiredBackbufferSizeX, desiredBackbufferSizeY)) {
73-
// On Android, if we get here, really no point in continuing.
7475
// The UI is supposed to render on any device both on OpenGL and Vulkan. If either of those don't work
7576
// on a device, we blacklist it. Hopefully we should have already failed in InitAPI anyway and reverted to GL back then.
7677
ERROR_LOG(Log::G3D, "Failed to initialize graphics context.");
@@ -124,6 +125,9 @@ - (bool)runVulkanRenderLoop {
124125

125126
CAMetalLayer *metalLayer = (CAMetalLayer *)self.view.layer;
126127
g_renderLoopThread = std::thread(VulkanRenderLoop, graphicsContext, metalLayer);
128+
129+
[(PPSSPPMetalView *)self.view startDisplayLink];
130+
127131
return true;
128132
}
129133

@@ -134,6 +138,8 @@ - (void)requestExitVulkanRenderLoop {
134138
ERROR_LOG(Log::System, "Render loop already exited");
135139
return;
136140
}
141+
[(PPSSPPMetalView *)self.view stopDisplayLink];
142+
137143
_assert_(g_renderLoopThread.joinable());
138144
exitRenderLoop = true;
139145
g_renderLoopThread.join();
@@ -190,18 +196,9 @@ - (void)loadView {
190196

191197
- (void)viewDidLoad {
192198
[super viewDidLoad];
193-
[self hideKeyboard];
194-
195-
[[DisplayManager shared] setupDisplayListener];
196199

197200
INFO_LOG(Log::System, "Metal viewDidLoad");
198201

199-
UIScreen* screen = [(AppDelegate*)[UIApplication sharedApplication].delegate screen];
200-
self.view.frame = [screen bounds];
201-
self.view.multipleTouchEnabled = YES;
202-
// self.view.insetsLayoutMarginsFromSafeArea = NO;
203-
// self.view.clipsToBounds = YES;
204-
205202
graphicsContext = new IOSVulkanContext();
206203

207204
[[DisplayManager shared] updateResolution:[UIScreen mainScreen]];
@@ -210,11 +207,8 @@ - (void)viewDidLoad {
210207
_assert_msg_(false, "Failed to init Vulkan");
211208
}
212209

213-
if ([[GCController controllers] count] > 0) {
214-
[self setupController:[[GCController controllers] firstObject]];
215-
}
216-
217210
INFO_LOG(Log::G3D, "Detected size: %dx%d", g_display.pixel_xres, g_display.pixel_yres);
211+
INFO_LOG(Log::System, "Done with metal viewDidLoad");
218212
}
219213

220214
- (UIView *)getView {
@@ -266,4 +260,33 @@ @implementation PPSSPPMetalView
266260
/** Returns a Metal-compatible layer. */
267261
+(Class) layerClass { return [CAMetalLayer class]; }
268262

263+
- (void)dealloc {
264+
[self stopDisplayLink];
265+
}
266+
267+
#pragma mark - Display Link
268+
269+
- (void)startDisplayLink {
270+
NSLog(@"Starting display link");
271+
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(onVSync:)];
272+
self.displayLink.preferredFramesPerSecond = 60; // or 0 for native refresh rate
273+
[self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
274+
}
275+
276+
- (void)stopDisplayLink {
277+
NSLog(@"Stopping display link");
278+
[self.displayLink invalidate];
279+
self.displayLink = nil;
280+
}
281+
282+
- (void)onVSync:(CADisplayLink *)dl {
283+
static uint64_t presentId = 0;
284+
presentId++;
285+
286+
NSTimeInterval timestamp = dl.timestamp;
287+
NSTimeInterval targetTimestamp = dl.targetTimestamp;
288+
289+
NativeVSync(presentId, from_mach_time_interval(timestamp), from_mach_time_interval(targetTimestamp));
290+
}
291+
269292
@end

0 commit comments

Comments
 (0)