DynamicTexture constructor leaks a WebGL texture on every create/destroy cycle (4.2.1)
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: 4.2.1
- Operating system: MAC OSX (latest)
- Browser: Chrome (latest)
Description
In WebGL mode, creating and removing a DynamicTexture leaves one WebGL texture wrapper retained in
renderer.glTextureWrappers.
The DynamicTexture constructor allocates a texture through the base Texture/TextureSource constructor, then replaces
frame.source.glTexture with this.drawingContext.texture without disposing the original wrapper.
Removing the DynamicTexture destroys the replacement, but the original remains registered with the renderer. In an
isolated reproduction, the original WebGL texture also remains valid according to gl.isTexture().
Expected: after each create/remove cycle, the wrapper count returns to its baseline.
Actual: the retained wrapper count increases by one per cycle.
Example Test Code
Run against unpatched Phaser 4.2.1:
<!doctype html>
<html>
<body>
<script src="https://cdn.jsdelivr.net/npm/phaser@4.2.1/dist/phaser.js"></script>
<script>
new Phaser.Game({
type: Phaser.WEBGL,
width: 64,
height: 64,
audio: { noAudio: true },
scene: {
create: function () {
const renderer = this.game.renderer;
const baseline = renderer.glTextureWrappers.length;
for (let i = 0; i < 4; i++) {
const key = `texture-leak-${i}`;
this.textures.addDynamicTexture(key, 8, 8);
this.textures.remove(key);
console.log(
`Cycle ${i + 1}: retained wrappers =`,
renderer.glTextureWrappers.length - baseline
);
}
}
}
});
</script>
</body>
</html>
Expected counts: 0, 0, 0, 0.
Actual counts: 1, 2, 3, 4.
Additional Information
Disposing the original texture before replacing it in the DynamicTexture constructor eliminates the growth in the
isolated reproduction:
if (!isCanvas)
{
var frame = this.get();
renderer.deleteTexture(frame.source.glTexture);
frame.source.glTexture = this.drawingContext.texture;
}
Related history: #6669 reports a DynamicTexture create/destroy memory leak in Phaser 3.70. This report concerns the
DrawingContext replacement path in 4.2.1; I have not established whether it shares the same underlying cause.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the DynamicTexture constructor and trace the textures.addDynamicTexture/remove path, especially the replacement of frame.source.glTexture and renderer.glTextureWrappers. Run the HTML reproduction in WebGL and verify that each create/remove cycle returns the wrapper count to its baseline and no original texture remains valid.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- computer-graphics, game-dev
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 72/100