Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CPU Usage #6115

Merged
merged 56 commits into from
Jan 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
38d7303
Scene render loop updates with opt in requestRender mode
ggetz Dec 13, 2017
97f226f
Merge branch 'master' into requestRender-optin-mode
ggetz Dec 18, 2017
ddbd5e3
Sandcastle updates and specs
ggetz Dec 18, 2017
f215d5c
Update CHANGES.md
ggetz Dec 19, 2017
06270d5
Merge branch 'master' into requestRender-optin-mode
ggetz Dec 19, 2017
1789480
Fix eslint errors
ggetz Dec 20, 2017
b2b08b8
Eslint
ggetz Dec 20, 2017
9c11b92
Fixes
ggetz Dec 20, 2017
94165ba
Include scene morphing and update tests
ggetz Dec 21, 2017
0527041
Callback fix
ggetz Dec 21, 2017
93a40af
Fix typo in CHANGES.md
pjcozzi Dec 21, 2017
87a10e8
Update CHANGES.md, docs
ggetz Dec 22, 2017
1f20508
Code fixes
ggetz Dec 22, 2017
ee37455
Update performance display
ggetz Dec 22, 2017
8eace56
Cleanup scene specs
ggetz Dec 22, 2017
9659b2c
Sandcastle example thumbnail
ggetz Dec 22, 2017
3a7e9f2
Cleanup, update docs, tests, and displays for Sandcastle
ggetz Jan 3, 2018
72cacdb
Eslint errors fix
ggetz Jan 3, 2018
a99bc64
CesiumWidget and Viewer requestRender specs
ggetz Jan 3, 2018
d698876
Rendering/Update events
ggetz Jan 4, 2018
14b7cb4
Update Sandacastle render event usgae, tweak CHANGES.md
ggetz Jan 5, 2018
f69edc1
Merge pull request #6065 from AnalyticalGraphicsInc/requestRender-opt…
lilleyse Jan 8, 2018
d66c837
Globe imagery and terrain loading trigger renders in requestRenderMode
ggetz Jan 10, 2018
1387307
Only update imagery if quadtreeSurfaceTileProvider
ggetz Jan 10, 2018
6ffb328
Updated CHANGES.md
ggetz Jan 10, 2018
682d1b5
Cleanup
ggetz Jan 12, 2018
3c2cfc1
Cleanup globe callbacks
ggetz Jan 12, 2018
61be0f7
Merge pull request #6107 from AnalyticalGraphicsInc/requestRender-globe
lilleyse Jan 12, 2018
78ad148
Merge branch 'master' into cpu-usage
ggetz Jan 12, 2018
0770422
Update scene rendering performance sandcastke example
ggetz Jan 16, 2018
a090eb9
Cleanup comments
ggetz Jan 17, 2018
4aad513
Correctly reset scene when switching scenarios
ggetz Jan 17, 2018
2a5b01e
Clarify sandcastle demo
ggetz Jan 17, 2018
a2d173c
Merge branch 'master' into cpu-usage
Jan 18, 2018
7e202ae
Changed update/render for cpu usage, update specs, cleanup example
ggetz Jan 22, 2018
3662bfc
Fox specs
ggetz Jan 22, 2018
2bb47cf
Merge branch 'master' into cpu-usage
Jan 23, 2018
867f2cc
Spec fixes
ggetz Jan 23, 2018
88b1bab
Cleanup specs
ggetz Jan 23, 2018
6cb6f92
Clean bad merge
ggetz Jan 23, 2018
abeec78
Add scene.forceRender
ggetz Jan 24, 2018
52ae61a
Cleanup forceRender
ggetz Jan 24, 2018
60af769
Change default maximumRenderTimeChange, adjust camera update events
ggetz Jan 24, 2018
1be2923
Merge remote-tracking branch 'origin/master' into cpu-usage
ggetz Jan 24, 2018
2fa7d2e
Resolve tileLoadedCallback changes
ggetz Jan 24, 2018
2aa195a
Update docs to include link to blog post:
ggetz Jan 25, 2018
73efe7d
Merge remote-tracking branch 'origin' into cpu-usage
ggetz Jan 25, 2018
0c9869d
Setting track entity prompts render, clean sandcastle, clean specs
ggetz Jan 25, 2018
dc1ad2c
Fix eslint error
ggetz Jan 26, 2018
7e24f94
Merge branch 'master' into cpu-usage
Jan 26, 2018
79e9bc3
Merge remote-tracking branch 'origin/master' into cpu-usage
ggetz Jan 26, 2018
f9c0578
Updated CHANGES.md, add requestRender mode to CesiumViewer.js
ggetz Jan 26, 2018
15c4cd6
Update example to latest use latest tileset API
ggetz Jan 29, 2018
ea73622
Merge branch 'cpu-usage' of github.com:AnalyticalGraphicsInc/cesium i…
Jan 29, 2018
d8be8cf
Merge branch 'master' into cpu-usage
Jan 29, 2018
c982b3e
tweak sandcastle
Jan 29, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Apps/CesiumViewer/CesiumViewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ define([
viewer = new Viewer('cesiumContainer', {
imageryProvider : imageryProvider,
baseLayerPicker : !defined(imageryProvider),
scene3DOnly : endUserOptions.scene3DOnly
scene3DOnly : endUserOptions.scene3DOnly,
requestRenderMode : true
});
} catch (exception) {
loadingIndicator.style.display = 'none';
Expand Down
4 changes: 2 additions & 2 deletions Apps/Sandcastle/gallery/Camera.html
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@
viewer.camera.flyHome(0);

clock.multiplier = 3 * 60 * 60;
scene.preRender.addEventListener(icrf);
scene.postUpdate.addEventListener(icrf);
scene.globe.enableLighting = true;
}

Expand Down Expand Up @@ -387,7 +387,7 @@
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);

clock.multiplier = 1.0;
scene.preRender.removeEventListener(icrf);
scene.postUpdate.removeEventListener(icrf);
scene.globe.enableLighting = false;
};

Expand Down
2 changes: 1 addition & 1 deletion Apps/Sandcastle/gallery/Cardboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
camera.up = new Cesium.Cartesian3(0.0, 0.0, 1.0);
camera.right = new Cesium.Cartesian3(0.0, -1.0, 0.0);

viewer.scene.preRender.addEventListener(function(scene, time) {
viewer.scene.postUpdate.addEventListener(function(scene, time) {
var position = entity.position.getValue(time);
if (!Cesium.defined(position)) {
return;
Expand Down
14 changes: 8 additions & 6 deletions Apps/Sandcastle/gallery/HeadingPitchRoll.html
Original file line number Diff line number Diff line change
Expand Up @@ -202,12 +202,7 @@ <h1>Loading...</h1>
var speedSpan = document.getElementById('speed');
var fromBehind = document.getElementById('fromBehind');

viewer.scene.preRender.addEventListener(function(scene, time) {
headingSpan.innerHTML = Cesium.Math.toDegrees(hpRoll.heading).toFixed(1);
pitchSpan.innerHTML = Cesium.Math.toDegrees(hpRoll.pitch).toFixed(1);
rollSpan.innerHTML = Cesium.Math.toDegrees(hpRoll.roll).toFixed(1);
speedSpan.innerHTML = speed.toFixed(1);

viewer.scene.preUpdate.addEventListener(function(scene, time) {
speedVector = Cesium.Cartesian3.multiplyByScalar(Cesium.Cartesian3.UNIT_X, speed / 10, speedVector);
position = Cesium.Matrix4.multiplyByPoint(planePrimitive.modelMatrix, speedVector, position);
pathPosition.addSample(Cesium.JulianDate.now(), position);
Expand All @@ -221,6 +216,13 @@ <h1>Loading...</h1>
camera.lookAt(center, hpRange);
}
});

viewer.scene.preRender.addEventListener(function(scene, time) {
headingSpan.innerHTML = Cesium.Math.toDegrees(hpRoll.heading).toFixed(1);
pitchSpan.innerHTML = Cesium.Math.toDegrees(hpRoll.pitch).toFixed(1);
rollSpan.innerHTML = Cesium.Math.toDegrees(hpRoll.roll).toFixed(1);
speedSpan.innerHTML = speed.toFixed(1);
});
//Sandcastle_End
Sandcastle.finishedLoading();
}
Expand Down
12 changes: 7 additions & 5 deletions Apps/Sandcastle/gallery/LocalToFixedFrame.html
Original file line number Diff line number Diff line change
Expand Up @@ -212,18 +212,20 @@ <h1>Loading...</h1>
var pitchSpan = document.getElementById('pitch');
var rollSpan = document.getElementById('roll');

viewer.scene.preRender.addEventListener(function(scene, time) {
headingSpan.innerHTML = Cesium.Math.toDegrees(hpRoll.heading).toFixed(1);
pitchSpan.innerHTML = Cesium.Math.toDegrees(hpRoll.pitch).toFixed(1);
rollSpan.innerHTML = Cesium.Math.toDegrees(hpRoll.roll).toFixed(1);

viewer.scene.preUpdate.addEventListener(function(scene, time) {
for (var i = 0; i < primitives.length; i++) {
var primitive = primitives[i].primitive;
var converter = primitives[i].converter;
var position = primitives[i].position;
Cesium.Transforms.headingPitchRollToFixedFrame(position, hpRoll, Cesium.Ellipsoid.WGS84, converter, primitive.modelMatrix);
}
});

viewer.scene.preRender.addEventListener(function(scene, time) {
headingSpan.innerHTML = Cesium.Math.toDegrees(hpRoll.heading).toFixed(1);
pitchSpan.innerHTML = Cesium.Math.toDegrees(hpRoll.pitch).toFixed(1);
rollSpan.innerHTML = Cesium.Math.toDegrees(hpRoll.roll).toFixed(1);
});
//Sandcastle_End
Sandcastle.finishedLoading();
}
Expand Down
2 changes: 1 addition & 1 deletion Apps/Sandcastle/gallery/Particle System.html
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@
p.velocity = Cesium.Cartesian3.add(p.velocity, gravityScratch, p.velocity);
}

viewer.scene.preRender.addEventListener(function(scene, time) {
viewer.scene.preUpdate.addEventListener(function(scene, time) {
particleSystem.modelMatrix = computeModelMatrix(entity, time);

// Account for any changes to the emitter model matrix.
Expand Down
296 changes: 296 additions & 0 deletions Apps/Sandcastle/gallery/Scene Rendering Performance.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,296 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta name="description" content="Use explicit rendering to improve app performance.">
<meta name="cesium-sandcastle-labels" content="Showcases, Tutorials">
<title>Cesium Demo</title>
<script type="text/javascript" src="../Sandcastle-header.js"></script>
<script type="text/javascript" src="../../../ThirdParty/requirejs-2.1.20/require.js"></script>
<script type="text/javascript">
if(typeof require === "function") {
require.config({
baseUrl : '../../../Source',
waitSeconds : 120
});
}
</script>
</head>
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
<style>
@import url(../templates/bucket.css);

#toolbar {
background: rgba(42, 42, 42, 0.8);
padding: 4px;
border-radius: 4px;
}

#toolbar h3, h4 {
margin: 0 0 2px 0;
}

#toolbar i {
font-size: 85%;
}

#toolbar table {
margin: 2px 3px;
max-width: 280px;
}

#toolbar td {
padding-bottom: 10px;
}

#toolbar .cesium-button {
margin: 6px 0 0;
}

#toolbar input {
vertical-align: middle;
}

#toolbar input:disabled{
color: darkgray;
}
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar">
<table>
<tbody><tr>
<td>
<h3>
<code><span data-bind="text: lastRenderTime"></span></code>
</h3>
Simulation time at last render frame
<button type="button" class="cesium-button" data-bind="click: requestRender">Render new frame</button>
</td>
</tr>
<tr>
<td>
<h3>
<input value="true" data-bind="checked: requestRenderMode, valueUpdate: 'input'" type="checkbox">
<code>requestRenderMode</code> enabled
</h3>
<i>When enabled, a new frame is only rendered when scene updates occur, or a new frame is explicitly rendered.</i>
</td>
</tr>
<tr data-bind="visible: showTimeOptions">
<td>
<h4>
<input value="true" data-bind="checked: timeChangeEnabled, valueUpdate: 'input'" type="checkbox">
Render when simulation time changes
</h4>
<i>Automatically render when the simulation time changes by "Max delta time". Adjust the simulation time on the animation widget and "Max delta time" value to see their relationship.</i>
</td>
</tr>
<tr data-bind="visible: showTimeOptions">
<td>
<h4>Max delta time</h4>
<input min="0" max="20" step="0.1" data-bind="value: maximumRenderTimeChange, valueUpdate: 'input', enable: timeChangeEnabled" type="range">
<input size="2" data-bind="value: maximumRenderTimeChange, valueUpdate: 'input', enable: timeChangeEnabled" type="text">
</td>
</tr>
</tbody></table>
</div>
<script id="cesium_sandcastle_script">
function startup(Cesium) {
'use strict';
//Sandcastle_Begin
// Create a viewer that won't render a new frame unless
// updates to the scene require it to reduce overall CPU usage.
var viewer = new Cesium.Viewer('cesiumContainer', {
requestRenderMode : true,
maximumRenderTimeChange : Infinity
});

var scene = viewer.scene;
scene.debugShowFramesPerSecond = true;

var viewModel = {
requestRenderMode : true,
showTimeOptions : false,
timeChangeEnabled : false,
maximumRenderTimeChange : 0.0,
lastRenderTime : '',
requestRender : function () {
scene.requestRender();
}
};

// Clear scene and set default view.
var handler;
function resetScene() {
viewer.trackedEntity = undefined;
viewer.dataSources.removeAll();
viewer.entities.removeAll();
viewer.scene.primitives.removeAll();
viewer.clock.shouldAnimate = false;
handler = handler && handler.destroy();
scene.skyBox.show = true;
scene.camera.flyHome(0.0);
scene.requestRender();
viewModel.showTimeOptions = false;
viewModel.timeChangeEnabled = false;
viewModel.maximumRenderTimeChange = 0;
}

// Load a tileset and set the view.
// No need to call scene.requestRender()
function loadTilesetScenario() {
resetScene();

Cesium.CesiumIon.create3DTileset(1458, { accessToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIxYmJiNTAxOC1lOTg5LTQzN2EtODg1OC0zMWJjM2IxNGNlYmMiLCJpZCI6NDQsImFzc2V0cyI6WzE0NThdLCJpYXQiOjE0OTkyNjM4MjB9.1WKijRa-ILkmG6utrhDWX6rDgasjD7dZv-G5ZyCmkKg' })
.then(function(tileset) {
viewer.scene.primitives.add(tileset);
viewer.zoomTo(tileset);
})
.otherwise(function(error) {
console.log(error);
});
}

// Load an animated model and set the view.
// No need to call scene.requestRender()
// Enable and adjust maximum simulation time change to see
// animations at desired speed.
function loadModelScenario() {
resetScene();
viewModel.timeChangeEnabled = true;
viewModel.showTimeOptions = true;

var entity = viewer.entities.add({
name : 'Aircraft',
position : Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, 5000.0),
model : {
uri : '../../SampleData/models/CesiumAir/Cesium_Air.glb',
minimumPixelSize : 128,
maximumScale : 20000
}
});

viewer.trackedEntity = entity;
viewer.clock.shouldAnimate = true;
}

// Load CZML DataSource with a model and set the trackedEntity.
// No need to call scene.requestRender()
// Enable and adjust maximum simulation time change to see
// animations at desired speed.
function loadCzmlScenario() {
resetScene();
viewModel.showTimeOptions = true;
viewModel.timeChangeEnabled = true;
viewModel.maximumRenderTimeChange = 10.0;

viewer.dataSources.add(Cesium.CzmlDataSource.load('../../SampleData/simple.czml'));
viewer.clock.shouldAnimate = true;
}

// Pick an entity, only rendering when needed.
function pickingScenario() {
resetScene();

var entity = viewer.entities.add({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call requestRender after adding this primitive

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, that might not work since the entity is creating this primitive asynchronously. How is an end user supposed to handle that case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it is being created asynchronously, the return from the web worker will prompt a render automatically. Adding requestRender right after adding it to the scene would be best though, as it will ensure the primitive creation is kicked off.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah okay, I thought it wasn't added until I moved the camera but I couldn't seem to reproduce it so maybe I just interpreted the timing wrong.

Adding requestRender right after adding it to the scene would be best though, as it will ensure the primitive creation is kicked off.

I'm confused, will the web worker not start otherwise?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can confirm that the entity does render without changing the camera. The call to primitives.update is still happens during a render since it's not trivial. So the geometry creation wont start until a render happens. This is similar to how we're loading in the globe tiles (see conversation above).

position : Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),
box : {
dimensions : new Cesium.Cartesian3(1000000.0, 1000000.0, 30000.0),
material : Cesium.Color.CORNFLOWERBLUE
}
});

scene.requestRender();

// If the mouse is over the box, change its scale and color,
// then request a new render frame.
var lastPicked;
handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
handler.setInputAction(function(movement) {
var pickedObject = scene.pick(movement.endPosition);
if (Cesium.defined(pickedObject) && (pickedObject.id === entity)) {
if (Cesium.defined(lastPicked)) {
return;
}

entity.box.material = Cesium.Color.YELLOW;
scene.requestRender();
lastPicked = pickedObject;
} else if (Cesium.defined(lastPicked)) {
entity.box.material = Cesium.Color.CORNFLOWERBLUE;
scene.requestRender();
lastPicked = undefined;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
}

// Changes to the scene with the API will require
// calling requestRender() on change.
function setScenePropertiesScenario() {
resetScene();

scene.skyBox.show = false;
scene.backgroundColor = Cesium.Color.CORNFLOWERBLUE;
scene.requestRender();
}

// BEGIN SANDCASTLE EXAMPLE UI SETUP

var toolbar = document.getElementById('toolbar');
Cesium.knockout.track(viewModel);
Cesium.knockout.applyBindings(viewModel, toolbar);

Cesium.knockout.getObservable(viewModel, 'requestRenderMode').subscribe(function(value) {
scene.requestRenderMode = value;
});

Cesium.knockout.getObservable(viewModel, 'timeChangeEnabled').subscribe(function(value) {
scene.maximumRenderTimeChange = value ? viewModel.maximumRenderTimeChange : Infinity;
});

Cesium.knockout.getObservable(viewModel, 'maximumRenderTimeChange').subscribe(function(value) {
scene.maximumRenderTimeChange = value;
});

scene.postRender.addEventListener(function() {
var time = Cesium.JulianDate.toGregorianDate(scene.lastRenderTime);
var value = time.hour + ':' + time.minute + ':' + time.second + ':' + time.millisecond.toFixed(0);
Cesium.knockout.getObservable(viewModel, 'lastRenderTime')(value);
});

var scenarios = [{
text : 'Default view',
onselect : resetScene
}, {
text : 'Load a 3D tileset and set the view',
onselect : loadTilesetScenario
}, {
text : 'Mouseover picking',
Copy link
Contributor

@lilleyse lilleyse Jan 17, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it's just me, but the picking feels like it has a bit of a delay. Is that expected?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the delay. It only happens the first time an entity is added to the scene. I need to look more to see what's causing this.

Copy link
Contributor Author

@ggetz ggetz Jan 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lilleyse I believe this is resolved, let me know if you are still seeing the delay.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, works perfectly now.

onselect : pickingScenario
}, {
text : 'Load time-dynamic CZML',
onselect : loadCzmlScenario
}, {
text : 'Animated model',
onselect : loadModelScenario
}, {
text : 'Scene changes with API',
onselect : setScenePropertiesScenario
}];

Sandcastle.addToolbarMenu(scenarios);

//Sandcastle_End
Sandcastle.finishedLoading();
}
if (typeof Cesium !== "undefined") {
startup(Cesium);
} else if (typeof require === "function") {
require(["Cesium"], startup);
}
</script>
</body>
</html>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading