[Bug Report]Uint8Arry exception in TranscodeCRNToDXT.js

Hi I’m testing a b3dm tiles contain crn textures.

I saw a strange thins : some textures were displayed and some textures were not displayed. It was not a particular texture problem.

And found a exception at worker side (occurs in createTaskProcessorWorker.js:57 line

function createTaskProcessorWorker(workerFunction) {
var postMessage;
var transferableObjects = ;
var responseMessage = {
id : undefined,
result : undefined,
error : undefined
};

    return function(event) {
        /*global self*/
        var data = event.data;

        transferableObjects.length = 0;
        responseMessage.id = data.id;
        responseMessage.error = undefined;
        responseMessage.result = undefined;

        try {
            responseMessage.result = workerFunction(data.parameters, transferableObjects);
        } catch (e) {
            if (e instanceof Error) {
                // Errors can't be posted in a message, copy the properties
                responseMessage.error = {
                    name : e.name,
                    message : e.message,
                    stack : e.stack
                };
            } else {
                responseMessage.error = e;
            }
        }

        if (!defined(postMessage)) {
            postMessage = defaultValue(self.webkitPostMessage, self.postMessage);
        }

        if (!data.canTransferArrayBuffer) {
            transferableObjects.length = 0;
        }

        try {
            postMessage(responseMessage, transferableObjects);
        } catch (e) {
            // something went wrong trying to post the message, post a simpler
            // error that we can be sure will be cloneable
            responseMessage.result = undefined;
            responseMessage.error = 'postMessage failed with error: ' + formatError(e) + '\n  with responseMessage: ' + JSON.stringify(responseMessage);
            postMessage(responseMessage);
        }
    };
}

``

**Exception detail => **

"RangeError: Source is too large

at Uint8Array.set (native)

at transcodeCRNToDXT (Workers/transcodeCRNToDXT.js:136:23 )

at createTaskProcessorWorker.js:55:42"

**So I looked at transcodeCRNToDXT exception point( **transcodeCRNToDXT.js:136 line)

=> level0DXTData.set(dxtData, 0)

function transcodeCRNToDXT(arrayBuffer, transferableObjects) {
// Copy the contents of the arrayBuffer into emscriptens heap.
var srcSize = arrayBuffer.byteLength;
var bytes = new Uint8Array(arrayBuffer);
var src = crunch._malloc(srcSize);
arrayBufferCopy(bytes, crunch.HEAPU8, src, srcSize);

    // Determine what type of compressed data the file contains.
    var crnFormat = crunch._crn_get_dxt_format(src, srcSize);
    var format = DXT_FORMAT_MAP[crnFormat];
    if (!defined(format)) {
        throw new RuntimeError('Unsupported compressed format.');
    }

    // Gather basic metrics about the DXT data.
    var levels = crunch._crn_get_levels(src, srcSize);
    var width = crunch._crn_get_width(src, srcSize);
    var height = crunch._crn_get_height(src, srcSize);

    // Determine the size of the decoded DXT data.
    var dstSize = 0;
    var i;
    for (i = 0; i < levels; ++i) {
        dstSize += PixelFormat.compressedTextureSizeInBytes(format, width >> i, height >> i);
    }

    // Allocate enough space on the emscripten heap to hold the decoded DXT data
    // or reuse the existing allocation if a previous call to this function has
    // already acquired a large enough buffer.
    if(cachedDstSize < dstSize) {
        if(defined(dst)) {
            crunch._free(dst);
        }
        dst = crunch._malloc(dstSize);
        dxtData = new Uint8Array(crunch.HEAPU8.buffer, dst, dstSize);
        cachedDstSize = dstSize;
    }

    // Decompress the DXT data from the Crunch file into the allocated space.
    crunch._crn_decompress(src, srcSize, dst, dstSize, 0, levels);

    // Release the crunch file data from the emscripten heap.
    crunch._free(src);

    // Mipmaps are unsupported, so copy the level 0 texture
    // When mipmaps are supported, a copy will still be necessary as dxtData is a view on the heap.
    var length = PixelFormat.compressedTextureSizeInBytes(format, width, height);
    var level0DXTData = new Uint8Array(length);
    level0DXTData.set(dxtData, 0);

    transferableObjects.push(level0DXTData.buffer);
    return new CompressedTextureBuffer(format, width, height, level0DXTData);
}

``

I think cache buffer(dxtData) is too big to copy to result buffer(level0DXTData).

So I replaced

level0DXTData.set(dxtData, 0);

=>

level0DXTData = dxtData.slice(0, length);

And it works.

I’m not sure it is perfect solution. so I hope cesium team review my solution.

Thanks

Shyoo.

Thanks for another bug report! We chose to avoid using slice because it is not support in IE11, but missed this edge case. I opened a PR here: https://github.com/AnalyticalGraphicsInc/cesium/pull/5618/files. Can you test if that works for you?

Thanks, It works!

I’ve tested it only on chrome and firefox.

PS: Before this patch, I also couldn’t see crn texture on IE11 and Edge. So I guessed crouch decoder js(emscripten) can not run on IE11 and Edge. I’m not sure.