shaderir: Use pointers for Block

This commit is contained in:
Hajime Hoshi 2020-08-09 15:55:59 +09:00
parent 07514a37c8
commit ee9257e626
7 changed files with 58 additions and 44 deletions

View File

@ -92,7 +92,7 @@ type block struct {
pos token.Pos
outer *block
ir shaderir.Block
ir *shaderir.Block
}
func (b *block) findLocalVariable(name string) (int, shaderir.Type, bool) {
@ -140,6 +140,7 @@ func Compile(fs *token.FileSet, f *ast.File, vertexEntry, fragmentEntry string,
vertexEntry: vertexEntry,
fragmentEntry: fragmentEntry,
}
s.global.ir = &shaderir.Block{}
s.parse(f)
if len(s.errs) > 0 {
@ -221,6 +222,7 @@ func (cs *compileState) parse(f *ast.File) {
Index: len(cs.funcs),
InParams: inT,
OutParams: outT,
Block: &shaderir.Block{},
},
})
}
@ -657,7 +659,9 @@ func (cs *compileState) parseBlock(outer *block, stmts []ast.Stmt, inParams, out
block := &block{
vars: vars,
outer: outer,
ir: &shaderir.Block{},
}
defer func() {
var offset int
if outer == &cs.global {

View File

@ -103,7 +103,7 @@ func (cs *compileState) parseStmt(block *block, stmt ast.Stmt, inParams []variab
}
stmts = append(stmts, shaderir.Stmt{
Type: shaderir.BlockStmt,
Blocks: []shaderir.Block{
Blocks: []*shaderir.Block{
b.ir,
},
})
@ -261,7 +261,7 @@ func (cs *compileState) parseStmt(block *block, stmt ast.Stmt, inParams []variab
stmts = append(stmts, shaderir.Stmt{
Type: shaderir.For,
Blocks: []shaderir.Block{bodyir},
Blocks: []*shaderir.Block{bodyir},
ForVarType: vartype,
ForVarIndex: varidx,
ForInit: init,
@ -281,7 +281,7 @@ func (cs *compileState) parseStmt(block *block, stmt ast.Stmt, inParams []variab
stmts = append(stmts, shaderir.Stmt{
Type: shaderir.BlockStmt,
Blocks: []shaderir.Block{b.ir},
Blocks: []*shaderir.Block{b.ir},
})
return stmts, true
}
@ -300,7 +300,7 @@ func (cs *compileState) parseStmt(block *block, stmt ast.Stmt, inParams []variab
}
stmts = append(stmts, ss...)
var bs []shaderir.Block
var bs []*shaderir.Block
b, ok := cs.parseBlock(block, stmt.Body.List, inParams, nil)
if !ok {
return nil, false

View File

@ -88,10 +88,10 @@ func Compile(p *shaderir.Program) (vertexShader, fragmentShader string) {
}
}
if len(p.VertexFunc.Block.Stmts) > 0 {
if p.VertexFunc.Block != nil && len(p.VertexFunc.Block.Stmts) > 0 {
vslines = append(vslines, "")
vslines = append(vslines, "void main(void) {")
vslines = append(vslines, c.glslBlock(p, &p.VertexFunc.Block, &p.VertexFunc.Block, 0, 0)...)
vslines = append(vslines, c.glslBlock(p, p.VertexFunc.Block, p.VertexFunc.Block, 0, 0)...)
vslines = append(vslines, "}")
}
}
@ -126,10 +126,10 @@ func Compile(p *shaderir.Program) (vertexShader, fragmentShader string) {
}
}
if len(p.FragmentFunc.Block.Stmts) > 0 {
if p.FragmentFunc.Block != nil && len(p.FragmentFunc.Block.Stmts) > 0 {
fslines = append(fslines, "")
fslines = append(fslines, "void main(void) {")
fslines = append(fslines, c.glslBlock(p, &p.FragmentFunc.Block, &p.FragmentFunc.Block, 0, 0)...)
fslines = append(fslines, c.glslBlock(p, p.FragmentFunc.Block, p.FragmentFunc.Block, 0, 0)...)
fslines = append(fslines, "}")
}
}
@ -239,7 +239,7 @@ func (c *compileContext) glslFunc(p *shaderir.Program, f *shaderir.Func, prototy
return lines
}
lines = append(lines, fmt.Sprintf("%s {", sig))
lines = append(lines, c.glslBlock(p, &f.Block, &f.Block, 0, idx)...)
lines = append(lines, c.glslBlock(p, f.Block, f.Block, 0, idx)...)
lines = append(lines, "}")
return lines
@ -275,7 +275,7 @@ func constantToNumberLiteral(t shaderir.ConstType, v constant.Value) string {
func localVariableName(p *shaderir.Program, topBlock *shaderir.Block, idx int) string {
switch topBlock {
case &p.VertexFunc.Block:
case p.VertexFunc.Block:
na := len(p.Attributes)
nv := len(p.Varyings)
switch {
@ -288,7 +288,7 @@ func localVariableName(p *shaderir.Program, topBlock *shaderir.Block, idx int) s
default:
return fmt.Sprintf("l%d", idx-(na+nv+1))
}
case &p.FragmentFunc.Block:
case p.FragmentFunc.Block:
nv := len(p.Varyings)
switch {
case idx == 0:
@ -306,6 +306,10 @@ func localVariableName(p *shaderir.Program, topBlock *shaderir.Block, idx int) s
}
func (c *compileContext) glslBlock(p *shaderir.Program, topBlock, block *shaderir.Block, level int, localVarIndex int) []string {
if block == nil {
return nil
}
idt := strings.Repeat("\t", level+1)
var lines []string
@ -383,17 +387,17 @@ func (c *compileContext) glslBlock(p *shaderir.Program, topBlock, block *shaderi
lines = append(lines, fmt.Sprintf("%s%s;", idt, glslExpr(&s.Exprs[0])))
case shaderir.BlockStmt:
lines = append(lines, idt+"{")
lines = append(lines, c.glslBlock(p, topBlock, &s.Blocks[0], level+1, localVarIndex)...)
lines = append(lines, c.glslBlock(p, topBlock, s.Blocks[0], level+1, localVarIndex)...)
lines = append(lines, idt+"}")
case shaderir.Assign:
// TODO: Give an appropriate context
lines = append(lines, fmt.Sprintf("%s%s = %s;", idt, glslExpr(&s.Exprs[0]), glslExpr(&s.Exprs[1])))
case shaderir.If:
lines = append(lines, fmt.Sprintf("%sif (%s) {", idt, glslExpr(&s.Exprs[0])))
lines = append(lines, c.glslBlock(p, topBlock, &s.Blocks[0], level+1, localVarIndex)...)
lines = append(lines, c.glslBlock(p, topBlock, s.Blocks[0], level+1, localVarIndex)...)
if len(s.Blocks) > 1 {
lines = append(lines, fmt.Sprintf("%s} else {", idt))
lines = append(lines, c.glslBlock(p, topBlock, &s.Blocks[1], level+1, localVarIndex)...)
lines = append(lines, c.glslBlock(p, topBlock, s.Blocks[1], level+1, localVarIndex)...)
}
lines = append(lines, fmt.Sprintf("%s}", idt))
case shaderir.For:
@ -436,7 +440,7 @@ func (c *compileContext) glslBlock(p *shaderir.Program, topBlock, block *shaderi
end := constantToNumberLiteral(ct, s.ForEnd)
t0, t1 := typeString(&t)
lines = append(lines, fmt.Sprintf("%sfor (%s %s%s = %s; %s %s %s; %s) {", idt, t0, v, t1, init, v, op, end, delta))
lines = append(lines, c.glslBlock(p, topBlock, &s.Blocks[0], level+1, localVarIndex)...)
lines = append(lines, c.glslBlock(p, topBlock, s.Blocks[0], level+1, localVarIndex)...)
lines = append(lines, fmt.Sprintf("%s}", idt))
case shaderir.Continue:
lines = append(lines, idt+"continue;")

View File

@ -20,10 +20,11 @@ import (
. "github.com/hajimehoshi/ebiten/internal/shaderir"
"github.com/hajimehoshi/ebiten/internal/shaderir/glsl"
"github.com/hajimehoshi/ebiten/internal/shaderir/metal"
)
func block(localVars []Type, stmts ...Stmt) Block {
return Block{
func block(localVars []Type, stmts ...Stmt) *Block {
return &Block{
LocalVars: localVars,
Stmts: stmts,
}
@ -36,10 +37,10 @@ func exprStmt(expr Expr) Stmt {
}
}
func blockStmt(block Block) Stmt {
func blockStmt(block *Block) Stmt {
return Stmt{
Type: BlockStmt,
Blocks: []Block{block},
Blocks: []*Block{block},
}
}
@ -57,18 +58,18 @@ func assignStmt(lhs Expr, rhs Expr) Stmt {
}
}
func ifStmt(cond Expr, block Block, elseBlock Block) Stmt {
func ifStmt(cond Expr, block *Block, elseBlock *Block) Stmt {
return Stmt{
Type: If,
Exprs: []Expr{cond},
Blocks: []Block{block, elseBlock},
Blocks: []*Block{block, elseBlock},
}
}
func forStmt(index, init, end int, op Op, delta int, block Block) Stmt {
func forStmt(index, init, end int, op Op, delta int, block *Block) Stmt {
return Stmt{
Type: For,
Blocks: []Block{block},
Blocks: []*Block{block},
ForVarType: Type{Main: Int},
ForVarIndex: index,
ForInit: constant.MakeInt64(int64(init)),
@ -837,6 +838,7 @@ void main(void) {
t.Errorf("%s fragment: got: %s, want: %s", tc.Name, got, want)
}
}
metal.Compile(&tc.Program, "Vertex", "Fragment")
})
}
}

View File

@ -95,7 +95,7 @@ func Compile(p *shaderir.Program, vertex, fragment string) (shader string) {
}
}
if len(p.VertexFunc.Block.Stmts) > 0 {
if p.VertexFunc.Block != nil && len(p.VertexFunc.Block.Stmts) > 0 {
lines = append(lines, "")
lines = append(lines,
fmt.Sprintf("vertex Varyings %s(", vertex),
@ -111,14 +111,14 @@ func Compile(p *shaderir.Program, vertex, fragment string) (shader string) {
}
lines[len(lines)-1] += ") {"
lines = append(lines, fmt.Sprintf("\tVaryings %s = {};", vertexOut))
lines = append(lines, c.metalBlock(p, &p.VertexFunc.Block, &p.VertexFunc.Block, 0, 0)...)
lines = append(lines, c.metalBlock(p, p.VertexFunc.Block, p.VertexFunc.Block, 0, 0)...)
if last := fmt.Sprintf("\treturn %s;", vertexOut); lines[len(lines)-1] != last {
lines = append(lines, last)
}
lines = append(lines, "}")
}
if len(p.FragmentFunc.Block.Stmts) > 0 {
if p.FragmentFunc.Block != nil && len(p.FragmentFunc.Block.Stmts) > 0 {
lines = append(lines, "")
lines = append(lines,
fmt.Sprintf("fragment float4 %s(", fragment),
@ -133,7 +133,7 @@ func Compile(p *shaderir.Program, vertex, fragment string) (shader string) {
}
lines[len(lines)-1] += ") {"
lines = append(lines, fmt.Sprintf("\tfloat4 %s = float4(0);", fragmentOut))
lines = append(lines, c.metalBlock(p, &p.FragmentFunc.Block, &p.FragmentFunc.Block, 0, 0)...)
lines = append(lines, c.metalBlock(p, p.FragmentFunc.Block, p.FragmentFunc.Block, 0, 0)...)
if last := fmt.Sprintf("\treturn %s;", fragmentOut); lines[len(lines)-1] != last {
lines = append(lines, last)
}
@ -245,7 +245,7 @@ func (c *compileContext) metalFunc(p *shaderir.Program, f *shaderir.Func, protot
return lines
}
lines = append(lines, fmt.Sprintf("%s {", sig))
lines = append(lines, c.metalBlock(p, &f.Block, &f.Block, 0, idx)...)
lines = append(lines, c.metalBlock(p, f.Block, f.Block, 0, idx)...)
lines = append(lines, "}")
return lines
@ -281,7 +281,7 @@ func constantToNumberLiteral(t shaderir.ConstType, v constant.Value) string {
func localVariableName(p *shaderir.Program, topBlock *shaderir.Block, idx int) string {
switch topBlock {
case &p.VertexFunc.Block:
case p.VertexFunc.Block:
na := len(p.Attributes)
nv := len(p.Varyings)
switch {
@ -294,7 +294,7 @@ func localVariableName(p *shaderir.Program, topBlock *shaderir.Block, idx int) s
default:
return fmt.Sprintf("l%d", idx-(na+nv+1))
}
case &p.FragmentFunc.Block:
case p.FragmentFunc.Block:
nv := len(p.Varyings)
switch {
case idx == 0:
@ -312,6 +312,10 @@ func localVariableName(p *shaderir.Program, topBlock *shaderir.Block, idx int) s
}
func (c *compileContext) metalBlock(p *shaderir.Program, topBlock, block *shaderir.Block, level int, localVarIndex int) []string {
if block == nil {
return nil
}
idt := strings.Repeat("\t", level+1)
var lines []string
@ -391,17 +395,17 @@ func (c *compileContext) metalBlock(p *shaderir.Program, topBlock, block *shader
lines = append(lines, fmt.Sprintf("%s%s;", idt, metalExpr(&s.Exprs[0])))
case shaderir.BlockStmt:
lines = append(lines, idt+"{")
lines = append(lines, c.metalBlock(p, topBlock, &s.Blocks[0], level+1, localVarIndex)...)
lines = append(lines, c.metalBlock(p, topBlock, s.Blocks[0], level+1, localVarIndex)...)
lines = append(lines, idt+"}")
case shaderir.Assign:
// TODO: Give an appropriate context
lines = append(lines, fmt.Sprintf("%s%s = %s;", idt, metalExpr(&s.Exprs[0]), metalExpr(&s.Exprs[1])))
case shaderir.If:
lines = append(lines, fmt.Sprintf("%sif (%s) {", idt, metalExpr(&s.Exprs[0])))
lines = append(lines, c.metalBlock(p, topBlock, &s.Blocks[0], level+1, localVarIndex)...)
lines = append(lines, c.metalBlock(p, topBlock, s.Blocks[0], level+1, localVarIndex)...)
if len(s.Blocks) > 1 {
lines = append(lines, fmt.Sprintf("%s} else {", idt))
lines = append(lines, c.metalBlock(p, topBlock, &s.Blocks[1], level+1, localVarIndex)...)
lines = append(lines, c.metalBlock(p, topBlock, s.Blocks[1], level+1, localVarIndex)...)
}
lines = append(lines, fmt.Sprintf("%s}", idt))
case shaderir.For:
@ -444,7 +448,7 @@ func (c *compileContext) metalBlock(p *shaderir.Program, topBlock, block *shader
end := constantToNumberLiteral(ct, s.ForEnd)
ts := typeString(&t, false, false)
lines = append(lines, fmt.Sprintf("%sfor (%s %s = %s; %s %s %s; %s) {", idt, ts, v, init, v, op, end, delta))
lines = append(lines, c.metalBlock(p, topBlock, &s.Blocks[0], level+1, localVarIndex)...)
lines = append(lines, c.metalBlock(p, topBlock, s.Blocks[0], level+1, localVarIndex)...)
lines = append(lines, fmt.Sprintf("%s}", idt))
case shaderir.Continue:
lines = append(lines, idt+"continue;")
@ -452,9 +456,9 @@ func (c *compileContext) metalBlock(p *shaderir.Program, topBlock, block *shader
lines = append(lines, idt+"break;")
case shaderir.Return:
switch {
case topBlock == &p.VertexFunc.Block:
case topBlock == p.VertexFunc.Block:
lines = append(lines, fmt.Sprintf("%sreturn %s;", idt, vertexOut))
case topBlock == &p.FragmentFunc.Block:
case topBlock == p.FragmentFunc.Block:
lines = append(lines, fmt.Sprintf("%sreturn %s;", idt, fragmentOut))
case len(s.Exprs) == 0:
lines = append(lines, idt+"return;")

View File

@ -36,7 +36,7 @@ type Func struct {
InParams []Type
OutParams []Type
Return Type
Block Block
Block *Block
}
// VertexFunc takes pseudo params, and the number if len(attributes) + len(varyings) + 1.
@ -45,7 +45,7 @@ type Func struct {
// If len(attributes) + 1 <= index < len(attributes) + len(varyings) + 1, the params are out-params and represent
// varying variables.
type VertexFunc struct {
Block Block
Block *Block
}
// FragmentFunc takes pseudo params, and the number is len(varyings) + 2.
@ -53,7 +53,7 @@ type VertexFunc struct {
// If index == len(varyings), the param represents (index-1)th verying variable.
// If index == len(varyings)+1, the param is an out-param representing the color of the pixel (gl_FragColor in GLSL).
type FragmentFunc struct {
Block Block
Block *Block
}
type Block struct {
@ -64,7 +64,7 @@ type Block struct {
type Stmt struct {
Type StmtType
Exprs []Expr
Blocks []Block
Blocks []*Block
ForVarType Type
ForVarIndex int
ForInit constant.Value

View File

@ -173,7 +173,7 @@ var (
},
}
defaultVertexFunc = shaderir.VertexFunc{
Block: shaderir.Block{
Block: &shaderir.Block{
Stmts: []shaderir.Stmt{
{
Type: shaderir.Assign,
@ -279,7 +279,7 @@ func ShaderProgramFill(r, g, b, a byte) shaderir.Program {
p := defaultProgram()
p.FragmentFunc = shaderir.FragmentFunc{
Block: shaderir.Block{
Block: &shaderir.Block{
Stmts: []shaderir.Stmt{
{
Type: shaderir.Assign,
@ -413,7 +413,7 @@ func ShaderProgramImages(imageNum int) shaderir.Program {
})
p.FragmentFunc = shaderir.FragmentFunc{
Block: shaderir.Block{
Block: &shaderir.Block{
LocalVars: []shaderir.Type{
{Main: shaderir.Vec4},
},