General discussion about LÖVE, Lua, game development, puns, and unicorns.
ddabrahim
Prole
Posts: 9
Joined: Mon May 17, 2021 8:05 pm
Contact:

Hi.

I am a complete beginner with both LOVE and Lua.
When I learn a new framework/engine, the first thing I always do is a raw performance test where I move and rotate around a bunch of sprites on the screen and check distance from an object that follow the mouse, once any of the moving objects get close to the mouse, I remove it from rendering and delete it.

In this test, LOVE did not performed too well compared to others. I was getting only 30FPS with 'just' 10k sprites on the screen NOT moving. Not that I need this many, but I do like to know the limits the framework has that I am using, and other frameworks do perform a lot better in similar scenario. With other frameworks, usually I get 30FPS with 20k-100k sprites MOVING on the screen on same hardware.

I am using only a for loop to iterate through each and every sprite stored in a table to draw them on the screen and compare distance and remove them from the table. It is obviously not optimal but some frameworks even this way perform 3x better than LOVE, so wondering if is there any technique I could use to get better results with LOVE in this simple test?

For one, I was thinking about batch rendering, would that be possible to draw all sprites with a single draw call for example instead of a for loop?
An other thing I was thinking about is to iterate through each instance in update asynchronously and just use a global in the draw callback function, would something like that be possible, useful?
Or any other ideas?

Here is the code to show what I'm doing:
https://gofile.io/d/Ibvlfl

I would appreciate any help.
Thanks.
Last edited by ddabrahim on Mon May 31, 2021 9:09 pm, edited 1 time in total.
grump
Party member
Posts: 749
Joined: Sat Jul 22, 2017 7:43 pm

### Re: Tips about optimising performance

If you posted your test code, then people could tell you why you're doing it wrong.
zorg
Party member
Posts: 3096
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

### Re: Tips about optimising performance

What grump said; some more info: löve already uses auto-batching (unless you do something that breaks said batching), or you can use SpriteBatch objects to do batching and draw the batch itself with one call.
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
ddabrahim
Prole
Posts: 9
Joined: Mon May 17, 2021 8:05 pm
Contact:

### Re: Tips about optimising performance

grump wrote: Mon May 31, 2021 7:01 pm If you posted your test code, then people could tell you why you're doing it wrong.
Done, I have updated the original post with a link:
https://gofile.io/d/Ibvlfl
ddabrahim
Prole
Posts: 9
Joined: Mon May 17, 2021 8:05 pm
Contact:

### Re: Tips about optimising performance

zorg wrote: Mon May 31, 2021 7:35 pm What grump said; some more info: löve already uses auto-batching (unless you do something that breaks said batching), or you can use SpriteBatch objects to do batching and draw the batch itself with one call.
Thanks, SpriteBatch sounds like what I am looking for, I'll look in to it.
grump
Party member
Posts: 749
Joined: Sat Jul 22, 2017 7:43 pm

### Re: Tips about optimising performance

Those are not really sprites. The geometry for 20,000 circles drawn in immediate mode has to be constructed, transformed and transmitted to the GPU in every frame. At 30 fps, that's maybe 15,000,000 vertices per second streamed to the GPU, possibly more.

If you draw one pair of circles to a Canvas, which makes it an actual sprite, and use that in a SpriteBatch it should be faster. Or you can make a mesh and use drawInstanced, but that's more complicated.
togFox
Party member
Posts: 207
Joined: Sat Jan 30, 2021 9:46 am

### Re: Tips about optimising performance

Or use actual sprites maybe (I didn't see the code but assuming code uses love.draw.circle)
ddabrahim
Prole
Posts: 9
Joined: Mon May 17, 2021 8:05 pm
Contact:

### Re: Tips about optimising performance

grump wrote: Mon May 31, 2021 9:52 pm draw one pair of circles to a Canvas, which makes it an actual sprite, and use that in a SpriteBatch it should be faster. Or you can make a mesh and use drawInstanced, but that's more complicated.
Thank you. I'm going to look in to that.
togFox wrote: Tue Jun 01, 2021 6:07 am Or use actual sprites maybe (I didn't see the code but assuming code uses love.draw.circle)
I also tried to draw images using love.graphics.draw() in case that is what you mean, but I was getting similar performance, did not make much difference.
Nikki
Prole
Posts: 41
Joined: Wed Jan 25, 2017 5:42 pm

### Re: Tips about optimising performance

You could use a Canvas (aka render to Texture)

the existing code on my low end machine starts at 30 fps, the canvas code below 200 fps

Code: Select all


local player = {}
local coins = {}

love.window.setVSync( false )
player.x = 100
player.y = 100
player.draw = function()
player.x = love.mouse.getX()
player.y = love.mouse.getY()
love.graphics.setColor(1,1,1)
love.graphics.setColor(1,0,0)
end
player.distanceFrom = function(_other)
local horizontal_distance = player.x - _other.x
local vertical_distance = player.y - _other.y

local a = horizontal_distance * horizontal_distance
local b = vertical_distance ^2

local c = a + b
local distance = math.sqrt(c)

return distance
end

love.graphics.setCanvas(canvas)
love.graphics.clear()
love.graphics.setBlendMode("alpha")
love.graphics.setColor(0.7,0.5,0)
love.graphics.setColor(1,1,1)
love.graphics.setCanvas()

for i =1,10000,1 do
end

end

function love.update(dt)

for i,coin in ipairs(coins) do
table.remove(coins,i)
end
end

end

function love.draw()

player.draw()
love.graphics.setColor(1,1,1)
love.graphics.setBlendMode("alpha", "premultiplied")
for i,coin in ipairs(coins) do
coin.draw()
end
love.graphics.setBlendMode("alpha")

love.graphics.setColor(1,0,0)
love.graphics.print(love.timer.getFPS())
end

local coin = {}
coin.x = math.random(0,1000)
coin.y = math.random(0,700)

coin.draw = function()
love.graphics.draw(canvas, coin.x, coin.y)
end

return coin
end


edit:
and removing the coin.draw() function
to just do that render code inline gives me another 40fps

Code: Select all

for i,coin in ipairs(coins) do
love.graphics.draw(canvas, coin.x, coin.y)
end

ddabrahim
Prole
Posts: 9
Joined: Mon May 17, 2021 8:05 pm
Contact:

### Re: Tips about optimising performance

Thanks a lot @Nikki, it was very useful, was not sure what is the best way to use canvas to reduce the number of draw calls.
An other thing I also did after is to draw only what is actually on the screen and even after I implement a camera and move around I get decent performance now.

### Who is online

Users browsing this forum: Google [Bot] and 16 guests