fix: buffers not updated when geometry is shared by multiple context.

This commit is contained in:
pissang 2022-07-18 15:04:46 +08:00
parent 4a6fdb8898
commit 8b21e6f5a2
3 changed files with 27 additions and 22 deletions

View File

@ -83,11 +83,6 @@ export class GeometryAttribute<TSize extends AttributeSize = AttributeSize> {
*/
semantic?: AttributeSemantic;
/**
* If attributes needs update buffer
*/
__dirty?: boolean = true;
/**
* Value of the attribute.
*/
@ -255,6 +250,7 @@ class GeometryBase {
private _attributeList: string[];
private _enabledAttributes?: string[];
private _attributesUploaded: Record<string, boolean> = {};
__indicesDirty: boolean = true;
@ -288,10 +284,7 @@ class GeometryBase {
* Usually called after you change the data in attributes.
*/
dirty() {
const enabledAttributes = this.getEnabledAttributes();
for (let i = 0; i < enabledAttributes.length; i++) {
this.dirtyAttribute(enabledAttributes[i]);
}
this._attributesUploaded = {};
this.dirtyIndices();
this._enabledAttributes = undefined;
}
@ -306,8 +299,7 @@ class GeometryBase {
* @param {string} [attrName]
*/
dirtyAttribute(attrName: string) {
const attr = this.attributes[attrName];
attr && (attr.__dirty = true);
this._attributesUploaded[attrName] = false;
}
/**
* Is any of attributes dirty.
@ -318,12 +310,23 @@ class GeometryBase {
}
const enabledAttributes = this.getEnabledAttributes();
for (let i = 0; i < enabledAttributes.length; i++) {
if (this.attributes[enabledAttributes[i]].__dirty) {
if (this.isAttributeDirty(enabledAttributes[i])) {
return true;
}
}
return false;
}
isAttributeDirty(attrName: string) {
return !this._attributesUploaded[attrName];
}
// Mark this attribute has been uploaded to GPU.
// Used internal
__markAttributeUploaded(attrName: string) {
this._attributesUploaded[attrName] = true;
}
/**
* Get indices of triangle at given index.
* @param {number} idx

View File

@ -79,26 +79,26 @@ class GLBuffers {
let k;
// FIXME If some attributes removed
for (k = 0; k < attributeList.length; k++) {
const name = attributeList[k];
const attribute = geometry.attributes[name];
const attrName = attributeList[k];
const attribute = geometry.attributes[attrName];
const existsBufferInfo = attributeBufferMap[name];
const existsBufferInfo = attributeBufferMap[attrName];
let buffer: WebGLBuffer;
if (existsBufferInfo) {
buffer = existsBufferInfo.buffer;
} else {
buffer = gl.createBuffer()!;
}
if (attribute.__dirty) {
if (geometry.isAttributeDirty(attrName)) {
// Only update when they are dirty.
// TODO: Use BufferSubData?
gl.bindBuffer(constants.ARRAY_BUFFER, buffer);
gl.bufferData(constants.ARRAY_BUFFER, attribute.value as Float32Array, DRAW);
attribute.__dirty = false;
geometry.__markAttributeUploaded(attrName);
}
attributeBuffers[k] = new GLAttributeBuffer(
name,
attrName,
attribute.type,
buffer,
attribute.size,
@ -208,19 +208,15 @@ class GLBuffers {
dispose(gl: WebGLRenderingContext) {
const attributeBuffers = this._attrbBuffs;
const indicesBuffer = this._idxBuff;
attributeBuffers && attributeBuffers.forEach((buffer) => gl.deleteBuffer(buffer.buffer));
if (indicesBuffer) {
gl.deleteBuffer(indicesBuffer.buffer);
}
const vao = this._vao;
const vaoExt = this._vaoExt;
if (vaoExt && vao && vao.vao) {
vaoExt.deleteVertexArrayOES(vao.vao);
}
this._attrbBuffs = [];
this._idxBuff = undefined;
}

View File

@ -421,6 +421,9 @@ class GLRenderer {
const glBuffersMap = this._glBuffersMap;
let buffers = glBuffersMap.get(geometry);
if (!buffers) {
// Force mark geometry to be dirty
// In case this geometry is used by multiple gl context.
geometry.dirty();
buffers = new GLBuffers(geometry);
glBuffersMap.set(geometry, buffers);
}
@ -555,6 +558,9 @@ class GLRenderer {
const instancedBufferMap = this._glInstancedBufferMap;
let buffer = instancedBufferMap.get(renderable as InstancedMesh);
if (!buffer) {
// Force mark renderable to be dirty if its a new created buffer.
// In case the object is used by multiple gl context.
renderable.__dirty = true;
buffer = new GLInstancedBuffers(renderable as InstancedMesh);
instancedBufferMap.set(renderable as InstancedMesh, buffer);
}