From f1bf03a6b5f0a70ca16dd216b1ff0b62538cf93e Mon Sep 17 00:00:00 2001 From: Marco Hutter Date: Tue, 26 Aug 2025 16:53:04 +0200 Subject: [PATCH 1/5] Drafts for polyline reqestRender handling --- packages/engine/Source/Scene/GroundPolylinePrimitive.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/engine/Source/Scene/GroundPolylinePrimitive.js b/packages/engine/Source/Scene/GroundPolylinePrimitive.js index 300c6cffbb7a..a427e8bcdba5 100644 --- a/packages/engine/Source/Scene/GroundPolylinePrimitive.js +++ b/packages/engine/Source/Scene/GroundPolylinePrimitive.js @@ -782,6 +782,7 @@ GroundPolylinePrimitive.prototype.update = function (frameState) { ); }; + // XXX primitiveOptions.asynchronous = false; this._primitive = new Primitive(primitiveOptions); } @@ -805,7 +806,9 @@ GroundPolylinePrimitive.prototype.update = function (frameState) { if (this.releaseGeometryInstances) { this.geometryInstances = undefined; } + return true; } + return false; }); }; From e508c36f584e9648c63cffa432e3f97d1677ef54 Mon Sep 17 00:00:00 2001 From: Marco Hutter Date: Tue, 23 Sep 2025 16:11:26 +0200 Subject: [PATCH 2/5] Baseline documentation of the staus quo --- .../engine/Source/Scene/PrimitiveState.js | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/packages/engine/Source/Scene/PrimitiveState.js b/packages/engine/Source/Scene/PrimitiveState.js index 08e862951b41..6420317b8f45 100644 --- a/packages/engine/Source/Scene/PrimitiveState.js +++ b/packages/engine/Source/Scene/PrimitiveState.js @@ -1,13 +1,136 @@ /** + * The states that describe the lifecycle of a Primitive, as + * represented by the primitive._state. + * + * The state transitions are triggered by calls to the update + * function, but the actual state changes may happen asynchronously if the + * asynchronous flag of the primitive was set to + * true. + * * @private */ const PrimitiveState = { + /** + * The initial state of a primitive. + * + * Note that this does NOT mean that the primitive is "ready", as indicated + * by the _ready property. It means the opposite: Nothing was + * done with the primitive at all. + * + * For primitives that are created with the asynchronous:true + * setting and that are in this state, the update call starts + * the creation of the geometry using web workers, and the primitive goes + * into the CREATING state. + * + * For synchronously created primitives, this state never matters. They will + * go into the COMBINED (or FAILED) state directly due to a call to the + * update function, if they are not yet FAILED, COMBINED, + * or COMPLETE. + */ READY: 0, + + /** + * The process of creating the primitive geometry is ongoing. + * + * A primitive can only ever be in this state when it was created + * with the asynchronous:true setting. + * + * It means that web workers are currently creating the geometry + * of the primitive. + * + * When the geometry creation succeeds, then the primitive will go + * into the CREATED state. Otherwise, it will go into the FAILED + * state. Both will happen asynchronously. + * + * The update function has to be called regularly + * until either of these states is reached. + */ CREATING: 1, + + /** + * The geometry for the primitive has been created. + * + * A primitive can only ever be in this state when it was created + * with the asynchronous:true setting. + * + * It means that web workers have (asynchronously) finished the + * creation of the geometry, but further (asynchronous) processing + * is necessary: If a primitive is determined to be in this state + * during a call to update, an asynchronous process + * is triggered to "combine" the geometry, meaning that the primitive + * will go into the COMBINING state. + */ CREATED: 2, + + /** + * The asynchronous creation of the geometry has been finished, but the + * asynchronous process of combining the geometry has not finished yet. + * + * A primitive can only ever be in this state when it was created + * with the asynchronous:true setting. + * + * It means that whatever is done with + * PrimitivePipeline.packCombineGeometryParameters has + * not finished yet. When combining the geometry succeeds, the + * primitive will go into the COMBINED state. Otherwise, it will + * go into the FAILED state. + */ COMBINING: 3, + + /** + * The geometry data is in a form that can be uploaded to the GPU. + * + * For synchronous primitives, this means that the geometry + * has been created (synchronously) due to the first call to the + * update function. + * + * For asynchronous primitives, this means that the asynchronous + * creation of the geometry and the asynchronous combination of the + * geometry have both finished. + * + * The update function has to be called regularly until + * this state is reached. When it is reached, the update + * call will cause the transition into the COMPLETE state. + */ COMBINED: 4, + + /** + * The geometry has been created and uploaded to the GPU. + * + * When this state is reached, it eventually causes the _ready + * flag of the primitive to become true. + * + * Note: Setting the ready flag does NOT happen in the + * update call: It only happens after rendering the next + * frame! + * + * Note: This state does not mean that nothing has to be done + * anymore (so the work is not "complete"). When the primitive is in + * this state, the update function still has to be + * called regularly. + */ COMPLETE: 5, + + /** + * The creation of the primitive failed. + * + * When this state is reached, it eventually causes the _ready + * flag of the primitive to become true. + * + * Note: Setting the ready flag does NOT happen in the + * update call: It only happens after rendering the next + * frame! + * + * This state can be reached when the (synchronous or asynchronous) + * creation of the geometry, or the (asynchronous) combination of + * the geometry caused any form of error. + * + * It may or may not imply the presence of the _error property. + * When the _error property is present on a FAILED primitive, + * this error will be thrown during the update call. When it + * is not present for a FAILED primitive, then the update call + * will do nothing. + */ FAILED: 6, }; export default Object.freeze(PrimitiveState); From fbcd4c804150949686bedf194684595469d621d0 Mon Sep 17 00:00:00 2001 From: Marco Hutter Date: Tue, 23 Sep 2025 16:21:52 +0200 Subject: [PATCH 3/5] Remove fix from GroundPolylinePrimitive --- packages/engine/Source/Scene/GroundPolylinePrimitive.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/engine/Source/Scene/GroundPolylinePrimitive.js b/packages/engine/Source/Scene/GroundPolylinePrimitive.js index a427e8bcdba5..300c6cffbb7a 100644 --- a/packages/engine/Source/Scene/GroundPolylinePrimitive.js +++ b/packages/engine/Source/Scene/GroundPolylinePrimitive.js @@ -782,7 +782,6 @@ GroundPolylinePrimitive.prototype.update = function (frameState) { ); }; - // XXX primitiveOptions.asynchronous = false; this._primitive = new Primitive(primitiveOptions); } @@ -806,9 +805,7 @@ GroundPolylinePrimitive.prototype.update = function (frameState) { if (this.releaseGeometryInstances) { this.geometryInstances = undefined; } - return true; } - return false; }); }; From 3eedab200fbacb32fc6b422adb902c414eea16fe Mon Sep 17 00:00:00 2001 From: Marco Hutter Date: Tue, 23 Sep 2025 16:25:12 +0200 Subject: [PATCH 4/5] Trigger rendering after primitive became ready --- packages/engine/Source/Scene/Primitive.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/engine/Source/Scene/Primitive.js b/packages/engine/Source/Scene/Primitive.js index d2fab03f88db..6486bff22a80 100644 --- a/packages/engine/Source/Scene/Primitive.js +++ b/packages/engine/Source/Scene/Primitive.js @@ -2489,10 +2489,16 @@ Primitive.prototype.destroy = function () { function setReady(primitive, frameState, state, error) { primitive._error = error; primitive._state = state; + frameState.afterRender.push(function () { primitive._ready = primitive._state === PrimitiveState.COMPLETE || primitive._state === PrimitiveState.FAILED; + + // Returning 'true' here will ensure that another rendering pass is + // triggered after the primitive actually became ready, to make sure + // that it is in fact rendered even in "request render mode" + return true; }); } export default Primitive; From 278df2c6b023be9d13a2b6e15b9288d244a7a883 Mon Sep 17 00:00:00 2001 From: ggetz Date: Wed, 1 Oct 2025 09:19:23 -0400 Subject: [PATCH 5/5] Update CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 0afa5f0dbc30..538c9b575a82 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ - Materials loaded from type now respect submaterials present in the referenced material type. [#10566](https://github.com/CesiumGS/cesium/issues/10566) - Reverts `createImageBitmap` options update to continue support for older browsers [#12846](https://github.com/CesiumGS/cesium/issues/12846) - Fix flickering artifact in Gaussian splat models caused by incorrect sorting results. [#12662](https://github.com/CesiumGS/cesium/issues/12662) +- Fix rendering for geometry entities when `requestRenderMode` is enabled. [#12841](https://github.com/CesiumGS/cesium/pull/12841) - Improved performance and reduced memory usage of `Event` class. [#12896](https://github.com/CesiumGS/cesium/pull/12896) - Fixes vertical misalignment of glyphs in labels with small fonts [#8474](https://github.com/CesiumGS/cesium/issues/8474) - Prevent runtime errors for certain forms of invalid PNTS files [#12872](https://github.com/CesiumGS/cesium/issues/12872)