-const memory = new WebAssembly.Memory( { initial: 2, maximum: 8 })
+const canvas = document.querySelector('canvas')
+
+// hidpi
+const width = canvas.width, height = canvas.height
+canvas.style.width = width + 'px'
+canvas.style.height = height + 'px'
+canvas.width = width * window.devicePixelRatio
+canvas.height = height * window.devicePixelRatio
+
+const gl = canvas.getContext('webgl')
+
+const shaderMap = new Map()
+var currentShaderId = 0
+function createShaderId() {
+ const id = currentShaderId
+ currentShaderId += 1
+ return id
+}
+
+const programMap = new Map()
+var currentProgramId = 0
+function createProgramId() {
+ const id = currentProgramId
+ currentProgramId += 1
+ return id
+}
+
+const bufferMap = new Map()
+var currentBufferId = 0
+function createBufferId() {
+ const id = currentBufferId
+ currentBufferId += 1
+ return id
+}
+
+const uniformLocMap = new Map()
+var currentUniformLocId = 0
+function createUniformLocId() {
+ const id = currentUniformLocId
+ currentUniformLocId += 1
+ return id
+}
+
+var memory
+var decoder = new TextDecoder('utf-8')
+
+function getUint32(addr) {
+ const view = new DataView(memory.buffer)
+ return view.getUint32(addr, true)
+}
+
+function setUint32(addr, val) {
+ const view = new DataView(memory.buffer)
+ view.setUint32(addr, val, true)
+}
+
+function getString(addr) {
+ const view = new DataView(memory.buffer)
+ var len = 0
+ while (view.getUint8(addr + len) != 0) len++
+ return decoder.decode(memory.buffer.slice(addr, addr + len))
+}
+
const imports = {
env: {
- __syscall1: (n, a) => console.log(n),
- __syscall3: (n, a, b, c) => console.log(n),
- __syscall5: (n, a, b, c, d, e) => console.log(n)
+ glCreateShader: shaderType => {
+ const id = createShaderId()
+ const shader = gl.createShader(shaderType)
+ shaderMap.set(id, shader)
+ return id
+ },
+ glShaderSource: (id, numSrcs, srcs, lens) => {
+ const shader = shaderMap.get(id)
+ var totalSource = ''
+ for (let i = 0; i < numSrcs; i++) {
+ const addr = srcs + i * 4
+ const src = getUint32(addr)
+ const len = getUint32(lens + i * 4)
+ totalSource += decoder.decode(memory.buffer.slice(src, src + len))
+ }
+ gl.shaderSource(shader, totalSource)
+ },
+ glCompileShader: id => gl.compileShader(shaderMap.get(id)),
+ glCreateProgram: () => {
+ const id = createProgramId()
+ const prog = gl.createProgram()
+ programMap.set(id, prog)
+ return id
+ },
+ glAttachShader: (progId, shaderId) => {
+ gl.attachShader(programMap.get(progId), shaderMap.get(shaderId))
+ },
+ glLinkProgram: (progId) => gl.linkProgram(programMap.get(progId)),
+ glUseProgram: (progId) => gl.useProgram(programMap.get(progId)),
+ glGetAttribLocation: (progId, name) =>
+ gl.getAttribLocation(programMap.get(progId), getString(name)),
+ glEnableVertexAttribArray: (loc) => gl.enableVertexAttribArray(loc),
+ glVertexAttribPointer: (loc, size, type, normalized, stride, offset) => {
+ gl.vertexAttribPointer(loc, size, type, normalized, stride, offset)
+ },
+ glGenBuffers: (num, addr) => {
+ for (let i = 0; i < num; i++) {
+ const id = createBufferId()
+ const buffer = gl.createBuffer()
+ bufferMap.set(id, buffer)
+ setUint32(addr + i * 4, id)
+ }
+ },
+ glBindBuffer: (target, bufferId) => gl.bindBuffer(target, bufferMap.get(bufferId)),
+ glBufferData: (target, size, addr, usage) => {
+ const data = new Float32Array(memory.buffer.slice(addr, addr + size * 4))
+ gl.bufferData(target, data, usage)
+ },
+ glGetUniformLocation: (progId, name) => {
+ const id = createUniformLocId()
+ const loc = gl.getUniformLocation(programMap.get(progId), getString(name))
+ uniformLocMap.set(id, loc)
+ return id
+ },
+ glUniformMatrix4fv: (loc, count, transpose, addr) => {
+ if (count != 1) throw Error('count must be 1')
+ const vals = new Float32Array(memory.buffer.slice(addr, addr + 4 * 16))
+ gl.uniformMatrix4fv(uniformLocMap.get(loc), transpose, vals)
+ }
}
}
console.log(e.data)
}
+var instance
+
+function draw(tick) {
+ instance.exports.update(tick)
+ gl.drawArrays(gl.TRIANGLES, 0, 3)
+ requestAnimationFrame(draw);
+}
+
function instantiate(bytes) {
return WebAssembly.compile(bytes).
- then(m => new WebAssembly.Instance(m, imports));
+ then(m => {
+ const inst = new WebAssembly.Instance(m, imports)
+ memory = inst.exports.memory
+ return inst
+ })
}
fetch('test.wasm')
.then(response => response.arrayBuffer())
.then(bytes => instantiate(bytes))
- .then(instance => console.log(instance.exports.foo()));
+ .then(i => {
+ instance = i
+ instance.exports.setup()
+ requestAnimationFrame(draw);
+ })