Bevy utilizes pipelined rendering as illustrated in the image below. It is rendering the previous frame at the same time as the app is processing the next frame update.
While integrating Iced as a Bevy plugin, I learned that Iced does not currently work with such an approach due to text caching in the widget state. The reason is that the widget stores text as a
Paragraph
(in an Arc
), and gives a Weak
reference to the renderer. If the strong reference in the widget is dropped, the weak reference in the renderer is invalidated. So when the frame is to be rendered, there is a race between the rendering of the previous frame and the creation of the next frame. If the next frame needs to update the text, and it happens before the render thread manages to render the previous frame, the Paragraph
is dropped and no text is rendered.
Usually the Paragraph
’s stored within the widgets don’t update between frames, and in that case there is no problem. The problem occurs for one frame whenever the Paragraph
is replaced. For end users this is perhaps most frequently seen as text blinking while typing in a TextInput
field.
To solve the issue, we can use a strong reference in the renderer instead of a weak reference. I have implemented this and it works. What do you think? Are there any reasons why we should keep it as a weak reference? And do you think pipelined rendering is something that would be interesting to support in the Iced runtime as well?