Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8102891

No rendering after scene graph update due to poor synchronization

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Fixed
    • Icon: P3 P3
    • 8
    • 8
    • javafx

      I have an app with a simple continuous animation. The animated nodes are expected to be rendered on every frame. I can see that occasionally rendering is skipped between two frame updates correctly performed by the scene graph. The easiest way to observe that is with -Djavafx.pulseLogger=true
      The logger reports FX and render thread activity including the number of rendered nodes:

      PULSE: 28 [83ms:115ms]
      T11 (3 +0ms): CSS Pass
      T11 (3 +0ms): Layout Pass
      T11 (6 +25ms): Waiting for previous rendering
      T11 (31 +5ms): Copy state to render graph
      T8 (75 +1ms): Dirty Opts Computed
      T8 (76 +35ms): Painted
      Counters:
              Nodes rendered: 15
              Nodes visited during render: 15

      PULSE: 29 [67ms:93ms]
      T11 (3 +0ms): CSS Pass
      T11 (3 +0ms): Layout Pass
      T11 (5 +0ms): Waiting for previous rendering
      T11 (5 +2ms): Copy state to render graph
      T8 (90 +0ms): Dirty Opts Computed

      PULSE: 30 [82ms:58ms]
      T11 (3 +0ms): CSS Pass
      T11 (4 +0ms): Layout Pass
      T11 (7 +15ms): Waiting for previous rendering
      T11 (22 +2ms): Copy state to render graph
      T8 (29 +0ms): Dirty Opts Computed
      T8 (30 +21ms): Painted
      Counters:
              Nodes rendered: 15
              Nodes visited during render: 15

      Note that in pulse 29 the render thread was invoked but no nodes had been rendered.

      To understand what really happens I instrumented various steps in pulse processing:
      FX thread:
      QuantumToolikt.pulse -- two events are reported: 'pulse start' and 'pulse end'
      Scene.synchronizeSceneNodes -- the number of dirty nodes is reported
      ViewScene.repaint -- 'addRenderJob' event is reported
      Render thread:
      PresentingPainter.run -- two events, 'lock' and 'unlock' (i.e. enter and exit) are reported.
      BaseNode.accumulateDirtyRegions -- dirty and childDirty flags are reported

      The following sequence of events reveals the synchronization problem:

      [FX] pulse start
      [FX] synchronizeSceneNodes: 15
      [FX} addRenderJob
      [FX] pulse end
      [FX] pulse start
      [FX} synchronizeSceneNodes: 15 -- nodes are synchronized before the previous update has been rendered
      [Render] PresentingPainter: lock
      [Render] BaseNode: dirty: DIRTY chDirty: true -- nodes from two updates will be rendered
      [Render] PresentingPainter: unlock
      [FX] addRenderJob
      [FX} pulse end
      [Render] PresentingPainter: lock
      [Render] BaseNode: dirty: CLEAN chDirty: false -- nothing to render
      [Render] PresentingPainter: unlock
      ...

      While it is true that the FX thread will wait until the render thread is finished with the current RenderJob task, nothing prevents the FX thread from starting a new pulse and synchronizing the nodes again if the previous RenderJob has not yet started.
      On embedded, even if there has been no actual rendering during a render task the back buffer is drawn at the end of the task anyway wasting CPU/GPU resources for no actual value.

            snorthov Steve Northover (Inactive)
            omazurov Oleg Mazurov (Inactive)
            Votes:
            1 Vote for this issue
            Watchers:
            10 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported: