HTML and CSS Reference
In-Depth Information
Listing 21-17. Worker-enabled loadCRN Method
DXTLoader.prototype.loadCRN = function(src, texture, callback) {
if(!texture) {
texture = this.gl.createTexture();
}
// If we're using a worker to handle the decoding create a pending texture
// and put it on the waiting list.
var pending = new CrunchPendingTexture(texture, callback);
this.pendingTextures[pending.id] = pending;
// Then tell the worker to load the CRN file.
this.worker.postMessage({id: pending.id, src: src});
return texture;
}
And just like that, you've worker-ized your loading! Now all the heavy-duty decompression happens in the worker
while the WebGL calls remain on the main thread where they belong.
To see this in action, open up the gallery application once more, select the “CRN” format, and then choose
“Decompress in a Worker” from the new select that appears. The decompression times will no longer appear in the
console, but they should be roughly the same as what you were seeing earlier when the decompression was taking
place in the main thread. The difference now is that the decompression can happen in parallel to the main thread,
which only needs to handle the quick upload.
Now you are able to load your tiny crunched textures, decompress them asynchronously, and upload them to the
GPU as compressed DXTs. You've achieved your goal of minimizing bandwidth and video memory, not blocking your
rendering pipeline as much, and used some cool new web technologies to do it! Hooray!
This approach isn't without a downside, however. In order to send the decoded DXT data over the worker thread,
the data must be copied. This creates “trash” for the garbage collector to clean up, and it can lead to longer or more
frequent garbage collects. Typically, you could avoid this copy by using a Transferable Object, which allows you to
give ownership of an object like an ArrayBuffer over to another worker or to the main thread without copying. That's
not an option in your case, however, because you can only transfer buffers, not views. To do that would require you
to transfer the entire Emscripten “heap” to the main thread and back again. That's not only overkill but it would also
prevent other Crunch textures from being decoded until you returned the buffer to the worker. In the end, the copy
and subsequent garbage collection is an unfortunate but necessary side effect of using Emscripten.
Notes on dxt-util.js
The version of dxt-util.js that is included with the source code for this chapter performs all of the same logic that you
walked through, but has a couple of differences that make it easier to use as a drop-in library for any project. First off,
the library puts everything in a DXTUtil “namespace,” which lessens the chance of collisions with other libraries and
protects the variables you declare within that scope from outside modification, which is a fairly common and prudent
thing for JavaScript libraries to do. This means that you actually create an instance of the loader class by calling
var loader = new DXTUtil.Loader(gl, true);
The second argument given there is a Boolean to indicate whether or not Crunch files should be decoded in a
Worker. Given the benefits described in this chapter, most of the time you'll want this set to true, but it's convenient for
demonstrations like the Gallery app to be able to toggle it off and on.
 
Search WWH ::




Custom Search