Preloading and Texture-Memory

Guys I tried everything and only working solution would be preloading images. Please, it is the only thing that fixes problem. Doesn’t anyone know how preloading works? To simplify my question:

  • Can I preload textures without compromising texture-memory? (offscreen or invisible. it is the same texture memory atm if there is anything i don’t know of)

That’s exactly what preloading is meant to do … it preloads files/data into memory (in some cases uncompress/format convert them while doing this). Sadly you can’t have both, save time by preloading/precalculating stuff but without the required memory - that’s the very core of the compromise.

I’m not sure I understand what you meant with regards to your 7 levels - all you need to preload at any time are the images for a single (the currently played) level. If the users replays the same level - great, just reuse the already loaded images if not *first* free the graphics of the current level and then preload the ones for the next level.

If there are images shared between levels, only free those not used in the next level and of course only preload those not loaded already.

If it does take a little time to preload any level, that’s what loading screens were invented for - be creative, show random tips for your game, add a small animation etc. etc.

Also with regards of PoT, I haven’t done any research on this as I always pack my images into texturesheets and always use PoT. If it’s not required anymore, does this mean, all the hardware these days, even all the cheap/crappy phones out there, handle any texture size (and do so without performance hit) these days? Or is it just Corona that, in case your assets are not PoT, does an internal fix by upscaling the textures, adjusting UVs to the partial region your image uses but all this at the cost of wasting some texture memory?

Hello first thank you for replying, I guess that settled it. At least I have all the knowledge about it now. By 7 levels I mean 7 different type of decors, scenes but since it is an endless runner, there is no pause in between. And that was my problem, graphic heavy, moving fast and as you’ve guessed, freezes when preloading before scenes/levels.

I don’t know how to quote to a post of someone in different topic but I can paste the link of page where a Corona moderator Tom saying:
“The guide that you are referencing to is outdated. the “Power of 2” (PoT) rule applied to openGL 1.x in Corona’s Graphics 1 days. Our current CoronaSDK uses openGL 2.x which doesn’t have the PoT limitation. This means the texture memory number that is returned should match the actual size of the images loaded.”

forums.coronalabs.com/topic/57142-texture-memory-optimization-problem-pot-rule/
5th post

I was testing around to see the difference between ruled image and another. If you load and check the texture-memory usage between those, you will see it is not applied. Actually this is how I found the link. I was confused and searched in corona forums to check why PoT had no impact.

You don’t need to do your pre-loads all at once as long as you start them well before needing the assets.

You can use three different techniques to dribble out the loads (and releases):

  1. Using a timer or enterFrame listener (prior is probably better), start pre-loading the next ‘decor’ graphics one at a time and waiting between pre-loads for a period.

  2. Do the same thing, but use the slightly more technical co-routine approach while accumulating load duration to avoid going over the frame duration (this is really overkill and can be accomplished in a less sophisticated enterFrame handler).

  • check star time
  • load texture A
  • check duration since start, if < xxx milliseconds, continue, if not suspend
  • load texture B
  • … repeat till done or suspended
  • use timer or enterFrame to resume next frame
  1. Put together your own custom ‘tracking’ code to keep track of which textures are in use and which are soon to be used.  Then, with the above techniques load and unload dynamically without simply doing them all in one huge push.

Note: This is a really interesting technical problem.  I’m curous to hear what solution you come up with. 

Hey, this is exactly what I thought of after posting and did that. When I am about to preload next scene (like 1k-2k earlier),  I passed my textures to a table and if table is full, I am looping to load till system.getTimer difference is over 16 (assuming 16.667 ms for a frame). But I see that 16 is not correct, because fps will drop to 11 in that time. It is either system.getTimer() is not returning me with miliseconds or corona framework will take some time off for itself in the background (probably the second). But I am really excited that I think I will get through this. Because it is a steady slowed down frame, ready to be fixed!

Interesting info (at least for me):
* If I use busy waiting (testing purposes) and break in 8-10ms, my fps will drop to 30. A steady 30.
* Busy waiting loop to break in 4ms: A steady 60 fps.
* 139*250 px picture loaded in 3.2ms, 1000x553 px picture loaded in 19.5ms.

