X-Git-Url: http://git.lukelau.me/?p=wasm.git;a=blobdiff_plain;f=main.js;h=f12efc10b96760a876215bbd564024b7cf5a13fd;hp=5ee3c09e5927561e041a73315b5e5367d6b1eba8;hb=HEAD;hpb=3ef5cb466b695cba27e45bbb273af1a9aa71bad9 diff --git a/main.js b/main.js index 5ee3c09..f12efc1 100644 --- a/main.js +++ b/main.js @@ -1,9 +1,127 @@ -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) + } } } @@ -12,12 +130,28 @@ sock.onmessage = function (e) { 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); + })