6

We have two different platform and with CPU frequency the same setting, and found the time cost of canvas->flush() on the rasterizer thread has huge difference at YT start time, the quick one only has 1.632ms at most time, and the slow one has 7.292ms at most time, so is there a way find the root cause of the difference and to optimize it?

cobalt version : Cobalt 11.132145 with ARM-Linux and Opengl

1. enter image description here 2.Code of canvas->flush()

    void HardwareRasterizer::Impl::Submit(
    const scoped_refptr<render_tree::Node>& render_tree,
    const scoped_refptr<backend::RenderTarget>& render_target,
    const Options& options) {
  DCHECK(thread_checker_.CalledOnValidThread());
  scoped_refptr<backend::RenderTargetEGL> render_target_egl(
      base::polymorphic_downcast<backend::RenderTargetEGL*>(
          render_target.get()));
  // Skip rendering if we lost the surface. This can happen just before suspend
  // on Android, so now we're just waiting for the suspend to clean up.
  if (render_target_egl->is_surface_bad()) {
    return;
  }
  backend::GraphicsContextEGL::ScopedMakeCurrent scoped_make_current(
      graphics_context_, render_target_egl);
  // Make sure the render target's framebuffer is bound before continuing.
  // Skia will usually do this, but it is possible for some render trees to
  // have non-skia draw calls only, in which case this needs to be done.
  GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER,
                            render_target_egl->GetPlatformHandle()));
  // First reset the graphics context state for the pending render tree
  // draw calls, in case we have modified state in between.
  gr_context_->resetContext();
  AdvanceFrame();
  // Get a SkCanvas that outputs to our hardware render target.
  SkCanvas* canvas = GetCanvasFromRenderTarget(render_target);
  canvas->save();
  if (options.flags & Rasterizer::kSubmitFlags_Clear) {
    canvas->clear(SkColorSetARGB(0, 0, 0, 0));
  } else if (options.dirty) {
    // Only a portion of the display is dirty. Reuse the previous frame
    // if possible.
    if (render_target_egl->ContentWasPreservedAfterSwap()) {
      canvas->clipRect(CobaltRectFToSkiaRect(*options.dirty));
    }
  }
  // Rasterize the passed in render tree to our hardware render target.
  RasterizeRenderTreeToCanvas(render_tree, canvas, kBottomLeft_GrSurfaceOrigin);
  {
    TRACE_EVENT0("cobalt::renderer", "Skia Flush");
    canvas->flush();
  }
  graphics_context_->SwapBuffers(render_target_egl);
  canvas->restore();
}

enter image description here

enter image description here

bitchainer
  • 535
  • 2
  • 19

1 Answers1

4

The Skia flush() call is the function in which all of the OpenGL functions will be called (prior to that function being called, all of the drawing functions are simply serialized and queued in an internal Skia format).

Therefore, I would investigate your GL driver implementation in this case. It could be that your CPU is waiting on your GPU to consume some of the draw commands sent to it by GLES.

Andrew Top
  • 2,517
  • 1
  • 17
  • 10
  • Hi andrew, I found the fClears.reset() in GrInOrderDrawBuffer::reset in GrInOrderDrawBuffer.cpp cost most time of the skia flush, if remove it(fClears.reset()), then the skia flush time would cost only about 2ms, see the picture above, so is there a way to improve with it? – bitchainer Mar 12 '18 at 07:38
  • Hi andrew, after tracing with the skia code, I found the wait time cost of flush is at the GrGLRenderTarget::onRelease, it just call some egl interfaces, so do you have some suggestion to improve with it? – bitchainer Mar 13 '18 at 09:43
  • GrGLRenderTarget::onRelease will be called when a render target is being deleted. If this is happening each frame, it may be due to an intermediate render target. In your base.gypi file, you can try tweaking (increasing) the value of skia_cache_size_in_bytes, scratch_surface_cache_size_in_bytes, and offscreen_target_cache_size_in_bytes. If those have no effect, if you have access to your EGL implementation, it may be worth digging into it to see exactly what it is doing when onRelease() is called. It is possible that it just happens to be flushing previously queued commands in that call. – Andrew Top Mar 14 '18 at 19:21
  • 1
    Hi andrew, thank you for your suggestion, all the three cache size adjust from 4M to 48M still does not work, I would ask for our egl related engineer for help. – bitchainer Mar 15 '18 at 02:35
  • 1
    Hi, @bitchainer! Did you find a solution for this problem? – Mikolaytis Apr 21 '20 at 22:17