diff --git a/internal/shaderir/glsl.go b/internal/shaderir/glsl.go index 0d2822cfe..1f63da442 100644 --- a/internal/shaderir/glsl.go +++ b/internal/shaderir/glsl.go @@ -19,6 +19,40 @@ import ( "strings" ) +func isValidSwizzling(s string) bool { + if len(s) < 1 || 4 < len(s) { + return false + } + + const ( + xyzw = "xyzw" + rgba = "rgba" + strq = "strq" + ) + + switch { + case strings.IndexByte(xyzw, s[0]) >= 0: + for _, c := range s { + if strings.IndexRune(xyzw, c) == -1 { + return false + } + } + case strings.IndexByte(rgba, s[0]) >= 0: + for _, c := range s { + if strings.IndexRune(rgba, c) == -1 { + return false + } + } + case strings.IndexByte(strq, s[0]) >= 0: + for _, c := range s { + if strings.IndexRune(strq, c) == -1 { + return false + } + } + } + return false +} + func (p *Program) structName(t *Type) string { if t.Main != Struct { panic("shaderir: the given type at structName must be a struct") @@ -190,6 +224,11 @@ func (p *Program) glslBlock(b *Block, level int, localVarIndex int) []string { } case BuiltinFuncExpr: return string(e.BuiltinFunc) + case SwizzlingExpr: + if isValidSwizzling(e.Swizzling) { + return fmt.Sprintf("?(unexpected swizzling: %s)", e.Swizzling) + } + return e.Swizzling case Ident: return e.Ident case Unary: diff --git a/internal/shaderir/ir_test.go b/internal/shaderir/ir_test.go index a479b59a1..ebba64f28 100644 --- a/internal/shaderir/ir_test.go +++ b/internal/shaderir/ir_test.go @@ -98,6 +98,13 @@ func builtinFuncExpr(f BuiltinFunc) Expr { } } +func swizzlingExpr(swizzling string) Expr { + return Expr{ + Type: SwizzlingExpr, + Swizzling: swizzling, + } +} + func identExpr(ident string) Expr { return Expr{ Type: Ident, @@ -455,7 +462,7 @@ varying vec3 V0;`, {Main: Vec4}, }, OutParams: []Type{ - {Main: Float}, + {Main: Vec2}, }, Block: block( nil, @@ -463,15 +470,15 @@ varying vec3 V0;`, varNameExpr(Local, 1), fieldSelectorExpr( varNameExpr(Local, 0), - identExpr("x"), + swizzlingExpr("xz"), ), ), ), }, }, }, - Glsl: `void F0(in vec4 l0, out float l1) { - l1 = (l0).x; + Glsl: `void F0(in vec4 l0, out vec2 l1) { + l1 = (l0).xz; }`, }, { diff --git a/internal/shaderir/program.go b/internal/shaderir/program.go index f85d5523c..50d934271 100644 --- a/internal/shaderir/program.go +++ b/internal/shaderir/program.go @@ -89,6 +89,7 @@ type Expr struct { Int int32 Float float32 BuiltinFunc BuiltinFunc + Swizzling string Ident string Op Op } @@ -100,6 +101,7 @@ const ( FloatExpr VarName BuiltinFuncExpr + SwizzlingExpr Ident Unary Binary