mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 02:38:53 +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