Przeglądaj źródła

Merge pull request #198 from DamianImrich/go114

Wasm go1.13+ support
Daniel Salvadori 5 lat temu
rodzic
commit
8b2d7dab53
4 zmienionych plików z 158 dodań i 19 usunięć
  1. 18 17
      gls/gls-browser.go
  2. 16 0
      util/wasm/wasm112.go
  3. 121 0
      util/wasm/wasm113.go
  4. 3 2
      window/canvas.go

+ 18 - 17
gls/gls-browser.go

@@ -8,6 +8,7 @@ package gls
 
 import (
 	"fmt"
+	"github.com/g3n/engine/util/wasm"
 	"syscall/js"
 	"unsafe"
 )
@@ -279,10 +280,10 @@ func (gs *GLS) BlendFuncSeparate(srcRGB uint32, dstRGB uint32, srcAlpha uint32,
 // bound to target, deleting any pre-existing data store.
 func (gs *GLS) BufferData(target uint32, size int, data interface{}, usage uint32) {
 
-	dataTA := js.TypedArrayOf(data)
+	dataTA, free := wasm.SliceToTypedArray(data)
 	gs.gl.Call("bufferData", int(target), dataTA, int(usage))
 	gs.checkError("BufferData")
-	dataTA.Release()
+	free()
 }
 
 // ClearColor specifies the red, green, blue, and alpha values
@@ -589,7 +590,7 @@ func (gs *GLS) GetString(name uint32) string {
 func (gs *GLS) GetUniformLocation(program uint32, name string) int32 {
 
 	loc := gs.gl.Call("getUniformLocation", gs.programMap[program], name)
-	if loc == js.Null() {
+	if wasm.Equal(loc, js.Null()) {
 		return -1
 	}
 	gs.uniformMap[gs.uniformMapIndex] = loc
@@ -657,10 +658,10 @@ func (gs *GLS) ShaderSource(shader uint32, src string) {
 // TexImage2D specifies a two-dimensional texture image.
 func (gs *GLS) TexImage2D(target uint32, level int32, iformat int32, width int32, height int32, format uint32, itype uint32, data interface{}) {
 
-	dataTA := js.TypedArrayOf(data)
+	dataTA, free := wasm.SliceToTypedArray(data)
 	gs.gl.Call("texImage2D", int(target), level, iformat, width, height, 0, int(format), int(itype), dataTA)
 	gs.checkError("TexImage2D")
-	dataTA.Release()
+	free()
 }
 
 // CompressedTexImage2D specifies a two-dimensional compressed texture image.
@@ -738,9 +739,9 @@ func (gs *GLS) Uniform4f(location int32, v0, v1, v2, v3 float32) {
 func (gs *GLS) UniformMatrix3fv(location int32, count int32, transpose bool, pm *float32) {
 
 	data := (*[1 << 30]float32)(unsafe.Pointer(pm))[:9*count]
-	dataTA := js.TypedArrayOf(data)
+	dataTA, free := wasm.SliceToTypedArray(data)
 	gs.gl.Call("uniformMatrix3fv", gs.uniformMap[uint32(location)], transpose, dataTA)
-	dataTA.Release()
+	free()
 	gs.checkError("UniformMatrix3fv")
 	gs.stats.Unisets++
 }
@@ -749,9 +750,9 @@ func (gs *GLS) UniformMatrix3fv(location int32, count int32, transpose bool, pm
 func (gs *GLS) UniformMatrix4fv(location int32, count int32, transpose bool, pm *float32) {
 
 	data := (*[1 << 30]float32)(unsafe.Pointer(pm))[:16*count]
-	dataTA := js.TypedArrayOf(data)
+	dataTA, free := wasm.SliceToTypedArray(data)
 	gs.gl.Call("uniformMatrix4fv", gs.uniformMap[uint32(location)], transpose, dataTA)
-	dataTA.Release()
+	free()
 	gs.checkError("UniformMatrix4fv")
 	gs.stats.Unisets++
 }
@@ -760,9 +761,9 @@ func (gs *GLS) UniformMatrix4fv(location int32, count int32, transpose bool, pm
 func (gs *GLS) Uniform1fv(location int32, count int32, v *float32) {
 
 	data := (*[1 << 30]float32)(unsafe.Pointer(v))[:count]
-	dataTA := js.TypedArrayOf(data)
+	dataTA, free := wasm.SliceToTypedArray(data)
 	gs.gl.Call("uniform1fv", gs.uniformMap[uint32(location)], dataTA)
-	dataTA.Release()
+	free()
 	gs.checkError("Uniform1fv")
 	gs.stats.Unisets++
 }
@@ -771,9 +772,9 @@ func (gs *GLS) Uniform1fv(location int32, count int32, v *float32) {
 func (gs *GLS) Uniform2fv(location int32, count int32, v *float32) {
 
 	data := (*[1 << 30]float32)(unsafe.Pointer(v))[:2*count]
-	dataTA := js.TypedArrayOf(data)
+	dataTA, free := wasm.SliceToTypedArray(data)
 	gs.gl.Call("uniform2fv", gs.uniformMap[uint32(location)], dataTA)
-	dataTA.Release()
+	free()
 	gs.checkError("Uniform2fv")
 	gs.stats.Unisets++
 }
@@ -782,9 +783,9 @@ func (gs *GLS) Uniform2fv(location int32, count int32, v *float32) {
 func (gs *GLS) Uniform3fv(location int32, count int32, v *float32) {
 
 	data := (*[1 << 30]float32)(unsafe.Pointer(v))[:3*count]
-	dataTA := js.TypedArrayOf(data)
+	dataTA, free := wasm.SliceToTypedArray(data)
 	gs.gl.Call("uniform3fv", gs.uniformMap[uint32(location)], dataTA)
-	dataTA.Release()
+	free()
 	gs.checkError("Uniform3fv")
 	gs.stats.Unisets++
 }
@@ -793,9 +794,9 @@ func (gs *GLS) Uniform3fv(location int32, count int32, v *float32) {
 func (gs *GLS) Uniform4fv(location int32, count int32, v *float32) {
 
 	data := (*[1 << 30]float32)(unsafe.Pointer(v))[:4*count]
-	dataTA := js.TypedArrayOf(data)
+	dataTA, free := wasm.SliceToTypedArray(data)
 	gs.gl.Call("uniform4fv", gs.uniformMap[uint32(location)], dataTA)
-	dataTA.Release()
+	free()
 	gs.checkError("Uniform4fv")
 	gs.stats.Unisets++
 }

+ 16 - 0
util/wasm/wasm112.go

@@ -0,0 +1,16 @@
+// +build !go1.13
+
+package wasm
+
+import (
+	"syscall/js"
+)
+
+func SliceToTypedArray(s interface{}) (val js.Value, free func()) {
+	dataTA := js.TypedArrayOf(s)
+	return dataTA.Value, func(){dataTA.Release()}
+}
+
+func Equal(a, b js.Value) bool {
+	return a == b
+}

+ 121 - 0
util/wasm/wasm113.go

@@ -0,0 +1,121 @@
+// +build go1.13
+
+package wasm
+
+import (
+	"reflect"
+	"runtime"
+	"syscall/js"
+	"unsafe"
+)
+
+func sliceToByteSlice(s interface{}) []byte {
+	switch s := s.(type) {
+	case []int8:
+		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
+		return *(*[]byte)(unsafe.Pointer(h))
+	case []int16:
+		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
+		h.Len *= 2
+		h.Cap *= 2
+		return *(*[]byte)(unsafe.Pointer(h))
+	case []int32:
+		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
+		h.Len *= 4
+		h.Cap *= 4
+		return *(*[]byte)(unsafe.Pointer(h))
+	case []int64:
+		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
+		h.Len *= 8
+		h.Cap *= 8
+		return *(*[]byte)(unsafe.Pointer(h))
+	case []uint8:
+		return s
+	case []uint16:
+		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
+		h.Len *= 2
+		h.Cap *= 2
+		return *(*[]byte)(unsafe.Pointer(h))
+	case []uint32:
+		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
+		h.Len *= 4
+		h.Cap *= 4
+		return *(*[]byte)(unsafe.Pointer(h))
+	case []uint64:
+		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
+		h.Len *= 8
+		h.Cap *= 8
+		return *(*[]byte)(unsafe.Pointer(h))
+	case []float32:
+		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
+		h.Len *= 4
+		h.Cap *= 4
+		return *(*[]byte)(unsafe.Pointer(h))
+	case []float64:
+		h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
+		h.Len *= 8
+		h.Cap *= 8
+		return *(*[]byte)(unsafe.Pointer(h))
+	default:
+		panic("jsutil: unexpected value at sliceToBytesSlice()")
+	}
+}
+
+func SliceToTypedArray(s interface{}) (val js.Value, free func()) {
+	free = func(){}
+	switch s := s.(type) {
+	case []int8:
+		a := js.Global().Get("Uint8Array").New(len(s))
+		js.CopyBytesToJS(a, sliceToByteSlice(s))
+		runtime.KeepAlive(s)
+		buf := a.Get("buffer")
+		return js.Global().Get("Int8Array").New(buf, a.Get("byteOffset"), a.Get("byteLength")), free
+	case []int16:
+		a := js.Global().Get("Uint8Array").New(len(s) * 2)
+		js.CopyBytesToJS(a, sliceToByteSlice(s))
+		runtime.KeepAlive(s)
+		buf := a.Get("buffer")
+		return js.Global().Get("Int16Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/2), free
+	case []int32:
+		a := js.Global().Get("Uint8Array").New(len(s) * 4)
+		js.CopyBytesToJS(a, sliceToByteSlice(s))
+		runtime.KeepAlive(s)
+		buf := a.Get("buffer")
+		return js.Global().Get("Int32Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/4), free
+	case []uint8:
+		a := js.Global().Get("Uint8Array").New(len(s))
+		js.CopyBytesToJS(a, s)
+		runtime.KeepAlive(s)
+		return a, free
+	case []uint16:
+		a := js.Global().Get("Uint8Array").New(len(s) * 2)
+		js.CopyBytesToJS(a, sliceToByteSlice(s))
+		runtime.KeepAlive(s)
+		buf := a.Get("buffer")
+		return js.Global().Get("Uint16Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/2), free
+	case []uint32:
+		a := js.Global().Get("Uint8Array").New(len(s) * 4)
+		js.CopyBytesToJS(a, sliceToByteSlice(s))
+		runtime.KeepAlive(s)
+		buf := a.Get("buffer")
+		return js.Global().Get("Uint32Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/4), free
+	case []float32:
+		a := js.Global().Get("Uint8Array").New(len(s) * 4)
+		js.CopyBytesToJS(a, sliceToByteSlice(s))
+		runtime.KeepAlive(s)
+		buf := a.Get("buffer")
+		return js.Global().Get("Float32Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/4), free
+	case []float64:
+		a := js.Global().Get("Uint8Array").New(len(s) * 8)
+		js.CopyBytesToJS(a, sliceToByteSlice(s))
+		runtime.KeepAlive(s)
+		buf := a.Get("buffer")
+		return js.Global().Get("Float64Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/8), free
+	default:
+		panic("jsutil: unexpected value at SliceToTypedArray()")
+	}
+}
+
+func Equal(a, b js.Value) bool {
+	return a.Equal(b)
+}

+ 3 - 2
window/canvas.go

@@ -10,6 +10,7 @@ import (
 	"fmt"
 	"github.com/g3n/engine/core"
 	"github.com/g3n/engine/gls"
+	"github.com/g3n/engine/util/wasm"
 	_ "image/png"
 	"syscall/js"
 )
@@ -357,14 +358,14 @@ func Init(canvasId string) error {
 		w.canvas = doc.Call("createElement", "WebGlCanvas")
 	} else {
 		w.canvas = doc.Call("getElementById", canvasId)
-		if w.canvas == js.Null() {
+		if wasm.Equal(w.canvas, js.Null()) {
 			panic(fmt.Sprintf("Cannot find canvas with provided id: %s", canvasId))
 		}
 	}
 
 	// Get reference to WebGL context
 	webglCtx := w.canvas.Call("getContext", "webgl2")
-	if webglCtx == js.Undefined() {
+	if wasm.Equal(webglCtx, js.Undefined()) {
 		return fmt.Errorf("Browser doesn't support WebGL2")
 	}