Figure out how Quartz Debug works |
||
Issue descriptionIt seems to know when contents has "actually" been committed to the display. This information would be very helpful for scheduling in the GPU process, and for analytics to determine the rate at which we're rendering.
,
Apr 13 2016
Looks like any process can call it: """ typedef int CGSConnectionID; CGSConnectionID _CGSDefaultConnection(void); CGError CGSGetPerformanceData(CGSConnectionID cid, float *outFPS, float *unk, float *unk2, float *unk3); ... float a, b, c, d; CGSGetPerformanceData(_CGSDefaultConnection(), &a, &b, &c, &d); NSLog(@"%f %f %f %f", a, b, c, d); """ """ 2016-04-13 16:40:10.119 frame_rate_test[27937:1371128] 54.722847 163570240.000000 3779.651855 5034.785156 2016-04-13 16:40:10.119 frame_rate_test[27937:1371128] 54.719250 163559808.000000 3780.466553 5035.580566 2016-04-13 16:40:10.119 frame_rate_test[27937:1371128] 54.714527 163546096.000000 3781.223145 5036.311523 2016-04-13 16:40:10.119 frame_rate_test[27937:1371128] 54.710693 163534976.000000 3782.025635 5037.093262 2016-04-13 16:40:10.119 frame_rate_test[27937:1371128] 54.707233 163524944.000000 3782.847168 5037.896484 2016-04-13 16:40:10.119 frame_rate_test[27937:1371128] 54.703812 163515024.000000 3783.670898 5038.701660 2016-04-13 16:40:10.119 frame_rate_test[27937:1371128] 54.700424 163505184.000000 3784.496338 5039.508789 2016-04-13 16:40:10.222 frame_rate_test[27937:1371128] 54.674274 169140448.000000 3566.996582 4868.529297 """
,
Apr 14 2016
It looks like the ether ate one of my responses :(.
Deep in the method _CGXUpdateDisplay, the following 5 functions are called back to back:
"""
rbx = _CGXUpdateDisplaySynchronizeSeed();
_WSPerformanceBlitUpdate(var_53C, *(int8_t *)(r12 + 0x124) & 0xff);
_WSUpdateSignpostSignal(0xd);
_WSUpdateSignpostDispatchAndReset();
_WSPostLocalNotification(0x12c, var_228, 0x8);
"""
This gives us a nice idea of things to look for.
--------------
_WSPerformanceBlitUpdate() increments gTotalUpdateCounter, which is query-able with
CGError CGSGetPerformanceTotalUpdateCount(CGSConnectionID cid, int* b, int *c, int*d, int* e);
This seems to monotically update every 5ms.
--------------
CGError CGSGetWindowFlushSeed(CGSConnectionID cid, int window_id, int*c);
might be what we want. It returns a monotonically updating number. Each time the window is redrawn (from a view changing), it is incremented. Any time the window is obscured, and then brought back into view (but not redrawn), it is incremented.
note that window_id = [self.window performSelector:@selector(_realWindowNumber)];.
-----------------
,
Apr 14 2016
Looking at the CAOpenGLLayer approach: The method CAOpenGLLayer_timer_callback is added as a run loop timer. It's pretty complicated, but one of the methods it calls is _CAImageQueueGetUnconsumedImageCount. I bet we could use that to tell us if our image has been "consumed" by the window server.
,
Apr 14 2016
Adding sunnyps@ and vmiura@, since they had some interest in this topic.
,
Apr 15 2016
I started trying out these methods in Chromium. CGSGetWindowFlushSeed always returns 0 if the content view is layer backed, so it's useless for us. I don't know how to interpret the values from CGSGetPerformanceTotalUpdateCount(), so I'm not sure what to do with it. CGSGetPerformanceData() works as expected, but doesn't provide very granular information.
,
Apr 16 2016
Alright, I think that's all the low hanging fruit. Next things to investigate would be the delightful sounding CGNotificationCenter and registering callbacks with it. Maybe do more digging in CAImageQueue, and in general, understanding the window server better. We should probably get some tests using CGSGetPerformanceData.
,
Jun 22 2016
It would be nice to write a test that uses CGSGetPerformanceData to measure real WebGL performance: https://codereview.chromium.org/2089293002/
,
Jul 15 2016
I ran across the following SPI:
"""
@interface CAContext ()
- (void)setFencePort:(mach_port_t)port;
- (void)setFencePort:(mach_port_t)port commitHandler:(void(^)(void))block;
"""
And this nice block of code:
"""
[CATransaction begin];
[CATransaction setDisableActions:YES];
[m_hostingLayer setFrame:CGRectMake(layerPosition.width(), layerPosition.height(), viewSize.width(), viewSize.height())];
[CATransaction commit];
if (flushSynchronously) {
[CATransaction flush];
#if !HAVE(COREANIMATION_FENCES)
// We can't synchronize here if we're using fences or we'll blow the fence every time (and we don't need to).
[CATransaction synchronize];
#endif
}
m_webPage.send(Messages::DrawingAreaProxy::DidUpdateGeometry());
m_inUpdateGeometry = false;
#if HAVE(COREANIMATION_FENCES)
m_layerHostingContext->setFencePort(fencePort.sendRight());
#endif
"""
Will investigate further.
,
Jul 15 2016
Also this:
"""
typedef enum {
kCATransactionPhasePreLayout,
kCATransactionPhasePreCommit,
kCATransactionPhasePostCommit,
} CATransactionPhase;
@interface CATransaction ()
+ (void)addCommitHandler:(void(^)(void))block forPhase:(CATransactionPhase)phase;
@end
"""
,
Jul 18 2016
Oooh, this looks very promising! |
||
►
Sign in to add a comment |
||
Comment 1 by erikc...@chromium.org
, Apr 13 2016