我有一个WebAssembly实例,它创建一个WebGL2上下文。理想情况下,退出显示上下文的页面部分时,我想破坏上下文并让模块和纹理等被垃圾回收。问题是,我无法找到保留对WebAssembly对象的引用的内容。
如何参考该对象标识所有位置(属性,闭包)? (Chrome devtools或其他易于使用的工具)
我不确定这是否是您的问题的答案,但是...在您写的详细信息中
我想破坏上下文并让模块和纹理等被垃圾回收。
让纹理等被垃圾收集是清理WebGL资源的错误方法。参见Are WebGL objects garbage collected?
如果知道何时完成WebAssembly,则可以通过扩展上下文来跟踪JavaScript中的资源。范例
const allWebGL2ContextsResources = new Map();
HTMLCanvasElement.prototype.getContext = function(origFn) {
return function(type, attribs) {
const ctx = origFn.call(this, type, attribs);
if (type === 'webgl2') {
if (!allWebGL2ContextsResources.has(ctx)) {
allWebGL2ContextsResources.set(ctx, new Set());
}
}
return ctx;
};
}(HTMLCanvasElement.prototype.getContext);
const types = ['Buffer', 'Texture', 'Renderbuffer', 'Framebuffer', 'Shader', 'Program', 'Sampler', 'TransformFeedback'];
for (const type of types) {
const createName = `create${type}`;
const deleteName = `delete${type}`;
WebGL2RenderingContext.prototype[createType] = function(origFn) {
return function(...args) {
const obj = orignFn.call(this, ...args);
allWebGL2ContextsResources.get(this).add(obj);
return obj;
};
}(WebGL2RenderingContext.prototype[createType]);
WebGL2RenderingContext.prototype[deleteType] = function(origFn) {
return function(obj) {
const obj = origFn.call(this, obj);
allWebGL2ContextsResources(this).delete(obj);
};
}(WebGL2RenderingContext.prototype[deleteType]);
}
鉴于,当您启动WebAssembly代码时,新的WebGL2上下文将被添加到allWebGL2Contexts
,因此您可以先与副本进行比较,然后找到添加的上下文。或更改代码以发出事件或调用回调或发现上下文所需的任何操作。
完成WebAssembly代码后,您可以遍历资源并将其删除。范例
for (const obj of allWebGL2ContextsResources.get(someContext).entries()) {
for (const type of types) {
const Type = `WebGL${type}`;
if (obj instanceof window[Type]) {
someContext[`delete${type}`](obj);
continue;
}
}
}
allWebGL2ContextsResources.delete(someContext);
否则您可能会失去上下文。参见How do I clean up and unload a WebGL canvas context from GPU after use?
假设您正在使用emscripten,那么另一个选择是emscripten已经跟踪资源,因此您可以modify the emscripten WebGL2 library公开上下文和跟踪,或添加一些清除功能以释放所有被跟踪的内容或丢失上下文。