According to these I have 2 ideas.

  1. I will chop of my pictures to really a lot of pieces and write a code to autoload pieces. And I wont compromise my fps.
  2. I will break at when is at 30 fps rate! And set my speed variables accordingly before that. So when it lags to 30 fps, it will be a steady 30fps and it wont be noticeable for a small time since character and world will adjust to that.

But going path 2, I still need to chop of images. So I might as well get them all done and achieve 60 fps in that time without messing with variables. Any other suggestion is appreciated.

I will let you guys know how it went after I’m done. Nice to hear you are curious btw, I kinda felt lonely (:

If you’re trying to run at 60FPS, 16 ms for running your scripts is way way way too long.

Remember, a single frame of execution includes:

A - Time Corona needs to draw, handle physics calculations, transitions, etc.

B - Time your scripts run for during that frame

So if you take 16 ms, that leaves 0.66 for Corona.

Also, you need to measure ‘time since end of last frame’, not time in current frame.  Then use a variable best case value.

i.e. Say your best case value is 5ms, but it has been 15 ms since the last frame already.  Simply run for 1ms or safer yet skip work in this frame.

If on the other hand it has only been 7 ms since the last frame, run the full 5 ms best case duration then stop.

Never try to fill all the time.  That is a recipe for frame hiccups.

Hey. I had to practice some imagemagick commands for the long run so it took me a while to be done with the images. That was nice to measure time since end of last frame. But I checked the values and this thing happens:
time between took - 16ms
time between took - 0…
time between took - 0…
time between took - 15ms
time between took - 0…
time between took - 0…​
time between took - 17ms

But I cant measure how long it WILL took. When I do if allowedtime > 8, half of the time loading process works in a frame that is going to be busy without even loading. It looks like Corona does heavy work in one of 3 frame. Then I did a basic test and tried to load when it WAS a busy frame (the ones that took over 14ms), things almost worked out. Sadly, is it safe to count on this? Since I don’t have any idea how long Corona’s work will take in that frame, I can’t see any other way. It looks like I need to either load when a busy frame just ended or I will note the busy one and load in the next 2 frames.

Edit: Sorry. As I’ve said it was a basic test and I was dumb to think it could be a pattern. I cant count on that for sure. Things I do, in game changes, even loading itself will mess up with the pattern even if there was one

Are you doing this directly in your app or in a test bench while you work out the methodology?

It looks like this is from your app:

time between took - 16ms
time between took - 0…
time between took - 0…
time between took - 15ms
time between took - 0…
time between took - 0…​
time between took - 17ms

These numbers tell me your app is already in trouble.  A 0ms frame duration is Corona trying to catch up because there was too much work shoehorned into a prior frame.

If I have time today I’ll write up a test-bench showing you want I mean by my original advice.

Hey I had an unnecessary enterframe event. Once I deleted that actual numbers goes around:

time took in this frame 0.19999999999891

time between last frame 16.200000000001

time took in this frame 0.19999999999891

time between last frame 20.700000000001

time took in this frame 0.10000000000036

time between last frame 9.7999999999993

time took in this frame 0.20000000000073

time between last frame 18.699999999999

time took in this frame 0.20000000000073

time between last frame 10.9

time took in this frame 0.20000000000073
(No more 0s since last frame)

My only enterframe now and the related function : (timed() function here is system.getTimer())

onWorldMove = function() local frameStartedAt = timed() print("time between last frame ", frameStartedAt - tempValues.lastDeltaT) --- ..... enterframe actions here local deltaT = timed() local maxAllowedTime = 15.5 - frameStartedAt - deltaT if maxAllowedTime \> 8 then textureProcess(deltaT, maxAllowedTime-3) end end textureProcess = function(deltaT, allowedTime) local newTexture = graphics.newTexture if textureProcessData.load then local textureData = textureProcessData.load local textures = textureData.textures local lastProcessed = 0 for i=textureData.from,1,-1 do newTexture( { type="image", filename=textures[i] } ):preload() print("texture",i,"name",textures[i]) if timed() - deltaT \> allowedTime - 5 then lastProcessed = i break end end if lastProcessed \<=1 then textureProcessData.load = nil else textureProcessData.load.from = lastProcessed-1 end end end