javascript - 将 WebAsembly 内存传递给 WebGL2
问题描述
在 WebGL2 中,大多数现有函数都有其他版本,它们接受ArrayBuffer
允许在这些缓冲区内传递偏移量和长度的 s。据说,这应该更容易从 WebAssembly 内存中传递数据而无需创建临时视图,但有一个问题:这些函数只接受ArrayBufferView
.
- 这种限制的原因是什么?为什么将字节复制到 GPU 的函数应该关心它们的语义,即 Uint8/Int32/Float32 等?
- 如何绕过它,而不是
DataView
每次都创建一个(这将完全违背首先使用这些功能的目的)?一次创建 DataView 是行不通的,因为 WebAssembly 内存可以重新分配其缓冲区,并且无法设置内存调整大小的回调。
解决方案
我不知道为什么texImage2D
etc 会使用 ArrayBufferView 而不仅仅是 ArrayBuffer。我同意这似乎毫无意义。
在最坏的情况下,您应该只能在缓冲区更改时创建一个新视图。
例子:
;; hello.wat
(module
;; Import our trace function so that we can call it in main
(import "env" "trace" (func $trace (param i32)))
;; Define our initial memory with a single page (64KiB).
(memory $0 1)
;; Store a null terminated string at byte offset 0.
(data (i32.const 0) "Hello world!\00")
;; Export the memory so it can be read in the host environment.
(export "memory" (memory $0))
(func $alloc (param $0 i32) (result i32)
get_local $0
grow_memory
)
(export "alloc" (func $alloc))
;; Define the main function with no parameters.
(func $main
;; Call the trace function with the constant value 0.
(call $trace (i32.const 0))
)
;; Export the main function so that the host can call it.
(export "main" (func $main))
)
和调用它的js
// hello.js
async function doit() {
const response = await fetch('../out/main.wasm');
const buffer = await response.arrayBuffer();
const module = await WebAssembly.compile(buffer);
const instance = await WebAssembly.instantiate(module, {
env: {
trace
}
});
let exports = instance.exports;
let view = new Uint8Array(exports.memory.buffer);
function getView() {
if (view.buffer !== exports.memory.buffer) {
console.log('new view');
view = new Uint8Array(exports.memory.buffer);
}
return view;
}
function trace(byteOffset) {
let s = '';
const view = getView();
for (let i = byteOffset; view[i]; i++) {
s += String.fromCharCode(view[i]);
}
console.log(s);
}
exports.main();
exports.main();
exports.main();
exports.alloc(10);
exports.main();
exports.main();
exports.main();
}
doit().then(() => {
console.log("done");
});
创建新视图的唯一时间是 WebAssembly 重新分配缓冲区
由于显然您需要不同类型的视图,具体取决于type
传递给 WebGL2 的参数,您需要一组视图而不是一个视图,并且根据类型参数,您需要获得正确类型的视图。
从评论中复制:
texImage2D 和 bufferData 等通常不是在紧密循环中调用的函数,因此优化它们超过上述点似乎没什么大不了的?检查简单,不会影响性能,避免GC
当被调用时,我没有找到任何方法来获取回调
grow_memory
。另一方面,如果您正在编写自己的 WebAssembly,您可以轻松地让所有grow_memory
调用都通过您自己的函数,并将该函数调用到 JavaScript 中以更新您的视图。我猜这就是emscripten所做的。它有一个运行时库。我假设当他们想要增加内存时调用运行时库,因此他们可以更新他们的视图。
推荐阅读
- c++ - 为什么 *ptr 在 printf 中?
- python-3.5 - 如何使用虚拟环境修复 python3 中 Opencv3 的警告“QObject::moveToThread:”?
- r - 根据另一列更改列值,但仅适用于第一列和第二列 (R) 中的某些条件
- java - 如何使用等效线性运算符“=”
- dart - Dart - 如何订购日期时间对象?
- powerbi - 使用 DAX 或查询编辑器替换或替换 - Power BI
- javascript - 使用 axios 发出 xml 请求时浏览器中出现 415(不支持的媒体类型)
- php - 字符串php的深色十六进制颜色
- artificial-intelligence - 我在游戏机里造吃豆人,怎么造幽灵来追吃豆人像AI贪婪
- php - PHP 5.4 自动加载器无法按预期使用命名空间