OPENRNDR / Shaders crashing due to computer memory filling up

i know this is the second time now i’m making a post with a similar title but the solution isn’t the same i promise

So, I’ve made a small program that takes the camera input, saves the current and the previous frame in memory and renders the difference between them using a custom filter shader.
The program works fine (kinda sluggish and flickering sometimes), but after being on for like 5 minutes it has filled up the memory of the computer and shit starts breaking loose.
I am not creating 10000 circles and rendering them each frame, most of what I’m doing revolves around a single ColorBuffer and there is no intuitively visible problem here. There are even no mutable "var"s in use.

This might have something to do with the shader, since I previously implemented the same effect by manually looping over each pixel and doing everything using the cpu in kotlin.

But wall of text aside here is the code for the main program

application {
    configure {
        width = 1920
        height = 1080
    }

    program {
        val diffShaderText = File("data/shaders/difference.glsl").readText()
        class DiffShader : Filter(filterShaderFromCode(diffShaderText, "diff-shader")) {
            var input1: ColorBuffer by parameters
        }
        val diffShader = DiffShader()

        val videoPlayer = VideoPlayerFFMPEG.fromDevice(imageWidth = width, imageHeight = height)
        val rt = renderTarget(width, height) {
            colorBuffer()
        }
        videoPlayer.play()

        val previousFrame = colorBuffer(width, height)
        extend {
            drawer.isolatedWithTarget(rt) {
                clear(ColorRGBa.BLACK)
                videoPlayer.draw(drawer)
            }

            val differenceOutput = colorBuffer(width, height)
            diffShader.input1 = previousFrame
            diffShader.apply(rt.colorBuffer(0), differenceOutput)
            drawer.image(differenceOutput)

            rt.colorBuffer(0).copyTo(previousFrame)
        }
    }
}

And here is the code for the shader
tex0 is the current frame and input1 is the previous one

#version 330
in vec2 v_texCoord0;
uniform sampler2D tex0;
out vec4 o_color;

uniform sampler2D input1;

float treshold = 0.1;
float multiplier = 100.0;

void main() {
    vec4 color1 = texture(tex0, v_texCoord0);
    vec4 color2 = texture(input1, v_texCoord0);
    vec4 colorDiff = vec4(
        abs(color1.r-color2.r),
        abs(color1.g-color2.g),
        abs(color1.b-color2.b),
        1.0);


    vec4 color = vec4(
        (colorDiff.r-treshold)*multiplier,
        (colorDiff.g-treshold)*multiplier,
        (colorDiff.b-treshold)*multiplier,
        1.0
    );

    o_color = color;
}

Edit: Some details of my setup:

  • I’m on Arch Linux
  • I have 32Gb of RAM
  • The project is built on top of the template which was just cloned today (2022-2-20)

Hi @ehr! :slight_smile:

This line

            val differenceOutput = colorBuffer(width, height)

creates a new buffer on every animation frame.

You could try

  • Calling differenceOutput.destroy() to free the memory.
  • Move the line outside of the extend { ... } block so the buffer is only created once.

Does that help?

Cheers!

Thanks a lot for the help!

Moving the creation of the ColorBuffer helped. I thought the garbage collection would deal with that / I didn’t think about it at all when I wrote it. I thought that since the val is local to the extend block it would cease to exist once the extend block ended, but I was wrong.

1 Like

:slight_smile: In most cases things are automatically freed but colorBuffer allocates memory in the GPU (probably calling lwjgl) and I believe it is not freed unless requested. Maybe something to add to the guide.