• Editor
  • spine run-time Atlas - optimization note.. and request?

Related Discussions
...

Hi All, Nate,

Sorry to keep asking questions about optimization stuff (I'm sure you're all super busy adding new features).

This one seemed worth mentioning - not super high priority since there's a workaround.
Testing on an old Motorola Droid I get 11fps if I do the following:

        atlas = Atlas_readAtlasFile("bird_orange.atlas");
	for( int i = 0; i < 30; ++i )
	{
	  customLoader = SUPER(CustomAttachmentLoader_create(atlas));
	  skeletonJson = SkeletonJson_createWithLoader(customLoader);
	  skeletonData = SkeletonJson_readSkeletonDataFile(skeletonJson, "skeleton.json");
	  animationStateData = AnimationStateData_create( skeletonData );
	  skeletonNode = CCSkeleton::create(skeletonData, animationStateData );
	  skeletonNode->setSkin( "bird_orange" );
	  skeletonNode->setSlotsToBindPose();
	  skeletonNode->setAnimation("animation_test_0", true);
	  skeletonNode->timeScale = 0.8f;
	  skeletonNode->setPosition(ccp(windowSize.width / 3 * 2, parentNode->getContentSize().height/2 + i*5));
	  parentNode->addChild(skeletonNode);
	}

But if simply recreate the atlas each time, I get 19.5fps. That's a pretty huge difference and allows us to support all those 2.2 devices out there.

	for( int i = 0; i < 30; ++i )
	{
          atlas = Atlas_readAtlasFile("bird_orange.atlas"); //<===========================New Atlas Each Time
	  customLoader = SUPER(CustomAttachmentLoader_create(atlas));
	  skeletonJson = SkeletonJson_createWithLoader(customLoader);
	  skeletonData = SkeletonJson_readSkeletonDataFile(skeletonJson, "skeleton.json");
	  animationStateData = AnimationStateData_create( skeletonData );
	  skeletonNode = CCSkeleton::create(skeletonData, animationStateData );
	  skeletonNode->setSkin( "bird_orange" );
	  skeletonNode->setSlotsToBindPose();
	  skeletonNode->setAnimation("animation_test_0", true);
	  skeletonNode->timeScale = 0.8f;
	  skeletonNode->setPosition(ccp(windowSize.width / 3 * 2, parentNode->getContentSize().height/2 + i*5));
	  parentNode->addChild(skeletonNode);
	}

Thanks,
-Chad

Creating the atlas each time will use more memory (30x more, in your example).

spine-cocos2dx uses textureAtlas->https://github.com/cocos2d/cocos2d-x/blob/master/cocos2dx/textures/CCTextureAtlas.cpp#L587]drawNumberOfQuads. It seems to have a number of different paths it can take, so that could be an optimization. That method will be called for each CCSkeleton, which means one draw call per skeleton. It shouldn't matter if the same texture is used each time. I think you are seeing something specific to the Droid. I have a Droid and it's a terrible phone, even when it just came out. I would test on a variety of old phones before jumping to any conclusions.

Probably the best optimization for spine-cocos2dx is to batch multiple skeletons to reduce draw calls. Unfortunately I don't see how this is easily done due to how cocos2dx is designed. Each individual node doesn't know about any other nodes. We could have a container that only holds CCSkeleton nodes, and the container would batch for all of them. This would work, but means you can't mix skeleton nodes with other nodes or you lose batching.

Torque2D has a similar issue, where batching can easily happen for a single node, but not multiple nodes. libgdx doesn't have this problem because it uses a single batcher for all nodes. Solution: use libgdx. 😉

I see,
Good point about the extra memory usage. I did notice though that the cocos2d-x texture cache at least prevents multiple loads of the atlas image.

You're totally right about that Droid.. it's super sluggish - that's why I use it as our lowest common denominator test device 🙂 just figured this was worth mentioning in case it was a more universal bug.

Thanks for the response!
-Chad

Oh right, forgot about the texture cache... probably because it's a Bad Idea that exists only because of other problems caused by having to cram your entire game into a scene graph. 🙂 It's similar to the batching problem, nodes don't know about other nodes, so it is difficult to reuse the same images without loading them twice. A scene graph has those issues plus it couples model and view, so I'm not convinced it's a good way to build games. But by all means, carry on. 🙂

lol.. sounds like you got some beef with cocos2dx & scene graphs 🙂
wish I could've picked your brain on the subject back when we were comparing game development frameworks!

anyway.. we're super happy with the spine run-time as it is on cocos2d-x :rock: