internal/shader: introduce integer vectors (ivec2, ivec3, ivec4)

Closes #1911
This commit is contained in:
Hajime Hoshi 2022-11-20 15:36:07 +09:00
parent f09c4a624e
commit 0b9cbaa1ed
22 changed files with 795 additions and 53 deletions

View File

@ -1739,19 +1739,19 @@ func (s *Shader) flattenUniforms(uniforms [][]uint32) []uint32 {
} else { } else {
fs = append(fs, 0) fs = append(fs, 0)
} }
case shaderir.Vec2: case shaderir.Vec2, shaderir.IVec2:
if u != nil { if u != nil {
fs = append(fs, u...) fs = append(fs, u...)
} else { } else {
fs = append(fs, 0, 0) fs = append(fs, 0, 0)
} }
case shaderir.Vec3: case shaderir.Vec3, shaderir.IVec3:
if u != nil { if u != nil {
fs = append(fs, u...) fs = append(fs, u...)
} else { } else {
fs = append(fs, 0, 0, 0) fs = append(fs, 0, 0, 0)
} }
case shaderir.Vec4: case shaderir.Vec4, shaderir.IVec4:
if u != nil { if u != nil {
fs = append(fs, u...) fs = append(fs, u...)
} else { } else {
@ -1824,7 +1824,7 @@ func (s *Shader) flattenUniforms(uniforms [][]uint32) []uint32 {
} else { } else {
fs = append(fs, make([]uint32, (t.Length-1)*4+1)...) fs = append(fs, make([]uint32, (t.Length-1)*4+1)...)
} }
case shaderir.Vec2: case shaderir.Vec2, shaderir.IVec2:
if u != nil { if u != nil {
for j := 0; j < t.Length; j++ { for j := 0; j < t.Length; j++ {
fs = append(fs, u[2*j:2*(j+1)]...) fs = append(fs, u[2*j:2*(j+1)]...)
@ -1835,7 +1835,7 @@ func (s *Shader) flattenUniforms(uniforms [][]uint32) []uint32 {
} else { } else {
fs = append(fs, make([]uint32, (t.Length-1)*4+2)...) fs = append(fs, make([]uint32, (t.Length-1)*4+2)...)
} }
case shaderir.Vec3: case shaderir.Vec3, shaderir.IVec3:
if u != nil { if u != nil {
for j := 0; j < t.Length; j++ { for j := 0; j < t.Length; j++ {
fs = append(fs, u[3*j:3*(j+1)]...) fs = append(fs, u[3*j:3*(j+1)]...)
@ -1846,7 +1846,7 @@ func (s *Shader) flattenUniforms(uniforms [][]uint32) []uint32 {
} else { } else {
fs = append(fs, make([]uint32, (t.Length-1)*4+3)...) fs = append(fs, make([]uint32, (t.Length-1)*4+3)...)
} }
case shaderir.Vec4: case shaderir.Vec4, shaderir.IVec4:
if u != nil { if u != nil {
fs = append(fs, u...) fs = append(fs, u...)
} else { } else {

View File

@ -576,7 +576,7 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
t := g.shaders[shaderID].ir.Uniforms[i] t := g.shaders[shaderID].ir.Uniforms[i]
switch t.Main { switch t.Main {
case shaderir.Vec3: case shaderir.Vec3, shaderir.IVec3:
// float3 requires 16-byte alignment (#2463). // float3 requires 16-byte alignment (#2463).
v1 := make([]uint32, 4) v1 := make([]uint32, 4)
copy(v1[0:3], v[0:3]) copy(v1[0:3], v[0:3])
@ -590,7 +590,7 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
uniformVars[i] = v1 uniformVars[i] = v1
case shaderir.Array: case shaderir.Array:
switch t.Sub[0].Main { switch t.Sub[0].Main {
case shaderir.Vec3: case shaderir.Vec3, shaderir.IVec3:
v1 := make([]uint32, t.Length*4) v1 := make([]uint32, t.Length*4)
for j := 0; j < t.Length; j++ { for j := 0; j < t.Length; j++ {
offset0 := j * 3 offset0 := j * 3

View File

@ -470,6 +470,12 @@ func (c *context) uniforms(p program, location string, v []uint32, typ shaderir.
c.ctx.Uniform3fv(int32(l), uint32sToFloat32s(v)) c.ctx.Uniform3fv(int32(l), uint32sToFloat32s(v))
case shaderir.Vec4: case shaderir.Vec4:
c.ctx.Uniform4fv(int32(l), uint32sToFloat32s(v)) c.ctx.Uniform4fv(int32(l), uint32sToFloat32s(v))
case shaderir.IVec2:
c.ctx.Uniform2iv(int32(l), uint32sToInt32s(v))
case shaderir.IVec3:
c.ctx.Uniform3iv(int32(l), uint32sToInt32s(v))
case shaderir.IVec4:
c.ctx.Uniform4iv(int32(l), uint32sToInt32s(v))
case shaderir.Mat2: case shaderir.Mat2:
c.ctx.UniformMatrix2fv(int32(l), uint32sToFloat32s(v)) c.ctx.UniformMatrix2fv(int32(l), uint32sToFloat32s(v))
case shaderir.Mat3: case shaderir.Mat3:

View File

@ -99,8 +99,11 @@ package gl
// typedef void (APIENTRYP GPUNIFORM1I)(GLint location, GLint v0); // typedef void (APIENTRYP GPUNIFORM1I)(GLint location, GLint v0);
// typedef void (APIENTRYP GPUNIFORM1IV)(GLint location, GLsizei count, const GLint * value); // typedef void (APIENTRYP GPUNIFORM1IV)(GLint location, GLsizei count, const GLint * value);
// typedef void (APIENTRYP GPUNIFORM2FV)(GLint location, GLsizei count, const GLfloat * value); // typedef void (APIENTRYP GPUNIFORM2FV)(GLint location, GLsizei count, const GLfloat * value);
// typedef void (APIENTRYP GPUNIFORM2IV)(GLint location, GLsizei count, const GLint * value);
// typedef void (APIENTRYP GPUNIFORM3FV)(GLint location, GLsizei count, const GLfloat * value); // typedef void (APIENTRYP GPUNIFORM3FV)(GLint location, GLsizei count, const GLfloat * value);
// typedef void (APIENTRYP GPUNIFORM3IV)(GLint location, GLsizei count, const GLint * value);
// typedef void (APIENTRYP GPUNIFORM4FV)(GLint location, GLsizei count, const GLfloat * value); // typedef void (APIENTRYP GPUNIFORM4FV)(GLint location, GLsizei count, const GLfloat * value);
// typedef void (APIENTRYP GPUNIFORM4IV)(GLint location, GLsizei count, const GLint * value);
// typedef void (APIENTRYP GPUNIFORMMATRIX2FV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); // typedef void (APIENTRYP GPUNIFORMMATRIX2FV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
// typedef void (APIENTRYP GPUNIFORMMATRIX3FV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); // typedef void (APIENTRYP GPUNIFORMMATRIX3FV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
// typedef void (APIENTRYP GPUNIFORMMATRIX4FV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); // typedef void (APIENTRYP GPUNIFORMMATRIX4FV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
@ -291,12 +294,21 @@ package gl
// static void glowUniform2fv(GPUNIFORM2FV fnptr, GLint location, GLsizei count, const GLfloat * value) { // static void glowUniform2fv(GPUNIFORM2FV fnptr, GLint location, GLsizei count, const GLfloat * value) {
// (*fnptr)(location, count, value); // (*fnptr)(location, count, value);
// } // }
// static void glowUniform2iv(GPUNIFORM2IV fnptr, GLint location, GLsizei count, const GLint * value) {
// (*fnptr)(location, count, value);
// }
// static void glowUniform3fv(GPUNIFORM3FV fnptr, GLint location, GLsizei count, const GLfloat * value) { // static void glowUniform3fv(GPUNIFORM3FV fnptr, GLint location, GLsizei count, const GLfloat * value) {
// (*fnptr)(location, count, value); // (*fnptr)(location, count, value);
// } // }
// static void glowUniform3iv(GPUNIFORM3IV fnptr, GLint location, GLsizei count, const GLint * value) {
// (*fnptr)(location, count, value);
// }
// static void glowUniform4fv(GPUNIFORM4FV fnptr, GLint location, GLsizei count, const GLfloat * value) { // static void glowUniform4fv(GPUNIFORM4FV fnptr, GLint location, GLsizei count, const GLfloat * value) {
// (*fnptr)(location, count, value); // (*fnptr)(location, count, value);
// } // }
// static void glowUniform4iv(GPUNIFORM4IV fnptr, GLint location, GLsizei count, const GLint * value) {
// (*fnptr)(location, count, value);
// }
// static void glowUniformMatrix2fv(GPUNIFORMMATRIX2FV fnptr, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) { // static void glowUniformMatrix2fv(GPUNIFORMMATRIX2FV fnptr, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
// (*fnptr)(location, count, transpose, value); // (*fnptr)(location, count, transpose, value);
// } // }
@ -385,8 +397,11 @@ type defaultContext struct {
gpUniform1i C.GPUNIFORM1I gpUniform1i C.GPUNIFORM1I
gpUniform1iv C.GPUNIFORM1IV gpUniform1iv C.GPUNIFORM1IV
gpUniform2fv C.GPUNIFORM2FV gpUniform2fv C.GPUNIFORM2FV
gpUniform2iv C.GPUNIFORM2IV
gpUniform3fv C.GPUNIFORM3FV gpUniform3fv C.GPUNIFORM3FV
gpUniform3iv C.GPUNIFORM3IV
gpUniform4fv C.GPUNIFORM4FV gpUniform4fv C.GPUNIFORM4FV
gpUniform4iv C.GPUNIFORM4IV
gpUniformMatrix2fv C.GPUNIFORMMATRIX2FV gpUniformMatrix2fv C.GPUNIFORMMATRIX2FV
gpUniformMatrix3fv C.GPUNIFORMMATRIX3FV gpUniformMatrix3fv C.GPUNIFORMMATRIX3FV
gpUniformMatrix4fv C.GPUNIFORMMATRIX4FV gpUniformMatrix4fv C.GPUNIFORMMATRIX4FV
@ -705,16 +720,31 @@ func (c *defaultContext) Uniform2fv(location int32, value []float32) {
runtime.KeepAlive(value) runtime.KeepAlive(value)
} }
func (c *defaultContext) Uniform2iv(location int32, value []int32) {
C.glowUniform2iv(c.gpUniform2iv, (C.GLint)(location), (C.GLsizei)(len(value)/2), (*C.GLint)(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) Uniform3fv(location int32, value []float32) { func (c *defaultContext) Uniform3fv(location int32, value []float32) {
C.glowUniform3fv(c.gpUniform3fv, (C.GLint)(location), (C.GLsizei)(len(value)/3), (*C.GLfloat)(unsafe.Pointer(&value[0]))) C.glowUniform3fv(c.gpUniform3fv, (C.GLint)(location), (C.GLsizei)(len(value)/3), (*C.GLfloat)(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value) runtime.KeepAlive(value)
} }
func (c *defaultContext) Uniform3iv(location int32, value []int32) {
C.glowUniform3iv(c.gpUniform3iv, (C.GLint)(location), (C.GLsizei)(len(value)/3), (*C.GLint)(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) Uniform4fv(location int32, value []float32) { func (c *defaultContext) Uniform4fv(location int32, value []float32) {
C.glowUniform4fv(c.gpUniform4fv, (C.GLint)(location), (C.GLsizei)(len(value)/4), (*C.GLfloat)(unsafe.Pointer(&value[0]))) C.glowUniform4fv(c.gpUniform4fv, (C.GLint)(location), (C.GLsizei)(len(value)/4), (*C.GLfloat)(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value) runtime.KeepAlive(value)
} }
func (c *defaultContext) Uniform4iv(location int32, value []int32) {
C.glowUniform4iv(c.gpUniform4iv, (C.GLint)(location), (C.GLsizei)(len(value)/4), (*C.GLint)(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) UniformMatrix2fv(location int32, value []float32) { func (c *defaultContext) UniformMatrix2fv(location int32, value []float32) {
C.glowUniformMatrix2fv(c.gpUniformMatrix2fv, (C.GLint)(location), (C.GLsizei)(len(value)/4), 0, (*C.GLfloat)(unsafe.Pointer(&value[0]))) C.glowUniformMatrix2fv(c.gpUniformMatrix2fv, (C.GLint)(location), (C.GLsizei)(len(value)/4), 0, (*C.GLfloat)(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value) runtime.KeepAlive(value)
@ -951,14 +981,26 @@ func (c *defaultContext) LoadFunctions() error {
if c.gpUniform2fv == nil { if c.gpUniform2fv == nil {
return errors.New("gl: glUniform2fv is missing") return errors.New("gl: glUniform2fv is missing")
} }
c.gpUniform2iv = (C.GPUNIFORM2IV)(c.getProcAddress("glUniform2iv"))
if c.gpUniform2iv == nil {
return errors.New("gl: glUniform2iv is missing")
}
c.gpUniform3fv = (C.GPUNIFORM3FV)(c.getProcAddress("glUniform3fv")) c.gpUniform3fv = (C.GPUNIFORM3FV)(c.getProcAddress("glUniform3fv"))
if c.gpUniform3fv == nil { if c.gpUniform3fv == nil {
return errors.New("gl: glUniform3fv is missing") return errors.New("gl: glUniform3fv is missing")
} }
c.gpUniform3iv = (C.GPUNIFORM3IV)(c.getProcAddress("glUniform3iv"))
if c.gpUniform3iv == nil {
return errors.New("gl: glUniform3iv is missing")
}
c.gpUniform4fv = (C.GPUNIFORM4FV)(c.getProcAddress("glUniform4fv")) c.gpUniform4fv = (C.GPUNIFORM4FV)(c.getProcAddress("glUniform4fv"))
if c.gpUniform4fv == nil { if c.gpUniform4fv == nil {
return errors.New("gl: glUniform4fv is missing") return errors.New("gl: glUniform4fv is missing")
} }
c.gpUniform4iv = (C.GPUNIFORM4IV)(c.getProcAddress("glUniform4iv"))
if c.gpUniform4iv == nil {
return errors.New("gl: glUniform4iv is missing")
}
c.gpUniformMatrix2fv = (C.GPUNIFORMMATRIX2FV)(c.getProcAddress("glUniformMatrix2fv")) c.gpUniformMatrix2fv = (C.GPUNIFORMMATRIX2FV)(c.getProcAddress("glUniformMatrix2fv"))
if c.gpUniformMatrix2fv == nil { if c.gpUniformMatrix2fv == nil {
return errors.New("gl: glUniformMatrix2fv is missing") return errors.New("gl: glUniformMatrix2fv is missing")

View File

@ -84,8 +84,11 @@ type defaultContext struct {
fnUniform1i js.Value fnUniform1i js.Value
fnUniform1iv js.Value fnUniform1iv js.Value
fnUniform2fv js.Value fnUniform2fv js.Value
fnUniform2iv js.Value
fnUniform3fv js.Value fnUniform3fv js.Value
fnUniform3iv js.Value
fnUniform4fv js.Value fnUniform4fv js.Value
fnUniform4iv js.Value
fnUniformMatrix2fv js.Value fnUniformMatrix2fv js.Value
fnUniformMatrix3fv js.Value fnUniformMatrix3fv js.Value
fnUniformMatrix4fv js.Value fnUniformMatrix4fv js.Value
@ -210,8 +213,11 @@ func NewDefaultContext(v js.Value) (Context, error) {
fnUniform1i: v.Get("uniform1i").Call("bind", v), fnUniform1i: v.Get("uniform1i").Call("bind", v),
fnUniform1iv: v.Get("uniform1iv").Call("bind", v), fnUniform1iv: v.Get("uniform1iv").Call("bind", v),
fnUniform2fv: v.Get("uniform2fv").Call("bind", v), fnUniform2fv: v.Get("uniform2fv").Call("bind", v),
fnUniform2iv: v.Get("uniform2iv").Call("bind", v),
fnUniform3fv: v.Get("uniform3fv").Call("bind", v), fnUniform3fv: v.Get("uniform3fv").Call("bind", v),
fnUniform3iv: v.Get("uniform3iv").Call("bind", v),
fnUniform4fv: v.Get("uniform4fv").Call("bind", v), fnUniform4fv: v.Get("uniform4fv").Call("bind", v),
fnUniform4iv: v.Get("uniform4iv").Call("bind", v),
fnUniformMatrix2fv: v.Get("uniformMatrix2fv").Call("bind", v), fnUniformMatrix2fv: v.Get("uniformMatrix2fv").Call("bind", v),
fnUniformMatrix3fv: v.Get("uniformMatrix3fv").Call("bind", v), fnUniformMatrix3fv: v.Get("uniformMatrix3fv").Call("bind", v),
fnUniformMatrix4fv: v.Get("uniformMatrix4fv").Call("bind", v), fnUniformMatrix4fv: v.Get("uniformMatrix4fv").Call("bind", v),
@ -582,6 +588,16 @@ func (c *defaultContext) Uniform2fv(location int32, value []float32) {
} }
} }
func (c *defaultContext) Uniform2iv(location int32, value []int32) {
l := c.getUniformLocation(location)
arr := jsutil.TemporaryInt32Array(len(value), value)
if c.webGL2 {
c.fnUniform2iv.Invoke(l, arr, 0, len(value))
} else {
c.fnUniform2iv.Invoke(l, arr.Call("subarray", 0, len(value)))
}
}
func (c *defaultContext) Uniform3fv(location int32, value []float32) { func (c *defaultContext) Uniform3fv(location int32, value []float32) {
l := c.getUniformLocation(location) l := c.getUniformLocation(location)
arr := jsutil.TemporaryFloat32Array(len(value), value) arr := jsutil.TemporaryFloat32Array(len(value), value)
@ -592,6 +608,16 @@ func (c *defaultContext) Uniform3fv(location int32, value []float32) {
} }
} }
func (c *defaultContext) Uniform3iv(location int32, value []int32) {
l := c.getUniformLocation(location)
arr := jsutil.TemporaryInt32Array(len(value), value)
if c.webGL2 {
c.fnUniform3iv.Invoke(l, arr, 0, len(value))
} else {
c.fnUniform3iv.Invoke(l, arr.Call("subarray", 0, len(value)))
}
}
func (c *defaultContext) Uniform4fv(location int32, value []float32) { func (c *defaultContext) Uniform4fv(location int32, value []float32) {
l := c.getUniformLocation(location) l := c.getUniformLocation(location)
arr := jsutil.TemporaryFloat32Array(len(value), value) arr := jsutil.TemporaryFloat32Array(len(value), value)
@ -602,6 +628,16 @@ func (c *defaultContext) Uniform4fv(location int32, value []float32) {
} }
} }
func (c *defaultContext) Uniform4iv(location int32, value []int32) {
l := c.getUniformLocation(location)
arr := jsutil.TemporaryInt32Array(len(value), value)
if c.webGL2 {
c.fnUniform4iv.Invoke(l, arr, 0, len(value))
} else {
c.fnUniform4iv.Invoke(l, arr.Call("subarray", 0, len(value)))
}
}
func (c *defaultContext) UniformMatrix2fv(location int32, value []float32) { func (c *defaultContext) UniformMatrix2fv(location int32, value []float32) {
l := c.getUniformLocation(location) l := c.getUniformLocation(location)
arr := jsutil.TemporaryFloat32Array(len(value), value) arr := jsutil.TemporaryFloat32Array(len(value), value)

View File

@ -86,8 +86,11 @@ type defaultContext struct {
gpUniform1i uintptr gpUniform1i uintptr
gpUniform1iv uintptr gpUniform1iv uintptr
gpUniform2fv uintptr gpUniform2fv uintptr
gpUniform2iv uintptr
gpUniform3fv uintptr gpUniform3fv uintptr
gpUniform3iv uintptr
gpUniform4fv uintptr gpUniform4fv uintptr
gpUniform4iv uintptr
gpUniformMatrix2fv uintptr gpUniformMatrix2fv uintptr
gpUniformMatrix3fv uintptr gpUniformMatrix3fv uintptr
gpUniformMatrix4fv uintptr gpUniformMatrix4fv uintptr
@ -406,16 +409,31 @@ func (c *defaultContext) Uniform2fv(location int32, value []float32) {
runtime.KeepAlive(value) runtime.KeepAlive(value)
} }
func (c *defaultContext) Uniform2iv(location int32, value []int32) {
purego.SyscallN(c.gpUniform2iv, uintptr(location), uintptr(len(value)/2), uintptr(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) Uniform3fv(location int32, value []float32) { func (c *defaultContext) Uniform3fv(location int32, value []float32) {
purego.SyscallN(c.gpUniform3fv, uintptr(location), uintptr(len(value)/3), uintptr(unsafe.Pointer(&value[0]))) purego.SyscallN(c.gpUniform3fv, uintptr(location), uintptr(len(value)/3), uintptr(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value) runtime.KeepAlive(value)
} }
func (c *defaultContext) Uniform3iv(location int32, value []int32) {
purego.SyscallN(c.gpUniform3iv, uintptr(location), uintptr(len(value)/3), uintptr(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) Uniform4fv(location int32, value []float32) { func (c *defaultContext) Uniform4fv(location int32, value []float32) {
purego.SyscallN(c.gpUniform4fv, uintptr(location), uintptr(len(value)/4), uintptr(unsafe.Pointer(&value[0]))) purego.SyscallN(c.gpUniform4fv, uintptr(location), uintptr(len(value)/4), uintptr(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value) runtime.KeepAlive(value)
} }
func (c *defaultContext) Uniform4iv(location int32, value []int32) {
purego.SyscallN(c.gpUniform4iv, uintptr(location), uintptr(len(value)/4), uintptr(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value)
}
func (c *defaultContext) UniformMatrix2fv(location int32, value []float32) { func (c *defaultContext) UniformMatrix2fv(location int32, value []float32) {
purego.SyscallN(c.gpUniformMatrix2fv, uintptr(location), uintptr(len(value)/4), 0, uintptr(unsafe.Pointer(&value[0]))) purego.SyscallN(c.gpUniformMatrix2fv, uintptr(location), uintptr(len(value)/4), 0, uintptr(unsafe.Pointer(&value[0])))
runtime.KeepAlive(value) runtime.KeepAlive(value)
@ -652,14 +670,26 @@ func (c *defaultContext) LoadFunctions() error {
if c.gpUniform2fv == 0 { if c.gpUniform2fv == 0 {
return errors.New("gl: glUniform2fv is missing") return errors.New("gl: glUniform2fv is missing")
} }
c.gpUniform2iv = c.getProcAddress("glUniform2iv")
if c.gpUniform2iv == 0 {
return errors.New("gl: glUniform2iv is missing")
}
c.gpUniform3fv = c.getProcAddress("glUniform3fv") c.gpUniform3fv = c.getProcAddress("glUniform3fv")
if c.gpUniform3fv == 0 { if c.gpUniform3fv == 0 {
return errors.New("gl: glUniform3fv is missing") return errors.New("gl: glUniform3fv is missing")
} }
c.gpUniform3iv = c.getProcAddress("glUniform3iv")
if c.gpUniform3iv == 0 {
return errors.New("gl: glUniform3iv is missing")
}
c.gpUniform4fv = c.getProcAddress("glUniform4fv") c.gpUniform4fv = c.getProcAddress("glUniform4fv")
if c.gpUniform4fv == 0 { if c.gpUniform4fv == 0 {
return errors.New("gl: glUniform4fv is missing") return errors.New("gl: glUniform4fv is missing")
} }
c.gpUniform4iv = c.getProcAddress("glUniform4iv")
if c.gpUniform4iv == 0 {
return errors.New("gl: glUniform4iv is missing")
}
c.gpUniformMatrix2fv = c.getProcAddress("glUniformMatrix2fv") c.gpUniformMatrix2fv = c.getProcAddress("glUniformMatrix2fv")
if c.gpUniformMatrix2fv == 0 { if c.gpUniformMatrix2fv == 0 {
return errors.New("gl: glUniformMatrix2fv is missing") return errors.New("gl: glUniformMatrix2fv is missing")

View File

@ -287,14 +287,26 @@ func (g *gomobileContext) Uniform2fv(location int32, value []float32) {
g.ctx.Uniform2fv(gl.Uniform{Value: location}, value) g.ctx.Uniform2fv(gl.Uniform{Value: location}, value)
} }
func (g *gomobileContext) Uniform2iv(location int32, value []int32) {
g.ctx.Uniform2iv(gl.Uniform{Value: location}, value)
}
func (g *gomobileContext) Uniform3fv(location int32, value []float32) { func (g *gomobileContext) Uniform3fv(location int32, value []float32) {
g.ctx.Uniform3fv(gl.Uniform{Value: location}, value) g.ctx.Uniform3fv(gl.Uniform{Value: location}, value)
} }
func (g *gomobileContext) Uniform3iv(location int32, value []int32) {
g.ctx.Uniform3iv(gl.Uniform{Value: location}, value)
}
func (g *gomobileContext) Uniform4fv(location int32, value []float32) { func (g *gomobileContext) Uniform4fv(location int32, value []float32) {
g.ctx.Uniform4fv(gl.Uniform{Value: location}, value) g.ctx.Uniform4fv(gl.Uniform{Value: location}, value)
} }
func (g *gomobileContext) Uniform4iv(location int32, value []int32) {
g.ctx.Uniform4iv(gl.Uniform{Value: location}, value)
}
func (g *gomobileContext) UniformMatrix2fv(location int32, value []float32) { func (g *gomobileContext) UniformMatrix2fv(location int32, value []float32) {
g.ctx.UniformMatrix2fv(gl.Uniform{Value: location}, value) g.ctx.UniformMatrix2fv(gl.Uniform{Value: location}, value)
} }

View File

@ -83,8 +83,11 @@ type Context interface {
Uniform1i(location int32, v0 int32) Uniform1i(location int32, v0 int32)
Uniform1iv(location int32, value []int32) Uniform1iv(location int32, value []int32)
Uniform2fv(location int32, value []float32) Uniform2fv(location int32, value []float32)
Uniform2iv(location int32, value []int32)
Uniform3fv(location int32, value []float32) Uniform3fv(location int32, value []float32)
Uniform3iv(location int32, value []int32)
Uniform4fv(location int32, value []float32) Uniform4fv(location int32, value []float32)
Uniform4iv(location int32, value []int32)
UniformMatrix2fv(location int32, value []float32) UniformMatrix2fv(location int32, value []float32)
UniformMatrix3fv(location int32, value []float32) UniformMatrix3fv(location int32, value []float32)
UniformMatrix4fv(location int32, value []float32) UniformMatrix4fv(location int32, value []float32)

View File

@ -54,6 +54,34 @@ func isModAvailableForConsts(lhs, rhs *shaderir.Expr) bool {
return false return false
} }
func isValidForModOp(lhs, rhs *shaderir.Expr, lhst, rhst shaderir.Type) bool {
isInt := func(s *shaderir.Expr, t shaderir.Type) bool {
if t.Main == shaderir.Int {
return true
}
if s.Const == nil {
return false
}
if s.ConstType == shaderir.ConstTypeInt {
return true
}
if canTruncateToInteger(s.Const) {
return true
}
return false
}
if isInt(lhs, lhst) {
return isInt(rhs, rhst)
}
if lhst.Main == shaderir.IVec2 || lhst.Main == shaderir.IVec3 || lhst.Main == shaderir.IVec4 {
return lhst.Equal(&rhst) || isInt(rhs, rhst)
}
return false
}
func canApplyBinaryOp(lhs, rhs *shaderir.Expr, lhst, rhst shaderir.Type, op shaderir.Op) bool { func canApplyBinaryOp(lhs, rhs *shaderir.Expr, lhst, rhst shaderir.Type, op shaderir.Op) bool {
if op == shaderir.AndAnd || op == shaderir.OrOr { if op == shaderir.AndAnd || op == shaderir.OrOr {
return lhst.Main == shaderir.Bool && rhst.Main == shaderir.Bool return lhst.Main == shaderir.Bool && rhst.Main == shaderir.Bool
@ -289,6 +317,11 @@ func (cs *compileState) parseExpr(block *block, fname string, expr ast.Expr, mar
cs.addError(e.Pos(), fmt.Sprintf("types don't match: %s %s %s", lhst.String(), e.Op, rhst.String())) cs.addError(e.Pos(), fmt.Sprintf("types don't match: %s %s %s", lhst.String(), e.Op, rhst.String()))
return nil, nil, nil, false return nil, nil, nil, false
} }
case shaderir.IVec2, shaderir.IVec3, shaderir.IVec4:
if !canTruncateToInteger(lhs[0].Const) {
cs.addError(e.Pos(), fmt.Sprintf("types don't match: %s %s %s", lhst.String(), e.Op, rhst.String()))
return nil, nil, nil, false
}
case shaderir.Int: case shaderir.Int:
if !canTruncateToInteger(lhs[0].Const) { if !canTruncateToInteger(lhs[0].Const) {
cs.addError(e.Pos(), fmt.Sprintf("constant %s truncated to integer", lhs[0].Const.String())) cs.addError(e.Pos(), fmt.Sprintf("constant %s truncated to integer", lhs[0].Const.String()))
@ -310,6 +343,11 @@ func (cs *compileState) parseExpr(block *block, fname string, expr ast.Expr, mar
cs.addError(e.Pos(), fmt.Sprintf("types don't match: %s %s %s", lhst.String(), e.Op, rhst.String())) cs.addError(e.Pos(), fmt.Sprintf("types don't match: %s %s %s", lhst.String(), e.Op, rhst.String()))
return nil, nil, nil, false return nil, nil, nil, false
} }
case shaderir.IVec2, shaderir.IVec3, shaderir.IVec4:
if !canTruncateToInteger(rhs[0].Const) {
cs.addError(e.Pos(), fmt.Sprintf("types don't match: %s %s %s", lhst.String(), e.Op, rhst.String()))
return nil, nil, nil, false
}
case shaderir.Int: case shaderir.Int:
if !canTruncateToInteger(rhs[0].Const) { if !canTruncateToInteger(rhs[0].Const) {
cs.addError(e.Pos(), fmt.Sprintf("constant %s truncated to integer", rhs[0].Const.String())) cs.addError(e.Pos(), fmt.Sprintf("constant %s truncated to integer", rhs[0].Const.String()))
@ -368,9 +406,7 @@ func (cs *compileState) parseExpr(block *block, fname string, expr ast.Expr, mar
// For `%`, both types must be deducible to integers. // For `%`, both types must be deducible to integers.
if op == shaderir.ModOp { if op == shaderir.ModOp {
// TODO: What about ivec? if !isValidForModOp(&lhs[0], &rhs[0], lhst, rhst) {
if lhst.Main != shaderir.Int && (lhs[0].ConstType == shaderir.ConstTypeNone || !canTruncateToInteger(lhs[0].Const)) ||
rhst.Main != shaderir.Int && (rhs[0].ConstType == shaderir.ConstTypeNone || !canTruncateToInteger(rhs[0].Const)) {
var wrongType shaderir.Type var wrongType shaderir.Type
if lhst.Main != shaderir.Int { if lhst.Main != shaderir.Int {
wrongType = lhst wrongType = lhst
@ -527,6 +563,24 @@ func (cs *compileState) parseExpr(block *block, fname string, expr ast.Expr, mar
return nil, nil, nil, false return nil, nil, nil, false
} }
t = shaderir.Type{Main: shaderir.Vec4} t = shaderir.Type{Main: shaderir.Vec4}
case shaderir.IVec2F:
if err := checkArgsForVec2BuiltinFunc(args, argts); err != nil {
cs.addError(e.Pos(), err.Error())
return nil, nil, nil, false
}
t = shaderir.Type{Main: shaderir.IVec2}
case shaderir.IVec3F:
if err := checkArgsForVec3BuiltinFunc(args, argts); err != nil {
cs.addError(e.Pos(), err.Error())
return nil, nil, nil, false
}
t = shaderir.Type{Main: shaderir.IVec3}
case shaderir.IVec4F:
if err := checkArgsForVec4BuiltinFunc(args, argts); err != nil {
cs.addError(e.Pos(), err.Error())
return nil, nil, nil, false
}
t = shaderir.Type{Main: shaderir.IVec4}
case shaderir.Mat2F: case shaderir.Mat2F:
if err := checkArgsForMat2BuiltinFunc(args, argts); err != nil { if err := checkArgsForMat2BuiltinFunc(args, argts); err != nil {
cs.addError(e.Pos(), err.Error()) cs.addError(e.Pos(), err.Error())
@ -901,16 +955,31 @@ func (cs *compileState) parseExpr(block *block, fname string, expr ast.Expr, mar
} }
var t shaderir.Type var t shaderir.Type
switch len(e.Sel.Name) { switch types[0].Main {
case 1: case shaderir.Vec2, shaderir.Vec3, shaderir.Vec4:
t.Main = shaderir.Float switch len(e.Sel.Name) {
case 2: case 1:
t.Main = shaderir.Vec2 t.Main = shaderir.Float
case 3: case 2:
t.Main = shaderir.Vec3 t.Main = shaderir.Vec2
case 4: case 3:
t.Main = shaderir.Vec4 t.Main = shaderir.Vec3
default: case 4:
t.Main = shaderir.Vec4
}
case shaderir.IVec2, shaderir.IVec3, shaderir.IVec4:
switch len(e.Sel.Name) {
case 1:
t.Main = shaderir.Int
case 2:
t.Main = shaderir.IVec2
case 3:
t.Main = shaderir.IVec3
case 4:
t.Main = shaderir.IVec4
}
}
if t.Equal(&shaderir.Type{}) {
cs.addError(e.Pos(), fmt.Sprintf("unexpected swizzling: %s", e.Sel.Name)) cs.addError(e.Pos(), fmt.Sprintf("unexpected swizzling: %s", e.Sel.Name))
return nil, nil, nil, false return nil, nil, nil, false
} }
@ -1064,6 +1133,8 @@ func (cs *compileState) parseExpr(block *block, fname string, expr ast.Expr, mar
switch t.Main { switch t.Main {
case shaderir.Vec2, shaderir.Vec3, shaderir.Vec4: case shaderir.Vec2, shaderir.Vec3, shaderir.Vec4:
typ = shaderir.Type{Main: shaderir.Float} typ = shaderir.Type{Main: shaderir.Float}
case shaderir.IVec2, shaderir.IVec3, shaderir.IVec4:
typ = shaderir.Type{Main: shaderir.Int}
case shaderir.Mat2: case shaderir.Mat2:
typ = shaderir.Type{Main: shaderir.Vec2} typ = shaderir.Type{Main: shaderir.Vec2}
case shaderir.Mat3: case shaderir.Mat3:
@ -1099,11 +1170,11 @@ func isValidSwizzling(swizzling string, t shaderir.Type) bool {
} }
switch t.Main { switch t.Main {
case shaderir.Vec2: case shaderir.Vec2, shaderir.IVec2:
return !strings.ContainsAny(swizzling, "zwbarq") return !strings.ContainsAny(swizzling, "zwbarq")
case shaderir.Vec3: case shaderir.Vec3, shaderir.IVec3:
return !strings.ContainsAny(swizzling, "waq") return !strings.ContainsAny(swizzling, "waq")
case shaderir.Vec4: case shaderir.Vec4, shaderir.IVec4:
return true return true
default: default:
return false return false

View File

@ -104,9 +104,15 @@ func (cs *compileState) parseStmt(block *block, fname string, stmt ast.Stmt, inP
} }
} else { } else {
switch lts[0].Main { switch lts[0].Main {
case shaderir.Int: case shaderir.Int, shaderir.IVec2, shaderir.IVec3, shaderir.IVec4:
if !cs.forceToInt(stmt, &rhs[0]) { if rts[0].Main != shaderir.Int {
return nil, false if !rts[0].Equal(&shaderir.Type{}) {
cs.addError(stmt.Pos(), fmt.Sprintf("invalid operation: mismatched types %s and %s", lts[0].String(), rts[0].String()))
return nil, false
}
if !cs.forceToInt(stmt, &rhs[0]) {
return nil, false
}
} }
case shaderir.Float: case shaderir.Float:
if rhs[0].Const != nil && if rhs[0].Const != nil &&
@ -151,7 +157,7 @@ func (cs *compileState) parseStmt(block *block, fname string, stmt ast.Stmt, inP
} }
} }
if op == shaderir.ModOp && lts[0].Main != shaderir.Int { if op == shaderir.ModOp && lts[0].Main != shaderir.Int && lts[0].Main != shaderir.IVec2 && lts[0].Main != shaderir.IVec3 && lts[0].Main != shaderir.IVec4 {
cs.addError(stmt.Pos(), fmt.Sprintf("invalid operation: operator %% not defined on %s", lts[0].String())) cs.addError(stmt.Pos(), fmt.Sprintf("invalid operation: operator %% not defined on %s", lts[0].String()))
return nil, false return nil, false
} }

View File

@ -974,6 +974,14 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
}`)); err != nil { }`)); err != nil {
t.Error(err) t.Error(err)
} }
if _, err := compileToIR([]byte(`package main
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
a := ivec2(1) + 2
return vec4(a.xxyy)
}`)); err != nil {
t.Error(err)
}
if _, err := compileToIR([]byte(`package main if _, err := compileToIR([]byte(`package main
@ -983,6 +991,14 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
}`)); err != nil { }`)); err != nil {
t.Error(err) t.Error(err)
} }
if _, err := compileToIR([]byte(`package main
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
a := ivec2(1) + 2.1
return vec4(a.xxyy)
}`)); err == nil {
t.Errorf("error must be non-nil but was nil")
}
if _, err := compileToIR([]byte(`package main if _, err := compileToIR([]byte(`package main
@ -992,6 +1008,14 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
}`)); err == nil { }`)); err == nil {
t.Errorf("error must be non-nil but was nil") t.Errorf("error must be non-nil but was nil")
} }
if _, err := compileToIR([]byte(`package main
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
a := ivec2(1) % 2
return vec4(a.xxyy)
}`)); err != nil {
t.Error(err)
}
if _, err := compileToIR([]byte(`package main if _, err := compileToIR([]byte(`package main
@ -1001,6 +1025,14 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
}`)); err == nil { }`)); err == nil {
t.Errorf("error must be non-nil but was nil") t.Errorf("error must be non-nil but was nil")
} }
if _, err := compileToIR([]byte(`package main
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
a := ivec2(1) % 2.1
return vec4(a.xxyy)
}`)); err == nil {
t.Errorf("error must be non-nil but was nil")
}
if _, err := compileToIR([]byte(`package main if _, err := compileToIR([]byte(`package main
@ -1011,6 +1043,15 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
}`)); err != nil { }`)); err != nil {
t.Error(err) t.Error(err)
} }
if _, err := compileToIR([]byte(`package main
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
a := ivec2(1)
a += 2
return vec4(a.xxyy)
}`)); err != nil {
t.Error(err)
}
if _, err := compileToIR([]byte(`package main if _, err := compileToIR([]byte(`package main
@ -1021,6 +1062,15 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
}`)); err != nil { }`)); err != nil {
t.Error(err) t.Error(err)
} }
if _, err := compileToIR([]byte(`package main
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
a := ivec2(1)
a += 2.1
return vec4(a.xxyy)
}`)); err == nil {
t.Errorf("error must be non-nil but was nil")
}
if _, err := compileToIR([]byte(`package main if _, err := compileToIR([]byte(`package main
@ -1031,6 +1081,15 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
}`)); err == nil { }`)); err == nil {
t.Errorf("error must be non-nil but was nil") t.Errorf("error must be non-nil but was nil")
} }
if _, err := compileToIR([]byte(`package main
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
a := ivec2(1)
a %= 2
return vec4(a.xxyy)
}`)); err != nil {
t.Error(err)
}
if _, err := compileToIR([]byte(`package main if _, err := compileToIR([]byte(`package main
@ -1038,6 +1097,15 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
a := vec2(1) a := vec2(1)
a %= 2.1 a %= 2.1
return a.xxyy return a.xxyy
}`)); err == nil {
t.Errorf("error must be non-nil but was nil")
}
if _, err := compileToIR([]byte(`package main
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
a := ivec2(1)
a %= 2.1
return vec4(a.xxyy)
}`)); err == nil { }`)); err == nil {
t.Errorf("error must be non-nil but was nil") t.Errorf("error must be non-nil but was nil")
} }
@ -1054,14 +1122,37 @@ func TestSyntaxOperatorMultiply(t *testing.T) {
{stmt: "a := 1 * vec2(2); _ = a", err: false}, {stmt: "a := 1 * vec2(2); _ = a", err: false},
{stmt: "a := int(1) * vec2(2); _ = a", err: true}, {stmt: "a := int(1) * vec2(2); _ = a", err: true},
{stmt: "a := 1.0 * vec2(2); _ = a", err: false}, {stmt: "a := 1.0 * vec2(2); _ = a", err: false},
{stmt: "a := 1.1 * vec2(2); _ = a", err: false},
{stmt: "a := 1 + vec2(2); _ = a", err: false}, {stmt: "a := 1 + vec2(2); _ = a", err: false},
{stmt: "a := int(1) + vec2(2); _ = a", err: true}, {stmt: "a := int(1) + vec2(2); _ = a", err: true},
{stmt: "a := 1.0 / vec2(2); _ = a", err: false}, {stmt: "a := 1.0 / vec2(2); _ = a", err: false},
{stmt: "a := 1.1 / vec2(2); _ = a", err: false},
{stmt: "a := 1.0 + vec2(2); _ = a", err: false}, {stmt: "a := 1.0 + vec2(2); _ = a", err: false},
{stmt: "a := 1.1 + vec2(2); _ = a", err: false},
{stmt: "a := 1 * vec3(2); _ = a", err: false}, {stmt: "a := 1 * vec3(2); _ = a", err: false},
{stmt: "a := 1.0 * vec3(2); _ = a", err: false}, {stmt: "a := 1.0 * vec3(2); _ = a", err: false},
{stmt: "a := 1.1 * vec3(2); _ = a", err: false},
{stmt: "a := 1 * vec4(2); _ = a", err: false}, {stmt: "a := 1 * vec4(2); _ = a", err: false},
{stmt: "a := 1.0 * vec4(2); _ = a", err: false}, {stmt: "a := 1.0 * vec4(2); _ = a", err: false},
{stmt: "a := 1.1 * vec4(2); _ = a", err: false},
{stmt: "a := 1 * ivec2(2); _ = a", err: false},
{stmt: "a := int(1) * ivec2(2); _ = a", err: false},
{stmt: "a := 1.0 * ivec2(2); _ = a", err: false},
{stmt: "a := 1.1 * ivec2(2); _ = a", err: true},
{stmt: "a := 1 + ivec2(2); _ = a", err: false},
{stmt: "a := int(1) + ivec2(2); _ = a", err: false},
{stmt: "a := 1.0 / ivec2(2); _ = a", err: false},
{stmt: "a := 1.1 / ivec2(2); _ = a", err: true},
{stmt: "a := 1.0 + ivec2(2); _ = a", err: false},
{stmt: "a := 1.1 + ivec2(2); _ = a", err: true},
{stmt: "a := 1 * ivec3(2); _ = a", err: false},
{stmt: "a := 1.0 * ivec3(2); _ = a", err: false},
{stmt: "a := 1.1 * ivec3(2); _ = a", err: true},
{stmt: "a := 1 * ivec4(2); _ = a", err: false},
{stmt: "a := 1.0 * ivec4(2); _ = a", err: false},
{stmt: "a := 1.1 * ivec4(2); _ = a", err: true},
{stmt: "a := 1 * mat2(2); _ = a", err: false}, {stmt: "a := 1 * mat2(2); _ = a", err: false},
{stmt: "a := 1.0 * mat2(2); _ = a", err: false}, {stmt: "a := 1.0 * mat2(2); _ = a", err: false},
{stmt: "a := float(1.0) / mat2(2); _ = a", err: true}, {stmt: "a := float(1.0) / mat2(2); _ = a", err: true},
@ -1072,30 +1163,67 @@ func TestSyntaxOperatorMultiply(t *testing.T) {
{stmt: "a := 1.0 * mat3(2); _ = a", err: false}, {stmt: "a := 1.0 * mat3(2); _ = a", err: false},
{stmt: "a := 1 * mat4(2); _ = a", err: false}, {stmt: "a := 1 * mat4(2); _ = a", err: false},
{stmt: "a := 1.0 * mat4(2); _ = a", err: false}, {stmt: "a := 1.0 * mat4(2); _ = a", err: false},
{stmt: "a := vec2(1) * 2; _ = a", err: false}, {stmt: "a := vec2(1) * 2; _ = a", err: false},
{stmt: "a := vec2(1) * 2.0; _ = a", err: false}, {stmt: "a := vec2(1) * 2.0; _ = a", err: false},
{stmt: "a := vec2(1) * 2.1; _ = a", err: false},
{stmt: "a := vec2(1) / 2.0; _ = a", err: false}, {stmt: "a := vec2(1) / 2.0; _ = a", err: false},
{stmt: "a := vec2(1) / 2.1; _ = a", err: false},
{stmt: "a := vec2(1) + 2.0; _ = a", err: false}, {stmt: "a := vec2(1) + 2.0; _ = a", err: false},
{stmt: "a := vec2(1) + 2.1; _ = a", err: false},
{stmt: "a := vec2(1) * int(2); _ = a", err: true}, {stmt: "a := vec2(1) * int(2); _ = a", err: true},
{stmt: "a := vec2(1) * vec2(2); _ = a", err: false}, {stmt: "a := vec2(1) * vec2(2); _ = a", err: false},
{stmt: "a := vec2(1) + vec2(2); _ = a", err: false}, {stmt: "a := vec2(1) + vec2(2); _ = a", err: false},
{stmt: "a := vec2(1) * vec3(2); _ = a", err: true}, {stmt: "a := vec2(1) * vec3(2); _ = a", err: true},
{stmt: "a := vec2(1) * vec4(2); _ = a", err: true}, {stmt: "a := vec2(1) * vec4(2); _ = a", err: true},
{stmt: "a := vec2(1) * ivec2(2); _ = a", err: true},
{stmt: "a := vec2(1) + ivec2(2); _ = a", err: true},
{stmt: "a := vec2(1) * ivec3(2); _ = a", err: true},
{stmt: "a := vec2(1) * ivec4(2); _ = a", err: true},
{stmt: "a := vec2(1) * mat2(2); _ = a", err: false}, {stmt: "a := vec2(1) * mat2(2); _ = a", err: false},
{stmt: "a := vec2(1) + mat2(2); _ = a", err: true}, {stmt: "a := vec2(1) + mat2(2); _ = a", err: true},
{stmt: "a := vec2(1) * mat3(2); _ = a", err: true}, {stmt: "a := vec2(1) * mat3(2); _ = a", err: true},
{stmt: "a := vec2(1) * mat4(2); _ = a", err: true}, {stmt: "a := vec2(1) * mat4(2); _ = a", err: true},
{stmt: "a := ivec2(1) * 2; _ = a", err: false},
{stmt: "a := ivec2(1) * 2.0; _ = a", err: false},
{stmt: "a := ivec2(1) * 2.1; _ = a", err: true},
{stmt: "a := ivec2(1) / 2.0; _ = a", err: false},
{stmt: "a := ivec2(1) / 2.1; _ = a", err: true},
{stmt: "a := ivec2(1) + 2.0; _ = a", err: false},
{stmt: "a := ivec2(1) + 2.1; _ = a", err: true},
{stmt: "a := ivec2(1) * int(2); _ = a", err: false},
{stmt: "a := ivec2(1) * vec2(2); _ = a", err: true},
{stmt: "a := ivec2(1) + vec2(2); _ = a", err: true},
{stmt: "a := ivec2(1) * vec3(2); _ = a", err: true},
{stmt: "a := ivec2(1) * vec4(2); _ = a", err: true},
{stmt: "a := ivec2(1) * ivec2(2); _ = a", err: false},
{stmt: "a := ivec2(1) + ivec2(2); _ = a", err: false},
{stmt: "a := ivec2(1) * ivec3(2); _ = a", err: true},
{stmt: "a := ivec2(1) * ivec4(2); _ = a", err: true},
{stmt: "a := ivec2(1) * mat2(2); _ = a", err: true},
{stmt: "a := ivec2(1) + mat2(2); _ = a", err: true},
{stmt: "a := ivec2(1) * mat3(2); _ = a", err: true},
{stmt: "a := ivec2(1) * mat4(2); _ = a", err: true},
{stmt: "a := mat2(1) * 2; _ = a", err: false}, {stmt: "a := mat2(1) * 2; _ = a", err: false},
{stmt: "a := mat2(1) * 2.0; _ = a", err: false}, {stmt: "a := mat2(1) * 2.0; _ = a", err: false},
{stmt: "a := mat2(1) * 2.1; _ = a", err: false},
{stmt: "a := mat2(1) / 2.0; _ = a", err: false}, {stmt: "a := mat2(1) / 2.0; _ = a", err: false},
{stmt: "a := mat2(1) / 2.1; _ = a", err: false},
{stmt: "a := mat2(1) / float(2); _ = a", err: false}, {stmt: "a := mat2(1) / float(2); _ = a", err: false},
{stmt: "a := mat2(1) * int(2); _ = a", err: true}, {stmt: "a := mat2(1) * int(2); _ = a", err: true},
{stmt: "a := mat2(1) + 2.0; _ = a", err: true}, {stmt: "a := mat2(1) + 2.0; _ = a", err: true},
{stmt: "a := mat2(1) + 2.1; _ = a", err: true},
{stmt: "a := mat2(1) + float(2); _ = a", err: true}, {stmt: "a := mat2(1) + float(2); _ = a", err: true},
{stmt: "a := mat2(1) * vec2(2); _ = a", err: false}, {stmt: "a := mat2(1) * vec2(2); _ = a", err: false},
{stmt: "a := mat2(1) + vec2(2); _ = a", err: true}, {stmt: "a := mat2(1) + vec2(2); _ = a", err: true},
{stmt: "a := mat2(1) * vec3(2); _ = a", err: true}, {stmt: "a := mat2(1) * vec3(2); _ = a", err: true},
{stmt: "a := mat2(1) * vec4(2); _ = a", err: true}, {stmt: "a := mat2(1) * vec4(2); _ = a", err: true},
{stmt: "a := mat2(1) * ivec2(2); _ = a", err: true},
{stmt: "a := mat2(1) + ivec2(2); _ = a", err: true},
{stmt: "a := mat2(1) * ivec3(2); _ = a", err: true},
{stmt: "a := mat2(1) * ivec4(2); _ = a", err: true},
{stmt: "a := mat2(1) * mat2(2); _ = a", err: false}, {stmt: "a := mat2(1) * mat2(2); _ = a", err: false},
{stmt: "a := mat2(1) / mat2(2); _ = a", err: true}, {stmt: "a := mat2(1) / mat2(2); _ = a", err: true},
{stmt: "a := mat2(1) * mat3(2); _ = a", err: true}, {stmt: "a := mat2(1) * mat3(2); _ = a", err: true},
@ -1117,6 +1245,8 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
} }
} }
// TODO
// Issue #1971 // Issue #1971
func TestSyntaxOperatorMultiplyAssign(t *testing.T) { func TestSyntaxOperatorMultiplyAssign(t *testing.T) {
cases := []struct { cases := []struct {
@ -1135,6 +1265,9 @@ func TestSyntaxOperatorMultiplyAssign(t *testing.T) {
{stmt: "a := 1.0; a *= vec2(2)", err: true}, {stmt: "a := 1.0; a *= vec2(2)", err: true},
{stmt: "a := 1.0; a *= vec3(2)", err: true}, {stmt: "a := 1.0; a *= vec3(2)", err: true},
{stmt: "a := 1.0; a *= vec4(2)", err: true}, {stmt: "a := 1.0; a *= vec4(2)", err: true},
{stmt: "a := 1.0; a *= ivec2(2)", err: true},
{stmt: "a := 1.0; a *= ivec3(2)", err: true},
{stmt: "a := 1.0; a *= ivec4(2)", err: true},
{stmt: "a := 1.0; a *= mat2(2)", err: true}, {stmt: "a := 1.0; a *= mat2(2)", err: true},
{stmt: "a := 1.0; a *= mat3(2)", err: true}, {stmt: "a := 1.0; a *= mat3(2)", err: true},
{stmt: "a := 1.0; a *= mat4(2)", err: true}, {stmt: "a := 1.0; a *= mat4(2)", err: true},
@ -1156,12 +1289,43 @@ func TestSyntaxOperatorMultiplyAssign(t *testing.T) {
{stmt: "a := vec2(1); a += vec2(2)", err: false}, {stmt: "a := vec2(1); a += vec2(2)", err: false},
{stmt: "a := vec2(1); a *= vec3(2)", err: true}, {stmt: "a := vec2(1); a *= vec3(2)", err: true},
{stmt: "a := vec2(1); a *= vec4(2)", err: true}, {stmt: "a := vec2(1); a *= vec4(2)", err: true},
{stmt: "a := vec2(1); a *= ivec2(2)", err: true},
{stmt: "a := vec2(1); a += ivec2(2)", err: true},
{stmt: "a := vec2(1); a *= ivec3(2)", err: true},
{stmt: "a := vec2(1); a *= ivec4(2)", err: true},
{stmt: "a := vec2(1); a *= mat2(2)", err: false}, {stmt: "a := vec2(1); a *= mat2(2)", err: false},
{stmt: "a := vec2(1); a += mat2(2)", err: true}, {stmt: "a := vec2(1); a += mat2(2)", err: true},
{stmt: "a := vec2(1); a /= mat2(2)", err: true}, {stmt: "a := vec2(1); a /= mat2(2)", err: true},
{stmt: "a := vec2(1); a *= mat3(2)", err: true}, {stmt: "a := vec2(1); a *= mat3(2)", err: true},
{stmt: "a := vec2(1); a *= mat4(2)", err: true}, {stmt: "a := vec2(1); a *= mat4(2)", err: true},
{stmt: "a := ivec2(1); a *= 2", err: false},
{stmt: "a := ivec2(1); a *= 2.0", err: false},
{stmt: "const c = 2; a := ivec2(1); a *= c", err: false},
{stmt: "const c = 2.0; a := ivec2(1); a *= c", err: false},
{stmt: "const c int = 2; a := ivec2(1); a *= c", err: false},
{stmt: "const c int = 2.0; a := ivec2(1); a *= c", err: false},
{stmt: "const c float = 2; a := ivec2(1); a *= c", err: true},
{stmt: "const c float = 2.0; a := ivec2(1); a *= c", err: true},
{stmt: "a := ivec2(1); a /= 2.0", err: false},
{stmt: "a := ivec2(1); a += 2.0", err: false},
{stmt: "a := ivec2(1); a *= int(2)", err: false},
{stmt: "a := ivec2(1); a *= float(2)", err: true},
{stmt: "a := ivec2(1); a /= float(2)", err: true},
{stmt: "a := ivec2(1); a *= vec2(2)", err: true},
{stmt: "a := ivec2(1); a += vec2(2)", err: true},
{stmt: "a := ivec2(1); a *= vec3(2)", err: true},
{stmt: "a := ivec2(1); a *= vec4(2)", err: true},
{stmt: "a := ivec2(1); a *= ivec2(2)", err: false},
{stmt: "a := ivec2(1); a += ivec2(2)", err: false},
{stmt: "a := ivec2(1); a *= ivec3(2)", err: true},
{stmt: "a := ivec2(1); a *= ivec4(2)", err: true},
{stmt: "a := ivec2(1); a *= mat2(2)", err: true},
{stmt: "a := ivec2(1); a += mat2(2)", err: true},
{stmt: "a := ivec2(1); a /= mat2(2)", err: true},
{stmt: "a := ivec2(1); a *= mat3(2)", err: true},
{stmt: "a := ivec2(1); a *= mat4(2)", err: true},
{stmt: "a := mat2(1); a *= 2", err: false}, {stmt: "a := mat2(1); a *= 2", err: false},
{stmt: "a := mat2(1); a *= 2.0", err: false}, {stmt: "a := mat2(1); a *= 2.0", err: false},
{stmt: "const c = 2; a := mat2(1); a *= c", err: false}, {stmt: "const c = 2; a := mat2(1); a *= c", err: false},
@ -1179,6 +1343,10 @@ func TestSyntaxOperatorMultiplyAssign(t *testing.T) {
{stmt: "a := mat2(1); a += vec2(2)", err: true}, {stmt: "a := mat2(1); a += vec2(2)", err: true},
{stmt: "a := mat2(1); a *= vec3(2)", err: true}, {stmt: "a := mat2(1); a *= vec3(2)", err: true},
{stmt: "a := mat2(1); a *= vec4(2)", err: true}, {stmt: "a := mat2(1); a *= vec4(2)", err: true},
{stmt: "a := mat2(1); a *= ivec2(2)", err: true},
{stmt: "a := mat2(1); a += ivec2(2)", err: true},
{stmt: "a := mat2(1); a *= ivec3(2)", err: true},
{stmt: "a := mat2(1); a *= ivec4(2)", err: true},
{stmt: "a := mat2(1); a *= mat2(2)", err: false}, {stmt: "a := mat2(1); a *= mat2(2)", err: false},
{stmt: "a := mat2(1); a += mat2(2)", err: false}, {stmt: "a := mat2(1); a += mat2(2)", err: false},
{stmt: "a := mat2(1); a /= mat2(2)", err: true}, {stmt: "a := mat2(1); a /= mat2(2)", err: true},
@ -1437,9 +1605,12 @@ func TestSyntaxConstructorFuncType(t *testing.T) {
{stmt: "i := 1.0; a := vec2(i); _ = a", err: false}, {stmt: "i := 1.0; a := vec2(i); _ = a", err: false},
{stmt: "a := vec2(vec2(1)); _ = a", err: false}, {stmt: "a := vec2(vec2(1)); _ = a", err: false},
{stmt: "a := vec2(vec3(1)); _ = a", err: true}, {stmt: "a := vec2(vec3(1)); _ = a", err: true},
{stmt: "a := vec2(ivec2(1)); _ = a", err: false},
{stmt: "a := vec2(ivec3(1)); _ = a", err: true},
{stmt: "a := vec2(1, 1); _ = a", err: false}, {stmt: "a := vec2(1, 1); _ = a", err: false},
{stmt: "a := vec2(1.0, 1.0); _ = a", err: false}, {stmt: "a := vec2(1.0, 1.0); _ = a", err: false},
{stmt: "a := vec2(1.1, 1.1); _ = a", err: false},
{stmt: "i := 1; a := vec2(i, i); _ = a", err: false}, {stmt: "i := 1; a := vec2(i, i); _ = a", err: false},
{stmt: "i := 1.0; a := vec2(i, i); _ = a", err: false}, {stmt: "i := 1.0; a := vec2(i, i); _ = a", err: false},
{stmt: "a := vec2(vec2(1), 1); _ = a", err: true}, {stmt: "a := vec2(vec2(1), 1); _ = a", err: true},
@ -1449,18 +1620,25 @@ func TestSyntaxConstructorFuncType(t *testing.T) {
{stmt: "a := vec3(1); _ = a", err: false}, {stmt: "a := vec3(1); _ = a", err: false},
{stmt: "a := vec3(1.0); _ = a", err: false}, {stmt: "a := vec3(1.0); _ = a", err: false},
{stmt: "a := vec3(1.1); _ = a", err: false},
{stmt: "i := 1; a := vec3(i); _ = a", err: false}, {stmt: "i := 1; a := vec3(i); _ = a", err: false},
{stmt: "i := 1.0; a := vec3(i); _ = a", err: false}, {stmt: "i := 1.0; a := vec3(i); _ = a", err: false},
{stmt: "a := vec3(vec3(1)); _ = a", err: false}, {stmt: "a := vec3(vec3(1)); _ = a", err: false},
{stmt: "a := vec3(vec2(1)); _ = a", err: true}, {stmt: "a := vec3(vec2(1)); _ = a", err: true},
{stmt: "a := vec3(vec4(1)); _ = a", err: true}, {stmt: "a := vec3(vec4(1)); _ = a", err: true},
{stmt: "a := vec3(ivec3(1)); _ = a", err: false},
{stmt: "a := vec3(ivec2(1)); _ = a", err: true},
{stmt: "a := vec3(ivec4(1)); _ = a", err: true},
{stmt: "a := vec3(1, 1, 1); _ = a", err: false}, {stmt: "a := vec3(1, 1, 1); _ = a", err: false},
{stmt: "a := vec3(1.0, 1.0, 1.0); _ = a", err: false}, {stmt: "a := vec3(1.0, 1.0, 1.0); _ = a", err: false},
{stmt: "a := vec3(1.1, 1.1, 1.1); _ = a", err: false},
{stmt: "i := 1; a := vec3(i, i, i); _ = a", err: false}, {stmt: "i := 1; a := vec3(i, i, i); _ = a", err: false},
{stmt: "i := 1.0; a := vec3(i, i, i); _ = a", err: false}, {stmt: "i := 1.0; a := vec3(i, i, i); _ = a", err: false},
{stmt: "a := vec3(vec2(1), 1); _ = a", err: false}, {stmt: "a := vec3(vec2(1), 1); _ = a", err: false},
{stmt: "a := vec3(1, vec2(1)); _ = a", err: false}, {stmt: "a := vec3(1, vec2(1)); _ = a", err: false},
{stmt: "a := vec3(ivec2(1), 1); _ = a", err: false},
{stmt: "a := vec3(1, ivec2(1)); _ = a", err: false},
{stmt: "a := vec3(vec3(1), 1); _ = a", err: true}, {stmt: "a := vec3(vec3(1), 1); _ = a", err: true},
{stmt: "a := vec3(1, vec3(1)); _ = a", err: true}, {stmt: "a := vec3(1, vec3(1)); _ = a", err: true},
{stmt: "a := vec3(vec3(1), vec3(1), vec3(1)); _ = a", err: true}, {stmt: "a := vec3(vec3(1), vec3(1), vec3(1)); _ = a", err: true},
@ -1473,32 +1651,122 @@ func TestSyntaxConstructorFuncType(t *testing.T) {
{stmt: "a := vec4(vec4(1)); _ = a", err: false}, {stmt: "a := vec4(vec4(1)); _ = a", err: false},
{stmt: "a := vec4(vec2(1)); _ = a", err: true}, {stmt: "a := vec4(vec2(1)); _ = a", err: true},
{stmt: "a := vec4(vec3(1)); _ = a", err: true}, {stmt: "a := vec4(vec3(1)); _ = a", err: true},
{stmt: "a := vec4(ivec4(1)); _ = a", err: false},
{stmt: "a := vec4(ivec2(1)); _ = a", err: true},
{stmt: "a := vec4(ivec3(1)); _ = a", err: true},
{stmt: "a := vec4(1, 1, 1, 1); _ = a", err: false}, {stmt: "a := vec4(1, 1, 1, 1); _ = a", err: false},
{stmt: "a := vec4(1.0, 1.0, 1.0, 1.0); _ = a", err: false}, {stmt: "a := vec4(1.0, 1.0, 1.0, 1.0); _ = a", err: false},
{stmt: "a := vec4(1.1, 1.1, 1.1, 1.1); _ = a", err: false},
{stmt: "i := 1; a := vec4(i, i, i, i); _ = a", err: false}, {stmt: "i := 1; a := vec4(i, i, i, i); _ = a", err: false},
{stmt: "i := 1.0; a := vec4(i, i, i, i); _ = a", err: false}, {stmt: "i := 1.0; a := vec4(i, i, i, i); _ = a", err: false},
{stmt: "a := vec4(vec2(1), 1, 1); _ = a", err: false}, {stmt: "a := vec4(vec2(1), 1, 1); _ = a", err: false},
{stmt: "a := vec4(1, vec2(1), 1); _ = a", err: false}, {stmt: "a := vec4(1, vec2(1), 1); _ = a", err: false},
{stmt: "a := vec4(ivec2(1), 1, 1); _ = a", err: false},
{stmt: "a := vec4(1, ivec2(1), 1); _ = a", err: false},
{stmt: "a := vec4(1, 1, vec2(1)); _ = a", err: false}, {stmt: "a := vec4(1, 1, vec2(1)); _ = a", err: false},
{stmt: "a := vec4(vec2(1), vec2(1)); _ = a", err: false}, {stmt: "a := vec4(vec2(1), vec2(1)); _ = a", err: false},
{stmt: "a := vec4(ivec2(1), ivec2(1)); _ = a", err: false},
{stmt: "a := vec4(vec3(1), 1); _ = a", err: false}, {stmt: "a := vec4(vec3(1), 1); _ = a", err: false},
{stmt: "a := vec4(1, vec3(1)); _ = a", err: false}, {stmt: "a := vec4(1, vec3(1)); _ = a", err: false},
{stmt: "a := vec4(ivec3(1), 1); _ = a", err: false},
{stmt: "a := vec4(1, ivec3(1)); _ = a", err: false},
{stmt: "a := vec4(vec4(1), 1); _ = a", err: true}, {stmt: "a := vec4(vec4(1), 1); _ = a", err: true},
{stmt: "a := vec4(1, vec4(1)); _ = a", err: true}, {stmt: "a := vec4(1, vec4(1)); _ = a", err: true},
{stmt: "a := vec4(vec4(1), vec4(1), vec4(1), vec4(1)); _ = a", err: true}, {stmt: "a := vec4(vec4(1), vec4(1), vec4(1), vec4(1)); _ = a", err: true},
{stmt: "a := vec4(1, 1, 1, 1, 1); _ = a", err: true}, {stmt: "a := vec4(1, 1, 1, 1, 1); _ = a", err: true},
{stmt: "a := ivec2(1); _ = a", err: false},
{stmt: "a := ivec2(1.0); _ = a", err: false},
{stmt: "i := 1; a := ivec2(i); _ = a", err: false},
{stmt: "i := 1.0; a := ivec2(i); _ = a", err: false},
{stmt: "a := ivec2(vec2(1)); _ = a", err: false},
{stmt: "a := ivec2(vec3(1)); _ = a", err: true},
{stmt: "a := ivec2(ivec2(1)); _ = a", err: false},
{stmt: "a := ivec2(ivec3(1)); _ = a", err: true},
{stmt: "a := ivec2(1, 1); _ = a", err: false},
{stmt: "a := ivec2(1.0, 1.0); _ = a", err: false},
{stmt: "i := 1; a := ivec2(i, i); _ = a", err: false},
{stmt: "i := 1.0; a := ivec2(i, i); _ = a", err: false},
{stmt: "a := ivec2(vec2(1), 1); _ = a", err: true},
{stmt: "a := ivec2(1, vec2(1)); _ = a", err: true},
{stmt: "a := ivec2(ivec2(1), 1); _ = a", err: true},
{stmt: "a := ivec2(1, ivec2(1)); _ = a", err: true},
{stmt: "a := ivec2(ivec2(1), ivec2(1)); _ = a", err: true},
{stmt: "a := ivec2(1, 1, 1); _ = a", err: true},
{stmt: "a := ivec3(1); _ = a", err: false},
{stmt: "a := ivec3(1.0); _ = a", err: false},
{stmt: "a := ivec3(1.1); _ = a", err: false},
{stmt: "i := 1; a := ivec3(i); _ = a", err: false},
{stmt: "i := 1.0; a := ivec3(i); _ = a", err: false},
{stmt: "a := ivec3(vec3(1)); _ = a", err: false},
{stmt: "a := ivec3(vec2(1)); _ = a", err: true},
{stmt: "a := ivec3(vec4(1)); _ = a", err: true},
{stmt: "a := ivec3(ivec3(1)); _ = a", err: false},
{stmt: "a := ivec3(ivec2(1)); _ = a", err: true},
{stmt: "a := ivec3(ivec4(1)); _ = a", err: true},
{stmt: "a := ivec3(1, 1, 1); _ = a", err: false},
{stmt: "a := ivec3(1.0, 1.0, 1.0); _ = a", err: false},
{stmt: "a := ivec3(1.1, 1.1, 1.1); _ = a", err: false},
{stmt: "i := 1; a := ivec3(i, i, i); _ = a", err: false},
{stmt: "i := 1.0; a := ivec3(i, i, i); _ = a", err: false},
{stmt: "a := ivec3(vec2(1), 1); _ = a", err: false},
{stmt: "a := ivec3(1, vec2(1)); _ = a", err: false},
{stmt: "a := ivec3(ivec2(1), 1); _ = a", err: false},
{stmt: "a := ivec3(1, ivec2(1)); _ = a", err: false},
{stmt: "a := ivec3(vec3(1), 1); _ = a", err: true},
{stmt: "a := ivec3(1, vec3(1)); _ = a", err: true},
{stmt: "a := ivec3(vec3(1), vec3(1), vec3(1)); _ = a", err: true},
{stmt: "a := ivec3(1, 1, 1, 1); _ = a", err: true},
{stmt: "a := ivec4(1); _ = a", err: false},
{stmt: "a := ivec4(1.0); _ = a", err: false},
{stmt: "i := 1; a := ivec4(i); _ = a", err: false},
{stmt: "i := 1.0; a := ivec4(i); _ = a", err: false},
{stmt: "a := ivec4(vec4(1)); _ = a", err: false},
{stmt: "a := ivec4(vec2(1)); _ = a", err: true},
{stmt: "a := ivec4(vec3(1)); _ = a", err: true},
{stmt: "a := ivec4(ivec4(1)); _ = a", err: false},
{stmt: "a := ivec4(ivec2(1)); _ = a", err: true},
{stmt: "a := ivec4(ivec3(1)); _ = a", err: true},
{stmt: "a := ivec4(1, 1, 1, 1); _ = a", err: false},
{stmt: "a := ivec4(1.0, 1.0, 1.0, 1.0); _ = a", err: false},
{stmt: "a := ivec4(1.1, 1.1, 1.1, 1.1); _ = a", err: false},
{stmt: "i := 1; a := ivec4(i, i, i, i); _ = a", err: false},
{stmt: "i := 1.0; a := ivec4(i, i, i, i); _ = a", err: false},
{stmt: "a := ivec4(vec2(1), 1, 1); _ = a", err: false},
{stmt: "a := ivec4(1, vec2(1), 1); _ = a", err: false},
{stmt: "a := ivec4(1, 1, vec2(1)); _ = a", err: false},
{stmt: "a := ivec4(ivec2(1), 1, 1); _ = a", err: false},
{stmt: "a := ivec4(1, ivec2(1), 1); _ = a", err: false},
{stmt: "a := ivec4(1, 1, ivec2(1)); _ = a", err: false},
{stmt: "a := ivec4(vec2(1), vec2(1)); _ = a", err: false},
{stmt: "a := ivec4(ivec2(1), ivec2(1)); _ = a", err: false},
{stmt: "a := ivec4(vec3(1), 1); _ = a", err: false},
{stmt: "a := ivec4(1, vec3(1)); _ = a", err: false},
{stmt: "a := ivec4(ivec3(1), 1); _ = a", err: false},
{stmt: "a := ivec4(1, ivec3(1)); _ = a", err: false},
{stmt: "a := ivec4(vec4(1), 1); _ = a", err: true},
{stmt: "a := ivec4(1, vec4(1)); _ = a", err: true},
{stmt: "a := ivec4(vec4(1), vec4(1), vec4(1), vec4(1)); _ = a", err: true},
{stmt: "a := ivec4(1, 1, 1, 1, 1); _ = a", err: true},
{stmt: "a := mat2(1); _ = a", err: false}, {stmt: "a := mat2(1); _ = a", err: false},
{stmt: "a := mat2(1.0); _ = a", err: false}, {stmt: "a := mat2(1.0); _ = a", err: false},
{stmt: "i := 1; a := mat2(i); _ = a", err: false}, {stmt: "i := 1; a := mat2(i); _ = a", err: false},
{stmt: "i := 1.0; a := mat2(i); _ = a", err: false}, {stmt: "i := 1.0; a := mat2(i); _ = a", err: false},
{stmt: "a := mat2(mat2(1)); _ = a", err: false}, {stmt: "a := mat2(mat2(1)); _ = a", err: false},
{stmt: "a := mat2(vec2(1)); _ = a", err: true}, {stmt: "a := mat2(vec2(1)); _ = a", err: true},
{stmt: "a := mat2(ivec2(1)); _ = a", err: true},
{stmt: "a := mat2(mat3(1)); _ = a", err: true}, {stmt: "a := mat2(mat3(1)); _ = a", err: true},
{stmt: "a := mat2(mat4(1)); _ = a", err: true}, {stmt: "a := mat2(mat4(1)); _ = a", err: true},
{stmt: "a := mat2(vec2(1), vec2(1)); _ = a", err: false}, {stmt: "a := mat2(vec2(1), vec2(1)); _ = a", err: false},
{stmt: "a := mat2(ivec2(1), ivec2(1)); _ = a", err: false},
{stmt: "a := mat2(1, 1); _ = a", err: true}, {stmt: "a := mat2(1, 1); _ = a", err: true},
{stmt: "a := mat2(1, vec2(1)); _ = a", err: true}, {stmt: "a := mat2(1, vec2(1)); _ = a", err: true},
{stmt: "a := mat2(vec2(1), vec3(1)); _ = a", err: true}, {stmt: "a := mat2(vec2(1), vec3(1)); _ = a", err: true},
@ -1521,10 +1789,12 @@ func TestSyntaxConstructorFuncType(t *testing.T) {
{stmt: "i := 1.0; a := mat3(i); _ = a", err: false}, {stmt: "i := 1.0; a := mat3(i); _ = a", err: false},
{stmt: "a := mat3(mat3(1)); _ = a", err: false}, {stmt: "a := mat3(mat3(1)); _ = a", err: false},
{stmt: "a := mat3(vec2(1)); _ = a", err: true}, {stmt: "a := mat3(vec2(1)); _ = a", err: true},
{stmt: "a := mat3(ivec2(1)); _ = a", err: true},
{stmt: "a := mat3(mat2(1)); _ = a", err: true}, {stmt: "a := mat3(mat2(1)); _ = a", err: true},
{stmt: "a := mat3(mat4(1)); _ = a", err: true}, {stmt: "a := mat3(mat4(1)); _ = a", err: true},
{stmt: "a := mat3(vec3(1), vec3(1), vec3(1)); _ = a", err: false}, {stmt: "a := mat3(vec3(1), vec3(1), vec3(1)); _ = a", err: false},
{stmt: "a := mat3(ivec3(1), ivec3(1), ivec3(1)); _ = a", err: false},
{stmt: "a := mat3(1, 1, 1); _ = a", err: true}, {stmt: "a := mat3(1, 1, 1); _ = a", err: true},
{stmt: "a := mat3(1, 1, vec3(1)); _ = a", err: true}, {stmt: "a := mat3(1, 1, vec3(1)); _ = a", err: true},
{stmt: "a := mat3(vec3(1), vec3(1), vec4(1)); _ = a", err: true}, {stmt: "a := mat3(vec3(1), vec3(1), vec4(1)); _ = a", err: true},
@ -1547,10 +1817,12 @@ func TestSyntaxConstructorFuncType(t *testing.T) {
{stmt: "i := 1.0; a := mat4(i); _ = a", err: false}, {stmt: "i := 1.0; a := mat4(i); _ = a", err: false},
{stmt: "a := mat4(mat4(1)); _ = a", err: false}, {stmt: "a := mat4(mat4(1)); _ = a", err: false},
{stmt: "a := mat4(vec2(1)); _ = a", err: true}, {stmt: "a := mat4(vec2(1)); _ = a", err: true},
{stmt: "a := mat4(ivec2(1)); _ = a", err: true},
{stmt: "a := mat4(mat2(1)); _ = a", err: true}, {stmt: "a := mat4(mat2(1)); _ = a", err: true},
{stmt: "a := mat4(mat3(1)); _ = a", err: true}, {stmt: "a := mat4(mat3(1)); _ = a", err: true},
{stmt: "a := mat4(vec4(1), vec4(1), vec4(1), vec4(1)); _ = a", err: false}, {stmt: "a := mat4(vec4(1), vec4(1), vec4(1), vec4(1)); _ = a", err: false},
{stmt: "a := mat4(ivec4(1), ivec4(1), ivec4(1), ivec4(1)); _ = a", err: false},
{stmt: "a := mat4(1, 1, 1, 1); _ = a", err: true}, {stmt: "a := mat4(1, 1, 1, 1); _ = a", err: true},
{stmt: "a := mat4(1, 1, 1, vec4(1)); _ = a", err: true}, {stmt: "a := mat4(1, 1, 1, vec4(1)); _ = a", err: true},
{stmt: "a := mat4(vec4(1), vec4(1), vec4(1), vec2(1)); _ = a", err: true}, {stmt: "a := mat4(vec4(1), vec4(1), vec4(1), vec2(1)); _ = a", err: true},
@ -1636,6 +1908,9 @@ func TestSyntaxBuiltinFuncSingleArgType(t *testing.T) {
{stmt: "a := {{.Func}}(vec2(1)); _ = a", err: false}, {stmt: "a := {{.Func}}(vec2(1)); _ = a", err: false},
{stmt: "a := {{.Func}}(vec3(1)); _ = a", err: false}, {stmt: "a := {{.Func}}(vec3(1)); _ = a", err: false},
{stmt: "a := {{.Func}}(vec4(1)); _ = a", err: false}, {stmt: "a := {{.Func}}(vec4(1)); _ = a", err: false},
{stmt: "a := {{.Func}}(ivec2(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(ivec3(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(ivec4(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(mat2(1)); _ = a", err: true}, {stmt: "a := {{.Func}}(mat2(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(mat3(1)); _ = a", err: true}, {stmt: "a := {{.Func}}(mat3(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(mat4(1)); _ = a", err: true}, {stmt: "a := {{.Func}}(mat4(1)); _ = a", err: true},
@ -1714,6 +1989,8 @@ func TestSyntaxBuiltinFuncDoubleArgsType(t *testing.T) {
{stmt: "a := {{.Func}}(vec4(1), vec3(1)); _ = a", err: true}, {stmt: "a := {{.Func}}(vec4(1), vec3(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(vec4(1), vec4(1)); _ = a", err: false}, {stmt: "a := {{.Func}}(vec4(1), vec4(1)); _ = a", err: false},
{stmt: "a := {{.Func}}(mat2(1), mat2(1)); _ = a", err: true}, {stmt: "a := {{.Func}}(mat2(1), mat2(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(ivec2(1), 1); _ = a", err: true},
{stmt: "a := {{.Func}}(ivec2(1), ivec2(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(1, 1, 1); _ = a", err: true}, {stmt: "a := {{.Func}}(1, 1, 1); _ = a", err: true},
} }
@ -1759,6 +2036,9 @@ func TestSyntaxBuiltinFuncDoubleArgsType2(t *testing.T) {
{stmt: "a := {{.Func}}(1, vec2(1)); _ = a", err: true}, {stmt: "a := {{.Func}}(1, vec2(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(1, vec3(1)); _ = a", err: true}, {stmt: "a := {{.Func}}(1, vec3(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(1, vec4(1)); _ = a", err: true}, {stmt: "a := {{.Func}}(1, vec4(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(1, ivec2(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(1, ivec3(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(1, ivec4(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(vec2(1), 1); _ = a", err: false}, // The second argument can be a scalar. {stmt: "a := {{.Func}}(vec2(1), 1); _ = a", err: false}, // The second argument can be a scalar.
{stmt: "a := {{.Func}}(vec2(1), vec2(1)); _ = a", err: false}, {stmt: "a := {{.Func}}(vec2(1), vec2(1)); _ = a", err: false},
{stmt: "a := {{.Func}}(vec2(1), vec3(1)); _ = a", err: true}, {stmt: "a := {{.Func}}(vec2(1), vec3(1)); _ = a", err: true},
@ -1772,6 +2052,8 @@ func TestSyntaxBuiltinFuncDoubleArgsType2(t *testing.T) {
{stmt: "a := {{.Func}}(vec4(1), vec3(1)); _ = a", err: true}, {stmt: "a := {{.Func}}(vec4(1), vec3(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(vec4(1), vec4(1)); _ = a", err: false}, {stmt: "a := {{.Func}}(vec4(1), vec4(1)); _ = a", err: false},
{stmt: "a := {{.Func}}(mat2(1), mat2(1)); _ = a", err: true}, {stmt: "a := {{.Func}}(mat2(1), mat2(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(ivec2(1), 1); _ = a", err: true},
{stmt: "a := {{.Func}}(ivec2(1), ivec2(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(1, 1, 1); _ = a", err: true}, {stmt: "a := {{.Func}}(1, 1, 1); _ = a", err: true},
} }
@ -1815,6 +2097,9 @@ func TestSyntaxBuiltinFuncStepType(t *testing.T) {
{stmt: "a := step(1, vec2(1)); _ = a", err: false}, // The first argument can be a scalar. {stmt: "a := step(1, vec2(1)); _ = a", err: false}, // The first argument can be a scalar.
{stmt: "a := step(1, vec3(1)); _ = a", err: false}, // The first argument can be a scalar. {stmt: "a := step(1, vec3(1)); _ = a", err: false}, // The first argument can be a scalar.
{stmt: "a := step(1, vec4(1)); _ = a", err: false}, // The first argument can be a scalar. {stmt: "a := step(1, vec4(1)); _ = a", err: false}, // The first argument can be a scalar.
{stmt: "a := step(1, ivec2(1)); _ = a", err: true},
{stmt: "a := step(1, ivec3(1)); _ = a", err: true},
{stmt: "a := step(1, ivec4(1)); _ = a", err: true},
{stmt: "a := step(vec2(1), 1); _ = a", err: true}, {stmt: "a := step(vec2(1), 1); _ = a", err: true},
{stmt: "a := step(vec2(1), vec2(1)); _ = a", err: false}, {stmt: "a := step(vec2(1), vec2(1)); _ = a", err: false},
{stmt: "a := step(vec2(1), vec3(1)); _ = a", err: true}, {stmt: "a := step(vec2(1), vec3(1)); _ = a", err: true},
@ -1828,6 +2113,7 @@ func TestSyntaxBuiltinFuncStepType(t *testing.T) {
{stmt: "a := step(vec4(1), vec3(1)); _ = a", err: true}, {stmt: "a := step(vec4(1), vec3(1)); _ = a", err: true},
{stmt: "a := step(vec4(1), vec4(1)); _ = a", err: false}, {stmt: "a := step(vec4(1), vec4(1)); _ = a", err: false},
{stmt: "a := step(mat2(1), mat2(1)); _ = a", err: true}, {stmt: "a := step(mat2(1), mat2(1)); _ = a", err: true},
{stmt: "a := step(ivec2(1), ivec2(1)); _ = a", err: true},
{stmt: "a := step(1, 1, 1); _ = a", err: true}, {stmt: "a := step(1, 1, 1); _ = a", err: true},
} }
@ -1879,7 +2165,7 @@ func TestSyntaxBuiltinFuncTripleArgsType(t *testing.T) {
{stmt: "a := {{.Func}}(vec4(1), 1, vec4(1)); _ = a", err: true}, {stmt: "a := {{.Func}}(vec4(1), 1, vec4(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(vec4(1), vec4(1), 1); _ = a", err: true}, {stmt: "a := {{.Func}}(vec4(1), vec4(1), 1); _ = a", err: true},
{stmt: "a := {{.Func}}(vec4(1), vec4(1), vec4(1)); _ = a", err: false}, {stmt: "a := {{.Func}}(vec4(1), vec4(1), vec4(1)); _ = a", err: false},
{stmt: "a := {{.Func}}(1, 1, 1, 1); _ = a", err: true}, {stmt: "a := {{.Func}}(ivec2(1), ivec2(1), ivec2(1)); _ = a", err: true},
} }
funcs := []string{ funcs := []string{
@ -1935,6 +2221,7 @@ func TestSyntaxBuiltinFuncClampType(t *testing.T) {
{stmt: "a := clamp(vec4(1), 1, vec4(1)); _ = a", err: true}, {stmt: "a := clamp(vec4(1), 1, vec4(1)); _ = a", err: true},
{stmt: "a := clamp(vec4(1), vec4(1), 1); _ = a", err: true}, {stmt: "a := clamp(vec4(1), vec4(1), 1); _ = a", err: true},
{stmt: "a := clamp(vec4(1), vec4(1), vec4(1)); _ = a", err: false}, {stmt: "a := clamp(vec4(1), vec4(1), vec4(1)); _ = a", err: false},
{stmt: "a := clamp(ivec2(1), 1, 1); _ = a", err: true},
{stmt: "a := clamp(1, 1, 1, 1); _ = a", err: true}, {stmt: "a := clamp(1, 1, 1, 1); _ = a", err: true},
} }
@ -1986,6 +2273,8 @@ func TestSyntaxBuiltinFuncMixType(t *testing.T) {
{stmt: "a := mix(vec4(1), 1, vec4(1)); _ = a", err: true}, {stmt: "a := mix(vec4(1), 1, vec4(1)); _ = a", err: true},
{stmt: "a := mix(vec4(1), vec4(1), 1); _ = a", err: false}, // The thrid argument can be a float. {stmt: "a := mix(vec4(1), vec4(1), 1); _ = a", err: false}, // The thrid argument can be a float.
{stmt: "a := mix(vec4(1), vec4(1), vec4(1)); _ = a", err: false}, {stmt: "a := mix(vec4(1), vec4(1), vec4(1)); _ = a", err: false},
{stmt: "a := mix(ivec2(1), ivec2(1), 1); _ = a", err: true},
{stmt: "a := mix(ivec2(1), ivec2(1), ivec2(1)); _ = a", err: true},
{stmt: "a := mix(1, 1, 1, 1); _ = a", err: true}, {stmt: "a := mix(1, 1, 1, 1); _ = a", err: true},
} }
@ -2039,6 +2328,9 @@ func TestSyntaxBuiltinFuncSmoothstepType(t *testing.T) {
{stmt: "a := smoothstep(vec4(1), 1, vec4(1)); _ = a", err: true}, {stmt: "a := smoothstep(vec4(1), 1, vec4(1)); _ = a", err: true},
{stmt: "a := smoothstep(vec4(1), vec4(1), 1); _ = a", err: true}, {stmt: "a := smoothstep(vec4(1), vec4(1), 1); _ = a", err: true},
{stmt: "a := smoothstep(vec4(1), vec4(1), vec4(1)); _ = a", err: false}, {stmt: "a := smoothstep(vec4(1), vec4(1), vec4(1)); _ = a", err: false},
{stmt: "a := smoothstep(ivec2(1), 1, 1); _ = a", err: true},
{stmt: "a := smoothstep(1, ivec2(1), 1); _ = a", err: true},
{stmt: "a := smoothstep(1, 1, ivec2(1)); _ = a", err: true},
{stmt: "a := smoothstep(1, 1, 1, 1); _ = a", err: true}, {stmt: "a := smoothstep(1, 1, 1, 1); _ = a", err: true},
} }
@ -2090,6 +2382,7 @@ func TestSyntaxBuiltinFuncRefractType(t *testing.T) {
{stmt: "a := refract(vec4(1), 1, vec4(1)); _ = a", err: true}, {stmt: "a := refract(vec4(1), 1, vec4(1)); _ = a", err: true},
{stmt: "a := refract(vec4(1), vec4(1), 1); _ = a", err: false}, // The third argument must be a float. {stmt: "a := refract(vec4(1), vec4(1), 1); _ = a", err: false}, // The third argument must be a float.
{stmt: "a := refract(vec4(1), vec4(1), vec4(1)); _ = a", err: true}, {stmt: "a := refract(vec4(1), vec4(1), vec4(1)); _ = a", err: true},
{stmt: "a := refract(ivec2(1), ivec2(1), 1); _ = a", err: true},
{stmt: "a := refract(1, 1, 1, 1); _ = a", err: true}, {stmt: "a := refract(1, 1, 1, 1); _ = a", err: true},
} }
@ -2139,6 +2432,7 @@ func TestSyntaxBuiltinFuncCrossType(t *testing.T) {
{stmt: "a := cross(vec4(1), vec3(1)); _ = a", err: true}, {stmt: "a := cross(vec4(1), vec3(1)); _ = a", err: true},
{stmt: "a := cross(vec4(1), vec4(1)); _ = a", err: true}, {stmt: "a := cross(vec4(1), vec4(1)); _ = a", err: true},
{stmt: "a := cross(mat2(1), mat2(1)); _ = a", err: true}, {stmt: "a := cross(mat2(1), mat2(1)); _ = a", err: true},
{stmt: "a := cross(ivec3(1), ivec3(1)); _ = a", err: true},
{stmt: "a := cross(1, 1, 1); _ = a", err: true}, {stmt: "a := cross(1, 1, 1); _ = a", err: true},
} }
@ -2173,6 +2467,9 @@ func TestSyntaxBuiltinFuncTransposeType(t *testing.T) {
{stmt: "a := transpose(vec2(1)); _ = a", err: true}, {stmt: "a := transpose(vec2(1)); _ = a", err: true},
{stmt: "a := transpose(vec3(1)); _ = a", err: true}, {stmt: "a := transpose(vec3(1)); _ = a", err: true},
{stmt: "a := transpose(vec4(1)); _ = a", err: true}, {stmt: "a := transpose(vec4(1)); _ = a", err: true},
{stmt: "a := transpose(ivec2(1)); _ = a", err: true},
{stmt: "a := transpose(ivec3(1)); _ = a", err: true},
{stmt: "a := transpose(ivec4(1)); _ = a", err: true},
{stmt: "a := transpose(mat2(1)); _ = a", err: false}, {stmt: "a := transpose(mat2(1)); _ = a", err: false},
{stmt: "a := transpose(mat3(1)); _ = a", err: false}, {stmt: "a := transpose(mat3(1)); _ = a", err: false},
{stmt: "a := transpose(mat4(1)); _ = a", err: false}, {stmt: "a := transpose(mat4(1)); _ = a", err: false},
@ -2220,6 +2517,8 @@ func TestSyntaxEqual(t *testing.T) {
{stmt: "a, b := false, 1.1; _ = a != b", err: true}, {stmt: "a, b := false, 1.1; _ = a != b", err: true},
{stmt: "a, b := false, vec2(1); _ = a == b", err: true}, {stmt: "a, b := false, vec2(1); _ = a == b", err: true},
{stmt: "a, b := false, vec2(1); _ = a != b", err: true}, {stmt: "a, b := false, vec2(1); _ = a != b", err: true},
{stmt: "a, b := false, ivec2(1); _ = a == b", err: true},
{stmt: "a, b := false, ivec2(1); _ = a != b", err: true},
{stmt: "a, b := false, mat2(1); _ = a == b", err: true}, {stmt: "a, b := false, mat2(1); _ = a == b", err: true},
{stmt: "a, b := false, mat2(1); _ = a != b", err: true}, {stmt: "a, b := false, mat2(1); _ = a != b", err: true},
@ -2241,6 +2540,8 @@ func TestSyntaxEqual(t *testing.T) {
{stmt: "a, b := 1, 1.1; _ = a != b", err: true}, {stmt: "a, b := 1, 1.1; _ = a != b", err: true},
{stmt: "a, b := 1, vec2(1); _ = a == b", err: true}, {stmt: "a, b := 1, vec2(1); _ = a == b", err: true},
{stmt: "a, b := 1, vec2(1); _ = a != b", err: true}, {stmt: "a, b := 1, vec2(1); _ = a != b", err: true},
{stmt: "a, b := 1, ivec2(1); _ = a == b", err: true},
{stmt: "a, b := 1, ivec2(1); _ = a != b", err: true},
{stmt: "a, b := 1, mat2(1); _ = a == b", err: true}, {stmt: "a, b := 1, mat2(1); _ = a == b", err: true},
{stmt: "a, b := 1, mat2(1); _ = a != b", err: true}, {stmt: "a, b := 1, mat2(1); _ = a != b", err: true},
@ -2262,6 +2563,8 @@ func TestSyntaxEqual(t *testing.T) {
{stmt: "a, b := 1.0, 1.1; _ = a != b", err: false}, {stmt: "a, b := 1.0, 1.1; _ = a != b", err: false},
{stmt: "a, b := 1.0, vec2(1); _ = a == b", err: true}, {stmt: "a, b := 1.0, vec2(1); _ = a == b", err: true},
{stmt: "a, b := 1.0, vec2(1); _ = a != b", err: true}, {stmt: "a, b := 1.0, vec2(1); _ = a != b", err: true},
{stmt: "a, b := 1.0, ivec2(1); _ = a == b", err: true},
{stmt: "a, b := 1.0, ivec2(1); _ = a != b", err: true},
{stmt: "a, b := 1.0, mat2(1); _ = a == b", err: true}, {stmt: "a, b := 1.0, mat2(1); _ = a == b", err: true},
{stmt: "a, b := 1.0, mat2(1); _ = a != b", err: true}, {stmt: "a, b := 1.0, mat2(1); _ = a != b", err: true},
@ -2283,6 +2586,8 @@ func TestSyntaxEqual(t *testing.T) {
{stmt: "a, b := 1.1, 1.1; _ = a != b", err: false}, {stmt: "a, b := 1.1, 1.1; _ = a != b", err: false},
{stmt: "a, b := 1.1, vec2(1); _ = a == b", err: true}, {stmt: "a, b := 1.1, vec2(1); _ = a == b", err: true},
{stmt: "a, b := 1.1, vec2(1); _ = a != b", err: true}, {stmt: "a, b := 1.1, vec2(1); _ = a != b", err: true},
{stmt: "a, b := 1.1, ivec2(1); _ = a == b", err: true},
{stmt: "a, b := 1.1, ivec2(1); _ = a != b", err: true},
{stmt: "a, b := 1.1, mat2(1); _ = a == b", err: true}, {stmt: "a, b := 1.1, mat2(1); _ = a == b", err: true},
{stmt: "a, b := 1.1, mat2(1); _ = a != b", err: true}, {stmt: "a, b := 1.1, mat2(1); _ = a != b", err: true},
@ -2304,9 +2609,34 @@ func TestSyntaxEqual(t *testing.T) {
{stmt: "a, b := vec2(1), 1.1; _ = a != b", err: true}, {stmt: "a, b := vec2(1), 1.1; _ = a != b", err: true},
{stmt: "a, b := vec2(1), vec2(1); _ = a == b", err: false}, {stmt: "a, b := vec2(1), vec2(1); _ = a == b", err: false},
{stmt: "a, b := vec2(1), vec2(1); _ = a != b", err: false}, {stmt: "a, b := vec2(1), vec2(1); _ = a != b", err: false},
{stmt: "a, b := vec2(1), ivec2(1); _ = a == b", err: true},
{stmt: "a, b := vec2(1), ivec2(1); _ = a != b", err: true},
{stmt: "a, b := vec2(1), mat2(1); _ = a == b", err: true}, {stmt: "a, b := vec2(1), mat2(1); _ = a == b", err: true},
{stmt: "a, b := vec2(1), mat2(1); _ = a != b", err: true}, {stmt: "a, b := vec2(1), mat2(1); _ = a != b", err: true},
{stmt: "_ = ivec2(1) == true", err: true},
{stmt: "_ = ivec2(1) != true", err: true},
{stmt: "_ = ivec2(1) == 1", err: true},
{stmt: "_ = ivec2(1) != 1", err: true},
{stmt: "_ = ivec2(1) == 1.0", err: true},
{stmt: "_ = ivec2(1) != 1.0", err: true},
{stmt: "_ = ivec2(1) == 1.1", err: true},
{stmt: "_ = ivec2(1) != 1.1", err: true},
{stmt: "a, b := ivec2(1), true; _ = a == b", err: true},
{stmt: "a, b := ivec2(1), true; _ = a != b", err: true},
{stmt: "a, b := ivec2(1), 1; _ = a == b", err: true},
{stmt: "a, b := ivec2(1), 1; _ = a != b", err: true},
{stmt: "a, b := ivec2(1), 1.0; _ = a == b", err: true},
{stmt: "a, b := ivec2(1), 1.0; _ = a != b", err: true},
{stmt: "a, b := ivec2(1), 1.1; _ = a == b", err: true},
{stmt: "a, b := ivec2(1), 1.1; _ = a != b", err: true},
{stmt: "a, b := ivec2(1), vec2(1); _ = a == b", err: true},
{stmt: "a, b := ivec2(1), vec2(1); _ = a != b", err: true},
{stmt: "a, b := ivec2(1), ivec2(1); _ = a == b", err: false},
{stmt: "a, b := ivec2(1), ivec2(1); _ = a != b", err: false},
{stmt: "a, b := ivec2(1), mat2(1); _ = a == b", err: true},
{stmt: "a, b := ivec2(1), mat2(1); _ = a != b", err: true},
{stmt: "_ = mat2(1) == true", err: true}, {stmt: "_ = mat2(1) == true", err: true},
{stmt: "_ = mat2(1) != true", err: true}, {stmt: "_ = mat2(1) != true", err: true},
{stmt: "_ = mat2(1) == 1", err: true}, {stmt: "_ = mat2(1) == 1", err: true},
@ -2325,6 +2655,8 @@ func TestSyntaxEqual(t *testing.T) {
{stmt: "a, b := mat2(1), 1.1; _ = a != b", err: true}, {stmt: "a, b := mat2(1), 1.1; _ = a != b", err: true},
{stmt: "a, b := mat2(1), vec2(1); _ = a == b", err: true}, {stmt: "a, b := mat2(1), vec2(1); _ = a == b", err: true},
{stmt: "a, b := mat2(1), vec2(1); _ = a != b", err: true}, {stmt: "a, b := mat2(1), vec2(1); _ = a != b", err: true},
{stmt: "a, b := mat2(1), ivec2(1); _ = a == b", err: true},
{stmt: "a, b := mat2(1), ivec2(1); _ = a != b", err: true},
{stmt: "a, b := mat2(1), mat2(1); _ = a == b", err: true}, // Comparing matrices are not allowed. {stmt: "a, b := mat2(1), mat2(1); _ = a == b", err: true}, // Comparing matrices are not allowed.
{stmt: "a, b := mat2(1), mat2(1); _ = a != b", err: true}, // Comparing matrices are not allowed. {stmt: "a, b := mat2(1), mat2(1); _ = a != b", err: true}, // Comparing matrices are not allowed.
@ -2346,6 +2678,8 @@ func TestSyntaxEqual(t *testing.T) {
{stmt: "a, b := false, 1.1; _ = a || b", err: true}, {stmt: "a, b := false, 1.1; _ = a || b", err: true},
{stmt: "a, b := false, vec2(1); _ = a && b", err: true}, {stmt: "a, b := false, vec2(1); _ = a && b", err: true},
{stmt: "a, b := false, vec2(1); _ = a || b", err: true}, {stmt: "a, b := false, vec2(1); _ = a || b", err: true},
{stmt: "a, b := false, ivec2(1); _ = a && b", err: true},
{stmt: "a, b := false, ivec2(1); _ = a || b", err: true},
{stmt: "a, b := false, mat2(1); _ = a && b", err: true}, {stmt: "a, b := false, mat2(1); _ = a && b", err: true},
{stmt: "a, b := false, mat2(1); _ = a || b", err: true}, {stmt: "a, b := false, mat2(1); _ = a || b", err: true},
@ -2367,6 +2701,8 @@ func TestSyntaxEqual(t *testing.T) {
{stmt: "a, b := 1.0, 1.1; _ = a || b", err: true}, {stmt: "a, b := 1.0, 1.1; _ = a || b", err: true},
{stmt: "a, b := 1.0, vec2(1); _ = a && b", err: true}, {stmt: "a, b := 1.0, vec2(1); _ = a && b", err: true},
{stmt: "a, b := 1.0, vec2(1); _ = a || b", err: true}, {stmt: "a, b := 1.0, vec2(1); _ = a || b", err: true},
{stmt: "a, b := 1.0, ivec2(1); _ = a && b", err: true},
{stmt: "a, b := 1.0, ivec2(1); _ = a || b", err: true},
{stmt: "a, b := 1.0, mat2(1); _ = a && b", err: true}, {stmt: "a, b := 1.0, mat2(1); _ = a && b", err: true},
{stmt: "a, b := 1.0, mat2(1); _ = a || b", err: true}, {stmt: "a, b := 1.0, mat2(1); _ = a || b", err: true},
} }
@ -2453,6 +2789,39 @@ func TestSwizzling(t *testing.T) {
{stmt: "var a vec4; var b vec3 = a.xyy; _ = b", err: false}, {stmt: "var a vec4; var b vec3 = a.xyy; _ = b", err: false},
{stmt: "var a vec4; var b vec3 = a.xyz; _ = b", err: false}, {stmt: "var a vec4; var b vec3 = a.xyz; _ = b", err: false},
{stmt: "var a vec4; var b vec4 = a.xyzw; _ = b", err: false}, {stmt: "var a vec4; var b vec4 = a.xyzw; _ = b", err: false},
{stmt: "var a ivec2; var b int = a.x; _ = b", err: false},
{stmt: "var a ivec2; var b int = a.y; _ = b", err: false},
{stmt: "var a ivec2; var b int = a.z; _ = b", err: true},
{stmt: "var a ivec2; var b int = a.w; _ = b", err: true},
{stmt: "var a ivec2; var b ivec2 = a.xy; _ = b", err: false},
{stmt: "var a ivec2; var b ivec3 = a.xyz; _ = b", err: true},
{stmt: "var a ivec2; var b ivec3 = a.xyw; _ = b", err: true},
{stmt: "var a ivec2; var b ivec3 = a.xyy; _ = b", err: false},
{stmt: "var a ivec2; var b ivec3 = a.xyz; _ = b", err: true},
{stmt: "var a ivec2; var b ivec4 = a.xyzw; _ = b", err: true},
{stmt: "var a ivec3; var b int = a.x; _ = b", err: false},
{stmt: "var a ivec3; var b int = a.y; _ = b", err: false},
{stmt: "var a ivec3; var b int = a.z; _ = b", err: false},
{stmt: "var a ivec3; var b int = a.w; _ = b", err: true},
{stmt: "var a ivec3; var b ivec2 = a.xy; _ = b", err: false},
{stmt: "var a ivec3; var b ivec3 = a.xyz; _ = b", err: false},
{stmt: "var a ivec3; var b ivec3 = a.xyw; _ = b", err: true},
{stmt: "var a ivec3; var b ivec3 = a.xyy; _ = b", err: false},
{stmt: "var a ivec3; var b ivec3 = a.xyz; _ = b", err: false},
{stmt: "var a ivec3; var b ivec4 = a.xyzw; _ = b", err: true},
{stmt: "var a ivec4; var b int = a.x; _ = b", err: false},
{stmt: "var a ivec4; var b int = a.y; _ = b", err: false},
{stmt: "var a ivec4; var b int = a.z; _ = b", err: false},
{stmt: "var a ivec4; var b int = a.w; _ = b", err: false},
{stmt: "var a ivec4; var b ivec2 = a.xy; _ = b", err: false},
{stmt: "var a ivec4; var b ivec3 = a.xyz; _ = b", err: false},
{stmt: "var a ivec4; var b ivec3 = a.xyw; _ = b", err: false},
{stmt: "var a ivec4; var b ivec3 = a.xyy; _ = b", err: false},
{stmt: "var a ivec4; var b ivec3 = a.xyz; _ = b", err: false},
{stmt: "var a ivec4; var b ivec4 = a.xyzw; _ = b", err: false},
} }
for _, c := range cases { for _, c := range cases {
@ -2482,84 +2851,105 @@ func TestConstType(t *testing.T) {
{stmt: "const a int = false", err: true}, {stmt: "const a int = false", err: true},
{stmt: "const a float = false", err: true}, {stmt: "const a float = false", err: true},
{stmt: "const a vec2 = false", err: true}, {stmt: "const a vec2 = false", err: true},
{stmt: "const a ivec2 = false", err: true},
{stmt: "const a = bool(false)", err: false}, {stmt: "const a = bool(false)", err: false},
{stmt: "const a bool = bool(false)", err: false}, {stmt: "const a bool = bool(false)", err: false},
{stmt: "const a int = bool(false)", err: true}, {stmt: "const a int = bool(false)", err: true},
{stmt: "const a float = bool(false)", err: true}, {stmt: "const a float = bool(false)", err: true},
{stmt: "const a vec2 = bool(false)", err: true}, {stmt: "const a vec2 = bool(false)", err: true},
{stmt: "const a ivec2 = bool(false)", err: true},
{stmt: "const a = int(false)", err: true}, {stmt: "const a = int(false)", err: true},
{stmt: "const a bool = int(false)", err: true}, {stmt: "const a bool = int(false)", err: true},
{stmt: "const a int = int(false)", err: true}, {stmt: "const a int = int(false)", err: true},
{stmt: "const a float = int(false)", err: true}, {stmt: "const a float = int(false)", err: true},
{stmt: "const a vec2 = int(false)", err: true}, {stmt: "const a vec2 = int(false)", err: true},
{stmt: "const a ivec2 = int(false)", err: true},
{stmt: "const a = float(false)", err: true}, {stmt: "const a = float(false)", err: true},
{stmt: "const a bool = float(false)", err: true}, {stmt: "const a bool = float(false)", err: true},
{stmt: "const a int = float(false)", err: true}, {stmt: "const a int = float(false)", err: true},
{stmt: "const a float = float(false)", err: true}, {stmt: "const a float = float(false)", err: true},
{stmt: "const a vec2 = float(false)", err: true}, {stmt: "const a vec2 = float(false)", err: true},
{stmt: "const a ivec2 = float(false)", err: true},
{stmt: "const a = 1", err: false}, {stmt: "const a = 1", err: false},
{stmt: "const a bool = 1", err: true}, {stmt: "const a bool = 1", err: true},
{stmt: "const a int = 1", err: false}, {stmt: "const a int = 1", err: false},
{stmt: "const a float = 1", err: false}, {stmt: "const a float = 1", err: false},
{stmt: "const a vec2 = 1", err: true}, {stmt: "const a vec2 = 1", err: true},
{stmt: "const a ivec2 = 1", err: true},
{stmt: "const a = int(1)", err: false}, {stmt: "const a = int(1)", err: false},
{stmt: "const a bool = int(1)", err: true}, {stmt: "const a bool = int(1)", err: true},
{stmt: "const a int = int(1)", err: false}, {stmt: "const a int = int(1)", err: false},
{stmt: "const a float = int(1)", err: true}, {stmt: "const a float = int(1)", err: true},
{stmt: "const a vec2 = int(1)", err: true}, {stmt: "const a vec2 = int(1)", err: true},
{stmt: "const a ivec2 = int(1)", err: true},
{stmt: "const a = float(1)", err: false}, {stmt: "const a = float(1)", err: false},
{stmt: "const a bool = float(1)", err: true}, {stmt: "const a bool = float(1)", err: true},
{stmt: "const a int = float(1)", err: true}, {stmt: "const a int = float(1)", err: true},
{stmt: "const a float = float(1)", err: false}, {stmt: "const a float = float(1)", err: false},
{stmt: "const a vec2 = float(1)", err: true}, {stmt: "const a vec2 = float(1)", err: true},
{stmt: "const a ivec2 = float(1)", err: true},
{stmt: "const a = 1.0", err: false}, {stmt: "const a = 1.0", err: false},
{stmt: "const a bool = 1.0", err: true}, {stmt: "const a bool = 1.0", err: true},
{stmt: "const a int = 1.0", err: false}, {stmt: "const a int = 1.0", err: false},
{stmt: "const a float = 1.0", err: false}, {stmt: "const a float = 1.0", err: false},
{stmt: "const a vec2 = 1.0", err: true}, {stmt: "const a vec2 = 1.0", err: true},
{stmt: "const a ivec2 = 1.0", err: true},
{stmt: "const a = int(1.0)", err: false}, {stmt: "const a = int(1.0)", err: false},
{stmt: "const a bool = int(1.0)", err: true}, {stmt: "const a bool = int(1.0)", err: true},
{stmt: "const a int = int(1.0)", err: false}, {stmt: "const a int = int(1.0)", err: false},
{stmt: "const a float = int(1.0)", err: true}, {stmt: "const a float = int(1.0)", err: true},
{stmt: "const a vec2 = int(1.0)", err: true}, {stmt: "const a vec2 = int(1.0)", err: true},
{stmt: "const a ivec2 = int(1.0)", err: true},
{stmt: "const a = float(1.0)", err: false}, {stmt: "const a = float(1.0)", err: false},
{stmt: "const a bool = float(1.0)", err: true}, {stmt: "const a bool = float(1.0)", err: true},
{stmt: "const a int = float(1.0)", err: true}, {stmt: "const a int = float(1.0)", err: true},
{stmt: "const a float = float(1.0)", err: false}, {stmt: "const a float = float(1.0)", err: false},
{stmt: "const a vec2 = float(1.0)", err: true}, {stmt: "const a vec2 = float(1.0)", err: true},
{stmt: "const a ivec2 = float(1.0)", err: true},
{stmt: "const a = 1.1", err: false}, {stmt: "const a = 1.1", err: false},
{stmt: "const a bool = 1.1", err: true}, {stmt: "const a bool = 1.1", err: true},
{stmt: "const a int = 1.1", err: true}, {stmt: "const a int = 1.1", err: true},
{stmt: "const a float = 1.1", err: false}, {stmt: "const a float = 1.1", err: false},
{stmt: "const a vec2 = 1.1", err: true}, {stmt: "const a vec2 = 1.1", err: true},
{stmt: "const a ivec2 = 1.1", err: true},
{stmt: "const a = int(1.1)", err: true}, {stmt: "const a = int(1.1)", err: true},
{stmt: "const a bool = int(1.1)", err: true}, {stmt: "const a bool = int(1.1)", err: true},
{stmt: "const a int = int(1.1)", err: true}, {stmt: "const a int = int(1.1)", err: true},
{stmt: "const a float = int(1.1)", err: true}, {stmt: "const a float = int(1.1)", err: true},
{stmt: "const a vec2 = int(1.1)", err: true}, {stmt: "const a vec2 = int(1.1)", err: true},
{stmt: "const a ivec2 = int(1.1)", err: true},
{stmt: "const a = float(1.1)", err: false}, {stmt: "const a = float(1.1)", err: false},
{stmt: "const a bool = float(1.1)", err: true}, {stmt: "const a bool = float(1.1)", err: true},
{stmt: "const a int = float(1.1)", err: true}, {stmt: "const a int = float(1.1)", err: true},
{stmt: "const a float = float(1.1)", err: false}, {stmt: "const a float = float(1.1)", err: false},
{stmt: "const a vec2 = float(1.1)", err: true}, {stmt: "const a vec2 = float(1.1)", err: true},
{stmt: "const a ivec2 = float(1.1)", err: true},
{stmt: "const a = vec2(0)", err: true}, {stmt: "const a = vec2(0)", err: true},
{stmt: "const a bool = vec2(0)", err: true}, {stmt: "const a bool = vec2(0)", err: true},
{stmt: "const a int = vec2(0)", err: true}, {stmt: "const a int = vec2(0)", err: true},
{stmt: "const a float = vec2(0)", err: true}, {stmt: "const a float = vec2(0)", err: true},
{stmt: "const a vec2 = vec2(0)", err: true}, {stmt: "const a vec2 = vec2(0)", err: true},
{stmt: "const a ivec2 = vec2(0)", err: true},
{stmt: "const a = ivec2(0)", err: true},
{stmt: "const a bool = ivec2(0)", err: true},
{stmt: "const a int = ivec2(0)", err: true},
{stmt: "const a float = ivec2(0)", err: true},
{stmt: "const a vec2 = ivec2(0)", err: true},
{stmt: "const a ivec2 = ivec2(0)", err: true},
} }
for _, c := range cases { for _, c := range cases {

View File

@ -39,6 +39,12 @@ func (cs *compileState) parseType(block *block, fname string, expr ast.Expr) (sh
return shaderir.Type{Main: shaderir.Vec3}, true return shaderir.Type{Main: shaderir.Vec3}, true
case "vec4": case "vec4":
return shaderir.Type{Main: shaderir.Vec4}, true return shaderir.Type{Main: shaderir.Vec4}, true
case "ivec2":
return shaderir.Type{Main: shaderir.IVec2}, true
case "ivec3":
return shaderir.Type{Main: shaderir.IVec3}, true
case "ivec4":
return shaderir.Type{Main: shaderir.IVec4}, true
case "mat2": case "mat2":
return shaderir.Type{Main: shaderir.Mat2}, true return shaderir.Type{Main: shaderir.Mat2}, true
case "mat3": case "mat3":
@ -177,7 +183,7 @@ func checkArgsForVec2BuiltinFunc(args []shaderir.Expr, argts []shaderir.Type) er
if canBeFloatImplicitly(args[0], argts[0]) { if canBeFloatImplicitly(args[0], argts[0]) {
return nil return nil
} }
if argts[0].Main == shaderir.Vec2 { if argts[0].IsVector() && argts[0].VectorElementCount() == 2 {
return nil return nil
} }
case 2: case 2:
@ -205,14 +211,14 @@ func checkArgsForVec3BuiltinFunc(args []shaderir.Expr, argts []shaderir.Type) er
if canBeFloatImplicitly(args[0], argts[0]) { if canBeFloatImplicitly(args[0], argts[0]) {
return nil return nil
} }
if argts[0].Main == shaderir.Vec3 { if argts[0].IsVector() && argts[0].VectorElementCount() == 3 {
return nil return nil
} }
case 2: case 2:
if canBeFloatImplicitly(args[0], argts[0]) && argts[1].Main == shaderir.Vec2 { if canBeFloatImplicitly(args[0], argts[0]) && argts[1].IsVector() && argts[1].VectorElementCount() == 2 {
return nil return nil
} }
if argts[0].Main == shaderir.Vec2 && canBeFloatImplicitly(args[1], argts[1]) { if argts[0].IsVector() && argts[0].VectorElementCount() == 2 && canBeFloatImplicitly(args[1], argts[1]) {
return nil return nil
} }
case 3: case 3:
@ -240,27 +246,27 @@ func checkArgsForVec4BuiltinFunc(args []shaderir.Expr, argts []shaderir.Type) er
if canBeFloatImplicitly(args[0], argts[0]) { if canBeFloatImplicitly(args[0], argts[0]) {
return nil return nil
} }
if argts[0].Main == shaderir.Vec4 { if argts[0].IsVector() && argts[0].VectorElementCount() == 4 {
return nil return nil
} }
case 2: case 2:
if canBeFloatImplicitly(args[0], argts[0]) && argts[1].Main == shaderir.Vec3 { if canBeFloatImplicitly(args[0], argts[0]) && argts[1].IsVector() && argts[1].VectorElementCount() == 3 {
return nil return nil
} }
if argts[0].Main == shaderir.Vec2 && argts[1].Main == shaderir.Vec2 { if argts[0].IsVector() && argts[0].VectorElementCount() == 2 && argts[1].IsVector() && argts[1].VectorElementCount() == 2 {
return nil return nil
} }
if argts[0].Main == shaderir.Vec3 && canBeFloatImplicitly(args[1], argts[1]) { if argts[0].IsVector() && argts[0].VectorElementCount() == 3 && canBeFloatImplicitly(args[1], argts[1]) {
return nil return nil
} }
case 3: case 3:
if canBeFloatImplicitly(args[0], argts[0]) && canBeFloatImplicitly(args[1], argts[1]) && argts[2].Main == shaderir.Vec2 { if canBeFloatImplicitly(args[0], argts[0]) && canBeFloatImplicitly(args[1], argts[1]) && argts[2].IsVector() && argts[2].VectorElementCount() == 2 {
return nil return nil
} }
if canBeFloatImplicitly(args[0], argts[0]) && argts[1].Main == shaderir.Vec2 && canBeFloatImplicitly(args[2], argts[2]) { if canBeFloatImplicitly(args[0], argts[0]) && argts[1].IsVector() && argts[1].VectorElementCount() == 2 && canBeFloatImplicitly(args[2], argts[2]) {
return nil return nil
} }
if argts[0].Main == shaderir.Vec2 && canBeFloatImplicitly(args[1], argts[1]) && canBeFloatImplicitly(args[2], argts[2]) { if argts[0].IsVector() && argts[0].VectorElementCount() == 2 && canBeFloatImplicitly(args[1], argts[1]) && canBeFloatImplicitly(args[2], argts[2]) {
return nil return nil
} }
case 4: case 4:
@ -292,7 +298,7 @@ func checkArgsForMat2BuiltinFunc(args []shaderir.Expr, argts []shaderir.Type) er
return nil return nil
} }
case 2: case 2:
if argts[0].Main == shaderir.Vec2 && argts[1].Main == shaderir.Vec2 { if argts[0].IsVector() && argts[0].VectorElementCount() == 2 && argts[1].IsVector() && argts[1].VectorElementCount() == 2 {
return nil return nil
} }
case 4: case 4:
@ -331,7 +337,9 @@ func checkArgsForMat3BuiltinFunc(args []shaderir.Expr, argts []shaderir.Type) er
return nil return nil
} }
case 3: case 3:
if argts[0].Main == shaderir.Vec3 && argts[1].Main == shaderir.Vec3 && argts[2].Main == shaderir.Vec3 { if argts[0].IsVector() && argts[0].VectorElementCount() == 3 &&
argts[1].IsVector() && argts[1].VectorElementCount() == 3 &&
argts[2].IsVector() && argts[2].VectorElementCount() == 3 {
return nil return nil
} }
case 9: case 9:
@ -370,7 +378,10 @@ func checkArgsForMat4BuiltinFunc(args []shaderir.Expr, argts []shaderir.Type) er
return nil return nil
} }
case 4: case 4:
if argts[0].Main == shaderir.Vec4 && argts[1].Main == shaderir.Vec4 && argts[2].Main == shaderir.Vec4 && argts[3].Main == shaderir.Vec4 { if argts[0].IsVector() && argts[0].VectorElementCount() == 4 &&
argts[1].IsVector() && argts[1].VectorElementCount() == 4 &&
argts[2].IsVector() && argts[2].VectorElementCount() == 4 &&
argts[3].IsVector() && argts[3].VectorElementCount() == 4 {
return nil return nil
} }
case 16: case 16:

View File

@ -164,7 +164,7 @@ func Compile(p *shaderir.Program, version GLSLVersion) (vertexShader, fragmentSh
} }
str := fmt.Sprintf("U%d[%d]", i, t.Length-1) str := fmt.Sprintf("U%d[%d]", i, t.Length-1)
switch t.Sub[0].Main { switch t.Sub[0].Main {
case shaderir.Vec2, shaderir.Vec3, shaderir.Vec4: case shaderir.Vec2, shaderir.Vec3, shaderir.Vec4, shaderir.IVec2, shaderir.IVec3, shaderir.IVec4:
str += ".x" str += ".x"
case shaderir.Mat2, shaderir.Mat3, shaderir.Mat4: case shaderir.Mat2, shaderir.Mat3, shaderir.Mat4:
str += "[0][0]" str += "[0][0]"
@ -325,7 +325,9 @@ func (c *compileContext) varInit(p *shaderir.Program, t *shaderir.Type) string {
return "false" return "false"
case shaderir.Int: case shaderir.Int:
return "0" return "0"
case shaderir.Float, shaderir.Vec2, shaderir.Vec3, shaderir.Vec4, shaderir.Mat2, shaderir.Mat3, shaderir.Mat4: case shaderir.Float, shaderir.Vec2, shaderir.Vec3, shaderir.Vec4,
shaderir.IVec2, shaderir.IVec3, shaderir.IVec4,
shaderir.Mat2, shaderir.Mat3, shaderir.Mat4:
return fmt.Sprintf("%s(0)", basicTypeString(t.Main)) return fmt.Sprintf("%s(0)", basicTypeString(t.Main))
default: default:
t0, t1 := c.typ(p, t) t0, t1 := c.typ(p, t)

View File

@ -92,6 +92,12 @@ func basicTypeString(t shaderir.BasicType) string {
return "vec3" return "vec3"
case shaderir.Vec4: case shaderir.Vec4:
return "vec4" return "vec4"
case shaderir.IVec2:
return "ivec2"
case shaderir.IVec3:
return "ivec3"
case shaderir.IVec4:
return "ivec4"
case shaderir.Mat2: case shaderir.Mat2:
return "mat2" return "mat2"
case shaderir.Mat3: case shaderir.Mat3:

View File

@ -215,7 +215,7 @@ func (c *compileContext) varInit(p *shaderir.Program, t *shaderir.Type) string {
panic("not implemented") panic("not implemented")
case shaderir.Bool: case shaderir.Bool:
return "false" return "false"
case shaderir.Int: case shaderir.Int, shaderir.IVec2, shaderir.IVec3, shaderir.IVec4:
return "0" return "0"
case shaderir.Float, shaderir.Vec2, shaderir.Vec3, shaderir.Vec4, shaderir.Mat2, shaderir.Mat3, shaderir.Mat4: case shaderir.Float, shaderir.Vec2, shaderir.Vec3, shaderir.Vec4, shaderir.Mat2, shaderir.Mat3, shaderir.Mat4:
return "0.0" return "0.0"
@ -404,7 +404,7 @@ func (c *compileContext) block(p *shaderir.Program, topBlock, block *shaderir.Bl
} }
if callee.Type == shaderir.BuiltinFuncExpr { if callee.Type == shaderir.BuiltinFuncExpr {
switch callee.BuiltinFunc { switch callee.BuiltinFunc {
case shaderir.Vec2F, shaderir.Vec3F, shaderir.Vec4F: case shaderir.Vec2F, shaderir.Vec3F, shaderir.Vec4F, shaderir.IVec2F, shaderir.IVec3F, shaderir.IVec4F:
if len(args) == 1 { if len(args) == 1 {
// Use casting. For example, `float4(1)` doesn't work. // Use casting. For example, `float4(1)` doesn't work.
return fmt.Sprintf("(%s)(%s)", expr(&e.Exprs[0]), args[0]) return fmt.Sprintf("(%s)(%s)", expr(&e.Exprs[0]), args[0])

View File

@ -46,19 +46,19 @@ func calculateMemoryOffsets(uniforms []shaderir.Type) []int {
case shaderir.Int: case shaderir.Int:
offsets = append(offsets, head) offsets = append(offsets, head)
head += 4 head += 4
case shaderir.Vec2: case shaderir.Vec2, shaderir.IVec2:
if head%boundaryInBytes >= 4*3 { if head%boundaryInBytes >= 4*3 {
head = align(head) head = align(head)
} }
offsets = append(offsets, head) offsets = append(offsets, head)
head += 4 * 2 head += 4 * 2
case shaderir.Vec3: case shaderir.Vec3, shaderir.IVec3:
if head%boundaryInBytes >= 4*2 { if head%boundaryInBytes >= 4*2 {
head = align(head) head = align(head)
} }
offsets = append(offsets, head) offsets = append(offsets, head)
head += 4 * 3 head += 4 * 3
case shaderir.Vec4: case shaderir.Vec4, shaderir.IVec4:
if head%boundaryInBytes >= 4*1 { if head%boundaryInBytes >= 4*1 {
head = align(head) head = align(head)
} }

View File

@ -92,6 +92,12 @@ func basicTypeString(t shaderir.BasicType) string {
return "float3" return "float3"
case shaderir.Vec4: case shaderir.Vec4:
return "float4" return "float4"
case shaderir.IVec2:
return "int2"
case shaderir.IVec3:
return "int3"
case shaderir.IVec4:
return "int4"
case shaderir.Mat2: case shaderir.Mat2:
return "float2x2" return "float2x2"
case shaderir.Mat3: case shaderir.Mat3:
@ -115,6 +121,12 @@ func (c *compileContext) builtinFuncString(f shaderir.BuiltinFunc) string {
return "float3" return "float3"
case shaderir.Vec4F: case shaderir.Vec4F:
return "float4" return "float4"
case shaderir.IVec2F:
return "int2"
case shaderir.IVec3F:
return "int3"
case shaderir.IVec4F:
return "int4"
case shaderir.Mat2F: case shaderir.Mat2F:
return "float2x2" return "float2x2"
case shaderir.Mat3F: case shaderir.Mat3F:

View File

@ -203,7 +203,9 @@ func (c *compileContext) varInit(p *shaderir.Program, t *shaderir.Type) string {
return "false" return "false"
case shaderir.Int: case shaderir.Int:
return "0" return "0"
case shaderir.Float, shaderir.Vec2, shaderir.Vec3, shaderir.Vec4, shaderir.Mat2, shaderir.Mat3, shaderir.Mat4: case shaderir.Float, shaderir.Vec2, shaderir.Vec3, shaderir.Vec4,
shaderir.IVec2, shaderir.IVec3, shaderir.IVec4,
shaderir.Mat2, shaderir.Mat3, shaderir.Mat4:
return fmt.Sprintf("%s(0)", basicTypeString(t.Main)) return fmt.Sprintf("%s(0)", basicTypeString(t.Main))
default: default:
t := c.typ(p, t) t := c.typ(p, t)

View File

@ -100,6 +100,12 @@ func basicTypeString(t shaderir.BasicType) string {
return "float3" return "float3"
case shaderir.Vec4: case shaderir.Vec4:
return "float4" return "float4"
case shaderir.IVec2:
return "int2"
case shaderir.IVec3:
return "int3"
case shaderir.IVec4:
return "int4"
case shaderir.Mat2: case shaderir.Mat2:
return "float2x2" return "float2x2"
case shaderir.Mat3: case shaderir.Mat3:
@ -129,6 +135,12 @@ func builtinFuncString(f shaderir.BuiltinFunc) string {
return "float3" return "float3"
case shaderir.Vec4F: case shaderir.Vec4F:
return "float4" return "float4"
case shaderir.IVec2F:
return "int2"
case shaderir.IVec3F:
return "int3"
case shaderir.IVec4F:
return "int4"
case shaderir.Mat2F: case shaderir.Mat2F:
return "float2x2" return "float2x2"
case shaderir.Mat3F: case shaderir.Mat3F:

View File

@ -224,6 +224,9 @@ const (
Vec2F BuiltinFunc = "vec2" Vec2F BuiltinFunc = "vec2"
Vec3F BuiltinFunc = "vec3" Vec3F BuiltinFunc = "vec3"
Vec4F BuiltinFunc = "vec4" Vec4F BuiltinFunc = "vec4"
IVec2F BuiltinFunc = "ivec2"
IVec3F BuiltinFunc = "ivec3"
IVec4F BuiltinFunc = "ivec4"
Mat2F BuiltinFunc = "mat2" Mat2F BuiltinFunc = "mat2"
Mat3F BuiltinFunc = "mat3" Mat3F BuiltinFunc = "mat3"
Mat4F BuiltinFunc = "mat4" Mat4F BuiltinFunc = "mat4"
@ -281,6 +284,9 @@ func ParseBuiltinFunc(str string) (BuiltinFunc, bool) {
Vec2F, Vec2F,
Vec3F, Vec3F,
Vec4F, Vec4F,
IVec2F,
IVec3F,
IVec4F,
Mat2F, Mat2F,
Mat3F, Mat3F,
Mat4F, Mat4F,

View File

@ -59,6 +59,12 @@ func (t *Type) String() string {
return "vec3" return "vec3"
case Vec4: case Vec4:
return "vec4" return "vec4"
case IVec2:
return "ivec2"
case IVec3:
return "ivec3"
case IVec4:
return "ivec4"
case Mat2: case Mat2:
return "mat2" return "mat2"
case Mat3: case Mat3:
@ -93,6 +99,12 @@ func (t *Type) Uint32Count() int {
return 3 return 3
case Vec4: case Vec4:
return 4 return 4
case IVec2:
return 2
case IVec3:
return 3
case IVec4:
return 4
case Mat2: case Mat2:
return 4 return 4
case Mat3: case Mat3:
@ -108,12 +120,31 @@ func (t *Type) Uint32Count() int {
func (t *Type) IsVector() bool { func (t *Type) IsVector() bool {
switch t.Main { switch t.Main {
case Vec2, Vec3, Vec4: case Vec2, Vec3, Vec4, IVec2, IVec3, IVec4:
return true return true
} }
return false return false
} }
func (t *Type) VectorElementCount() int {
switch t.Main {
case Vec2:
return 2
case Vec3:
return 3
case Vec4:
return 4
case IVec2:
return 2
case IVec3:
return 3
case IVec4:
return 4
default:
return -1
}
}
func (t *Type) IsMatrix() bool { func (t *Type) IsMatrix() bool {
switch t.Main { switch t.Main {
case Mat2, Mat3, Mat4: case Mat2, Mat3, Mat4:
@ -132,6 +163,9 @@ const (
Vec2 Vec2
Vec3 Vec3
Vec4 Vec4
IVec2
IVec3
IVec4
Mat2 Mat2
Mat3 Mat3
Mat4 Mat4

View File

@ -1293,6 +1293,16 @@ var U [4]int
func Fragment(position vec4, texCoord vec2, color vec4) vec4 { func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
return vec4(float(U[0])/255.0, float(U[1])/255.0, float(U[2])/255.0, float(U[3])/255.0) return vec4(float(U[0])/255.0, float(U[1])/255.0, float(U[2])/255.0, float(U[3])/255.0)
} }
`
const intVec = `package main
var U0 ivec4
var U1 [2]ivec3
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
return vec4(float(U0.x)/255.0, float(U0.y)/255.0, float(U1[0].z)/255.0, float(U1[1].x)/255.0)
}
` `
testCases := []struct { testCases := []struct {
@ -1382,6 +1392,57 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
Shader: intArray, Shader: intArray,
Want: color.RGBA{0x85, 0xa3, 0x08, 0xd3}, Want: color.RGBA{0x85, 0xa3, 0x08, 0xd3},
}, },
{
Name: "0xff,array",
Uniforms: map[string]any{
"U": [...]int{0xff, 0xff, 0xff, 0xff},
},
Shader: intArray,
Want: color.RGBA{0xff, 0xff, 0xff, 0xff},
},
{
Name: "int,array",
Uniforms: map[string]any{
"U": [...]int16{0x24, 0x3f, 0x6a, 0x88},
},
Shader: intArray,
Want: color.RGBA{0x24, 0x3f, 0x6a, 0x88},
},
{
Name: "uint,array",
Uniforms: map[string]any{
"U": [...]uint8{0x85, 0xa3, 0x08, 0xd3},
},
Shader: intArray,
Want: color.RGBA{0x85, 0xa3, 0x08, 0xd3},
},
{
Name: "0xff,ivec",
Uniforms: map[string]any{
"U0": [...]int{0xff, 0xff, 0xff, 0xff},
"U1": [...]int{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
},
Shader: intVec,
Want: color.RGBA{0xff, 0xff, 0xff, 0xff},
},
{
Name: "int,ivec",
Uniforms: map[string]any{
"U0": [...]int16{0x24, 0x3f, 0x6a, 0x88},
"U1": [...]int16{0x85, 0xa3, 0x08, 0xd3, 0x13, 0x19},
},
Shader: intVec,
Want: color.RGBA{0x24, 0x3f, 0x08, 0xd3},
},
{
Name: "uint,ivec",
Uniforms: map[string]any{
"U0": [...]uint8{0x24, 0x3f, 0x6a, 0x88},
"U1": [...]uint8{0x85, 0xa3, 0x08, 0xd3, 0x13, 0x19},
},
Shader: intVec,
Want: color.RGBA{0x24, 0x3f, 0x08, 0xd3},
},
} }
for _, tc := range testCases { for _, tc := range testCases {
tc := tc tc := tc
@ -1408,7 +1469,7 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
} }
// Issue #2463 // Issue #2463
func TestShaderVec3Array(t *testing.T) { func TestShaderUniformVec3Array(t *testing.T) {
const shader = `package main const shader = `package main
var U [4]vec3 var U [4]vec3