Skip to content

Commit

Permalink
Reintegrate request scheduler
Browse files Browse the repository at this point in the history
  • Loading branch information
lilleyse committed Jun 13, 2017
1 parent d4b0afb commit 02ba0eb
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 92 deletions.
47 changes: 29 additions & 18 deletions Source/Scene/Cesium3DTile.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ define([
'../Core/Rectangle',
'../Core/Request',
'../Core/RequestScheduler',
'../Core/RequestState',
'../Core/RequestType',
'../Core/RuntimeError',
'../ThirdParty/when',
Expand Down Expand Up @@ -48,6 +49,7 @@ define([
Rectangle,
Request,
RequestScheduler,
RequestState,
RequestType,
RuntimeError,
when,
Expand Down Expand Up @@ -173,13 +175,13 @@ define([
var hasEmptyContent;
var contentState;
var contentUrl;
var requestServer;
var serverKey;

if (defined(contentHeader)) {
hasEmptyContent = false;
contentState = Cesium3DTileContentState.UNLOADED;
contentUrl = joinUrls(basePath, contentHeader.url);
requestServer = RequestScheduler.getRequestServer(contentUrl);
serverKey = RequestScheduler.getServerKey(contentUrl);
} else {
content = new Empty3DTileContent(tileset, this);
hasEmptyContent = true;
Expand All @@ -193,7 +195,7 @@ define([
this._contentReadyPromise = undefined;
this._expiredContent = undefined;

this._requestServer = requestServer;
this._serverKey = serverKey;

/**
* When <code>true</code>, the tile has no content.
Expand Down Expand Up @@ -300,7 +302,6 @@ define([
this._screenSpaceError = 0;
this._screenSpaceErrorComputedFrame = -1;
this._finalResolution = true;
this._requestHeap = undefined;
this._depth = 0;
this._centerZDepth = 0;
this._stackLength = 0;
Expand Down Expand Up @@ -415,9 +416,9 @@ define([
* @readonly
* @private
*/
requestServer : {
serverKey : {
get : function() {
return this._requestServer;
return this._serverKey;
}
},

Expand Down Expand Up @@ -584,6 +585,12 @@ define([
};
}

function createPriorityFunction(tile) {
return function() {
return tile._distanceToCamera;
};
}

/**
* Requests the tile's content.
* <p>
Expand All @@ -599,10 +606,6 @@ define([
return false;
}

if (!this._requestServer.hasAvailableRequests()) {
return false;
}

var url = this._contentUrl;
var expired = this.contentExpired;
if (expired) {
Expand All @@ -611,19 +614,20 @@ define([
url = joinUrls(url, timestampQuery, false);
}

var distance = this._distanceToCamera;
var promise = RequestScheduler.schedule(new Request({
url : url,
server : this._requestServer,
requestFunction : loadArrayBuffer,
var request = new Request({
throttle : true,
throttleByServer : true,
type : RequestType.TILES3D,
distance : distance
}));
priorityFunction : createPriorityFunction(this)
});

var promise = loadArrayBuffer(url, undefined, request);

if (!defined(promise)) {
return false;
}

var contentState = this._contentState;
this._contentState = Cesium3DTileContentState.LOADING;
this._contentReadyToProcessPromise = when.defer();
this._contentReadyPromise = when.defer();
Expand Down Expand Up @@ -672,7 +676,14 @@ define([
that._contentState = Cesium3DTileContentState.READY;
that._contentReadyPromise.resolve(content);
});
}).otherwise(contentFailedFunction);
}).otherwise(function(error) {
if (request.state === RequestState.CANCELLED) {
// Cancelled due to low priority - try again later.
that._contentState = contentState;
return;
}
contentFailedFunction(error);
});

return true;
};
Expand Down
58 changes: 13 additions & 45 deletions Source/Scene/Cesium3DTileset.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ define([
'../Core/ManagedArray',
'../Core/Math',
'../Core/Matrix4',
'../Core/RequestScheduler',
'../Core/RequestType',
'../Core/RuntimeError',
'../Renderer/ClearCommand',
'../Renderer/Pass',
Expand Down Expand Up @@ -63,8 +61,6 @@ define([
ManagedArray,
CesiumMath,
Matrix4,
RequestScheduler,
RequestType,
RuntimeError,
ClearCommand,
Pass,
Expand Down Expand Up @@ -185,6 +181,7 @@ define([
this._gltfUpAxis = undefined;
this._processingQueue = [];
this._selectedTiles = [];
this._requestedTiles = [];
this._desiredTiles = new ManagedArray();
this._selectedTilesToStyle = [];
this._loadTimestamp = undefined;
Expand All @@ -200,7 +197,6 @@ define([

this._cullWithChildrenBounds = defaultValue(options.cullWithChildrenBounds, true);

this._requestHeaps = {};
this._hasMixedContent = false;

this._baseTraversal = new Cesium3DTilesetTraversal.BaseTraversal();
Expand Down Expand Up @@ -724,7 +720,7 @@ define([
var that = this;

// We don't know the distance of the tileset until tileset.json is loaded, so use the default distance for now
RequestScheduler.request(tilesetUrl, loadJson, undefined, RequestType.TILES3D).then(function(tilesetJson) {
loadJson(tilesetUrl).then(function(tilesetJson) {
that._root = that.loadTileset(tilesetUrl, tilesetJson);
var gltfUpAxis = defined(tilesetJson.asset.gltfUpAxis) ? Axis.fromName(tilesetJson.asset.gltfUpAxis) : Axis.Y;
that._asset = tilesetJson.asset;
Expand Down Expand Up @@ -1199,23 +1195,6 @@ define([
if (this._cullWithChildrenBounds) {
Cesium3DTileOptimizations.checkChildrenWithinParent(tile3D);
}

// Create a load heap, one for each unique server. We can only make limited requests to a given
// server so it is unnecessary to keep a queue of all tiles needed to be loaded.
// Instead of creating a list of all tiles to load and then sorting it entirely to find the best ones,
// we keep just a heap so we have the best `maximumRequestsPerServer` to load. The order of these does
// not matter much as we will try to load them all.
// The heap approach is a O(n log k) to find the best tiles for loading.
var requestServer = tile3D.requestServer;
if (defined(requestServer)) {
if (!defined(this._requestHeaps[requestServer])) {
var heap = new Heap(sortForLoad);
this._requestHeaps[requestServer] = heap;
heap.maximumSize = RequestScheduler.maximumRequestsPerServer;
heap.reserve(heap.maximumSize);
}
tile3D._requestHeap = this._requestHeaps[requestServer];
}
}

return rootTile;
Expand Down Expand Up @@ -1309,20 +1288,10 @@ define([
(tile._depth > ancestor._depth + skipLevels);
}

function sortForLoad(a, b) {
var distanceDifference = a._distanceToCamera - b._distanceToCamera;
if (a.refine === Cesium3DTileRefine.ADD || b.refine === Cesium3DTileRefine.ADD) {
return distanceDifference;
}

var screenSpaceErrorDifference = b._screenSpaceError - a._screenSpaceError;
return screenSpaceErrorDifference === 0 ? distanceDifference : screenSpaceErrorDifference;
}

///////////////////////////////////////////////////////////////////////////

function requestContent(tileset, tile, outOfCore) {
if (!outOfCore || tile.hasEmptyContent) {
function requestContent(tileset, tile) {
if (tile.hasEmptyContent) {
return;
}

Expand Down Expand Up @@ -1351,15 +1320,14 @@ define([
tile.contentReadyPromise.then(removeFunction).otherwise(removeFunction);
}

function requestTiles(tileset, requestHeaps, outOfCore) {
for (var name in requestHeaps) {
if (requestHeaps.hasOwnProperty(name)) {
var heap = requestHeaps[name];
var tile;
while (defined(tile = heap.pop())) {
requestContent(tileset, tile, outOfCore);
}
}
function requestTiles(tileset, outOfCore) {
if (!outOfCore) {
return;
}
var requestedTiles = tileset._requestedTiles;
var length = requestedTiles.length;
for (var i = 0; i < length; ++i) {
requestContent(tileset, requestedTiles[i]);
}
}

Expand Down Expand Up @@ -1754,7 +1722,7 @@ define([
}

Cesium3DTilesetTraversal.selectTiles(this, frameState, outOfCore);
requestTiles(this, this._requestHeaps, outOfCore);
requestTiles(this, outOfCore);
updateTiles(this, frameState);

if (outOfCore) {
Expand Down
68 changes: 39 additions & 29 deletions Source/Scene/Cesium3DTilesetTraversal.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ define([

tileset._desiredTiles.length = 0;
tileset._selectedTiles.length = 0;
tileset._requestedTiles.length = 0;
tileset._selectedTilesToStyle.length = 0;
tileset._hasMixedContent = false;

Expand Down Expand Up @@ -65,7 +66,7 @@ define([
return;
}

loadTile(root, frameState);
loadTile(tileset, root, frameState);

if (!tileset.skipLevelOfDetail) {
// just execute base traversal and add tiles to _desiredTiles
Expand Down Expand Up @@ -302,30 +303,36 @@ define([
};

BaseTraversal.prototype.getChildren = function(tile) {
if (baseUpdateAndCheckChildren(this.tileset, tile, this.baseScreenSpaceError, this.frameState)) {
var children = tile.children;
var childrenLength = children.length;
var allReady = true;
var replacementWithContent = tile.refine === Cesium3DTileRefine.REPLACE && tile.hasRenderableContent;
for (var i = 0; i < childrenLength; ++i) {
var child = children[i];
loadTile(child, this.frameState);
touch(this.tileset, child, this.outOfCore);

// content cannot be replaced until all of the nearest descendants with content are all loaded
if (replacementWithContent) {
if (!child.hasEmptyContent) {
allReady = allReady && child.contentAvailable;
} else {
allReady = allReady && this.internalDFS.execute(child);
}
var tileset = this.tileset;
var outOfCore = this.outOfCore;
var frameState = this.frameState;
if (!baseUpdateAndCheckChildren(tileset, tile, this.baseScreenSpaceError, frameState)) {
return emptyArray;
}

var children = tile.children;
var childrenLength = children.length;
var allReady = true;
var replacementWithContent = tile.refine === Cesium3DTileRefine.REPLACE && tile.hasRenderableContent;
for (var i = 0; i < childrenLength; ++i) {
var child = children[i];
loadTile(tileset, child, frameState);
touch(tileset, child, outOfCore);

// content cannot be replaced until all of the nearest descendants with content are all loaded
if (replacementWithContent) {
if (!child.hasEmptyContent) {
allReady = allReady && child.contentAvailable;
} else {
allReady = allReady && this.internalDFS.execute(child);
}
}
}

if (allReady) {
return children;
}
if (allReady) {
return children;
}

return emptyArray;
};

Expand Down Expand Up @@ -397,16 +404,20 @@ define([
};

InternalBaseTraversal.prototype.getChildren = function(tile) {
if (!baseUpdateAndCheckChildren(this.tileset, tile, this.baseScreenSpaceError, this.frameState)) {
var tileset = this.tileset;
var frameState = this.frameState;
var outOfCore = this.outOfCore;

if (!baseUpdateAndCheckChildren(tileset, tile, this.baseScreenSpaceError, frameState)) {
return emptyArray;
}

var children = tile.children;
var childrenLength = children.length;
for (var i = 0; i < childrenLength; ++i) {
var child = children[i];
loadTile(child, this.frameState);
touch(this.tileset, child, this.outOfCore);
loadTile(tileset, child, frameState);
touch(tileset, child, outOfCore);
if (!tile.contentAvailable) {
this.allLoaded = false;
}
Expand Down Expand Up @@ -563,11 +574,11 @@ define([
var tiles = parent.children;
var length = tiles.length;
for (var i = 0; i < length; ++i) {
loadTile(tiles[i], this.frameState);
loadTile(this.tileset, tiles[i], this.frameState);
touch(this.tileset, tiles[i], this.outOfCore);
}
} else {
loadTile(tile, this.frameState);
loadTile(this.tileset, tile, this.frameState);
touch(this.tileset, tile, this.outOfCore);
}
}
Expand Down Expand Up @@ -630,11 +641,10 @@ define([
}
}

function loadTile(tile, frameState) {
function loadTile(tileset, tile, frameState) {
if ((tile.contentUnloaded || tile.contentExpired) && tile._requestedFrame !== frameState.frameNumber) {
tile._requestedFrame = frameState.frameNumber;
computeSSE(tile, frameState);
tile._requestHeap.insert(tile);
tileset._requestedTiles.push(tile);
}
}

Expand Down

0 comments on commit 02ba0eb

Please sign in to comment.