Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
rendertarget:save slowdown — Gideros Forum

rendertarget:save slowdown

keszeghkeszegh Member
edited October 2016 in General questions
so i try to save a lot of rt's after each other (animation image sequence), and for a reason i don't understand it slow downs awfully at a certain point.

in the following test code it is fast until ~245 frames and then each next frame takes as much time as all the previous ones together or something like this:
for j=1,1000 do
	rt=RenderTarget.new(1024,1024)   
	rt:save("d:/test/test"..j..".png")
	rt=nil
end
is it a bug in gideros? or what should i do? i tried with a coroutine that is yielded once per enterframe but the same thing happens.

Comments

  • hgy29hgy29 Maintainer
    Could it be a GC issue ? What if you reuse your render targets instead of recreating them ?
  • saving the same rt indeed went without the slowdown.

    however, in my use case i actually have a huge table of rt's and i'm saving them one.
  • it looks that indeed calling collectgarbage in each loop corrects the issue. it was not evident that rt:save uses up memory somehow.
  • hgy29hgy29 Maintainer
    Indeed, rt:save() shouldn't use lua memory at all. Is there anything else in your loop that could allocate memory ? In your first post RenderTarget.new was probably the culprit.
  • SinisterSoftSinisterSoft Maintainer
    edited October 2016
    Stop the garbage collector, then restart it afterwards...

    http://luatut.com/collectgarbage.html

    Devices nowadays have huge amount of memory - no need to worry about it.
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • keszeghkeszegh Member
    edited October 2016
    well, in my original setting there was a loop creating an array of rendertargets, which did not slow down. and then there was another loop of saving these into files, and this is the one which slowed down. so an example which shows that there is no allocation of memory within the code yet it slows down:
    rtArray={}
     
    for j=1,1000 do
    	rtArray[j]=RenderTarget.new(1024,1024)   		
    end
     
    for j=1,1000 do
    	rtArray[j]:save("d:/test/test"..j..".png")	
    	--rtArray[j]=nil
    end
    and only the second "for cycle" slows down after exporting ~250 frames.
  • hgy29hgy29 Maintainer
    Damn, 1000 RTs of 1024*1024*4 bytes, 4 gigabytes of GPU memory!
    +1 -1 (+2 / -0 )Share on Facebook
  • 1000 render targets of 1k x 1k is a bit much. ;)
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • What you should do is just make one, then in the loop just keep clearing, drawing, saving 1000 times.
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • @hgy29, @Sinistersoft,
    what i want is a kind of 'video capture as an image sequence' but the problem is that saving a screenshot takes more time than an enterframe (1/60 sec), so it won't work realtime. perhaps i should make a save only after every second enterframe, but as a 'save' is one event, i guess it would still make it lag.
    so my workaround was that i make only the rt and only save all rt's after such a 'realtime capture session'. but as you said, memory gets out of hands quickly.
    let me know if you have other ideas about it.

    btw with some smaller screen area (800x600) it seemed to work as i wanted.actually while creating those many rt's when the texture memory got around 4gb then it went back to almost zero (saved the texture memory to normal memory or i dunno what happened) and again started to increase. still at the end saving to a file all rt's it worked, without the big slowdown i was talking about.
  • hgy29hgy29 Maintainer
    Don't know if it will work, but maybe you can grab RenderTarget's content into lua string (rt:getPixels()), optionnaly gzip the strings so that they take less memory, and reuse your render target ?

    Then reconstruct each frame later on (non realtime) and save them.
  • keszeghkeszegh Member
    edited October 2016
    @hgy29, i vaguely remember somebody on the forum said that getpixels is quite slow. but nevertheless what you propose makes sense.
    for the time being i decided to restrict 'live recording' to 30fps (and i save the frame immediately to file, so there is no huge array built) and that works with a tolerable lag. this way also there is no long postprocessing stage, which is good.


    still i think there is a question left open about how rt:save() is using memory, how can it lag so much - as in my previous example the save loop lagged and not the rtArray[i]:new() loop.
  • hgy29hgy29 Maintainer
    getPixel() is slow if you try to get pixels one by one (due to the copy from GPU memoty to CPU memory), but it should be reasonnably fast if grabbing all pixels in one shot. rt:save() does the same internally.

    Really I don't think rt:save() consume memory, and all in all not GC-based memory, IMO the issue is more something in OpenGL driver, having to copy texture data from/to GPU memory to cope with GPU memory size. Dealing with that much memory, maybe your computer uses swap, etc. But, in a sense you are right, because I can't explain why GC'ing regularly would help...
  • If you want to capture the screen - then just run the game on the PC and use 3rd party screen capturing software to grab it?
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • @SinisterSoft,
    that's good but not perfect as that will also grabs the mouse cursor, the gui, etc of my animating app, while optimally only the drawing area is saved.
  • keszeghkeszegh Member
    edited October 2016
    btw @hgy29 and @SinisterSoft,
    i can also think of at least two solutions which would be better for me in many other ways:

    1. multiple window gideros pc application, now that we have viewports, the sdk framework is essentially there. would this be very hard to add for the core developers?

    2. being able to 'send via Spout' a viewport.
    i even tried this but there was not enough help for me to get started:
    http://giderosmobile.com/forum/discussion/6398/is-it-possible-to-make-my-gideros-app-work-with-spout#Item_10

    here @hgy29 tried to help me, but it was far from enough for me. i tried to make an uwp exported app, so that maybe i can hack in it the feature i need, but i failed already at the first step of running the uwp app:
    http://giderosmobile.com/forum/discussion/6709/uwp-exported-project-not-running#Item_1

    in processing and many other frameworks there is a plugin to Spout, but it seems that i'm unable to write one for gideros with my current knowledge.

    (thanks for spending time on my problem)
  • I think that multiple window Gideros should treat each window as a screen - so that each has it's own stage.

    That way we could say that one of the stages isn't actually a normal output, but is in fact a remote screen - eg chromecast.

    In windows the stage would be a real 2nd window away from the normal window.

    Likes: keszegh

    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
    +1 -1 (+1 / -0 )Share on Facebook
Sign In or Register to comment.