Skip to content

Commit

Permalink
Fixes disposing framebuffers like in v4 (#5387)
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanpopelyshev authored and bigtimebuddy committed Jan 27, 2019
1 parent 3794f0b commit 33c73cc
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 6 deletions.
11 changes: 11 additions & 0 deletions packages/core/src/framebuffer/Framebuffer.js
@@ -1,3 +1,4 @@
import Runner from 'mini-runner';
import Texture from '../textures/BaseTexture';
import { FORMATS, TYPES } from '@pixi/constants';

Expand Down Expand Up @@ -29,6 +30,8 @@ export default class Framebuffer
this.colorTextures = [];

this.glFramebuffers = {};

this.disposeRunner = new Runner('disposeFramebuffer', 2);
}

/**
Expand Down Expand Up @@ -140,4 +143,12 @@ export default class Framebuffer
this.depthTexture.setSize(width, height);
}
}

/**
* disposes WebGL resources that are connected to this geometry
*/
dispose()
{
this.disposeRunner.run(this, false);
}
}
75 changes: 73 additions & 2 deletions packages/core/src/framebuffer/FramebufferSystem.js
Expand Up @@ -12,6 +12,21 @@ import { settings } from '../settings';
*/
export default class FramebufferSystem extends System
{
/**
* @param {PIXI.Renderer} renderer - The renderer this System works for.
*/
constructor(renderer)
{
super(renderer);

/**
* A list of managed framebuffers
* @member {PIXI.Framebuffer[]}
* @readonly
*/
this.managedFramebuffers = [];
}

/**
* Sets up the renderer context and necessary buffers.
*/
Expand All @@ -24,6 +39,8 @@ export default class FramebufferSystem extends System
this.viewport = new Rectangle();
this.hasMRT = true;

this.disposeAll(true);

// webgl2
if (!gl.drawBuffers)
{
Expand Down Expand Up @@ -85,7 +102,7 @@ export default class FramebufferSystem extends System
else if (fbo.dirtySize !== framebuffer.dirtySize)
{
fbo.dirtySize = framebuffer.dirtySize;
this.resizeFramebuffer(framebuffer, fbo);
this.resizeFramebuffer(framebuffer);
}
}

Expand Down Expand Up @@ -208,6 +225,9 @@ export default class FramebufferSystem extends System

framebuffer.glFramebuffers[this.CONTEXT_UID] = fbo;

this.managedFramebuffers.push(framebuffer);
framebuffer.disposeRunner.add(this);

return fbo;
}

Expand All @@ -216,7 +236,6 @@ export default class FramebufferSystem extends System
*
* @protected
* @param {PIXI.Framebuffer} framebuffer
* @param {object} fbo Framebuffer object corresponding to renderer context
*/
resizeFramebuffer(framebuffer)
{
Expand Down Expand Up @@ -330,4 +349,56 @@ export default class FramebufferSystem extends System
// fbo.enableStencil();
}
}

/**
* Disposes framebuffer
* @param {PIXI.Framebuffer} framebuffer framebuffer that has to be disposed of
* @param {boolean} [contextLost=false] If context was lost, we suppress all delete function calls
*/
disposeFramebuffer(framebuffer, contextLost)
{
const fbo = framebuffer.glFramebuffers[this.CONTEXT_UID];
const gl = this.gl;

if (!fbo)
{
return;
}

delete framebuffer.glFramebuffers[this.CONTEXT_UID];

const index = this.managedFramebuffers.indexOf(framebuffer);

if (index >= 0)
{
this.managedFramebuffers.splice(index, 1);
}

framebuffer.disposeRunner.remove(this);

if (!contextLost)
{
gl.deleteFramebuffer(fbo.framebuffer);
if (fbo.stencil)
{
gl.deleteRenderbuffer(fbo.stencil);
}
}
}

/**
* Disposes all framebuffers, but not textures bound to them
* @param {boolean} [contextLost=false] If context was lost, we suppress all delete function calls
*/
disposeAll(contextLost)
{
const list = this.managedFramebuffers;

this.managedFramebuffers = [];

for (let i = 0; i < list.count; i++)
{
this.disposeFramebuffer(list[i], contextLost);
}
}
}
21 changes: 19 additions & 2 deletions packages/core/src/renderTexture/BaseRenderTexture.js
Expand Up @@ -85,7 +85,7 @@ export default class BaseRenderTexture extends BaseTexture

this.clearColor = [0, 0, 0, 0];

this.frameBuffer = new Framebuffer(this.width * this.resolution, this.height * this.resolution)
this.framebuffer = new Framebuffer(this.width * this.resolution, this.height * this.resolution)
.addColorTexture(0, this)
.enableStencil();

Expand Down Expand Up @@ -116,7 +116,21 @@ export default class BaseRenderTexture extends BaseTexture
{
width = Math.ceil(width);
height = Math.ceil(height);
this.frameBuffer.resize(width * this.resolution, height * this.resolution);
this.framebuffer.resize(width * this.resolution, height * this.resolution);
}

/**
* Frees the texture and framebuffer from WebGL memory without destroying this texture object.
* This means you can still use the texture later which will upload it to GPU
* memory again.
*
* @fires PIXI.BaseTexture#dispose
*/
dispose()
{
this.framebuffer.dispose();

super.dispose();
}

/**
Expand All @@ -126,6 +140,9 @@ export default class BaseRenderTexture extends BaseTexture
destroy()
{
super.destroy(true);

this.framebuffer = null;

this.renderer = null;
}
}
2 changes: 1 addition & 1 deletion packages/core/src/renderTexture/RenderTextureSystem.js
Expand Up @@ -92,7 +92,7 @@ export default class RenderTextureSystem extends System
sourceFrame = destinationFrame;
}

this.renderer.framebuffer.bind(baseTexture.frameBuffer, destinationFrame);
this.renderer.framebuffer.bind(baseTexture.framebuffer, destinationFrame);

this.renderer.projection.update(destinationFrame, sourceFrame, resolution, false);
this.renderer.stencil.setMaskStack(baseTexture.stencilMaskStack);
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/textures/TextureGCSystem.js
Expand Up @@ -93,7 +93,7 @@ export default class TextureGCSystem extends System
const texture = managedTextures[i];

// only supports non generated textures at the moment!
if (!texture.frameBuffer && this.count - texture.touched > this.maxIdle)
if (!texture.framebuffer && this.count - texture.touched > this.maxIdle)
{
tm.destroyTexture(texture, true);
managedTextures[i] = null;
Expand Down

0 comments on commit 33c73cc

Please sign in to comment.