LÖVELINESS a LÖVE Chrome Extension

Discuss any ports of LÖVE to different platforms.
User avatar
Nixola
Inner party member
Posts: 1949
Joined: Tue Dec 06, 2011 7:11 pm
Location: Italy

Re: LÖVELINESS a LÖVE Chrome Extension

Post by Nixola »

I've only noticed that The Binding of Crate Box can't reach 60FPS on my PC with LÖVELINESS (it might be the Ubuntu Nvidia driver), while it can using LÖVE
Also, oddly enough, I don't have shader support with LÖVE but I've got it with LÖVELINESS.
lf = love.filesystem
ls = love.sound
la = love.audio
lp = love.physics
lt = love.thread
li = love.image
lg = love.graphics
User avatar
farvardin
Party member
Posts: 167
Joined: Sat Jun 28, 2008 6:46 pm

Re: LÖVELINESS a LÖVE Chrome Extension

Post by farvardin »

binji wrote:
farvardin wrote:so it works with google chrome, but not with chromium on linux mint
Yes, this is a known issue https://github.com/binji/love-nacl/issues/17. Linux Mint doesn't include the Native Client plugin with Chromium for some reason. It's also strange that the "test" button didn't work. That should have launched a new window that would tell you pretty quickly that Native Client was not enabled.

I've updated chromium later, and the test button does work now.
User avatar
Nixola
Inner party member
Posts: 1949
Joined: Tue Dec 06, 2011 7:11 pm
Location: Italy

Re: LÖVELINESS a LÖVE Chrome Extension

Post by Nixola »

This update broke Mari0 from the examples page, at least for me on Ubuntu x64 with Chrome 29.0.1547.65 and the Ubuntu Nvidia driver 325 from xorg-edgers; the one downloaded from Stabyourself works. I can only see the LÖVELINESS background color with yours, but rightclicking in the area where the game should be doesn't do anything.
EDIT: Great, after the first run the downloaded one doesn't work either, same as before. Something with love.filsesystem maybe?
EDIT (2): This is all I get in the console:

Code: Select all

onPortConnected: injected
port.onMessage: {"cmd":"setSettings","data":{"enabled":true,"textColor":"rgb(255, 255, 255)","backgroundColor":"rgb(70, 136, 71)"},"sender":"background"}
onPortConnected: background
port.onMessage: {"cmd":"setSettings","data":{"enabled":true,"textColor":"rgb(255, 255, 255)","backgroundColor":"rgb(70, 136, 71)"},"sender":"background"}
It seems to run sometimes, actually, but I often have to reload the page to make it work
lf = love.filesystem
ls = love.sound
la = love.audio
lp = love.physics
lt = love.thread
li = love.image
lg = love.graphics
Damien666
Prole
Posts: 10
Joined: Tue Sep 17, 2013 3:12 am

Re: LÖVELINESS a LÖVE Chrome Extension

Post by Damien666 »

Just got this, its amazing , if you wanna download just right click link and click save link.
User avatar
binji
Prole
Posts: 32
Joined: Fri Apr 26, 2013 9:43 am
Contact:

Re: LÖVELINESS a LÖVE Chrome Extension

Post by binji »

Nixola wrote:I've only noticed that The Binding of Crate Box can't reach 60FPS on my PC with LÖVELINESS
I looked into this: the problem is likely that The Binding of Crate Box draws everything as separate image draw calls. I haven't tried it, but I bet switching this to use a spritebatch will improve performance. (A little background: for security reasons, NaCl runs in its own process. But this also means that draw calls have to be sent to the Chrome GPU process for rendering, which is slower than having it all in one process. Batching draw calls is good to do on all platforms, but really helps on NaCl)
Nixola wrote:It seems to run sometimes, actually, but I often have to reload the page to make it work
This may be related to https://github.com/binji/love-nacl/issues/23. I've noticed that mari0 is a bit flaky when loading, even from standalone LÖVE. My guess is some synchronization problem with its multithreaded loading, but I haven't really looked into it too closely. It's not too hard to repro, though, so maybe I'll investigate. :)
[[LÖVE Chrome Extension]]
LÖVELINESS
Examples page
Github project page
User avatar
Nixola
Inner party member
Posts: 1949
Joined: Tue Dec 06, 2011 7:11 pm
Location: Italy

