Help Optimizing Live Performance Jitter Patch – Questions About GPU Processing, OpenGL Confusion, Save/Recall Issues, and Scaling Artifacts

fas11030's icon

Hi all,

I’m building a fairly large Jitter patch intended for use as a live performance video rig, but I’ve run into a few roadblocks and could really use some guidance:

  1. Performance Optimization (GPU Offloading):
    The patch is running quite slowly, which is impacting video playback. Are there accessible and relatively straightforward ways to shift more of the processing and rendering load to the GPU instead of the CPU, without doing a lot of reprogramming?

  2. Understanding jit.fx and OpenGL Objects:
    I’m a bit confused about how jit.fx and OpenGL-based (jit.gl.*) objects work. With standard Jitter matrices, the signal path is very explicit with point-to-point routing, but with these OpenGL objects, it seems like their effects are applied more globally. Sometimes the Jitter window is affected automatically without being routed to, other times the effects appear to work inconsistently or unpredictably.

    • How should I be approaching design when working with jit.fx and jit.gl objects?

    • Is there a best practice for combining traditional Jitter matrix-based processing with OpenGL contexts? Should I be converting somehow to and from OpenGL objects to regular matrices?

    • Should I be using a specific approach to interface between the two?

  3. autopattr / pattrstorage Issues in Modular Patch with bpatcher:
    I’ve implemented a save/recall system using autopattr and pattrstorage, which has worked for me in the past. However, in this patch, I’m using bpatchers for modularity (e.g. for video source modules), and the save/recall system I’ve used before isn't working.

    • When I attempt to save, only the parameters within the bpatcher hosting the save/recall logic are recognized—nothing from the main patch or other bpatchers are picked up.

    • I’ve experimented with the @greedy attribute but haven’t had any success. Should I just not use the save/recall patch as a bpatcher and paste it into the parent patch to try to simplify things?

  4. Video Scaling and Pixelation (especially after jit.rota):
    I’m noticing pixelation issues, especially after scaling images using jit.rota. I need to scale all source videos to 1920x1080 to match the output resolution, but sometimes when upscaling lower-res video (e.g., sending a 640x360 source into a 1920x1080 jit.window), I get strange visual artifacts.

    • What’s the best way to scale video content cleanly without degrading quality or introducing glitches?

I’ve attached my patch to this post. Any help, suggestions, best practices, or examples would be hugely appreciated!
Thanks in advance!

TrackingPatch.maxpat
Max Patch



Computer info:

Processor          12th Gen Intel(R) Core(TM) i9-12900K   3.20 GHz

Installed RAM  32.0 GB (31.8 GB usable)

System type     64-bit operating system, x64-based processor

Edition Windows 10 Pro

Version              22H2

Installed on      ‎10/‎20/‎2022

OS build            19045.5737

Experience       Windows Feature Experience Pack 1000.19061.1000.0


Max Information:
"version" : "Version 9.0.5 (4ef99ba67c8) (x64 windows)",

"platform" : "windows",

"arch" : "x64",

"osversion" : "Microsoft Windows 10 Professional (build 19045), 64-bit"




TFL's icon
  1. No straightforward way, just a few general good practices to have, then it's really patch-specific in my opinion. Make sure you are using @output_texture 1 on your [jit.movie] and that you stay in the gl realm all the way, unless those textures are meant to affect some geometry/vertices and [jit.gl.tf]+[jit.gl.buffer] doesn't work for you in this regard, in which case you might need [jit.gl.asyncread] to read the GPU textures back to CPU matrices without too much impact on the performance. The patch you shared isn't working (it's missing all its bpatcher dependencies), but from what I can see, the [p Mosaic] and [jit.plume] part would benefit from being converted to jit.gl objects. Most if not all objects you are using here already have a jit.fx counterpart. I assume what is coming from the [r sw_1/2/3/4/5] are textures already, but not what you get from OBS, so you need to put a [jit.gl.texture] just after your [jit.ndi.receive]. Or if for some reason you want to keep the Mosaic process in the matrix realm, try throwing a [jit.gl.asyncread] before the first [jit.rota] and see how it goes (might need some specific routing for the matrices coming from OBS as they wouldn't need to be asyncread).

  2. As far as I know [jit.gl.pix] [jit.gl.slab] and [jit.fx.*] need regular routing just like using [jit.gen] or other jit. objects with matrices. Some objects like [jit.gl.pass], [jit.gl.node] can be used to apply effects more "globally" without patch cord routing though. About how to work with matrices and textures, it's basically what I said in 1: if you work with textures, stay as much as you can with jit.gl/jit.fx objects from the beginning. Converting matrices to textures in straightforward with [jit.gl.texture] but is a bit slow when done every frame, and converting textures to matrices can be done more efficiently with [jit.gl.asyncread] if you don't need 100% accurate timing, but should still be avoided when possible. You are working with jit.ndi objects here which sadly aren't compatible with textures, so you have to use these methods with them.

  3. [pattrstorage] can only work from its own patcher level down to any subpatcher level. So if you encapsulated it in a bpatcher, it won't be able to see what are in sibling patchers or in your main patcher. A workaround is simply to keep [pattrstorage] in your main patcher but have all the logic and UI to work with it in your [bpatcher]. I actually do that quite often as it helps for maintainability.

  4. There is no magical way to upscale textures. You're adding data to the source, and that new data need to be guessed from the existing data, either by linear interpolation (that's what [jit.gl.texture @dim 1920 1080] does by default), either without interpolation which will give a clean pixelated look (add @filter none to [jit.gl.texture]). The patcher below gives you an example for this. Nowaday GPU has fancy features like DLSS for Nvidia or FSR for AMD which upscale images using AI in realtime, but as far as I know it is only accessible for the final output and cannot be controlled from Max.

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

Also, your specs don't mention a dedicated GPU. Do you have one? Or are you working on the integrated GPU of your CPU (Intel UHD graphics 770)? If you have one, make sure Max is running on it instead of the integrated GPU!