internal/shader: allow integer types for abs and sign

Updates #2788
This commit is contained in:
Hajime Hoshi 2024-02-25 18:16:42 +09:00
parent 012fe52b6f
commit face5fd870
2 changed files with 69 additions and 8 deletions

View File

@ -537,19 +537,37 @@ func (cs *compileState) parseExpr(block *block, fname string, expr ast.Expr, mar
cs.addError(e.Pos(), fmt.Sprintf("number of %s's arguments must be 1 but %d", callee.BuiltinFunc, len(args)))
return nil, nil, nil, false
}
// If the argument is a non-typed constant value, treat this as a float value (#1874).
if args[0].Const != nil && argts[0].Main == shaderir.None && gconstant.ToFloat(args[0].Const).Kind() != gconstant.Unknown {
args[0].Const = gconstant.ToFloat(args[0].Const)
argts[0] = shaderir.Type{Main: shaderir.Float}
if args[0].Const != nil && argts[0].Main == shaderir.None {
switch callee.BuiltinFunc {
case shaderir.Abs, shaderir.Sign:
if args[0].Const.Kind() == gconstant.Int {
argts[0] = shaderir.Type{Main: shaderir.Int}
}
if args[0].Const.Kind() == gconstant.Float {
argts[0] = shaderir.Type{Main: shaderir.Float}
}
default:
// If the argument is a non-typed constant value, treat this as a float value (#1874).
if gconstant.ToFloat(args[0].Const).Kind() != gconstant.Unknown {
args[0].Const = gconstant.ToFloat(args[0].Const)
argts[0] = shaderir.Type{Main: shaderir.Float}
}
}
}
switch callee.BuiltinFunc {
case shaderir.Transpose:
if argts[0].Main != shaderir.Mat2 && argts[0].Main != shaderir.Mat3 && argts[0].Main != shaderir.Mat4 {
if !argts[0].IsMatrix() {
cs.addError(e.Pos(), fmt.Sprintf("cannot use %s as mat2, mat3, or mat4 value in argument to %s", argts[0].String(), callee.BuiltinFunc))
return nil, nil, nil, false
}
case shaderir.Abs, shaderir.Sign:
if argts[0].Main != shaderir.Float && !argts[0].IsFloatVector() && argts[0].Main != shaderir.Int && !argts[0].IsIntVector() {
cs.addError(e.Pos(), fmt.Sprintf("cannot use %s as float, vecN, int, or ivenN value in argument to %s", argts[0].String(), callee.BuiltinFunc))
return nil, nil, nil, false
}
default:
if argts[0].Main != shaderir.Float && argts[0].Main != shaderir.Vec2 && argts[0].Main != shaderir.Vec3 && argts[0].Main != shaderir.Vec4 {
if argts[0].Main != shaderir.Float && !argts[0].IsFloatVector() {
cs.addError(e.Pos(), fmt.Sprintf("cannot use %s as float, vec2, vec3, or vec4 value in argument to %s", argts[0].String(), callee.BuiltinFunc))
return nil, nil, nil, false
}

View File

@ -2103,8 +2103,6 @@ func TestSyntaxBuiltinFuncSingleArgType(t *testing.T) {
"log2",
"sqrt",
"inversesqrt",
"abs",
"sign",
"floor",
"ceil",
"fract",
@ -2133,6 +2131,51 @@ func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
}
}
func TestSyntaxBuiltinFuncSingleArgTypeInteger(t *testing.T) {
cases := []struct {
stmt string
err bool
}{
{stmt: "a := {{.Func}}(); _ = a", err: true},
{stmt: "a := {{.Func}}(false); _ = a", err: true},
{stmt: "a := {{.Func}}(1); _ = a", err: false},
{stmt: "a := {{.Func}}(1.0); _ = a", err: false},
{stmt: "a := {{.Func}}(int(1)); _ = a", err: false},
{stmt: "a := {{.Func}}(vec2(1)); _ = a", err: false},
{stmt: "a := {{.Func}}(vec3(1)); _ = a", err: false},
{stmt: "a := {{.Func}}(vec4(1)); _ = a", err: false},
{stmt: "a := {{.Func}}(ivec2(1)); _ = a", err: false},
{stmt: "a := {{.Func}}(ivec3(1)); _ = a", err: false},
{stmt: "a := {{.Func}}(ivec4(1)); _ = a", err: false},
{stmt: "a := {{.Func}}(mat2(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(mat3(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(mat4(1)); _ = a", err: true},
{stmt: "a := {{.Func}}(1, 1); _ = a", err: true},
}
funcs := []string{
"abs",
"sign",
}
for _, c := range cases {
for _, f := range funcs {
stmt := strings.ReplaceAll(c.stmt, "{{.Func}}", f)
src := fmt.Sprintf(`package main
func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
%s
return dstPos
}`, stmt)
_, err := compileToIR([]byte(src))
if err == nil && c.err {
t.Errorf("%s must return an error but does not", stmt)
} else if err != nil && !c.err {
t.Errorf("%s must not return nil but returned %v", stmt, err)
}
}
}
}
// Issue #2184
func TestSyntaxBuiltinFuncDoubleArgsType(t *testing.T) {
cases := []struct {