In Geometry._applyToMesh, there are numOfMeshes === 1 checks, which uploads data to gpu if the geometry has exactly 1 mesh. _applyToMesh is used in 2 places, applyToMesh, where meshes are added one by one, it’s ok to use this check to upload for first mesh, another is _queueLoad, where _applyToMesh is called for each mesh bound to this geometry. If the gpu buffers are not correctly created and uploaded in _delayLoadingFunction, they would never be uploaded.
A quick git blame shows that this check origins about 11 years ago.
So, here is the question, why not just check for existance, or if possible, validity of the gpu buffer, instead of numOfMeshes === 1 checks?
Some pseudocode to make it more clear
private _applyToMesh(mesh: Mesh): void {
const numOfMeshes = this._meshes.length;
// vertexBuffers
for (const kind in this._vertexBuffers) {
const buf = this._vertexBuffers[kind];
if (!hasUploadedAndValidGpuBuffer(buf)) {
this._vertexBuffers[kind].create();
}
if (kind === VertexBuffer.PositionKind) {
if (!this._extend) {
this._updateExtend();
}
mesh.buildBoundingInfo(this._extend.minimum, this._extend.maximum);
mesh._createGlobalSubMesh(mesh.isUnIndexed);
//bounding info was just created again, world matrix should be applied again.
mesh._updateBoundingInfo();
}
}
// indexBuffer
if ((!this._indexBuffer || !isValid(this._indexBuffer)) && this._indices && this._indices.length > 0) {
this._indexBuffer = this._engine.createIndexBuffer(this._indices, this._updatable, "Geometry_" + this.id + "_IndexBuffer");
}
// morphTargets
mesh._syncGeometryWithMorphTargetManager();
// instances
mesh.synchronizeInstances();
}
And I have not found a method to check if a buffer if valid on gpu yet, so maybe it’s ok to just check for existance
I was trying to accelerate loading of a huge scene, and profiling shows _ImportGeometry and bufferData (uploads vertex to gpu) are taking considerable amount of cpu time, so I made a queue to throttle the load and try to delay gpu upload as much as possible.
The playgrounds only shows a minimal reproducation of this use case, including creating the geometry in advance, set indices (which won’t invoke a gpu upload), bind to meshes, and create vertex buffers later. But if the geometry is bound to 1 mesh, everything is ok, but with 2, gpu upload would never happen.
The actual code I used overwrites geometry._queueLoad to make a delayed and throttled creation of vertex buffers, but i do not think this changes the behavior of gpu upload.
I don’t think an extra flag needed in this case, after some futher looking with the code, the VertexBuffer.create(), which calls Buffer.create(), checks for existance of this._buffer, so it should be safe to just check for it.
A patch like this should just work.