From 18f17883bd787e088e60edc93075d551d1d2b9fd Mon Sep 17 00:00:00 2001 From: Sebastian Krzyszkowiak <dos@dosowisko.net> Date: Sat, 21 Oct 2023 04:20:52 +0200 Subject: [PATCH] py,st3m: Reactor: Don't make draw calls unless the drawlist is submittable In the current graphics pipeline, only a single drawlist can be submitted to the rasterizer's queue at a time. This means that at a given time, there are two "pending" frames: the one currently rasterized, and the one placed in the queue. Once the queued frame's rasterization starts, a new frame can be queued. This means that to achieve full pipeline utilization, a new frame can be submitted anytime between the moment when the queue becomes empty and when the rasterization of the new frame finishes. Previously, Reactor would eagerly make the draw calls as soon as a drawlist became free, setting the drawlist content in stone. Then, at the end of each think cycle, it would check whether the queue became free and submit the frame if that's the case. Since draw calls are lightweight, it usually wasn't the case right away, meaning that the already prepared drawlist would have to wait for (at least) the next think cycle until being submitted - for no actual benefit, as another frame would still be rasterized at that point of time. Reduce latency and only make the draw calls once a drawlist becomes submittable. The worst case latency regression is a fraction of draw call duration (which usually is very short anyway), while best case improvement is frame rendering time plus think cycle time (which can be very long for heavy frames). --- python_payload/st3m/reactor.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/python_payload/st3m/reactor.py b/python_payload/st3m/reactor.py index 3b4190fe3e..46bb5a744f 100644 --- a/python_payload/st3m/reactor.py +++ b/python_payload/st3m/reactor.py @@ -147,20 +147,19 @@ class Reactor: self._top.think(hr, delta) # Draw! - if self._ctx is None and sys_display.pipe_available(): - self._ctx = sys_display.ctx(0) - if self._ctx is not None: + if sys_display.pipe_available() and not sys_display.pipe_full(): + ctx = sys_display.ctx(0) + if ctx is not None: if self._last_ctx_get is not None: diff = start - self._last_ctx_get self.stats.record_render_time(diff) self._last_ctx_get = start - self._ctx.save() - self._top.draw(self._ctx) - self._ctx.restore() - if self._ctx is not None and not sys_display.pipe_full(): - sys_display.update(self._ctx) - self._ctx = None + ctx.save() + self._top.draw(ctx) + ctx.restore() + + sys_display.update(ctx) # Share! if ftop.run(delta): -- GitLab