StarlingGraphics / Starling-Extension-Graphics

flash.display.Graphics style extension for the Starling Flash GPU rendering framework
https://github.com/StarlingGraphics/Starling-Extension-Graphics/wiki
MIT License
285 stars 88 forks source link

How to cache vertex data #14

Closed Oldes closed 11 years ago

Oldes commented 11 years ago

Hi, doing more tests I found, that on mobile devices the shape creation is too slow (running my shape animation on iPad with 2fps where on PC I have 60fps still with hight AS peaks)... My original idea was using pools for once created shapes, but using it I hit vertext buffer limit. When I clear the shape, I will not hit the buffer limit, but it require re-tessellation of the shape when added to stage again.

So I just would like to know, if it would be possible to precompute the shape data and just initiate and reuse them when needed. Any idea? (I hope you understand what I'm trying to describe:-)

Maybe storing renderVertices and indices and not to need recreate them durring the render even when vertexBuffer and indexBuffer are disposed.

jonathanrpace commented 11 years ago

I think I understand. We currently generate the vertex/index data at the same time as we upload it to the GPU (usually the first time a shape is rendered).

If I understand correctly, you're asking if we could split this process and generate the vertex/index prior to being rendered. Then only upload the buffers when rendered?

It's probably not too hard to implement - and does give a bit more flexibility. However it would probably require some new opt-in functions for forcing certain behaviours under-the-hood. Something like

var shapeFrame1:Shape = new Shape()
shapeFrame1.graphics.doStuff()
shapeFrame1.preComputeVertexData()

var shapeFrame2Shape = new Shape()
shapeFrame2.graphics.doStuff()
shapeFrame2.preComputeVertexData()

...

// Later on
removeChild(shapeFrame1)
shapeFrame1.disposeBuffers() // But retain vertex data, so you can loop the animation
addChild( shapeFrame2 )  // This would then trigger uploading the new vertex/index buffers

This would move the cost of tessellation to your set-up phase, but you'd still be incurring the cost of re-uploading a vertex/index buffer each frame. Your mileage will vary depending on how complex these shapes are.

For truly efficient performance you're going to need something far more custom than the graphics API (something along the lines of a single vertex buffer containing all frames, then moving the offset each frame).

Oldes commented 11 years ago

Actually I'm already trying to dispose the vertex and index buffers on shape remove using:

public function disposeBuffers():void {
    if ( vertexBuffer )
    {
        vertexBuffer.dispose();
        vertexBuffer = null;
    }

    if ( indexBuffer )
    {
        indexBuffer.dispose();
        indexBuffer = null;
    }
}

and recreating the polygon only if needed using something like this in the render function:

if (bChanged) {
    indices.length = 0;
    renderVertices.length = 0
    createPolyLine(vertices, _closed, renderVertices, indices );
    bChanged = false;
}

but it looks the buffers are not released from the GPU. Is there something else what must be done to free the GPU resources?

jonathanrpace commented 11 years ago

No, that should be all you need to do to release the buffers.

All I can suggest is double checking they're not getting automatically re-created by the Stroke's Graphic base class (this should only happen during a render call. Off-stage shapes should be getting ignored).

Oldes commented 11 years ago

I will check it. Anyway.. with my change above I have 60fps on iPad once the shapes are created. But when I use Monocle to debug the application, I can see that although I'm disposing vertex and index buffers, they never drop down, just they do not rise once shapes are generated.

jonathanrpace commented 11 years ago

Ah, looks like Adobe's implemented some form of garbage collection with their GPU resources. Your dispose()'d buffers are probably marked as 'uneeded', but won't actually get removed from GPU memory until more room is required.

Good to hear your hitting a decent framerate. You'll be happy to hear that an update to the tessellation algorithm is on its way - it should reduce your tessellation cost quite a bit. Watch this space!