mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-13 12:32:05 +01:00
shader: Analyze blocks and shadowings
This commit is contained in:
parent
5de0493294
commit
6fa7b4bb5a
@ -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:
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user