mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
Add shaderir
This commit is contained in:
parent
6d182c4b55
commit
a5d570a7a8
71
internal/shaderir/glsl.go
Normal file
71
internal/shaderir/glsl.go
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// Copyright 2020 The Ebiten Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package shaderir
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *Program) structName(t *Type) string {
|
||||||
|
if t.MainType != Struct {
|
||||||
|
panic("shaderir: the given type at structName must be a struct")
|
||||||
|
}
|
||||||
|
s := t.serialize()
|
||||||
|
if n, ok := p.structNames[s]; ok {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
n := fmt.Sprintf("S%d", len(p.structNames))
|
||||||
|
p.structNames[s] = n
|
||||||
|
p.structTypes = append(p.structTypes, *t)
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Program) Glsl() string {
|
||||||
|
p.structNames = map[string]string{}
|
||||||
|
p.structTypes = nil
|
||||||
|
|
||||||
|
var lines []string
|
||||||
|
for _, u := range p.Uniforms {
|
||||||
|
lines = append(lines, fmt.Sprintf("uniform %s;", p.glslVarDecl(&u.Type, u.Name)))
|
||||||
|
}
|
||||||
|
|
||||||
|
var stLines []string
|
||||||
|
for i, t := range p.structTypes {
|
||||||
|
stLines = append(stLines, fmt.Sprintf("struct S%d {", i))
|
||||||
|
for j, st := range t.SubTypes {
|
||||||
|
stLines = append(stLines, fmt.Sprintf("\t%s;", p.glslVarDecl(&st, fmt.Sprintf("M%d", j))))
|
||||||
|
}
|
||||||
|
stLines = append(stLines, "};")
|
||||||
|
}
|
||||||
|
lines = append(stLines, lines...)
|
||||||
|
|
||||||
|
return strings.Join(lines, "\n") + "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Program) glslVarDecl(t *Type, varname string) string {
|
||||||
|
switch t.MainType {
|
||||||
|
case None:
|
||||||
|
return "?(none)"
|
||||||
|
case Image2D:
|
||||||
|
panic("not implemented")
|
||||||
|
case Array:
|
||||||
|
return fmt.Sprintf("")
|
||||||
|
case Struct:
|
||||||
|
return fmt.Sprintf("%s %s", p.structName(t), varname)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("%s %s", t.MainType.Glsl(), varname)
|
||||||
|
}
|
||||||
|
}
|
74
internal/shaderir/ir_test.go
Normal file
74
internal/shaderir/ir_test.go
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
// Copyright 2020 The Ebiten Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package shaderir_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/hajimehoshi/ebiten/internal/shaderir"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestOutput(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
Name string
|
||||||
|
Program Program
|
||||||
|
Glsl string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Name: "Empty",
|
||||||
|
Program: Program{},
|
||||||
|
Glsl: ``,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Uniform",
|
||||||
|
Program: Program{
|
||||||
|
Uniforms: []Variable{
|
||||||
|
{
|
||||||
|
Name: "U1",
|
||||||
|
Type: Type{MainType: Float},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Glsl: `uniform float U1;`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "UniformStruct",
|
||||||
|
Program: Program{
|
||||||
|
Uniforms: []Variable{
|
||||||
|
{
|
||||||
|
Name: "U1",
|
||||||
|
Type: Type{
|
||||||
|
MainType: Struct,
|
||||||
|
SubTypes: []Type{
|
||||||
|
{MainType: Float},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Glsl: `struct S0 {
|
||||||
|
float M0;
|
||||||
|
};
|
||||||
|
uniform S0 U1;`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range tests {
|
||||||
|
got := tc.Program.Glsl()
|
||||||
|
want := tc.Glsl + "\n"
|
||||||
|
if got != want {
|
||||||
|
t.Errorf("%s: got: %s, want: %s", tc.Name, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
111
internal/shaderir/program.go
Normal file
111
internal/shaderir/program.go
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// Copyright 2020 The Ebiten Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package shaderir
|
||||||
|
|
||||||
|
type Program struct {
|
||||||
|
Uniforms []Variable
|
||||||
|
Attributes []Variable
|
||||||
|
Varyings []Variable
|
||||||
|
Funcs []Func
|
||||||
|
VertexEntry string
|
||||||
|
FragmentEntry string
|
||||||
|
|
||||||
|
structNames map[string]string
|
||||||
|
structTypes []Type
|
||||||
|
}
|
||||||
|
|
||||||
|
type Variable struct {
|
||||||
|
Name string
|
||||||
|
Type Type
|
||||||
|
}
|
||||||
|
|
||||||
|
type Func struct {
|
||||||
|
Name string
|
||||||
|
InParams []Type
|
||||||
|
OutParams []Type
|
||||||
|
Block Block
|
||||||
|
}
|
||||||
|
|
||||||
|
type Block struct {
|
||||||
|
LocalVars []Type
|
||||||
|
Stmts []Stmt
|
||||||
|
}
|
||||||
|
|
||||||
|
type Stmt struct {
|
||||||
|
Type StmtType
|
||||||
|
Exprs []Expr
|
||||||
|
Condition Expr
|
||||||
|
ElseStmts []Expr
|
||||||
|
ForInit Expr
|
||||||
|
ForRest Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
type StmtType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
ExprStmt StmtType = iota
|
||||||
|
Assign
|
||||||
|
If
|
||||||
|
For
|
||||||
|
Continue
|
||||||
|
Break
|
||||||
|
Return
|
||||||
|
Discard
|
||||||
|
)
|
||||||
|
|
||||||
|
type Expr struct {
|
||||||
|
Type ExprType
|
||||||
|
Exprs []Expr
|
||||||
|
Value string
|
||||||
|
Op Op
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExprType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
Literal ExprType = iota
|
||||||
|
Ident
|
||||||
|
LocalVarID
|
||||||
|
Unary
|
||||||
|
Binary
|
||||||
|
Call
|
||||||
|
Selector
|
||||||
|
Index
|
||||||
|
)
|
||||||
|
|
||||||
|
type Op string
|
||||||
|
|
||||||
|
const (
|
||||||
|
Add Op = "+"
|
||||||
|
Sub Op = "-"
|
||||||
|
Neg Op = "!"
|
||||||
|
Mul Op = "*"
|
||||||
|
Div Op = "/"
|
||||||
|
Mod Op = "%"
|
||||||
|
LShift Op = "<<"
|
||||||
|
RShift Op = ">>"
|
||||||
|
LT Op = "<"
|
||||||
|
LE Op = "<="
|
||||||
|
GT Op = ">"
|
||||||
|
GE Op = ">="
|
||||||
|
Eq Op = "=="
|
||||||
|
NE Op = "!="
|
||||||
|
And Op = "&"
|
||||||
|
Xor Op = "^"
|
||||||
|
Or Op = "|"
|
||||||
|
AndAnd Op = "&&"
|
||||||
|
OrOr Op = "||"
|
||||||
|
Cond Op = "?:"
|
||||||
|
)
|
113
internal/shaderir/type.go
Normal file
113
internal/shaderir/type.go
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
// Copyright 2020 The Ebiten Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package shaderir
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Type struct {
|
||||||
|
MainType BasicType
|
||||||
|
SubTypes []Type
|
||||||
|
Length int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Type) serialize() string {
|
||||||
|
switch t.MainType {
|
||||||
|
case None:
|
||||||
|
return "none"
|
||||||
|
case Bool:
|
||||||
|
return "bool"
|
||||||
|
case Float:
|
||||||
|
return "float"
|
||||||
|
case Vec2:
|
||||||
|
return "vec2"
|
||||||
|
case Vec3:
|
||||||
|
return "vec3"
|
||||||
|
case Vec4:
|
||||||
|
return "vec4"
|
||||||
|
case Mat2:
|
||||||
|
return "mat2"
|
||||||
|
case Mat3:
|
||||||
|
return "mat3"
|
||||||
|
case Mat4:
|
||||||
|
return "mat4"
|
||||||
|
case Image2D:
|
||||||
|
return "image2d"
|
||||||
|
case Array:
|
||||||
|
return fmt.Sprintf("%s[%d]", t.SubTypes[0].serialize(), t.Length)
|
||||||
|
case Struct:
|
||||||
|
str := "struct{"
|
||||||
|
sub := make([]string, 0, len(t.SubTypes))
|
||||||
|
for _, st := range t.SubTypes {
|
||||||
|
sub = append(sub, st.serialize())
|
||||||
|
}
|
||||||
|
str += strings.Join(sub, ",")
|
||||||
|
str += "}"
|
||||||
|
return str
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("?(unknown type: %d)", t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type BasicType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
None BasicType = iota
|
||||||
|
Bool
|
||||||
|
Float
|
||||||
|
Vec2
|
||||||
|
Vec3
|
||||||
|
Vec4
|
||||||
|
Mat2
|
||||||
|
Mat3
|
||||||
|
Mat4
|
||||||
|
Image2D
|
||||||
|
Array
|
||||||
|
Struct
|
||||||
|
)
|
||||||
|
|
||||||
|
func (t BasicType) Glsl() string {
|
||||||
|
switch t {
|
||||||
|
case None:
|
||||||
|
return "?(none)"
|
||||||
|
case Bool:
|
||||||
|
return "bool"
|
||||||
|
case Float:
|
||||||
|
return "float"
|
||||||
|
case Vec2:
|
||||||
|
return "vec2"
|
||||||
|
case Vec3:
|
||||||
|
return "vec3"
|
||||||
|
case Vec4:
|
||||||
|
return "vec4"
|
||||||
|
case Mat2:
|
||||||
|
return "mat2"
|
||||||
|
case Mat3:
|
||||||
|
return "mat3"
|
||||||
|
case Mat4:
|
||||||
|
return "mat4"
|
||||||
|
case Image2D:
|
||||||
|
return "?(image2d)"
|
||||||
|
case Array:
|
||||||
|
// First-class array is not available on GLSL ES 2.
|
||||||
|
return "?(array)"
|
||||||
|
case Struct:
|
||||||
|
return "?(struct)"
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("?(unknown type: %d)", t)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user