From ddaed674dd9e93f1c0f22715b854ed3ea9c50e86 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sat, 16 May 2020 22:18:58 +0900 Subject: [PATCH] shaderir: Implement vertex function --- internal/shaderir/glsl.go | 43 +++++++++++++++++++++++----------- internal/shaderir/ir_test.go | 45 ++++++++++++++++++++++++++++++++++++ internal/shaderir/program.go | 29 ++++++++++++++++------- 3 files changed, 96 insertions(+), 21 deletions(-) diff --git a/internal/shaderir/glsl.go b/internal/shaderir/glsl.go index b4a3dc682..399150c40 100644 --- a/internal/shaderir/glsl.go +++ b/internal/shaderir/glsl.go @@ -51,6 +51,13 @@ func (p *Program) Glsl() string { lines = append(lines, p.glslFunc(&f)...) } + // Vertex func + if len(p.VertexFunc.Block.Stmts) > 0 { + lines = append(lines, "void main(void) {") + lines = append(lines, p.glslBlock(&p.VertexFunc.Block, 0, 0)...) + lines = append(lines, "}") + } + var stLines []string for i, t := range p.structTypes { stLines = append(stLines, fmt.Sprintf("struct S%d {", i)) @@ -116,13 +123,13 @@ func (p *Program) glslFunc(f *Func) []string { var lines []string lines = append(lines, fmt.Sprintf("%s %s(%s) {", p.glslType(&f.Return), f.Name, argsstr)) - lines = append(lines, p.glslBlock(&f.Block, f, 0, idx)...) + lines = append(lines, p.glslBlock(&f.Block, 0, idx)...) lines = append(lines, "}") return lines } -func (p *Program) glslBlock(b *Block, f *Func, level int, localVarIndex int) []string { +func (p *Program) glslBlock(b *Block, level int, localVarIndex int) []string { idt := strings.Repeat("\t", level+1) var lines []string @@ -142,12 +149,24 @@ func (p *Program) glslBlock(b *Block, f *Func, level int, localVarIndex int) []s switch e.Variable.Type { case Uniform: return fmt.Sprintf("U%d", e.Variable.Index) - case Attribute: - return fmt.Sprintf("A%d", e.Variable.Index) - case Varying: - return fmt.Sprintf("V%d", e.Variable.Index) case Local: - return fmt.Sprintf("l%d", e.Variable.Index) + idx := e.Variable.Index + if b == &p.VertexFunc.Block { + na := len(p.Attributes) + nv := len(p.Varyings) + switch { + case idx < na: + return fmt.Sprintf("A%d", idx) + case idx < na+nv: + return fmt.Sprintf("V%d", idx-na) + case idx == na+nv: + return "gl_Position" + default: + return fmt.Sprintf("l%d", idx-(na+nv)) + } + } else { + return fmt.Sprintf("l%d", idx) + } default: return fmt.Sprintf("?(unexpected variable type: %d)", e.Variable.Type) } @@ -187,16 +206,16 @@ func (p *Program) glslBlock(b *Block, f *Func, level int, localVarIndex int) []s lines = append(lines, fmt.Sprintf("%s%s;", idt, glslExpr(&s.Exprs[0]))) case BlockStmt: lines = append(lines, idt+"{") - lines = append(lines, p.glslBlock(&s.Blocks[0], f, level+1, localVarIndex)...) + lines = append(lines, p.glslBlock(&s.Blocks[0], level+1, localVarIndex)...) lines = append(lines, idt+"}") case Assign: lines = append(lines, fmt.Sprintf("%s%s = %s;", idt, glslExpr(&s.Exprs[0]), glslExpr(&s.Exprs[1]))) case If: lines = append(lines, fmt.Sprintf("%sif (%s) {", idt, glslExpr(&s.Exprs[0]))) - lines = append(lines, p.glslBlock(&s.Blocks[0], f, level+1, localVarIndex)...) + lines = append(lines, p.glslBlock(&s.Blocks[0], level+1, localVarIndex)...) if len(s.Blocks) > 1 { lines = append(lines, fmt.Sprintf("%s} else {", idt)) - lines = append(lines, p.glslBlock(&s.Blocks[1], f, level+1, localVarIndex)...) + lines = append(lines, p.glslBlock(&s.Blocks[1], level+1, localVarIndex)...) } lines = append(lines, fmt.Sprintf("%s}", idt)) case For: @@ -225,7 +244,7 @@ func (p *Program) glslBlock(b *Block, f *Func, level int, localVarIndex int) []s op = fmt.Sprintf("?(unexpected op: %s)", string(s.ForOp)) } lines = append(lines, fmt.Sprintf("%sfor (int l%d = %d; l%d %s %d; %s) {", idt, v, s.ForInit, v, op, s.ForEnd, delta)) - lines = append(lines, p.glslBlock(&s.Blocks[0], f, level+1, localVarIndex)...) + lines = append(lines, p.glslBlock(&s.Blocks[0], level+1, localVarIndex)...) lines = append(lines, fmt.Sprintf("%s}", idt)) case Continue: lines = append(lines, idt+"continue;") @@ -246,5 +265,3 @@ func (p *Program) glslBlock(b *Block, f *Func, level int, localVarIndex int) []s return lines } - -// TODO: Distinguish regular functions, vertex functions and fragment functions. e.g., Treat gl_Position correctly. diff --git a/internal/shaderir/ir_test.go b/internal/shaderir/ir_test.go index f8f4a7a28..422707d05 100644 --- a/internal/shaderir/ir_test.go +++ b/internal/shaderir/ir_test.go @@ -521,6 +521,51 @@ varying vec3 V0;`, for (int l3 = 0; l3 < 100; l3++) { l2 = l0; } +}`, + }, + { + Name: "VertexFunc", + Program: Program{ + Uniforms: []Type{ + {Main: Float}, + }, + Attributes: []Type{ + {Main: Vec4}, + {Main: Float}, + {Main: Vec2}, + }, + Varyings: []Type{ + {Main: Float}, + {Main: Vec2}, + }, + VertexFunc: VertexFunc{ + Block: block( + nil, + assignStmt( + varNameExpr(Local, 5), + varNameExpr(Local, 0), + ), + assignStmt( + varNameExpr(Local, 3), + varNameExpr(Local, 1), + ), + assignStmt( + varNameExpr(Local, 4), + varNameExpr(Local, 2), + ), + ), + }, + }, + Glsl: `uniform float U0; +attribute vec4 A0; +attribute float A1; +attribute vec2 A2; +varying float V0; +varying vec2 V1; +void main(void) { + gl_Position = A0; + V0 = A1; + V1 = A2; }`, }, } diff --git a/internal/shaderir/program.go b/internal/shaderir/program.go index f6a8d6b14..70f38f8f9 100644 --- a/internal/shaderir/program.go +++ b/internal/shaderir/program.go @@ -15,12 +15,12 @@ package shaderir type Program struct { - Uniforms []Type - Attributes []Type - Varyings []Type - Funcs []Func - VertexEntry string - FragmentEntry string + Uniforms []Type + Attributes []Type + Varyings []Type + Funcs []Func + VertexFunc VertexFunc + FragmentFunc FragmentFunc structNames map[string]string structTypes []Type @@ -37,6 +37,21 @@ type Func struct { Block Block } +// VertexFunc takes pseudo params, and the number if len(attributes) + len(varyings) + 1. +// If 0 <= index < len(attributes), the params are in-params and treated as attribute variables. +// If len(attributes) <= index < len(attributes) + len(varyings), the params are out-params and treated as varying +// variables. +// The last param represents the position in vec4 (gl_Position in GLSL). +type VertexFunc struct { + Block Block +} + +// FragmentFunc takes pseudo in-params, and the number is len(varyings) + 1. +// The last param represents the coordinate of the fragment (gl_FragCoord in GLSL) +type FragmentFunc struct { + Block Block +} + type Block struct { LocalVars []Type Stmts []Stmt @@ -100,8 +115,6 @@ type VariableType int const ( Uniform VariableType = iota - Attribute - Varying Local )