Adding Two FBOs?


#1

I have a class that’s drawing into it’s own FBO.

After drawing a lot of them in my main program, actually after 34 of them, the app on the iPad crashes with Message from debugger: Terminated due to memory issue.

Which leads me to think it might be better to do something like class->getFBO() and get the FBOs out of each, add them together into a main fbo and only draw that. Problem - I have no idea how to go about something like this :slightly_frowning_face:

They all have alpha values, the classes are stored in a vector, the only way I can think of doing this is converting them each to ofPixels, looking at them as a layer stack through the vector and keeping the relevant pixels from the top, but that sounds too like it’s not a very reasonable solution (and would be an issue with semi-transparent pixels, anyway) - so a nudge in the right direction would be welcome.

I’m using of_v20190105_ios_release and on a 2018 iPad Pro.


#2

I can of course keep adding them to the main renderer FBO and trashing them from the vector or something like that too, but I’m pretty sure there’s an elegant solution here that I’m missing.


#3

It is really difficult to have an overview of what you are doing from you description. Why are you collecting FBOs into a vector? If you need a bunch of them to make some calculation, then I would identify how many of them to you need, and then I would check after how many FBOs you application crashes. Once you find this value, let’s say 20 for example, you implement the logic that keeps your vector size under 20.

smth like:

    fboContainer.push_back(newFbo);
    if (fboContainer.size() >= 20){
        fboContainer.erase(fboContainer.begin());
    }

I the performance are fine, you are done. If not you could try to use a deque instead of a std::vector. This is because you are accessing the container from the beginning (when calling fboContainer.erase(fboContainer.begin())) and deque are faster in this case.


#4

I should have explained the problem a bit better :slight_smile:

So I’m developing a kind-of drawing app on the iPad. I have a class called Brush.h, which I’m simplifying here but basically it contains an FBO that uses ofMesh and ofShader to make a drawing.

Every time a user touches the screen, a new instance of Brush is pushed_back into my vector which holds all the Brushes, while the user has their finger down they can manipulate, draw, etc and then they’re done. Next time they put their finger down a new Brush is instantiated and pushed back into the vector, etc.

And then of course in my ofApp I’m updating all my Brushes and drawing them. Some of the brush algorithms depending on type are dynamic and update over time, some of them don’t etc. It’s probably ok if I make them all static and once they’re done drawing, the mesh etc is frozen, ie, the FBO has all the info I need.

It all works find till I run into the limit of 34 Brushes/34 FBOs that are being drawn from the ofApp.

So I was wondering if there was a way to combine these FBOs as they’re being formed into a final FBO (this only works if all the FBOs are static, of course). I know I can do something like this:

//ofApp.cpp
void ofApp::update(){
finalFbo.begin();
if (bToClear) ofClear(255); //this is when the app starts, or if I'm clearing the screen otherwise stack on top.
lastBrush.draw();
finalFbo.end();

void ofApp::draw(){
finalFbo.draw(0, 0);
}

This is considering that there’s no vector<Brushes> holding all my FBOs but I’m just stacking them up at every TouchUp() event - but I was wondering if there were some other options to consider. If somehow I could keep the dynamic ones as is, that would be even better.

I think I cannot avoid FBOs altogether from the Brush class as they’re going through two shaders to do some shading and blurring etc which I’d be hard pressed to do without passing them through FBOs.


#5

Not sure it’s correct direction but I assume your app reach to hardware memory limit(GPU side).
There’s a limitation of texture size, buffer size, VRAM, shared memory, … those I can’t explain precisely but there is limit ;-). And this hardware limit depends on devices (e.g. iPhone5,6, iPad pro, etc).
So one idea is download your fbo into ofPixel and store in vector and use it when you need. This way you can use RAM, which is much larger than GPU memory. In case if downloading fbo from GPU is slow, you can consider using PBO. (ofxPBO or ofxFastFboReader)

About GPU debug, I did a quick search and found Xcode has two tools for GPU profiling, might be helpful. https://developer.apple.com/documentation/metal/tools_profiling_and_debugging/gpu_activity_monitors/monitoring_your_app_s_graphics_activity

If you are able to test your app on Windows(+Nvidia GPU), you can also use Nvidia tools which look much better. https://developer.nvidia.com/nsight-visual-studio-edition


#6

Yes, I’m guessing I’m reaching the hardware memory on the GPU side, too. Thanks for the suggestions, I’ll look into those. The ofPixels way of doing it is of course valid but I don’t know if that’s very efficient, and ugh, I have to change a lot of the architecture of the app to try different methods out to hopefully find a fix, so annoying :neutral_face: