Skip to content

Commit

Permalink
Rendering/Update events
Browse files Browse the repository at this point in the history
  • Loading branch information
ggetz committed Jan 4, 2018
1 parent a99bc64 commit d698876
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 40 deletions.
7 changes: 5 additions & 2 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ Change Log

### 1.42 - 2017-02-01

* Added optional scene request render mode to reduce CPU usage
* `scene.requestRenderMode` enables a mode which will only request new render frames on changes to the scene, or when the simulation time change exceeds `scene.maximumRenderTimeChange`.
* Breaking changes
* `scene.preRender` and `scene.postRender` events are called immediately before and after scene rendering only if the scene renders a frame. See `scene.requestRenderMode`. Use `scene.preUpdate` and `scene.postUpdate` for task that require regular updates.
* Added optional scene request render mode to reduce CPU usage. [#6065](https://github.com/AnalyticalGraphicsInc/cesium/pull/6065)
* `scene.requestRenderMode` enables a mode which will only request new render frames on changes to the scene, or when the simulation time change exceeds `scene.maximumRenderTimeChange`.
* `scene.requestRender` will explicitly request a new render frame when in request render mode.
* Added `scene.preUpdate` and `scene.postUpdate` events that are raised before and after the scene updates respectively. The scene is always updated before executing a potential render.

### 1.41 - 2017-01-02

Expand Down
4 changes: 2 additions & 2 deletions Source/Scene/FrameRateMonitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ define([
this._pauseCount = 0;

var that = this;
this._preRenderRemoveListener = this._scene.preRender.addEventListener(function(scene, time) {
this._preUpdateRemoveListener = this._scene.preUpdate.addEventListener(function(scene, time) {
update(that, time);
});

Expand Down Expand Up @@ -274,7 +274,7 @@ define([
* @see FrameRateMonitor#isDestroyed
*/
FrameRateMonitor.prototype.destroy = function() {
this._preRenderRemoveListener();
this._preUpdateRemoveListener();

if (defined(this._visibilityChangeRemoveListener)) {
this._visibilityChangeRemoveListener();
Expand Down
116 changes: 84 additions & 32 deletions Source/Scene/Scene.js
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,9 @@ define([

this._transitioner = new SceneTransitioner(this);

this._preUpdate = new Event();
this._postUpdate = new Event();

this._renderError = new Event();
this._preRender = new Event();
this._postRender = new Event();
Expand Down Expand Up @@ -1024,6 +1027,45 @@ define([
}
},

/**
* Gets the event that will be raised before the scene is updated or rendered. Subscribers to the event
* receive the Scene instance as the first parameter and the current time as the second parameter.
* @memberof Scene.prototype
*
* @see scene#postUpdate
* @see scene#preRender
* @see scene#postRender
* @see scene#render
*
* @type {Event}
* @readonly
*/
preUpdate : {
get : function() {
return this._preUpdate;
}
},

/**
* Gets the event that will be raised immediately after the scene is updated and before the scene is rendered.
* Subscribers to the event receive the Scene instance as the first parameter and the current time as the second
* parameter.
* @memberof Scene.prototype
*
* @see scene#preUpdate
* @see scene#preRender
* @see scene#postRender
* @see scene#render
*
* @type {Event}
* @readonly
*/
postUpdate : {
get : function() {
return this._postUpdate;
}
},

/**
* Gets the event that will be raised when an error is thrown inside the <code>render</code> function.
* The Scene instance and the thrown error are the only two parameters passed to the event handler.
Expand All @@ -1041,10 +1083,16 @@ define([
},

/**
* Gets the event that will be raised at the start of each call to <code>render</code>. Subscribers to the event
* receive the Scene instance as the first parameter and the current time as the second parameter.
* Gets the event that will be raised after the scene is updated and immediately before the scene is rendered.
* Subscribers to the event receive the Scene instance as the first parameter and the current time as the second
* parameter.
* @memberof Scene.prototype
*
* @see scene#preUpdate
* @see scene#postUpdate
* @see scene#postRender
* @see scene#render
*
* @type {Event}
* @readonly
*/
Expand All @@ -1055,10 +1103,15 @@ define([
},

/**
* Gets the event that will be raised at the end of each call to <code>render</code>. Subscribers to the event
* Gets the event that will be raised immediately after the scene is rendered. Subscribers to the event
* receive the Scene instance as the first parameter and the current time as the second parameter.
* @memberof Scene.prototype
*
* @see scene#preUpdate
* @see scene#postUpdate
* @see scene#postRender
* @see scene#render
*
* @type {Event}
* @readonly
*/
Expand Down Expand Up @@ -2787,7 +2840,7 @@ define([
}
}

function callAfterRenderFunctions(frameState) {
function callAfterRenderCycleFunctions(frameState) {
// Functions are queued up during primitive update and executed here in case
// the function modifies scene state that should remain constant over the frame.
var functions = frameState.afterRender;
Expand Down Expand Up @@ -2860,14 +2913,7 @@ define([
}

function update(scene, time) {
var frameState = scene._frameState;

scene._groundPrimitives.update(frameState);
scene._primitives.update(frameState);

if (defined(scene.globe)) {
scene.globe.update(frameState);
}
// TODO: Update primitives, including globe
}

function render(scene, time) {
Expand Down Expand Up @@ -2922,6 +2968,18 @@ define([
context.endFrame();
}

function tryAndCatchError(scene, time, functionToExecute) {
try {
functionToExecute(scene, time);
} catch (error) {
scene._renderError.raiseEvent(scene, error);

if (scene.rethrowRenderErrors) {
throw error;
}
}
}

/**
* @private
*/
Expand All @@ -2930,39 +2988,33 @@ define([
time = JulianDate.now();
}

this._preRender.raiseEvent(this, time);
this._jobScheduler.resetBudgets();

var cameraChanged = checkForCameraUpdates(this);
// Update
this._preUpdate.raiseEvent(this, time);
tryAndCatchError(this, time, update);
this._postUpdate.raiseEvent(this, time);

var cameraChanged = checkForCameraUpdates(this);
var shouldRender = !this.requestRenderMode || this._renderRequested || cameraChanged || (this.mode === SceneMode.MORPHING);

if (!shouldRender && defined(this.maximumRenderTimeChange) && defined(this._lastRenderTime)) {
var difference = Math.abs(JulianDate.secondsDifference(this._lastRenderTime, time));
shouldRender = shouldRender || difference >= this.maximumRenderTimeChange;
}

try {
if (shouldRender) {
this._lastRenderTime = JulianDate.clone(time, this._lastRenderTime);
this._renderRequested = false;
if (shouldRender) {
this._lastRenderTime = JulianDate.clone(time, this._lastRenderTime);
this._renderRequested = false;

render(this, time);
} else {
update(this, time);
}
} catch (error) {
this._renderError.raiseEvent(this, error);

if (this.rethrowRenderErrors) {
throw error;
}
// Render
this._preRender.raiseEvent(this, time);
tryAndCatchError(this, time, render);
this._postRender.raiseEvent(this, time);
}

updateDebugShowFramesPerSecond(this, shouldRender);
RequestScheduler.update();
callAfterRenderFunctions(this._frameState);
this._postRender.raiseEvent(this, time);
callAfterRenderCycleFunctions(this._frameState);
};

/**
Expand Down Expand Up @@ -3143,7 +3195,7 @@ define([

var object = this._pickFramebuffer.end(scratchRectangle);
context.endFrame();
callAfterRenderFunctions(frameState);
callAfterRenderCycleFunctions(frameState);
return object;
};

Expand Down
2 changes: 1 addition & 1 deletion Source/Widgets/Viewer/Viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to
eventHelper.add(dataSourceCollection.dataSourceRemoved, Viewer.prototype._onDataSourceRemoved, this);

// Prior to each render, check if anything needs to be resized.
eventHelper.add(cesiumWidget.scene.preRender, Viewer.prototype.resize, this);
eventHelper.add(cesiumWidget.scene.postUpdate, Viewer.prototype.resize, this);
eventHelper.add(cesiumWidget.scene.postRender, Viewer.prototype._postRender, this);

// We need to subscribe to the data sources and collections so that we can clear the
Expand Down
59 changes: 56 additions & 3 deletions Specs/Scene/SceneSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -983,7 +983,47 @@ defineSuite([
s.destroyForSpecs();
});

it('raises the preRender event prior to rendering', function() {
it('alwayas raises preUpdate event prior to updating', function() {
var s = createScene();

var spyListener = jasmine.createSpy('listener');
s.preUpdate.addEventListener(spyListener);

s.render();

expect(spyListener.calls.count()).toBe(1);

s.requestRenderMode = true;
s.maximumRenderTimeChange = undefined;

s.render();

expect(spyListener.calls.count()).toBe(2);

s.destroyForSpecs();
});

it('always raises preUpdate event after updating', function() {
var s = createScene();

var spyListener = jasmine.createSpy('listener');
s.preUpdate.addEventListener(spyListener);

s.render();

expect(spyListener.calls.count()).toBe(1);

s.requestRenderMode = true;
s.maximumRenderTimeChange = undefined;

s.render();

expect(spyListener.calls.count()).toBe(2);

s.destroyForSpecs();
});

it('raises the preRender event prior to rendering only if the scene renders', function() {
var s = createScene();

var spyListener = jasmine.createSpy('listener');
Expand All @@ -993,10 +1033,17 @@ defineSuite([

expect(spyListener.calls.count()).toBe(1);

s.requestRenderMode = true;
s.maximumRenderTimeChange = undefined;

s.render();

expect(spyListener.calls.count()).toBe(1);

s.destroyForSpecs();
});

it('raises the postRender event after rendering', function() {
it('raises the postRender event after rendering if the scene rendered', function() {
var s = createScene();

var spyListener = jasmine.createSpy('listener');
Expand All @@ -1006,6 +1053,13 @@ defineSuite([

expect(spyListener.calls.count()).toBe(1);

s.requestRenderMode = true;
s.maximumRenderTimeChange = undefined;

s.render();

expect(spyListener.calls.count()).toBe(1);

s.destroyForSpecs();
});

Expand Down Expand Up @@ -1245,7 +1299,6 @@ defineSuite([
scene.destroyForSpecs();
});


it('Sets material', function() {
var scene = createScene();
var globe = scene.globe = new Globe(Ellipsoid.UNIT_SPHERE);
Expand Down

0 comments on commit d698876

Please sign in to comment.