3d573c1b03c717096b4c486ccfaba59356577a6d
[wasm.git] / main.js
1 const canvas = document.querySelector('canvas')
2
3 // hidpi
4 const width = canvas.width, height = canvas.height
5 canvas.style.width = width + 'px'
6 canvas.style.height = height + 'px'
7 canvas.width = width * window.devicePixelRatio
8 canvas.height = height * window.devicePixelRatio
9
10 const gl = canvas.getContext('webgl')
11
12 const shaderMap = new Map()
13 var currentShaderId = 0
14 function createShaderId() {
15         const id = currentShaderId
16         currentShaderId += 1
17         return id
18 }
19
20 const programMap = new Map()
21 var currentProgramId = 0
22 function createProgramId() {
23         const id = currentProgramId
24         currentProgramId += 1
25         return id
26 }
27
28 const bufferMap = new Map()
29 var currentBufferId = 0
30 function createBufferId() {
31         const id = currentBufferId
32         currentBufferId += 1
33         return id
34 }
35
36
37 var memory
38 var decoder = new TextDecoder('utf-8')
39
40 function getUint32(addr) {
41         const view = new DataView(memory.buffer)
42         return view.getUint32(addr, true)
43 }
44
45 function setUint32(addr, val) {
46         const view = new DataView(memory.buffer)
47         view.setUint32(addr, val, true)
48 }
49
50 function getString(addr) {
51         const view = new DataView(memory.buffer)
52         var len = 0
53         while (view.getUint8(addr + len) != 0) len++
54         return decoder.decode(memory.buffer.slice(addr, addr + len))
55 }
56
57 const imports = {
58         env: {
59                 glCreateShader: shaderType => {
60                         const id = createShaderId()
61                         const shader = gl.createShader(shaderType)
62                         shaderMap.set(id, shader)
63                         return id
64                 },
65                 glShaderSource: (id, numSrcs, srcs, lens) => {
66                         const shader = shaderMap.get(id)
67                         var totalSource = ''
68                         for (let i = 0; i < numSrcs; i++) {
69                                 const addr = srcs + i * 4
70                                 const src = getUint32(addr)
71                                 const len = getUint32(lens + i * 4)
72                                 totalSource += decoder.decode(memory.buffer.slice(src, src + len))
73                         }
74                         gl.shaderSource(shader, totalSource)
75                 },
76                 glCompileShader: id => gl.compileShader(shaderMap.get(id)),
77                 glCreateProgram: () => {
78                         const id = createProgramId()
79                         const prog = gl.createProgram()
80                         programMap.set(id, prog)
81                         return id
82                 },
83                 glAttachShader: (progId, shaderId) => {
84                         gl.attachShader(programMap.get(progId), shaderMap.get(shaderId))
85                 },
86                 glLinkProgram: (progId) => gl.linkProgram(programMap.get(progId)),
87                 glUseProgram: (progId) => gl.useProgram(programMap.get(progId)),
88                 glGetAttribLocation: (progId, name) => {
89                         const prog = programMap.get(progId)
90                         return gl.getAttribLocation(prog, getString(name))
91                 },
92                 glEnableVertexAttribArray: (loc) => gl.enableVertexAttribArray(loc),
93                 glVertexAttribPointer: (loc, size, type, normalized, stride, offset) => {
94                         gl.vertexAttribPointer(loc, size, type, normalized, stride, offset)
95                 },
96                 glGenBuffers: (num, addr) => {
97                         for (let i = 0; i < num; i++) {
98                                 const id = createBufferId()
99                                 const buffer = gl.createBuffer()
100                                 bufferMap.set(id, buffer)
101                                 setUint32(addr + i * 4, id)
102                         }
103                 },
104                 glBindBuffer: (target, bufferId) => gl.bindBuffer(target, bufferMap.get(bufferId)),
105                 glBufferData: (target, size, addr, usage) => {
106                         const data = new Float32Array(memory.buffer.slice(addr, addr + size * 4))
107                         gl.bufferData(target, data, usage)
108                 }
109         }
110 }
111
112 const sock = new WebSocket('ws://localhost:8889')
113 sock.onmessage = function (e) {
114         console.log(e.data)
115 }
116
117 function instantiate(bytes) {
118   return WebAssembly.compile(bytes).
119                 then(m => {
120                         const inst = new WebAssembly.Instance(m, imports)
121                         memory = inst.exports.memory
122                         return inst
123                 })
124 }
125
126 fetch('test.wasm')
127         .then(response => response.arrayBuffer())
128         .then(bytes => instantiate(bytes))
129         .then(instance => {
130                 instance.exports.setup()
131                 gl.drawArrays(gl.TRIANGLES, 0, 3)
132         })