Dynamic atlas manager on native platforms

Hey,

I’m trying to reduce the amount of draw calls in my project on iOS and Android but I don’t think dynamic atlas is working. The amount of draw calls when running the project through the browser is much lower than native builds. I can get 3 draw calls in the browser which is correct and I can use showDebug of the dynamic atlas manager to see the texture containing all the spriteFrames in the scene. However on iOS I get 8 draw calls, every spriteFrame is drawn separately. Also when I try and call the showDebug method on iOS it says the method doesn’t exist.

I’m using v2.1.3 of Cocos Creator. CLEANUP_IMAGE_CACHE is set false and the dynamic atlas manager is enabled. All the textures I’m testing with are packable. I’m getting the same high amount of draw calls on android also.

Any info or help would be appreciated.
Thanks.

After going through the engine code as far as I can tell the _getHash function of the Texture2D class is what’s stopping everything from being dynamically batched.

First thing is the premuliplyAlpha is being set to false instead of 1 or 0 like at the top of the method, this is causing the hash to return as NaN.

Second the image._glFormat seems to always be undefined which means the pixelFormat is always set to 0 so the hash never matches the dynamicAtlas.Atlas.DEFAULT_HASH when it checks if it’s packable.

If I change it so undefined _glFormat is ignored and premuliplyAlpha isn’t a bool dynamic atlas manager starts batching and my draw calls are reduced.

I haven’t been able to figure out why _glFormat is undefined yet.

_getHash () {
    if (!this._hashDirty) {
        return this._hash;
    }
    let genMipmaps = this._genMipmaps ? 1 : 0;
    let premultiplyAlpha = this._premultiplyAlpha ? 1 : 0;
    let flipY = this._flipY ? 1 : 0;
    let minFilter = this._minFilter === Filter.LINEAR ? 1 : 2;
    let magFilter = this._magFilter === Filter.LINEAR ? 1 : 2;
    let wrapS = this._wrapS === WrapMode.REPEAT ? 1 : (this._wrapS === WrapMode.CLAMP_TO_EDGE ? 2 : 3);
    let wrapT = this._wrapT === WrapMode.REPEAT ? 1 : (this._wrapT === WrapMode.CLAMP_TO_EDGE ? 2 : 3);
    let pixelFormat = this._format;
    let image = this._image;
    if (CC_JSB && image) {
        if (image._glFormat !== GL_RGBA)
            pixelFormat = 0;
        premultiplyAlpha = image._premultiplyAlpha;
    }

    this._hash = Number(`${minFilter}${magFilter}${pixelFormat}${wrapS}${wrapT}${genMipmaps}${premultiplyAlpha}${flipY}`);
    this._hashDirty = false;
    return this._hash;
},
_checkPackable () {
    let dynamicAtlas = cc.dynamicAtlasManager;
    if (!dynamicAtlas) return;

    if (this._isCompressed()) {
        this._packable = false;
        return;
    }

    let w = this.width, h = this.height;
    if (!this._image ||
        w > dynamicAtlas.maxFrameSize || h > dynamicAtlas.maxFrameSize || 
        w <= dynamicAtlas.minFrameSize || h <= dynamicAtlas.minFrameSize || 
        this._getHash() !== dynamicAtlas.Atlas.DEFAULT_HASH) {
        this._packable = false;
        return;
    }

    if (this._image && this._image instanceof HTMLCanvasElement) {
        this._packable = true;
    }
},
1 Like