Make Metal render loop more stable

Bug: skia:8737
Change-Id: Ib825e5f0c9502692cbecc60fbb68d0d1a2bc635f
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/208672
Auto-Submit: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/samplecode/SampleArc.cpp b/samplecode/SampleArc.cpp
index 54bada0..8c840ea 100644
--- a/samplecode/SampleArc.cpp
+++ b/samplecode/SampleArc.cpp
@@ -189,7 +189,9 @@
 
     bool onAnimate(const AnimTimer& timer) override {
         SkScalar angle = SkDoubleToScalar(fmod(timer.secs() * 360 / 24, 360));
-        fAnimatingDrawable->setSweep(angle);
+        if (fAnimatingDrawable) {
+            fAnimatingDrawable->setSweep(angle);
+        }
         return true;
     }
 
diff --git a/tools/sk_app/MetalWindowContext.mm b/tools/sk_app/MetalWindowContext.mm
index 1ce4e26..7f2d385 100644
--- a/tools/sk_app/MetalWindowContext.mm
+++ b/tools/sk_app/MetalWindowContext.mm
@@ -65,8 +65,16 @@
 sk_sp<SkSurface> MetalWindowContext::getBackbufferSurface() {
     sk_sp<SkSurface> surface;
     if (fContext) {
+        // Block to ensure we don't try to render to a frame that hasn't finished presenting
+        dispatch_semaphore_wait(fInFlightSemaphore, DISPATCH_TIME_FOREVER);
+
+        // TODO: Apple recommends grabbing the drawable (which we're implicitly doing here)
+        // for as little time as possible. I'm not sure it matters for our test apps, but
+        // you can get better throughput by doing any offscreen renders, texture uploads, or
+        // other non-dependant tasks first before grabbing the drawable.
         GrMtlTextureInfo fbInfo;
-        fbInfo.fTexture = [[fMTKView currentDrawable] texture];
+        MTLRenderPassDescriptor* descriptor = fMTKView.currentRenderPassDescriptor;
+        fbInfo.fTexture = [[[descriptor colorAttachments] objectAtIndexedSubscript:0] texture];
 
         GrBackendRenderTarget backendRT(fWidth,
                                         fHeight,
@@ -84,8 +92,6 @@
 }
 
 void MetalWindowContext::swapBuffers() {
-    // Block to ensure we don't try to render to a frame that hasn't finished presenting
-    dispatch_semaphore_wait(fInFlightSemaphore, DISPATCH_TIME_FOREVER);
 
     id<MTLCommandBuffer> commandBuffer = [fQueue commandBuffer];
     commandBuffer.label = @"Present";