From 827f999f056b042c78411a991d65a99080715e04 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Wed, 19 Aug 2015 11:10:29 -0400 Subject: [PATCH 1/2] Fix blinking on tile load 1. Use getTimeStamp to ensure an implementation all on browsers and in web workers. This was causing massive blinking in IE. 2. Fix decompression queueing to avoid blinking. --- Source/Scene/Model.js | 65 ++++++++++++++++++-------------------- Source/ThirdParty/o3dgc.js | 16 ++-------- 2 files changed, 34 insertions(+), 47 deletions(-) diff --git a/Source/Scene/Model.js b/Source/Scene/Model.js index bbd16ffa46b4..acf5cca12b9f 100644 --- a/Source/Scene/Model.js +++ b/Source/Scene/Model.js @@ -119,7 +119,7 @@ define([ this.decompressedViewsToCreate = new Queue(); this.decompressedViews = {}; - this.decompressionInFlight = 0; + this.decompressionInFlight = false; this.programsToCreate = new Queue(); this.shaders = {}; @@ -160,7 +160,7 @@ define([ LoadResources.prototype.finishedResourceCreation = function() { return ((this.buffersToCreate.length === 0) && (this.decompressedViewsToCreate.length === 0) && - (this.decompressionInFlight === 0) && + (!this.decompressionInFlight) && (this.programsToCreate.length === 0) && (this.texturesToCreate.length === 0) && (this.texturesToCreateFromBufferView.length === 0) && @@ -170,7 +170,7 @@ define([ LoadResources.prototype.finishedBuffersCreation = function() { return ((this.pendingBufferLoads === 0) && (this.decompressedViewsToCreate.length === 0) && - (this.decompressionInFlight === 0) && + (!this.decompressionInFlight) && (this.buffersToCreate.length === 0)); }; @@ -1303,7 +1303,7 @@ define([ /////////////////////////////////////////////////////////////////////////// - var open3dgcTaskProcessor = new TaskProcessor('decompressOpen3DGC'); + var open3dgcTaskProcessor = new TaskProcessor('decompressOpen3DGC', Number.POSITIVE_INFINITY); function decompressOpen3dgcSync(buffer, decompressedView) { var compressedBuffer = getSubarray(buffer, decompressedView.byteOffset, decompressedView.byteLength); @@ -1336,26 +1336,27 @@ define([ } var decompressPromise = decompressOpen3dgcAsync(buffer, decompressedView); - if (defined(decompressPromise)) { - return when(decompressPromise).then(function(result) { - return result.decompressedArrayBuffer; - }); - } else { - return decompressOpen3dgcSync(buffer, decompressedView); - } + return when(decompressPromise).then(function(result) { + return result.decompressedArrayBuffer; + }); + } + + function createDecompressClosure(loadResources, name) { + return function(decompressedArrayBuffer) { + loadResources.decompressedViews[name] = new Uint8Array(decompressedArrayBuffer); + }; } function createDecompressedView(model) { + var promises = []; var loadResources = model._loadResources; - - loadResources.decompressionInFlight++; - - var name = loadResources.decompressedViewsToCreate.dequeue(); - - var decompressPromise = decompressOpen3dgc(model, name); - decompressPromise.then(function(decompressedArrayBuffer) { - loadResources.decompressedViews[name] = new Uint8Array(decompressedArrayBuffer); - loadResources.decompressionInFlight--; + while (loadResources.decompressedViewsToCreate.length > 0) { + var name = loadResources.decompressedViewsToCreate.dequeue(); + var decompressPromise = decompressOpen3dgc(model, name); + promises.push(decompressPromise.then(createDecompressClosure(loadResources, name))); + } + when.all(promises, function() { + loadResources.decompressionInFlight = false; }); } @@ -1371,21 +1372,14 @@ define([ return; } - if (model.asynchronous) { - if (loadResources.decompressedViewsToCreate.length > 0) { - createDecompressedView(model); - } - } else { - while (loadResources.decompressedViewsToCreate.length > 0) { - createDecompressedView(model); - } - } + loadResources.decompressionInFlight = true; + createDecompressedView(model); } function createBuffers(model, context) { var loadResources = model._loadResources; - if (loadResources.pendingBufferLoads !== 0 || loadResources.decompressedViewsToCreate.length !== 0 || loadResources.decompressionInFlight !== 0) { + if (loadResources.pendingBufferLoads !== 0 || loadResources.decompressedViewsToCreate.length !== 0 || loadResources.decompressionInFlight) { return; } @@ -2915,11 +2909,14 @@ define([ throw this._loadError; } + var loadResources = this._loadResources; if (this._state === ModelState.LOADING) { - // Incrementally create WebGL resources as buffers/shaders/textures are downloaded - createResources(this, context); + if(this._loadResources.decompressionInFlight){ + return; + } + // Create WebGL resources as buffers/shaders/textures are downloaded + createResources(this, context, frameState); - var loadResources = this._loadResources; if (loadResources.finishedPendingLoads() && loadResources.finishedResourceCreation()) { this._state = ModelState.LOADED; this._loadResources = undefined; // Clear CPU memory since WebGL resources were created. @@ -2944,7 +2941,7 @@ define([ } } - var show = this.show && (this.scale !== 0.0); + var show = this.show && (this.scale !== 0.0) && (!defined(loadResources) || !loadResources.decompressionInFlight); if ((show && this._state === ModelState.LOADED) || justLoaded) { var animated = this.activeAnimations.update(frameState) || this._cesiumAnimationsDirty; diff --git a/Source/ThirdParty/o3dgc.js b/Source/ThirdParty/o3dgc.js index fd4d81dc4c29..ad3ad3fafaab 100644 --- a/Source/ThirdParty/o3dgc.js +++ b/Source/ThirdParty/o3dgc.js @@ -1,4 +1,4 @@ -define([], function() { +define(['../Core/getTimeStamp'], function(getTimeStamp) { /*! * https://github.com/amd/rest3d/tree/master/server/o3dgc @@ -182,25 +182,15 @@ define([], function() { return pos; } // Timer class - var windowPerformance = (typeof performance !== 'undefined') ? performance : {}; - if (!windowPerformance.now) { - local.nowOffset = Date.now(); - if (performance.timing && performance.timing.navigationStart) { - local.nowOffset = performance.timing.navigationStart; - } - windowPerformance.now = function now() { - return Date.now() - local.nowOffset; - }; - } module.Timer = function () { this.m_start = 0; this.m_end = 0; }; module.Timer.prototype.Tic = function () { - this.m_start = windowPerformance.now(); + this.m_start = getTimeStamp(); }; module.Timer.prototype.Toc = function () { - this.m_end = windowPerformance.now(); + this.m_end = getTimeStamp(); }; module.Timer.prototype.GetElapsedTime = function () { return this.m_end - this.m_start; From 1d208d4418be109253767ffe07ca25003d396cdd Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Wed, 19 Aug 2015 12:15:42 -0400 Subject: [PATCH 2/2] Use all available CPUs when decompressing data. --- Source/Scene/Model.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Source/Scene/Model.js b/Source/Scene/Model.js index acf5cca12b9f..0526d6a44496 100644 --- a/Source/Scene/Model.js +++ b/Source/Scene/Model.js @@ -1303,7 +1303,9 @@ define([ /////////////////////////////////////////////////////////////////////////// - var open3dgcTaskProcessor = new TaskProcessor('decompressOpen3DGC', Number.POSITIVE_INFINITY); + var decompressOpen3DGCTaskProcessors; + var concurrency; + var counter = 0; function decompressOpen3dgcSync(buffer, decompressedView) { var compressedBuffer = getSubarray(buffer, decompressedView.byteOffset, decompressedView.byteLength); @@ -1316,10 +1318,24 @@ define([ function decompressOpen3dgcAsync(buffer, decompressedView) { var compressedBuffer = copySubarray(buffer, decompressedView.byteOffset, decompressedView.byteLength); - return open3dgcTaskProcessor.scheduleTask({ + if (!defined(decompressOpen3DGCTaskProcessors)) { + concurrency = FeatureDetection.hardwareConcurrency; + decompressOpen3DGCTaskProcessors = new Array(concurrency); + for (var i = 0; i < decompressOpen3DGCTaskProcessors.length; i++) { + decompressOpen3DGCTaskProcessors[i] = new TaskProcessor('decompressOpen3DGC', Number.POSITIVE_INFINITY); + } + } + + var result = decompressOpen3DGCTaskProcessors[counter++].scheduleTask({ decompressedByteLength : decompressedView.decompressedByteLength, compressedBuffer : compressedBuffer }, [compressedBuffer.buffer]); + + if (counter === concurrency) { + counter = 0; + } + + return result; } function decompressOpen3dgc(model, name) {