trying to make a multipass shader. This patch crashes my system

booltox's icon

Greetings All,

Im trying to build a multi-pass shader using the jit.gl modules. I'm not having very much luck and you can see my previous post about trying this technique with javascript. The basic idea is that I want to ping-pong between a set of FBO (jit.gl.slab??) objects to run the same shader over a texture.

I put together this patch as an attempt to try a different way. And It will crash my system hard. I'm using the lates MAX/MSP on the latest OSX

If anybody can take a quick look at this and explain why it is exploding I would greatly appreciate it. It doesn't seem to matter what fragment shader you use. Mine takes two texture inputs.

WARNING: when I run this I have to reboot.

Max Patch
Copy patch and select New From Clipboard in Max.

Thanks,
_b

Andrew Benson's icon

For multipass, iterative feedback process things like this you will need to prevent endless loops somehow. Since the left inlet of jit.gl.slab also triggers processing/output, when you send the output texture back into your subpatch it retriggers the whole thing again. Try using @thru 0 on one of the jit.gl.slab objects, or use the right inlet for feedback texture, to stop the endless loop from occuring.

If I had a better idea of what you were trying to do, it would help me to suggest solutions to what you are trying to do specifically.

booltox's icon

thanks for responding.

Obviously I’m missing some basics. So these problems I’m having might be trivial to fix but in my experimentation I am encountering enough hard crashes that Im worried that I might be stepping into a realm that MAX struggles with.

I can break down what Im having trouble doing in Max.

First, I'm trying to run a fragment shader multiple times with an input texture that accumulates change with each pass. This is for a single ‘frame’ (bang?) update. There is a potentially large number of passes per frame, 20 or more. Also these happen to be the same shader.

My first attempt was to use a javascript node and try to implement the behavior as I would in that sort of language. I describe my approach here: https://cycling74.com/forums/opengl-fbo-ping-pong-like-behavior-with-jitter-is-it-possible

The important part of the process looks like this.

function bang()
{

radslab1.jit_gl_texture("tex1","texture");
radslab1.jit_gl_texture("tex0", "srcTexture");
radslab1.draw();

var i=0;
for (i = 0; i 

This is not working correctly. The first pass works but later ones do not. My suspicions lie with my use of radslab.out_name.

The second behavior that Im looking for is the ability to persist the result of the previous frame as an input for the next one. This is why there is a circular dependency going from the output of the slab back into the input. (note I didn’t really expect this to work but I also didn’t expect it to crash as hard as it does. That circular-dependency condition can be detected and a warning issued or god-forbid wrapped in exception handlers) I have been able to get around the crashing by connecting the output to a named gl.texture and then referencing that texture by name in the javascript. These seems right to me but I’m not yet sure how to implement it outside of the js node.

thanks for the input

Andrew Benson's icon

Hiya,
Hopefully this simple example will help demonstrate a way to do what you want to accomplish. It can be difficult sometimes to move from a procedural code background to a patcher-based data flow paradigm. It's important to know that just about everywhere (with some exceptions) in Max, an input in the left ('hot') inlet will trigger an output. With jit.gl.slab and jit.matrix, you can use the @thru attribute to prevent output when receiving an input that isn't a 'bang'. This is really important when using a feedback process. Also, you'll want to make sure that your input to slab and its output are 2 different textures. In feedback situations, this often means creating a second texture pass, which can be done by using another slab object, with no loaded shader. So you need to do something like:
- pass input texture to slab
- slab outputs to another texture
- copy output texture to slab input texture

Max Patch
Copy patch and select New From Clipboard in Max.

Another way to go about accumulation is to write (or use) a shader that takes 2 texture inputs and use the right inlet for the accumulated feedback texture.

mr_mapes's icon

A technique I use for avoiding stack overflow when fast iterating is essential - might not be elegant but it works:

use [metro] or [qmetro] clocking pretty darn fast(

The speed in which the feedback cycles becomes limited by the metronome but hopefully it's clocking fast enough not to limit the feedback cycle too much

booltox's icon

yes!
Thanks for your excellent help