Add uniforms
[wasm.git] / main.js
diff --git a/main.js b/main.js
index 0acc5025a1aa1a139280de5320ede495b87a9922..f12efc10b96760a876215bbd564024b7cf5a13fd 100644 (file)
--- a/main.js
+++ b/main.js
@@ -17,14 +17,50 @@ function createShaderId() {
        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 readUint32(buffer, addr) {
-       const view = new DataView(buffer)
+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: {
                glCreateShader: shaderType => {
@@ -38,13 +74,54 @@ const imports = {
                        var totalSource = ''
                        for (let i = 0; i < numSrcs; i++) {
                                const addr = srcs + i * 4
-                               const src = readUint32(memory.buffer, addr)
-                               const len = readUint32(memory.buffer, lens + 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: a => gl.compileShader(shaderMap.get(a))
+               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)
+               }
        }
 }
 
@@ -53,16 +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 => {
                        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);
+       })