aduros / flambe

Rapidly cook up games for HTML5, Flash, Android, and iOS.
https://github.com/aduros/flambe/wiki
MIT License
745 stars 118 forks source link

Flambe doesn't batch the textures created using the "subTexture" function. #314

Open aglitchman opened 9 years ago

aglitchman commented 9 years ago

When I enabled the flambe_debug_renderer, I noticed Flambe draws all animated sprites individually. Looks like Flambe doesn't batch the textures created using the "subTexture" function (flambe.swf.BitmapSymbol uses it). It should batch them because subtextures have same parent texture.

markknol commented 9 years ago

Could this gain performance?

aglitchman commented 9 years ago

Yes! OUYA showed 20 FPS when I added 50 different animated sprites from the same atlas (texture) to the stage. I temporarily fixed the bug by using this code (ImageSprite class):

    override public function draw (g :Graphics)
    {
        if (texture != null) {
            if (Std.is(texture, SubTexture)) {
                var sub = cast(texture, SubTexture);
                if (sub.parent != null) {
                    g.drawSubTexture(sub.parent, 0, 0, sub.x, sub.y, sub.width, sub.height);
                } else {
                    g.drawTexture(texture, 0, 0);
                }
            } else {
                g.drawTexture(texture, 0, 0);
            }
        }
    }

And now OUYA shows 60 FPS.

markknol commented 9 years ago

Wow that looks quite significant. @aduros should this be put on this spot?

aduros commented 9 years ago

Looks like a possible bug. I think it should be fixed in Stage3DGraphics/Batcher rather than up in ImageSprite.

volkipp commented 9 years ago

Does this code give you the same speedup? If you add this to Stage3DGraphics.hx (after the line that says root.assertNotDisposed() in drawSubTexture()):

        if (texture.parent != null) {
            sourceX += texture.x;
            sourceY += texture.y;
            texture = Lib.as(texture.parent, Stage3DTexture);
        }
volkipp commented 9 years ago

Sorry to spam the topic, but maybe this would work better / instead? In Stage3DBatcher.hx replace prepareDrawTexture with this:

    public function prepareDrawTexture (renderTarget :Stage3DTextureRoot,
        blendMode :BlendMode, scissor :Rectangle, texture :Stage3DTexture) :Int
    {
        if (_lastTexture == null || texture.root != _lastTexture.root) {
            flush();
            _lastTexture = texture;
        }
        return prepareQuad(5, renderTarget, blendMode, scissor, _drawTextureShader);
    }

I'm assuming that we don't need call flush() if we are using the same texture root, which would skip the flush() calls for those subtextures. Or am I wrong?