type.go (3649B)
1 // Copyright 2020 The Ebiten Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package shaderir 16 17 import ( 18 "fmt" 19 "strings" 20 ) 21 22 type Type struct { 23 Main BasicType 24 Sub []Type 25 Length int 26 } 27 28 func (t *Type) Equal(rhs *Type) bool { 29 if t.Main != rhs.Main { 30 return false 31 } 32 if t.Length != rhs.Length { 33 return false 34 } 35 if len(t.Sub) != len(rhs.Sub) { 36 return false 37 } 38 for i, s := range t.Sub { 39 if !s.Equal(&rhs.Sub[i]) { 40 return false 41 } 42 } 43 return true 44 } 45 46 func (t *Type) String() string { 47 switch t.Main { 48 case None: 49 return "none" 50 case Bool: 51 return "bool" 52 case Int: 53 return "int" 54 case Float: 55 return "float" 56 case Vec2: 57 return "vec2" 58 case Vec3: 59 return "vec3" 60 case Vec4: 61 return "vec4" 62 case Mat2: 63 return "mat2" 64 case Mat3: 65 return "mat3" 66 case Mat4: 67 return "mat4" 68 case Array: 69 return fmt.Sprintf("%s[%d]", t.Sub[0].String(), t.Length) 70 case Struct: 71 str := "struct{" 72 sub := make([]string, 0, len(t.Sub)) 73 for _, st := range t.Sub { 74 sub = append(sub, st.String()) 75 } 76 str += strings.Join(sub, ",") 77 str += "}" 78 return str 79 default: 80 return fmt.Sprintf("?(unknown type: %d)", t) 81 } 82 } 83 84 func (t *Type) FloatNum() int { 85 switch t.Main { 86 case Float: 87 return 1 88 case Vec2: 89 return 2 90 case Vec3: 91 return 3 92 case Vec4: 93 return 4 94 case Mat2: 95 return 4 96 case Mat3: 97 return 9 98 case Mat4: 99 return 16 100 case Array: 101 return t.Length * t.Sub[0].FloatNum() 102 default: // TODO: Parse a struct correctly 103 return -1 104 } 105 } 106 107 type BasicType int 108 109 const ( 110 None BasicType = iota 111 Bool 112 Int 113 Float 114 Vec2 115 Vec3 116 Vec4 117 Mat2 118 Mat3 119 Mat4 120 Array 121 Struct 122 ) 123 124 func descendantLocalVars(block, target *Block) ([]Type, bool) { 125 if block == target { 126 return block.LocalVars, true 127 } 128 129 var ts []Type 130 for _, s := range block.Stmts { 131 for _, b := range s.Blocks { 132 if ts2, found := descendantLocalVars(b, target); found { 133 n := b.LocalVarIndexOffset - block.LocalVarIndexOffset 134 ts = append(ts, block.LocalVars[:n]...) 135 ts = append(ts, ts2...) 136 return ts, true 137 } 138 } 139 } 140 return nil, false 141 } 142 143 func localVariableType(p *Program, topBlock, block *Block, absidx int) Type { 144 // TODO: Rename this function (truly-local variable?) 145 var ts []Type 146 for _, f := range p.Funcs { 147 if f.Block == topBlock { 148 ts = append(f.InParams, f.OutParams...) 149 break 150 } 151 } 152 153 ts2, _ := descendantLocalVars(topBlock, block) 154 ts = append(ts, ts2...) 155 return ts[absidx] 156 } 157 158 func (p *Program) LocalVariableType(topBlock, block *Block, idx int) Type { 159 switch topBlock { 160 case p.VertexFunc.Block: 161 na := len(p.Attributes) 162 nv := len(p.Varyings) 163 switch { 164 case idx < na: 165 return p.Attributes[idx] 166 case idx == na: 167 return Type{Main: Vec4} 168 case idx < na+nv+1: 169 return p.Varyings[idx-na-1] 170 default: 171 return localVariableType(p, topBlock, block, idx-(na+nv+1)) 172 } 173 case p.FragmentFunc.Block: 174 nv := len(p.Varyings) 175 switch { 176 case idx == 0: 177 return Type{Main: Vec4} 178 case idx < nv+1: 179 return p.Varyings[idx-1] 180 case idx == nv+1: 181 return Type{Main: Vec4} 182 default: 183 return localVariableType(p, topBlock, block, idx-(nv+2)) 184 } 185 default: 186 return localVariableType(p, topBlock, block, idx) 187 } 188 }