Drawing things efficiently - LÖVE internals question
Posted: Wed Oct 24, 2012 8:42 am
There have been several questions about efficiency lately on these forums, and those got me thinking.
I've been wondering whether it would be possible to increase the speed at which things are drawn. I think I've thought of a way, but it'd work only if several assumptions are correct, and it'd involve making a change to LÖVE's boot.lua . And still, it'd be difficult to see any benefit until both options where compared.
** The assumption **
My assumption is that LÖVE "translates" every love.graphics call to a C/C++ OpenGL call. This going around between Lua and C++ takes some time. I've been told that this context-switching takes significant time, but I have no means to attest that.
I tried to browse the LÖVE source code, to verify this assumption, but I'm kindof allergic to C++. I would be grateful if someone with more experience with the source code could confirm this.
** The proposed change **
Instead of switching to C/C++ every time, do that only once, by default when love.draw finishes. love.graphics calls would just "fill up" a pure-Lua table. In other words, this:
Would be translated into a Lua table like this:
love.run would have to be slightly modified. It would need a new function, which I have called love.graphics.flush(). It would be used like this:
** Consequences **
I've been wondering whether it would be possible to increase the speed at which things are drawn. I think I've thought of a way, but it'd work only if several assumptions are correct, and it'd involve making a change to LÖVE's boot.lua . And still, it'd be difficult to see any benefit until both options where compared.
** The assumption **
My assumption is that LÖVE "translates" every love.graphics call to a C/C++ OpenGL call. This going around between Lua and C++ takes some time. I've been told that this context-switching takes significant time, but I have no means to attest that.
I tried to browse the LÖVE source code, to verify this assumption, but I'm kindof allergic to C++. I would be grateful if someone with more experience with the source code could confirm this.
** The proposed change **
Instead of switching to C/C++ every time, do that only once, by default when love.draw finishes. love.graphics calls would just "fill up" a pure-Lua table. In other words, this:
Code: Select all
love.graphics.rectangle("fill", 100, 100, 200, 200)
love.graphics.draw(image, 10, 10)
Code: Select all
-- love.graphics.buffer will be most certainly an internal thing, not to be shared with the user.
-- I'm giving it that name just to make it clear that it's a buffer accesible from the love.graphics functions
love.graphics.buffer = {
{ "rectangle", "fill", 100, 100, 200, 200 },
{ "drawable", image, 10, 10 }
}
Code: Select all
-- inside love.run()
if love.graphics then
love.graphics.clear() -- this empties the buffer
if love.draw then love.draw() end -- this fills the buffer, but doesn't draw anything
love.graphics.flush() -- this draws everything stored in the buffer to OpenGL, with a single context switch
end
- I must stress this: I'm not sure this would make code any faster. There are many things I don't know. But if my assumptions are correct, and a single context switch + parsing a Lua table is faster than multiple context switches, then I think this might be worth trying.
- Custom love.run implementations would not work any more. So this should be released on a new version - 0.9.x, I'd say.
- love.graphics methods called from other places than love.draw (i.e. love.load or love.update) would stop working. I don't see this as a problem, since it is highly discouraged. But there is a difference between discouraging something and making it outright impossible.