shader: Analyze blocks and shadowings

This commit is contained in:
Hajime Hoshi 2020-05-31 23:57:03 +09:00
parent 5de0493294
commit 6fa7b4bb5a
4 changed files with 133 additions and 66 deletions

View File

@ -28,7 +28,7 @@ import (
type variable struct { type variable struct {
name string name string
typ typ typ typ
init ast.Expr init shaderir.Expr
} }
type constant struct { type constant struct {
@ -68,6 +68,22 @@ type block struct {
ir shaderir.Block ir shaderir.Block
} }
func (b *block) findLocalVariable(name string) (int, bool) {
idx := 0
for outer := b.outer; outer != nil; outer = outer.outer {
idx += len(outer.vars)
}
for i, v := range b.vars {
if v.name == name {
return idx + i, true
}
}
if b.outer != nil {
return b.outer.findLocalVariable(name)
}
return 0, false
}
type ParseError struct { type ParseError struct {
errs []string errs []string
} }
@ -106,7 +122,7 @@ func (s *compileState) addError(pos token.Pos, str string) {
func (cs *compileState) parse(f *ast.File) { func (cs *compileState) parse(f *ast.File) {
for _, d := range f.Decls { for _, d := range f.Decls {
cs.parseDecl(&cs.global, d, true) cs.parseDecl(&cs.global, d)
} }
if len(cs.errs) > 0 { if len(cs.errs) > 0 {
@ -118,7 +134,7 @@ func (cs *compileState) parse(f *ast.File) {
} }
} }
func (cs *compileState) parseDecl(b *block, d ast.Decl, global bool) { func (cs *compileState) parseDecl(b *block, d ast.Decl) {
switch d := d.(type) { switch d := d.(type) {
case *ast.GenDecl: case *ast.GenDecl:
switch d.Tok { switch d.Tok {
@ -140,18 +156,21 @@ func (cs *compileState) parseDecl(b *block, d ast.Decl, global bool) {
for _, s := range d.Specs { for _, s := range d.Specs {
s := s.(*ast.ValueSpec) s := s.(*ast.ValueSpec)
vs := cs.parseVariable(b, s) vs := cs.parseVariable(b, s)
if !global { if b == &cs.global {
b.vars = append(b.vars, vs...)
continue
}
for i, v := range vs { for i, v := range vs {
if v.name[0] < 'A' || 'Z' < v.name[0] { if v.name[0] < 'A' || 'Z' < v.name[0] {
cs.addError(s.Names[i].Pos(), fmt.Sprintf("global variables must be exposed: %s", v.name)) cs.addError(s.Names[i].Pos(), fmt.Sprintf("global variables must be exposed: %s", v.name))
} }
// TODO: Check RHS // TODO: Check init
cs.uniforms = append(cs.uniforms, v.name) cs.uniforms = append(cs.uniforms, v.name)
cs.ir.Uniforms = append(cs.ir.Uniforms, v.typ.ir) cs.ir.Uniforms = append(cs.ir.Uniforms, v.typ.ir)
} }
continue
}
for _, v := range vs {
b.vars = append(b.vars, v)
b.ir.LocalVars = append(b.ir.LocalVars, v.typ.ir)
}
} }
case token.IMPORT: case token.IMPORT:
cs.addError(d.Pos(), "import is forbidden") cs.addError(d.Pos(), "import is forbidden")
@ -181,10 +200,14 @@ func (s *compileState) parseVariable(block *block, vs *ast.ValueSpec) []variable
} }
} }
name := n.Name name := n.Name
var e shaderir.Expr
if init != nil {
e = s.parseExpr(block, init)
}
vars = append(vars, variable{ vars = append(vars, variable{
name: name, name: name,
typ: t, typ: t,
init: init, init: e,
}) })
} }
return vars return vars
@ -298,20 +321,26 @@ func (cs *compileState) parseBlock(outer *block, b *ast.BlockStmt, inParams, out
} }
case token.ASSIGN: case token.ASSIGN:
// TODO: What about the statement `a,b = b,a?` // TODO: What about the statement `a,b = b,a?`
for range l.Rhs { for i := range l.Rhs {
/*block.stmts = append(block.stmts, stmt{ block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{
stmtType: stmtAssign, Type: shaderir.Assign,
exprs: []ast.Expr{l.Lhs[i], l.Rhs[i]}, Exprs: []shaderir.Expr{
})*/ cs.parseExpr(block, l.Lhs[i]),
cs.parseExpr(block, l.Rhs[i]),
},
})
} }
} }
case *ast.BlockStmt: case *ast.BlockStmt:
/*block.stmts = append(block.stmts, stmt{ b := cs.parseBlock(block, l, nil, nil)
stmtType: stmtBlock, block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{
block: cs.parseBlock(block, l), Type: shaderir.BlockStmt,
})*/ Blocks: []shaderir.Block{
b.ir,
},
})
case *ast.DeclStmt: case *ast.DeclStmt:
cs.parseDecl(block, l.Decl, false) cs.parseDecl(block, l.Decl)
case *ast.ReturnStmt: case *ast.ReturnStmt:
for i, r := range l.Results { for i, r := range l.Results {
e := cs.parseExpr(block, r) e := cs.parseExpr(block, r)
@ -379,18 +408,6 @@ func (s *compileState) detectType(b *block, expr ast.Expr) typ {
} }
} }
func (b *block) findLocalVariable(name string) (int, bool) {
for i, v := range b.vars {
if v.name == name {
return i, true
}
}
if b.outer != nil {
return b.outer.findLocalVariable(name)
}
return 0, false
}
func (cs *compileState) parseExpr(block *block, expr ast.Expr) shaderir.Expr { func (cs *compileState) parseExpr(block *block, expr ast.Expr) shaderir.Expr {
switch e := expr.(type) { switch e := expr.(type) {
case *ast.BasicLit: case *ast.BasicLit:

View File

@ -36,8 +36,6 @@ var (
Boo vec4 Boo vec4
)`, )`,
VS: `uniform vec2 U0; VS: `uniform vec2 U0;
uniform vec4 U1;`,
FS: `uniform vec2 U0;
uniform vec4 U1;`, uniform vec4 U1;`,
}, },
{ {
@ -47,8 +45,6 @@ uniform vec4 U1;`,
func Foo(foo vec2) vec4 { func Foo(foo vec2) vec4 {
}`, }`,
VS: `void F0(in vec2 l0, out vec4 l1) { VS: `void F0(in vec2 l0, out vec4 l1) {
}`,
FS: `void F0(in vec2 l0, out vec4 l1) {
}`, }`,
}, },
{ {
@ -61,10 +57,6 @@ func Foo(foo vec2) vec4 {
VS: `void F0(in vec2 l0, out vec4 l1) { VS: `void F0(in vec2 l0, out vec4 l1) {
l1 = vec4(l0, 0, 1); l1 = vec4(l0, 0, 1);
return; return;
}`,
FS: `void F0(in vec2 l0, out vec4 l1) {
l1 = vec4(l0, 0, 1);
return;
}`, }`,
}, },
{ {
@ -81,11 +73,36 @@ func Foo(foo vec4) (float, float, float, float) {
l4 = (l0).w; l4 = (l0).w;
return; return;
}`, }`,
FS: `void F0(in vec4 l0, out float l1, out float l2, out float l3, out float l4) { },
l1 = (l0).x; {
l2 = (l0).y; Name: "blocks",
l3 = (l0).z; Src: `package main
l4 = (l0).w;
func Foo(foo vec2) vec4 {
var r vec4
{
r.x = foo.x
var foo vec3
{
r.y = foo.y
var foo vec4
r.z = foo.z
}
}
return r
}`,
VS: `void F0(in vec2 l0, out vec4 l1) {
vec4 l2 = vec4(0.0);
{
vec3 l3 = vec3(0.0);
(l2).x = (l0).x;
{
vec4 l4 = vec4(0.0);
(l2).y = (l3).y;
(l2).z = (l4).z;
}
}
l1 = l2;
return; return;
}`, }`,
}, },
@ -100,8 +117,10 @@ func Foo(foo vec4) (float, float, float, float) {
if got, want := vs, tc.VS+"\n"; got != want { if got, want := vs, tc.VS+"\n"; got != want {
t.Errorf("%s: got: %v, want: %v", tc.Name, got, want) t.Errorf("%s: got: %v, want: %v", tc.Name, got, want)
} }
if tc.FS != "" {
if got, want := fs, tc.FS+"\n"; got != want { if got, want := fs, tc.FS+"\n"; got != want {
t.Errorf("%s: got: %v, want: %v", tc.Name, got, want) t.Errorf("%s: got: %v, want: %v", tc.Name, got, want)
} }
} }
} }
}

View File

@ -162,6 +162,37 @@ func (p *Program) glslVarDecl(t *Type, varname string) string {
} }
} }
func (p *Program) glslVarInit(t *Type) string {
switch t.Main {
case None:
return "?(none)"
case Array:
panic("not implemented")
case Struct:
panic("not implemented")
case Bool:
return "false"
case Int:
return "0"
case Float:
return "0.0"
case Vec2:
return "vec2(0.0)"
case Vec3:
return "vec3(0.0)"
case Vec4:
return "vec4(0.0)"
case Mat2:
return "mat2(0.0)"
case Mat3:
return "mat3(0.0)"
case Mat4:
return "mat4(0.0)"
default:
panic(fmt.Sprintf("?(unexpected type: %s)", p.glslType(t)))
}
}
func (p *Program) glslFunc(f *Func) []string { func (p *Program) glslFunc(f *Func) []string {
var args []string var args []string
var idx int var idx int
@ -195,7 +226,7 @@ func (p *Program) glslBlock(b *Block, level int, localVarIndex int) []string {
var lines []string var lines []string
for _, t := range b.LocalVars { for _, t := range b.LocalVars {
lines = append(lines, fmt.Sprintf("%s%s;", idt, p.glslVarDecl(&t, fmt.Sprintf("l%d", localVarIndex)))) lines = append(lines, fmt.Sprintf("%s%s = %s;", idt, p.glslVarDecl(&t, fmt.Sprintf("l%d", localVarIndex)), p.glslVarInit(&t)))
localVarIndex++ localVarIndex++
} }

View File

@ -296,12 +296,12 @@ varying vec3 V0;`,
}, },
}, },
GlslVS: `void F0(in float l0, inout float l1, out float l2) { GlslVS: `void F0(in float l0, inout float l1, out float l2) {
mat4 l3; mat4 l3 = mat4(0.0);
mat4 l4; mat4 l4 = mat4(0.0);
}`, }`,
GlslFS: `void F0(in float l0, inout float l1, out float l2) { GlslFS: `void F0(in float l0, inout float l1, out float l2) {
mat4 l3; mat4 l3 = mat4(0.0);
mat4 l4; mat4 l4 = mat4(0.0);
}`, }`,
}, },
{ {
@ -337,19 +337,19 @@ varying vec3 V0;`,
}, },
}, },
GlslVS: `void F0(in float l0, inout float l1, out float l2) { GlslVS: `void F0(in float l0, inout float l1, out float l2) {
mat4 l3; mat4 l3 = mat4(0.0);
mat4 l4; mat4 l4 = mat4(0.0);
{ {
mat4 l5; mat4 l5 = mat4(0.0);
mat4 l6; mat4 l6 = mat4(0.0);
} }
}`, }`,
GlslFS: `void F0(in float l0, inout float l1, out float l2) { GlslFS: `void F0(in float l0, inout float l1, out float l2) {
mat4 l3; mat4 l3 = mat4(0.0);
mat4 l4; mat4 l4 = mat4(0.0);
{ {
mat4 l5; mat4 l5 = mat4(0.0);
mat4 l6; mat4 l6 = mat4(0.0);
} }
}`, }`,
}, },
@ -747,9 +747,9 @@ varying float V0;
varying vec2 V1; varying vec2 V1;
void main(void) { void main(void) {
vec2 l0; vec2 l0 = vec2(0.0);
vec4 l1; vec4 l1 = vec4(0.0);
float l2; float l2 = 0.0;
l1 = V0; l1 = V0;
gl_FragColor = V1; gl_FragColor = V1;
l0 = gl_FragCoord; l0 = gl_FragCoord;