Severe FPS drops on a 240Hz high-refresh-rate display

Severe frame rate drop issue.
Environment: Laptop with a high-resolution display (2560×1600). It runs smoothly at 60Hz, and stats shows a stable 60 FPS. However, when switching the display refresh rate to 240Hz, stats only shows around 30 FPS. I don’t know how to solve this issue.

Related code:
initRenderer() {

const viewElement = document.getElementById(this.id)

this.renderer = new THREE.WebGLRenderer({ antialias: true, powerPreference: 'high-performance' })

this.renderer.outputColorSpace = THREE.SRGBColorSpace

this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 1))

this.renderer.setSize(viewElement.clientWidth, viewElement.clientHeight)

viewElement.appendChild(this.renderer.domElement)

this.resizeRender({ width: viewElement.clientWidth, height: viewElement.clientHeight })

}

resizeRender({ width = 0, height = 0 } = {}) {

this.width = width

this.height = height

if (!this.renderer || width <= 0 || height <= 0) return

this.renderer.setSize(width, height)

}

animate() {

this.flushPendingHumanActions()

this.renderer.setScissorTest(true)

for (let i = 0; i < this.viewsCount; i++) {

  const view = this.views\[i\]

  if (view.viewHelper && view.viewHelper.animating === true) {

    view.viewHelper.update(delta)

  }


  const camera = view.camera

  const element = document.getElementById(view.id)

  if (!camera || !this.renderer || !element) {

    continue

  }

  const canvasRect = this.renderer.domElement.getBoundingClientRect()

  const rect = element.getBoundingClientRect()

  const width = rect.width

  const height = rect.height

  const left = rect.left - canvasRect.left

  const bottom = canvasRect.bottom - rect.bottom

  this.renderer.setViewport(left, bottom, width, height)

  this.renderer.setScissor(left, bottom, width, height)

  camera.aspect = width / height

  camera.updateProjectionMatrix()

  this.renderer.render(this.scene, camera)

  if (view.viewHelper) {

    const viewHelperLeft = left + width - VIEWHELPER_SIZE

    this.renderer.setScissor(

      viewHelperLeft,

      bottom,

      VIEWHELPER_SIZE,

      VIEWHELPER_SIZE

    )

    this.renderer.autoClear = false

    try {

      view.viewHelper.render(this.renderer, { left: viewHelperLeft, bottom })

    } finally {

      this.renderer.autoClear = true

      this.renderer.setScissor(left, bottom, width, height)

    }

  }

}

if (this.perfMonitor) {

  this.perfMonitor.update()

}

}

240 hz means you have 1000/240 milliseconds for your entire frame.. so like.. 4 msec…

It also looks like you’re rendering multiple viewports per frame?

How big is views count?

And.. how are you calling animate.. via renderer.setAnimationLoop ?

You’re probably right on the edge of what can reasonably be scheduled in requestAnimationFrame..

Regardless.. what you probably want to do is check the performance profile/capture in chrome…
It will tell you which parts are taking most of the frame time, and you can narrow down what you have to optimize from there.

You can also check renderer.info.render at the end of “animate” and check what your triangle counts + drawcall counts are:

If you’re trying to show multiple viewports, you probably want to make sure that your number of drawcalls is <~200, number of triangles ~2 million or so max… (rough numbers)