Improve performance for scaled polygons

Hello everyone,

I am still relatively new to the platform. Still waiting for my device. So for now I am only testing a Lua-project in the simulator on macOS .

I added two polygons with roughly 1k vertices and dimensions of ~600x600. I noticed the frame rate drops significantly when scaling them up. Everything works smooth when they are scaled up to maybe 10 times when I notice the frames drop. At 20x scaling the frame rate is merely 5fps. I don't know how polygons work in the background. I would think that only the part visible on the screen should be rendered.

  1. Can I somehow mask the polygon or force it to only render in screen space?

I've tried setAlwaysRedraw(false) and mark the dirty rect. Maybe I've done something wrong with that but there is no difference whether I do that or not.

  1. Could this problem be solved if I would rewrite everything in C, or would I need to split the polygon into many small pieces anyway?

There's no clock speed limiter on the simulator, so if it's dropping frames there, the hardware isn't going to stand a chance. You'll definitely want to address this.

It's possible that the implementation is rasterizing the entire polygon, even for pixels outside of the target area, and simply skipping over the problem pixels. If so, it makes sense that performance drops as the scale increases, because the number of pixels also increases at a rate equal to the square of the increase in scale.

From the point of view of computational complexity, I imagine it's probably a safer bet to process an arbitrary n-gon in this way as opposed to computing a clipped shape that intersects with the bounds of the target surface. In most cases the shape is likely to be of the approximate size of the screen or smaller, so doing all that extra work would slow it down in the typical use case.

I would guess that triangles are probably pretty well optimized in the rasterizer. Try converting your shapes to groups of triangles and see if performance improves.

1 Like

If it's slowing down the simulator it's probably not going to work at all on the device. :frowning: There's some code in the simulator to try and rate limit the Lua VM to match the device but that's not where your slowdown is happening. I'm really surprised it seems to have a sharp cliff when scaling up, though.. Sounds like a bug in some odd edge case.

Hm. No luck here reproducing that with this test:

p =
for i=1,1000 do p:setPointAt(i, math.random(), math.random()) end

scale =

function playdate.update()
	p = p * scale
	playdate.drawFPS(0, 228)

It stays at 30 fps until it's off screen. It actually does a lot better on the device than I expected. It runs at 30 until it's scaled up to around a quarter of the height of the screen, falls to 14 fps once it's full height, then works back up to 30 as line segments go off screen.

If you've got a reproducible demo, that'd be very useful!

1 Like

ah, and if I fillPolygon() instead it overflows the stack on the hardware because I'm using stack space to sort the vertices. Boo.

reading through your little code snippet I realised I'm not drawing a polygons, but a VectorSprite that I've snatched from the SDK's Asteroids example, which in turn draws the polygons.

After removing the intermediate layer and drawing the polygon right into the graphics'.. ¿frame buffer? I had no more performance issues other than the simulator throttling the frames to 30fps no matter what I draw.

So thanks for the tips, and I shall provide my example code right away next time.

Thank you for your quick reply. For now it seems the performance issue is gone after I stopped using a sprite to draw the polyton, which unfortunately I did not mention in the initial question.

However the simulator still caps my frame rate at a very steady 30fps no matter what I do, so I can't really expect the code from running smoothly on the hardware. When I'll have a test device and notice issues I will somehow find a way to triangulate the polygon. I guess doing Delaunay triangulation on the device won't be fast either. :smiley:

Are you doing setRefreshRate(0) for unlocked frame rate, or some other number for a rate greater than 30?

And I also used VectorSprite for my recent Cosmic Trash prototype and also had to remove it for performance reasons. I was rendering 2 scaled polygons each with only 16 vertices and frame rate was dropping to 20 during movement/translation/redrawing. This was surprising because using a sprite should speed things up by not having to redraw.

I did not know there was a rate limiter that I needed to disable. I just saw the frames dropping from 60 or so to 30 in the first second when the game starts. I guess for now limiting the frame rate makes sense for me.