Core: Explicitly throttle mousemove events #110148

Closed
Joseph Eagar wants to merge 1 commits from JosephEagar/blender:fix-inbetween-mousemove into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
Member

This PR changes the behavior of INBETWEEN_MOUSEMOVE to operate
as a simple limit on the number of MOUSEMOVE events per second.

The current behavior of INBETWEEN_MOUSEMOVE is indeterminate.
Apparently the idea was to drop MOUSEMOVE events for some
tools during heavy CPU load; this was implemented by
detecting runs of MOUSEMOVE events inside the
event queue and changing their type to INBETWEEN_MOUSEMOVE
(while leaving the event at the head of the run as MOUSEMOVE).

Basically the size of the event queue was used to throttle
MOUSEMOVE events, presumably under the assumption that
the size of the queue is proportional to CPU and GPU load.
There is however another determinant of the current event
queue size: input device drivers. Some tablet drivers will
push events in such a way that INBETWEEN_MOUSEMOVE
events are generated without any significant CPU load.

This caused #93796. While the fix for that bug was to not
ignore INBETWEEN_MOUSEMOVE events, other cases are not so clear.
For example anchored strokes in sculpt mode, along with the grab,
rotate, thumb, snake hook, elastic deform, boundary and pose
brushes are deliberately set to ignore INBETWEEN_MOUSEMOVE
events, and I think this makes sense. But this means the interactivity
of these tools will depend in part on the specific device and driver
setup of individual users, which is not good.

This PR changes the behavior of INBETWEEN_MOUSEMOVE to operate as a simple limit on the number of MOUSEMOVE events per second. The current behavior of INBETWEEN_MOUSEMOVE is indeterminate. Apparently the idea was to drop MOUSEMOVE events for some tools during heavy CPU load; this was implemented by detecting runs of MOUSEMOVE events inside the event queue and changing their type to INBETWEEN_MOUSEMOVE (while leaving the event at the head of the run as MOUSEMOVE). Basically the size of the event queue was used to throttle MOUSEMOVE events, presumably under the assumption that the size of the queue is proportional to CPU and GPU load. There is however another determinant of the current event queue size: input device drivers. Some tablet drivers will push events in such a way that INBETWEEN_MOUSEMOVE events are generated without any significant CPU load. This caused #93796. While the fix for that bug was to not ignore INBETWEEN_MOUSEMOVE events, other cases are not so clear. For example anchored strokes in sculpt mode, along with the grab, rotate, thumb, snake hook, elastic deform, boundary and pose brushes are deliberately set to ignore INBETWEEN_MOUSEMOVE events, and I think this makes sense. But this means the interactivity of these tools will depend in part on the specific device and driver setup of individual users, which is not good.
Joseph Eagar added 1 commit 2023-07-15 22:48:24 +02:00
4a6de9c13e Core: Explicitly throttle mousemove events
The behavior of INBETWEEN_MOUSEMOVE was indeterminate.
Apparently the idea was to drop mousemove events for some
tools during heavy CPU load; this was implemented by
changing the type of runs of MOUSEMOVE events inside the
event queue to INBETWEEN_MOUSEMOVE, with only the event
at the head of the queue MOUSEMOVE.

Basically the size of the event queue was used to throttle
MOUSEMOVE events, presumably under the assumption that
the size of the queue is proportional to CPU and GPU load.
This turned out to be incorrect.

This PR removes the old behavior and uses a simple time
limit instead for throttling.  There is a maximum number
of MOUSEMOVE events per second (MOUSEMOVES_PER_SECOND)
and events that fail this limit are retyped to
INBETWEEN_MOUSEMOVE.
Joseph Eagar requested review from Campbell Barton 2023-07-15 22:48:58 +02:00
Ray molenkamp requested review from Nicholas Rishel 2023-07-15 22:53:52 +02:00

The reason behind INBETWEEN_MOUSEMOVE is that for most operators these do not matter. For example for UI button highlighting or transform tools, doing work for such events would only waste CPU cycles.

This pull request makes those operators do unnecessary work again, which I don't think is the right solution. This is especially a problem when e.g. transforming a heavy mesh that is already slow, this would make it slower still. Sculpt/paint on the other hand get some type of rate limiting from stroke spacing and so are not affected the same way.

I think the solution for this should be in the sculpt/paint operators that do handle INBETWEEN_MOUSEMOVE. From what I remember these don't redraw on such inbetween events, but they could be made to redraw every N ms.

The ideal timing value is not entirely clear, if redrawing is slow compared to the sculpt/paint operation, doing too many redraws can make things even slower.

The reason behind `INBETWEEN_MOUSEMOVE` is that for most operators these do not matter. For example for UI button highlighting or transform tools, doing work for such events would only waste CPU cycles. This pull request makes those operators do unnecessary work again, which I don't think is the right solution. This is especially a problem when e.g. transforming a heavy mesh that is already slow, this would make it slower still. Sculpt/paint on the other hand get some type of rate limiting from stroke spacing and so are not affected the same way. I think the solution for this should be in the sculpt/paint operators that do handle `INBETWEEN_MOUSEMOVE`. From what I remember these don't redraw on such inbetween events, but they could be made to redraw every N ms. The ideal timing value is not entirely clear, if redrawing is slow compared to the sculpt/paint operation, doing too many redraws can make things even slower.

I don't believe we want to pursue this approach. This will just introduce a new bug for users asking why they have periodic straight line jumps in otherwise smooth brush strokes.

In general I suspect our approach of queuing separate events is killing performance, as each and every INBETWEEN_MOUSEMOVE needs to push/pop the full operator call stack. A more mechanically sympathetic approach would be to expose an interface to drain the INBETWEEN_MOUSEMOVE queue and handle them all at once in a single operator call, i.e the way most OS handle mouse events. Bonus points for extending GHOST and WM to queue runs of mouse movements in a single function call.

I don't believe we want to pursue this approach. This will just introduce a new bug for users asking why they have periodic straight line jumps in otherwise smooth brush strokes. In general I suspect our approach of queuing separate events is killing performance, as each and every `INBETWEEN_MOUSEMOVE` needs to push/pop the full operator call stack. A more mechanically sympathetic approach would be to expose an interface to drain the `INBETWEEN_MOUSEMOVE` queue and handle them all at once in a single operator call, i.e the way most OS handle mouse events. Bonus points for extending `GHOST` and `WM` to queue runs of mouse movements in a single function call.
Nicholas Rishel requested changes 2023-07-24 00:59:51 +02:00
Nicholas Rishel left a comment
Member

Rejected for systemic concerns noted in PR comments, requesting changes to put a pin in that.

Rejected for systemic concerns noted in PR comments, requesting changes to put a pin in that.
Campbell Barton requested changes 2024-01-09 03:10:02 +01:00
Campbell Barton left a comment
Owner

Rejecting as the current distinction between MOUSEMOVE & INBETWEEN_MOUSEMOVE works well enough and I'm not convinced removing cursor events is a good approach.

In general I'd rather give operators receive all the events and the operator code can choose to skip some.

Removing INBETWEEN_MOUSEMOVE will impact add-ons too, so this kind of a change could back-fire in ways we don't expect.

Rejecting as the current distinction between MOUSEMOVE & INBETWEEN_MOUSEMOVE works well enough and I'm not convinced removing cursor events is a good approach. In general I'd rather give operators receive all the events and the operator code can choose to skip some. Removing `INBETWEEN_MOUSEMOVE` will impact add-ons too, so this kind of a change could back-fire in ways we don't expect.

Let's close this then.

Let's close this then.

Pull request closed

Sign in to join this conversation.
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
4 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender#110148
No description provided.