phaserjs / phaserjs/phaser

Memory Leak when using MobilePipeline and SpinePlugin

Open
#7,193 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
40.3k
Forks
7.2k
PR merge metrics
No merged PRs in 30d

Description

Version

  • Phaser Version: 3.90
  • Operating system: All
  • Browser: All Mobile

Description

I have found a memory leak when using the MobilePipeline on webgl renderer. The default MultiPipeline works fine and has no memory leaks.

I happens as soon as you have a spine game object and any other game object. It will cause the render game.renderer.glAttribLocationWrappers to infinitely grow on very update.

Example Test Code

import Phaser from 'phaser';
import { SpinePlugin } from '@esotericsoftware/spine-phaser-v3';

class Example extends Phaser.Scene {
  preload() {
    this.load.atlas('buttons', 'nine-slice.png', 'nine-slice.json');
    this.load.spineJson('spineboy-json', 'spine/spineboy-pro.json');
    this.load.spineAtlas('spineboy-atlas', 'spine/spineboy-pma.atlas', false);
  }

  create() {
    // Need to have another game object
    var button = this.add.nineslice(400, 300, 'buttons', 'button-bg', 400, 110, 64, 64);
    button.setInteractive();
    button.on('pointerup', this.onButtonPressed, this);
    button.input.cursor = 'pointer';
    button.setSize(100, 50);

    const spineBoy = this.add.spine(500, 500, 'spineboy-json', 'spineboy-atlas');
    spineBoy.animationState.setAnimation(0, 'idle', true);
  }

  onButtonPressed() {
    console.log('button pressed');
  }

  update() {
    console.log('glAttribLocationWrappers', this.game.renderer.glAttribLocationWrappers.length);
  }
}

const config = {
  type: Phaser.WEBGL,
  width: 800,
  height: 600,
  backgroundColor: '#000000',
  parent: 'phaser-example',
  scene: Example,
  render: {
    autoMobilePipeline: false, // Disable mobile pipeline to force default
    defaultPipeline: 'MobilePipeline'  // Comment this out to use default 'MultiPipeline'
  },
  plugins: {
    scene: [{ key: 'spine.SpinePlugin', plugin: SpinePlugin, mapping: 'spine' }]
  }
};

const game = new Phaser.Game(config);

Additional Information

I have the console logging, to see it increase in the Mobile Pipeline and it won't in the default one.

From my investigation. I have found that the Mobile-vert,js shader has an unused attribute inTexId, and it is gettting compiled out and then in the WebGLRenderer.js createAttribLocation function its tries to create the wrapper but it cannot get a location which keeps adding to the glAttriLocationWrappers array and never removes it.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the provided Phaser scene and compare MobilePipeline with MultiPipeline while watching glAttribLocationWrappers. Inspect Mobile-vert.js and WebGLRenderer.js, especially createAttribLocation, then verify with the example that the wrapper collection no longer grows on each update when Spine and another game object are rendered.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
game-dev, performance
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.