Re: LÖVELINESS a LÖVE Chrome Extension

Post by Nixola »

LÖVELINESS does NOT like Bezier Goodness.

Code: Select all

onPortConnected: injected
port.onMessage: {"cmd":"setSettings","data":{"enabled":true,"textColor":"rgb(255, 255, 255)","backgroundColor":"rgb(70, 136, 71)"},"sender":"background"}
onPortConnected: background
port.onMessage: {"cmd":"setSettings","data":{"enabled":true,"textColor":"rgb(255, 255, 255)","backgroundColor":"rgb(70, 136, 71)"},"sender":"background"}
got module message: download:0,0
got module message: download:12715,0
got module message: download:14163,0
got module message: download:15611,0
got module message: download:19027,0
Done.
 file.php:1
got module message: OK
usage: 487 quota: 5242880 filesystem.js:113
Got command: fileSystemAccess params: yes
 file.php:1
Got command: makeDir params: /.love
 file.php:1
Got command: makeDir params: /.love/Particle Editor
 file.php:1
Got command: copyFile params: /.love/Particle Editor/run
 file.php:1
Got command: run params: 
 file.php:1
got module message: setWindow:800,600
NativeClient: NaCl module crashed file.php:1
lf = love.filesystem
ls = love.sound
la = love.audio
lp = love.physics
lt = love.thread
li = love.image
lg = love.graphics
User avatar
binji
Prole
Posts: 32
Joined: Fri Apr 26, 2013 9:43 am
Contact:

Re: LÖVELINESS a LÖVE Chrome Extension

Post by binji »

Nixola wrote:LÖVELINESS does NOT like Bezier Goodness.
Works for me. I took a look at your output, and it looks like it was actually failing on the "Particle System Editor" file here. I was able to get LÖVELINESS to crash now.

It looks like it is failing because Particle System Editor tries to create a ParticleSystem with size 0. I've fixed that bug, and it will be pushed out in the next release of LÖVELINESS.
binji wrote:I looked into this: the problem is likely that The Binding of Crate Box draws everything as separate image draw calls. I haven't tried it, but I bet switching this to use a spritebatch will improve performance.
And, as is always the case, if you guess about performance issues you will be wrong (or at least, not entirely right). I wrote a quick inline Lua profiler for this game, and found that the most expensive calls were creating the ParticleSystems. Each one creates its own SpriteBatch, which creates a Vertex Buffer Object. The default code here was calling glGetError at least twice, which is slow on NaCl (explained below). I have a fix for this in the next release of LÖVELINESS too.

This will run at 60fps most of the time, but if there's lots of fire (very heavy particle effect) it can drop to 30fps. It turns out that creating a ParticleSystem is still kinda slow. I made a quick optimization to the game to reuse destroyed particle systems and I'm able to run at 60fps pretty consistently. I may just add this optimization directly to LÖVELINESS, but I haven't yet.

And of course, there are a few other things that are slow but not worth worrying about too much. All the individual draw calls are pretty slow (as I guessed above), as is drawing the background. Once I hit 60fps I was not that interested in profiling anymore. :)

* why glGetError is slow: NaCl puts all GL calls into a command buffer which is executed by the GPU process of Chrome. When you call glGetError you force a command buffer flush, and all commands must be executed immediately so you can determine if there is an error. But there is no guarantee that your commands are going to execute immediately, so instead your code is blocked until the Chrome GPU process decides to execute those commands. And that's for each call to glGetError! So if you call 200/frame (such as Binding of CrateBox does) you're gonna have a bad time. :)
[[LÖVE Chrome Extension]]
LÖVELINESS
Examples page
Github project page
User avatar
slime
Solid Snayke
Posts: 3162
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: LÖVELINESS a LÖVE Chrome Extension

Post by slime »

