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