fix: SG-43585: Performance improvement of pyevaluate and pyexec - #1351
fix: SG-43585: Performance improvement of pyevaluate and pyexec#1351cedrik-fuoco-adsk wants to merge 6 commits into
Conversation
Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>
Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>
Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>
Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>
a022cca to
67bcfcf
Compare
…atency The Qt6/PySide6 migration regressed the JS->Python QWebChannel bridge in docked QWebEngineView panels: pyevaluate round-trips grew unbounded (into the seconds) while media plays, where Qt5 stayed flat (~8 ms). Root cause is the per-presented-frame ~80-90 ms full-window QOpenGLWidget composite, which serializes on the GUI thread and starves QWebChannel delivery. The two prior fixes (edit-mode churn skip, settle-window removal) only address the non-playing path, so the regression persisted whenever a handler started playback. Render the RV viewport as a native QOpenGLWindow (new GLWindow) embedded via QWidget::createWindowContainer, instead of a QOpenGLWidget: - The top-level QMainWindow is no longer forced onto the OpenGL RHI backend, so docked QWebEngineView panels render on the platform-default backend and QT_QUICK_BACKEND=software is no longer needed (removed). - The viewport presents on its own surface, off the full-window widget composite, so playback no longer starves the bridge. Bridge latency stays flat and self-healing while playing. GLView becomes a plain QWidget host that delegates the API RV expects to the GLWindow; QTGLVideoDevice gains a window-backed path alongside the widget one. Also fixed, exposed by the surface change: - Presentation / second output: DesktopVideoDevice::open no longer dereferences the control device's (now-null) QOpenGLWidget; ScreenView shares a QOpenGLContext via new backing-agnostic QTGLVideoDevice::glShareContext()/ glSurfaceFormat(). - Set Qt::AA_ShareOpenGLContexts (documented QtWebEngine requirement) so the second-output and upload-worker GL surfaces share with the viewport, and drop a null-context dereference in newSharedContextWorkerDevice that crashed when Multithread GPU Upload was enabled. - The UI blocking overlay is reworked from a raster child widget into a frameless translucent top-level window so it can dim and block input over the native viewport. Validated on Windows (release): flat bridge latency under playback spam, all web panels render docked, and viewport/events/drag-drop/annotations/ presentation/blocking-overlay all work. macOS and HDPI passes still pending. Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>
42d33f6 to
6879c31
Compare
|
While this commit (6879c31) seems promising in fixing the issue in my test, it's a shift in how GLView works, and it's experimental. I only tested it on Windows. @bernie-laberge @eloisebrosseau From my observation and testing, the root cause seems to be the following:
The fix:
Why Qt5 didn't have this problemBefore the Qt6 port, RV's viewport was a
|

SG-43585: Performance improvement of pyevaluate and pyexec
Linked issues
none
Summarize your change.
Two independent performance fixes for JS→Python web-panel bridge latency in Qt6:
Skip the redundant view-edit-mode deactivate→reactivate churn when a view change doesn't actually change the edit mode.
Stop a static (non-playback) askForRedraw() from opening the 2-second continuous-repaint "settle window".
Describe the reason for the change.
After the Qt5→Qt6 migration, JS<>Python web-panel bridge round-trips (
pyevaluate/pyexec) became slow and grew unbounded whenever the handler did RV work such asclearSession()/addSourceVerbose(). The bridge is synchronous on the Qt main (GUI) thread, so any redundant work RV does on that thread directly delays delivery of queued bridge calls. Two sources of avoidable GUI-thread work were the root cause:Redundant edit-mode churn.
clearSession()sets the default view twice withforce=true. Eachbefore/afterview-change event toggled the same view edit mode off and back on (up to 4× per clear), rebuilding menus and event tables for no net change.Settle-window repaint storm. A static
askForRedraw()started a 2-second window that keptisUpdating()true, so the ~120 Hz heartbeat kept repainting for ~2 s even after the single needed frame had been drawn. In Qt5 eachQGLWidgetswapped its own back buffer cheaply, so this was nearly free; in Qt6 every redraw forces a full-windowQOpenGLWidgetrecomposite + present, so the window saturated the GUI thread long after any real drawing was needed.First commit cuts the time it takes to do a
clearSession.Second commit makes a static redraw cost a single frame instead of ~2 s of continuous composites.
Describe what you have tested and on which operating system.
Windows