Does Crate Box create new particle systems each frame? The wiki page for love.graphics.newParticleSystem advises against that. Considering particle systems aren't meant to be created so frequently, I wouldn't spend too much time optimizing the internal graphics code for that. :)
binji wrote:why glGetError is slow: NaCl puts all GL calls into a command buffer which is executed by the GPU process of Chrome. When you call glGetError you force a command buffer flush, and all commands must be executed immediately so you can determine if there is an error.
I believe the same thing can happen in the actual OpenGL driver, so a glGetError call in NaCl might do the flush in Chrome and in the driver.
User avatar
adnzzzzZ
Party member
Posts: 305
Joined: Sun Dec 26, 2010 11:04 pm
Location: Porto Alegre, Brazil

Re: LÖVELINESS a LÖVE Chrome Extension

Post by adnzzzzZ »

This may be kinda off-topic, but just so I can learn something from this. If I were to fix this the solutions for improving performance they would be: reusing particle systems and creating them less frequently; using SpriteBatches instead of normal calls for drawing most things. Any other obvious improvements?
User avatar
binji
Prole
Posts: 32
Joined: Fri Apr 26, 2013 9:43 am
Contact:

Re: LÖVELINESS a LÖVE Chrome Extension

Post by binji »

adnzzzzZ wrote:If I were to fix this the solutions for improving performance they would be: reusing particle systems and creating them less frequently; using SpriteBatches instead of normal calls for drawing most things. Any other obvious improvements?
Yep, those are good places to start. I didn't look too closely at your code, so I can't really comment much about it. But here are a few general rules that I remember from game development. Of course, it is always important to measure and profile your performance! Also, some changes require making the code harder to read, understand and modify. So you should weigh developer productivity gains against the performance gains. And don't get obsessed with performance: the game that does nothing interesting but does it really fast, probably isn't a good game. :)

* Creating and destroying resources while the game is running is potentially slow, so avoid it if possible. Some ways to do this:
1) If you know how many resources of a certain type you need for this level, allocate them when the level starts. Use a free list to allow quick adding/removing of resources (not sure if this will be any faster in Lua, though).
2) If you don't know how many resources you need, pick a number and try it out. Have the code fail if you run out. Can you change the game design so it is OK if the number of these resources is limited?
3) If you don't know how many you need and you don't want to limit it arbitrarily, then reuse if possible, and allocate if not. That's the technique I used for the particle systems in your game.

* If you can, don't allocate/deallocate memory while the game is running either. This is just a corollary of the above rule. It may be a bit harder to achieve this in Lua, but should be possible. Of course, if you take it too far, then you lose a lot of the niceness of working with a scripting language.

* The fastest code is the code that never runs. Don't do any work that isn't necessary. Some ideas:
1) Partition your data. A common example: if you have N objects in your game, don't do O(N^2) collision checks if you don't care about enemy projectiles hitting player projectiles. Only check for collisions you care about (not sure if you do this, just saying in general). Another example: can you avoid updating/drawing objects when they are offscreen? There is a trade-off here, because keeping track of what is onscreen/offscreen could be more expensive than updating it always. Measure it!
2) Push changes instead of pulling -- that is, instead of checking "is this true", can you detect when it becomes true and perform the action then?

* When working in a scripting language, try to make your host environment do most of the work. Your host environment is almost always faster than your scripting language. Can you munge your data so that you can use a built-in function to do the work? Here's a silly example: use table.sort rather than writing your own sort algorithm in Lua. Here's a more realistic example: using SpriteBatch rather than looping over all things you want to draw in Lua.

* Abstractions are useful, but they have a cost. When you add an abstraction, you're typically also adding another layer of code that has to execute. It makes it easier to extend your code, but often can sacrifice performance. This is especially important to be aware of with Lua, where the cost of execution is higher. I've seen a few games fall into the trap of "death by 1000 cuts" -- there's no one thing that is slow, everything is!

Always important to remember: performance is a balance between technical constraints and design constraints. You probably don't have to think too much about performance if you're making tic-tac-toe or tetris. You may need to think about it more if you're making an open-world game or a bullet hell game. But even then you can "design around" the technical constraints of your code: if you write a game where you draw really awesome-looking enemies, but you can only draw one per frame, can you change the design so that fighting just that one enemy is fun?

I'm way off-topic now, though, so I'm going to stop. :D
[[LÖVE Chrome Extension]]
LÖVELINESS
Examples page
Github project page
Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests