我有一个创建WebGL2上下文的WebAssembly实例。理想情况下,当退出页面中显示上下文的部分时,我希望销毁上下文,并让模块和纹理等被垃圾收集。问题是,我无法找到是什么保留了对WebAssembly对象的引用。
如何通过引用该对象来识别所有位置(属性、闭包(?(Chrome开发工具或其他现成工具(
我不确定这是否是你问题的答案,但。。。在你的详细信息中,你写了
我想破坏上下文,让模块和纹理等被垃圾收集。
让纹理等被垃圾收集是清理WebGL资源的错误方法。请参阅WebGL对象是垃圾收集的吗?
如果您知道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);
或者你可能会失去上下文。请参阅如何在使用后从GPU中清理和卸载WebGL画布上下文?
假设您正在使用emscripten,那么另一个选项是emscripten已经跟踪资源,因此您可以修改emscripten WebGL2库以公开上下文和跟踪,或者添加一些清理功能以释放所有被跟踪的内容或丢失上下文。