shader.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951
  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. package shader
  15. import (
  16. "bufio"
  17. "bytes"
  18. "fmt"
  19. "go/ast"
  20. gconstant "go/constant"
  21. "go/parser"
  22. "go/token"
  23. "regexp"
  24. "strings"
  25. "github.com/hajimehoshi/ebiten/v2/internal/shaderir"
  26. )
  27. type variable struct {
  28. name string
  29. typ shaderir.Type
  30. forLoopCounter bool
  31. }
  32. type constant struct {
  33. name string
  34. typ shaderir.Type
  35. value gconstant.Value
  36. }
  37. type function struct {
  38. name string
  39. ir shaderir.Func
  40. }
  41. type compileState struct {
  42. fs *token.FileSet
  43. vertexEntry string
  44. fragmentEntry string
  45. unit shaderir.Unit
  46. ir shaderir.Program
  47. funcs []function
  48. global block
  49. errs []string
  50. }
  51. func (cs *compileState) findFunction(name string) (int, bool) {
  52. for i, f := range cs.funcs {
  53. if f.name == name {
  54. return i, true
  55. }
  56. }
  57. return 0, false
  58. }
  59. func (cs *compileState) findUniformVariable(name string) (int, bool) {
  60. for i, u := range cs.ir.UniformNames {
  61. if u == name {
  62. return i, true
  63. }
  64. }
  65. return 0, false
  66. }
  67. type typ struct {
  68. name string
  69. ir shaderir.Type
  70. }
  71. type block struct {
  72. types []typ
  73. vars []variable
  74. unusedVars map[int]token.Pos
  75. consts []constant
  76. pos token.Pos
  77. outer *block
  78. ir *shaderir.Block
  79. }
  80. func (b *block) totalLocalVariableCount() int {
  81. c := len(b.vars)
  82. if b.outer != nil {
  83. c += b.outer.totalLocalVariableCount()
  84. }
  85. return c
  86. }
  87. func (b *block) addNamedLocalVariable(name string, typ shaderir.Type, pos token.Pos) {
  88. b.vars = append(b.vars, variable{
  89. name: name,
  90. typ: typ,
  91. })
  92. if name == "_" {
  93. return
  94. }
  95. idx := len(b.vars) - 1
  96. if b.unusedVars == nil {
  97. b.unusedVars = map[int]token.Pos{}
  98. }
  99. b.unusedVars[idx] = pos
  100. }
  101. func (b *block) findLocalVariable(name string, markLocalVariableUsed bool) (int, shaderir.Type, bool) {
  102. if name == "" || name == "_" {
  103. panic("shader: variable name must be non-empty and non-underscore")
  104. }
  105. idx := 0
  106. for outer := b.outer; outer != nil; outer = outer.outer {
  107. idx += len(outer.vars)
  108. }
  109. for i, v := range b.vars {
  110. if v.name == name {
  111. if markLocalVariableUsed {
  112. delete(b.unusedVars, i)
  113. }
  114. return idx + i, v.typ, true
  115. }
  116. }
  117. if b.outer != nil {
  118. return b.outer.findLocalVariable(name, markLocalVariableUsed)
  119. }
  120. return 0, shaderir.Type{}, false
  121. }
  122. func (b *block) findLocalVariableByIndex(idx int) (shaderir.Type, bool) {
  123. bs := []*block{b}
  124. for outer := b.outer; outer != nil; outer = outer.outer {
  125. bs = append(bs, outer)
  126. }
  127. for i := len(bs) - 1; i >= 0; i-- {
  128. if len(bs[i].vars) <= idx {
  129. idx -= len(bs[i].vars)
  130. continue
  131. }
  132. return bs[i].vars[idx].typ, true
  133. }
  134. return shaderir.Type{}, false
  135. }
  136. func (b *block) findConstant(name string) (constant, bool) {
  137. if name == "" || name == "_" {
  138. panic("shader: constant name must be non-empty and non-underscore")
  139. }
  140. for _, c := range b.consts {
  141. if c.name == name {
  142. return c, true
  143. }
  144. }
  145. if b.outer != nil {
  146. return b.outer.findConstant(name)
  147. }
  148. return constant{}, false
  149. }
  150. type ParseError struct {
  151. errs []string
  152. }
  153. func (p *ParseError) Error() string {
  154. return strings.Join(p.errs, "\n")
  155. }
  156. func Compile(src []byte, vertexEntry, fragmentEntry string, textureCount int) (*shaderir.Program, error) {
  157. unit, err := ParseCompilerDirectives(src)
  158. if err != nil {
  159. return nil, err
  160. }
  161. fs := token.NewFileSet()
  162. f, err := parser.ParseFile(fs, "", src, parser.AllErrors)
  163. if err != nil {
  164. return nil, err
  165. }
  166. s := &compileState{
  167. fs: fs,
  168. vertexEntry: vertexEntry,
  169. fragmentEntry: fragmentEntry,
  170. unit: unit,
  171. }
  172. s.ir.SourceHash = shaderir.CalcSourceHash(src)
  173. s.global.ir = &shaderir.Block{}
  174. s.parse(f)
  175. if len(s.errs) > 0 {
  176. return nil, &ParseError{s.errs}
  177. }
  178. // TODO: Resolve identifiers?
  179. // TODO: Resolve constants
  180. // TODO: Make a call graph and reorder the elements.
  181. s.ir.TextureCount = textureCount
  182. return &s.ir, nil
  183. }
  184. func ParseCompilerDirectives(src []byte) (shaderir.Unit, error) {
  185. // TODO: Change the unit to pixels in v3 (#2645).
  186. unit := shaderir.Texels
  187. // Go's whitespace is U+0020 (SP), U+0009 (\t), U+000d (\r), and U+000A (\n).
  188. // See https://go.dev/ref/spec#Tokens
  189. reUnit := regexp.MustCompile(`^[ \t\r\n]*//kage:unit\s+([^ \t\r\n]+)[ \t\r\n]*$`)
  190. var unitParsed bool
  191. buf := bytes.NewBuffer(src)
  192. s := bufio.NewScanner(buf)
  193. for s.Scan() {
  194. m := reUnit.FindStringSubmatch(s.Text())
  195. if m == nil {
  196. continue
  197. }
  198. if unitParsed {
  199. return 0, fmt.Errorf("shader: at most one //kage:unit can exist in a shader")
  200. }
  201. switch m[1] {
  202. case "pixels":
  203. unit = shaderir.Pixels
  204. case "texels":
  205. unit = shaderir.Texels
  206. default:
  207. return 0, fmt.Errorf("shader: invalid value for //kage:unit: %s", m[1])
  208. }
  209. unitParsed = true
  210. }
  211. return unit, nil
  212. }
  213. func (s *compileState) addError(pos token.Pos, str string) {
  214. p := s.fs.Position(pos)
  215. s.errs = append(s.errs, fmt.Sprintf("%s: %s", p, str))
  216. }
  217. func (cs *compileState) parse(f *ast.File) {
  218. cs.ir.Unit = cs.unit
  219. // Parse GenDecl for global variables, and then parse functions.
  220. for _, d := range f.Decls {
  221. if _, ok := d.(*ast.FuncDecl); !ok {
  222. ss, ok := cs.parseDecl(&cs.global, "", d)
  223. if !ok {
  224. return
  225. }
  226. cs.global.ir.Stmts = append(cs.global.ir.Stmts, ss...)
  227. }
  228. }
  229. // Sort the uniform variable so that special variable starting with __ should come first.
  230. var unames []string
  231. var utypes []shaderir.Type
  232. for i, u := range cs.ir.UniformNames {
  233. if strings.HasPrefix(u, "__") {
  234. unames = append(unames, u)
  235. utypes = append(utypes, cs.ir.Uniforms[i])
  236. }
  237. }
  238. // TODO: Check len(unames) == graphics.PreservedUniformVariablesNum. Unfortunately this is not true on tests.
  239. for i, u := range cs.ir.UniformNames {
  240. if !strings.HasPrefix(u, "__") {
  241. unames = append(unames, u)
  242. utypes = append(utypes, cs.ir.Uniforms[i])
  243. }
  244. }
  245. cs.ir.UniformNames = unames
  246. cs.ir.Uniforms = utypes
  247. // Parse function names so that any other function call the others.
  248. // The function data is provisional and will be updated soon.
  249. var vertexInParams []variable
  250. var vertexOutParams []variable
  251. var fragmentInParams []variable
  252. var fragmentOutParams []variable
  253. var fragmentReturnType shaderir.Type
  254. for _, d := range f.Decls {
  255. fd, ok := d.(*ast.FuncDecl)
  256. if !ok {
  257. continue
  258. }
  259. n := fd.Name.Name
  260. for _, f := range cs.funcs {
  261. if f.name == n {
  262. cs.addError(d.Pos(), fmt.Sprintf("redeclared function: %s", n))
  263. return
  264. }
  265. }
  266. inParams, outParams, ret := cs.parseFuncParams(&cs.global, n, fd)
  267. if n == cs.vertexEntry {
  268. vertexInParams = inParams
  269. vertexOutParams = outParams
  270. continue
  271. }
  272. if n == cs.fragmentEntry {
  273. fragmentInParams = inParams
  274. fragmentOutParams = outParams
  275. fragmentReturnType = ret
  276. continue
  277. }
  278. var inT, outT []shaderir.Type
  279. for _, v := range inParams {
  280. inT = append(inT, v.typ)
  281. }
  282. for _, v := range outParams {
  283. outT = append(outT, v.typ)
  284. }
  285. cs.funcs = append(cs.funcs, function{
  286. name: n,
  287. ir: shaderir.Func{
  288. Index: len(cs.funcs),
  289. InParams: inT,
  290. OutParams: outT,
  291. Return: ret,
  292. Block: &shaderir.Block{},
  293. },
  294. })
  295. }
  296. // Check varying variables.
  297. // In testings, there might not be vertex and fragment entry points.
  298. if len(vertexOutParams) > 0 && len(fragmentInParams) > 0 {
  299. for i, p := range vertexOutParams {
  300. if len(fragmentInParams) <= i {
  301. break
  302. }
  303. t := fragmentInParams[i].typ
  304. if !p.typ.Equal(&t) {
  305. name := fragmentInParams[i].name
  306. cs.addError(0, fmt.Sprintf("fragment argument %s must be %s but was %s", name, p.typ.String(), t.String()))
  307. }
  308. }
  309. // The first out-param is treated as gl_Position in GLSL.
  310. if vertexOutParams[0].typ.Main != shaderir.Vec4 {
  311. cs.addError(0, "vertex entry point must have at least one returning vec4 value for a position")
  312. }
  313. if len(fragmentOutParams) != 0 || fragmentReturnType.Main != shaderir.Vec4 {
  314. cs.addError(0, "fragment entry point must have one returning vec4 value for a color")
  315. }
  316. }
  317. if len(cs.errs) > 0 {
  318. return
  319. }
  320. // Set attribute and varying veraibles.
  321. for _, p := range vertexInParams {
  322. cs.ir.Attributes = append(cs.ir.Attributes, p.typ)
  323. }
  324. if len(vertexOutParams) > 0 {
  325. // TODO: Check that these params are not arrays or structs
  326. // The 0th argument is a special variable for position and is not included in varying variables.
  327. for _, p := range vertexOutParams[1:] {
  328. cs.ir.Varyings = append(cs.ir.Varyings, p.typ)
  329. }
  330. }
  331. // Parse functions.
  332. for _, d := range f.Decls {
  333. if f, ok := d.(*ast.FuncDecl); ok {
  334. ss, ok := cs.parseDecl(&cs.global, f.Name.Name, d)
  335. if !ok {
  336. return
  337. }
  338. cs.global.ir.Stmts = append(cs.global.ir.Stmts, ss...)
  339. }
  340. }
  341. if len(cs.errs) > 0 {
  342. return
  343. }
  344. for _, f := range cs.funcs {
  345. cs.ir.Funcs = append(cs.ir.Funcs, f.ir)
  346. }
  347. }
  348. func (cs *compileState) parseDecl(b *block, fname string, d ast.Decl) ([]shaderir.Stmt, bool) {
  349. var stmts []shaderir.Stmt
  350. switch d := d.(type) {
  351. case *ast.GenDecl:
  352. switch d.Tok {
  353. case token.TYPE:
  354. // TODO: Parse other types
  355. for _, s := range d.Specs {
  356. s := s.(*ast.TypeSpec)
  357. t, ok := cs.parseType(b, fname, s.Type)
  358. if !ok {
  359. return nil, false
  360. }
  361. n := s.Name.Name
  362. for _, t := range b.types {
  363. if t.name == n {
  364. cs.addError(s.Pos(), fmt.Sprintf("%s redeclared in this block", n))
  365. return nil, false
  366. }
  367. }
  368. b.types = append(b.types, typ{
  369. name: n,
  370. ir: t,
  371. })
  372. }
  373. case token.CONST:
  374. for _, s := range d.Specs {
  375. s := s.(*ast.ValueSpec)
  376. cs, ok := cs.parseConstant(b, fname, s)
  377. if !ok {
  378. return nil, false
  379. }
  380. b.consts = append(b.consts, cs...)
  381. }
  382. case token.VAR:
  383. for _, s := range d.Specs {
  384. s := s.(*ast.ValueSpec)
  385. vs, inits, ss, ok := cs.parseVariable(b, fname, s)
  386. if !ok {
  387. return nil, false
  388. }
  389. stmts = append(stmts, ss...)
  390. if b == &cs.global {
  391. if len(inits) > 0 {
  392. cs.addError(s.Pos(), "a uniform variable cannot have initial values")
  393. return nil, false
  394. }
  395. // TODO: Should rhs be ignored?
  396. for i, v := range vs {
  397. if !strings.HasPrefix(v.name, "__") {
  398. if v.name[0] < 'A' || 'Z' < v.name[0] {
  399. cs.addError(s.Names[i].Pos(), fmt.Sprintf("global variables must be exposed: %s", v.name))
  400. }
  401. }
  402. for _, name := range cs.ir.UniformNames {
  403. if name == v.name {
  404. cs.addError(s.Pos(), fmt.Sprintf("%s redeclared in this block", name))
  405. return nil, false
  406. }
  407. }
  408. cs.ir.UniformNames = append(cs.ir.UniformNames, v.name)
  409. cs.ir.Uniforms = append(cs.ir.Uniforms, v.typ)
  410. }
  411. continue
  412. }
  413. // base must be obtained before adding the variables.
  414. base := b.totalLocalVariableCount()
  415. for _, v := range vs {
  416. b.addNamedLocalVariable(v.name, v.typ, d.Pos())
  417. }
  418. if len(inits) > 0 {
  419. for i := range vs {
  420. stmts = append(stmts, shaderir.Stmt{
  421. Type: shaderir.Assign,
  422. Exprs: []shaderir.Expr{
  423. {
  424. Type: shaderir.LocalVariable,
  425. Index: base + i,
  426. },
  427. inits[i],
  428. },
  429. })
  430. }
  431. }
  432. }
  433. case token.IMPORT:
  434. cs.addError(d.Pos(), "import is forbidden")
  435. default:
  436. cs.addError(d.Pos(), "unexpected token")
  437. }
  438. case *ast.FuncDecl:
  439. f, ok := cs.parseFunc(b, d)
  440. if !ok {
  441. return nil, false
  442. }
  443. if b != &cs.global {
  444. cs.addError(d.Pos(), "non-global function is not implemented")
  445. return nil, false
  446. }
  447. switch d.Name.Name {
  448. case cs.vertexEntry:
  449. cs.ir.VertexFunc.Block = f.ir.Block
  450. case cs.fragmentEntry:
  451. cs.ir.FragmentFunc.Block = f.ir.Block
  452. default:
  453. // The function is already registered for their names.
  454. for i := range cs.funcs {
  455. if cs.funcs[i].name == d.Name.Name {
  456. // Index is already determined by the provisional parsing.
  457. f.ir.Index = cs.funcs[i].ir.Index
  458. cs.funcs[i] = f
  459. break
  460. }
  461. }
  462. }
  463. default:
  464. cs.addError(d.Pos(), "unexpected decl")
  465. return nil, false
  466. }
  467. return stmts, true
  468. }
  469. // functionReturnTypes returns the original returning value types, if the given expression is call.
  470. //
  471. // Note that parseExpr returns the returning types for IR, not the original function.
  472. func (cs *compileState) functionReturnTypes(block *block, expr ast.Expr) ([]shaderir.Type, bool) {
  473. call, ok := expr.(*ast.CallExpr)
  474. if !ok {
  475. return nil, false
  476. }
  477. ident, ok := call.Fun.(*ast.Ident)
  478. if !ok {
  479. return nil, false
  480. }
  481. for _, f := range cs.funcs {
  482. if f.name == ident.Name {
  483. // TODO: Is it correct to combine out-params and return param?
  484. ts := f.ir.OutParams
  485. if f.ir.Return.Main != shaderir.None {
  486. ts = append(ts, f.ir.Return)
  487. }
  488. return ts, true
  489. }
  490. }
  491. return nil, false
  492. }
  493. func (s *compileState) parseVariable(block *block, fname string, vs *ast.ValueSpec) ([]variable, []shaderir.Expr, []shaderir.Stmt, bool) {
  494. if len(vs.Names) != len(vs.Values) && len(vs.Values) != 1 && len(vs.Values) != 0 {
  495. s.addError(vs.Pos(), "the numbers of lhs and rhs don't match")
  496. return nil, nil, nil, false
  497. }
  498. var declt shaderir.Type
  499. if vs.Type != nil {
  500. var ok bool
  501. declt, ok = s.parseType(block, fname, vs.Type)
  502. if !ok {
  503. return nil, nil, nil, false
  504. }
  505. }
  506. var (
  507. vars []variable
  508. inits []shaderir.Expr
  509. stmts []shaderir.Stmt
  510. )
  511. // These variables are used only in multiple-value context.
  512. var inittypes []shaderir.Type
  513. var initexprs []shaderir.Expr
  514. for i, n := range vs.Names {
  515. t := declt
  516. switch {
  517. case len(vs.Values) == 0:
  518. // No initialization
  519. case len(vs.Names) == len(vs.Values):
  520. // Single-value context
  521. init := vs.Values[i]
  522. es, rts, ss, ok := s.parseExpr(block, fname, init, true)
  523. if !ok {
  524. return nil, nil, nil, false
  525. }
  526. if t.Main == shaderir.None {
  527. ts, ok := s.functionReturnTypes(block, init)
  528. if !ok {
  529. ts = rts
  530. }
  531. if len(ts) > 1 {
  532. s.addError(vs.Pos(), "the numbers of lhs and rhs don't match")
  533. }
  534. t = ts[0]
  535. if t.Main == shaderir.None {
  536. t = toDefaultType(es[0].Const)
  537. }
  538. }
  539. for i, rt := range rts {
  540. if !canAssign(&t, &rt, es[i].Const) {
  541. s.addError(vs.Pos(), fmt.Sprintf("cannot use type %s as type %s in variable declaration", rt.String(), t.String()))
  542. }
  543. }
  544. inits = append(inits, es...)
  545. stmts = append(stmts, ss...)
  546. default:
  547. // Multiple-value context
  548. // See testcase/var_multiple.go for an actual case.
  549. if i == 0 {
  550. init := vs.Values[0]
  551. var ss []shaderir.Stmt
  552. var ok bool
  553. initexprs, inittypes, ss, ok = s.parseExpr(block, fname, init, true)
  554. if !ok {
  555. return nil, nil, nil, false
  556. }
  557. stmts = append(stmts, ss...)
  558. if t.Main == shaderir.None {
  559. ts, ok := s.functionReturnTypes(block, init)
  560. if ok {
  561. inittypes = ts
  562. }
  563. if len(ts) != len(vs.Names) {
  564. s.addError(vs.Pos(), "the numbers of lhs and rhs don't match")
  565. continue
  566. }
  567. }
  568. }
  569. if t.Main == shaderir.None && len(inittypes) > 0 {
  570. t = inittypes[i]
  571. // TODO: Is it possible to reach this?
  572. if t.Main == shaderir.None {
  573. t = toDefaultType(initexprs[i].Const)
  574. }
  575. }
  576. if !canAssign(&t, &inittypes[i], initexprs[i].Const) {
  577. s.addError(vs.Pos(), fmt.Sprintf("cannot use type %s as type %s in variable declaration", inittypes[i].String(), t.String()))
  578. }
  579. // Add the same initexprs for each variable.
  580. inits = append(inits, initexprs...)
  581. }
  582. name := n.Name
  583. for _, v := range append(block.vars, vars...) {
  584. if v.name == name {
  585. s.addError(vs.Pos(), fmt.Sprintf("duplicated local variable name: %s", name))
  586. return nil, nil, nil, false
  587. }
  588. }
  589. for _, c := range block.consts {
  590. if c.name == name {
  591. s.addError(vs.Pos(), fmt.Sprintf("duplicated local constant/variable name: %s", name))
  592. return nil, nil, nil, false
  593. }
  594. }
  595. vars = append(vars, variable{
  596. name: name,
  597. typ: t,
  598. })
  599. }
  600. return vars, inits, stmts, true
  601. }
  602. func (s *compileState) parseConstant(block *block, fname string, vs *ast.ValueSpec) ([]constant, bool) {
  603. var t shaderir.Type
  604. if vs.Type != nil {
  605. var ok bool
  606. t, ok = s.parseType(block, fname, vs.Type)
  607. if !ok {
  608. return nil, false
  609. }
  610. }
  611. var cs []constant
  612. for i, n := range vs.Names {
  613. name := n.Name
  614. for _, c := range block.consts {
  615. if c.name == name {
  616. s.addError(vs.Pos(), fmt.Sprintf("duplicated local constant name: %s", name))
  617. return nil, false
  618. }
  619. }
  620. for _, v := range block.vars {
  621. if v.name == name {
  622. s.addError(vs.Pos(), fmt.Sprintf("duplicated local constant/variable name: %s", name))
  623. return nil, false
  624. }
  625. }
  626. es, ts, ss, ok := s.parseExpr(block, fname, vs.Values[i], false)
  627. if !ok {
  628. return nil, false
  629. }
  630. if len(ss) > 0 {
  631. s.addError(vs.Pos(), fmt.Sprintf("invalid constant expression: %s", name))
  632. return nil, false
  633. }
  634. if len(ts) != 1 || len(es) != 1 {
  635. s.addError(vs.Pos(), fmt.Sprintf("invalid constant expression: %s", n))
  636. return nil, false
  637. }
  638. if es[0].Type != shaderir.NumberExpr {
  639. s.addError(vs.Pos(), fmt.Sprintf("constant expression must be a number but not: %s", n))
  640. return nil, false
  641. }
  642. if !t.Equal(&shaderir.Type{}) && !canAssign(&t, &ts[0], es[0].Const) {
  643. s.addError(vs.Pos(), fmt.Sprintf("cannot use %v as %s value in constant declaration", es[0].Const, t.String()))
  644. return nil, false
  645. }
  646. c := es[0].Const
  647. switch t.Main {
  648. case shaderir.Bool:
  649. case shaderir.Int:
  650. c = gconstant.ToInt(c)
  651. case shaderir.Float:
  652. c = gconstant.ToFloat(c)
  653. }
  654. cs = append(cs, constant{
  655. name: name,
  656. typ: t,
  657. value: c,
  658. })
  659. }
  660. return cs, true
  661. }
  662. func (cs *compileState) parseFuncParams(block *block, fname string, d *ast.FuncDecl) (in, out []variable, ret shaderir.Type) {
  663. for _, f := range d.Type.Params.List {
  664. t, ok := cs.parseType(block, fname, f.Type)
  665. if !ok {
  666. return
  667. }
  668. for _, n := range f.Names {
  669. in = append(in, variable{
  670. name: n.Name,
  671. typ: t,
  672. })
  673. }
  674. }
  675. if d.Type.Results == nil {
  676. return
  677. }
  678. for _, f := range d.Type.Results.List {
  679. t, ok := cs.parseType(block, fname, f.Type)
  680. if !ok {
  681. return
  682. }
  683. if len(f.Names) == 0 {
  684. out = append(out, variable{
  685. name: "",
  686. typ: t,
  687. })
  688. } else {
  689. for _, n := range f.Names {
  690. out = append(out, variable{
  691. name: n.Name,
  692. typ: t,
  693. })
  694. }
  695. }
  696. }
  697. // If there is only one returning value, it is treated as a returning value.
  698. // An array cannot be a returning value, especially for HLSL (#2923).
  699. //
  700. // For the vertex entry, a parameter (variable) is used as a returning value.
  701. // For example, GLSL doesn't treat gl_Position as a returning value.
  702. // Thus, the returning value is not set for the vertex entry.
  703. // TODO: This can be resolved by having an indirect function like what the fragment entry already does.
  704. // See internal/shaderir/glsl.adjustProgram.
  705. if len(out) == 1 && out[0].name == "" && out[0].typ.Main != shaderir.Array && fname != cs.vertexEntry {
  706. ret = out[0].typ
  707. out = nil
  708. }
  709. return
  710. }
  711. func (cs *compileState) parseFunc(block *block, d *ast.FuncDecl) (function, bool) {
  712. if d.Name == nil {
  713. cs.addError(d.Pos(), "function must have a name")
  714. return function{}, false
  715. }
  716. if d.Name.Name == "init" {
  717. cs.addError(d.Pos(), "init function is not implemented")
  718. return function{}, false
  719. }
  720. if d.Body == nil {
  721. cs.addError(d.Pos(), "function must have a body")
  722. return function{}, false
  723. }
  724. inParams, outParams, returnType := cs.parseFuncParams(block, d.Name.Name, d)
  725. if d.Name.Name == cs.fragmentEntry {
  726. if len(inParams) == 0 {
  727. inParams = append(inParams, variable{
  728. name: "_",
  729. typ: shaderir.Type{Main: shaderir.Vec4},
  730. })
  731. }
  732. // The 0th inParams is a special variable for position and is not included in varying variables.
  733. if diff := len(cs.ir.Varyings) - (len(inParams) - 1); diff > 0 {
  734. // inParams is not enough when the vertex shader has more returning values than the fragment shader's arguments.
  735. orig := len(inParams) - 1
  736. for i := 0; i < diff; i++ {
  737. inParams = append(inParams, variable{
  738. name: "_",
  739. typ: cs.ir.Varyings[orig+i],
  740. })
  741. }
  742. }
  743. }
  744. b, ok := cs.parseBlock(block, d.Name.Name, d.Body.List, inParams, outParams, returnType, true)
  745. if !ok {
  746. return function{}, false
  747. }
  748. if len(outParams) > 0 || returnType.Main != shaderir.None {
  749. var hasReturn func(stmts []shaderir.Stmt) bool
  750. hasReturn = func(stmts []shaderir.Stmt) bool {
  751. for _, stmt := range stmts {
  752. if stmt.Type == shaderir.Return {
  753. return true
  754. }
  755. for _, b := range stmt.Blocks {
  756. if hasReturn(b.Stmts) {
  757. return true
  758. }
  759. }
  760. }
  761. return false
  762. }
  763. if !hasReturn(b.ir.Stmts) {
  764. cs.addError(d.Pos(), fmt.Sprintf("function %s must have a return statement but not", d.Name))
  765. return function{}, false
  766. }
  767. }
  768. var inT, outT []shaderir.Type
  769. for _, v := range inParams {
  770. inT = append(inT, v.typ)
  771. }
  772. for _, v := range outParams {
  773. outT = append(outT, v.typ)
  774. }
  775. return function{
  776. name: d.Name.Name,
  777. ir: shaderir.Func{
  778. InParams: inT,
  779. OutParams: outT,
  780. Return: returnType,
  781. Block: b.ir,
  782. },
  783. }, true
  784. }
  785. func (cs *compileState) parseBlock(outer *block, fname string, stmts []ast.Stmt, inParams, outParams []variable, returnType shaderir.Type, checkLocalVariableUsage bool) (*block, bool) {
  786. var vars []variable
  787. if outer == &cs.global {
  788. vars = make([]variable, 0, len(inParams)+len(outParams))
  789. vars = append(vars, inParams...)
  790. vars = append(vars, outParams...)
  791. }
  792. var offset int
  793. for b := outer; b != nil; b = b.outer {
  794. offset += len(b.vars)
  795. }
  796. if outer == &cs.global {
  797. offset += len(inParams) + len(outParams)
  798. }
  799. block := &block{
  800. vars: vars,
  801. outer: outer,
  802. ir: &shaderir.Block{
  803. LocalVarIndexOffset: offset,
  804. },
  805. }
  806. defer func() {
  807. var offset int
  808. if outer == &cs.global {
  809. offset = len(inParams) + len(outParams)
  810. }
  811. for _, v := range block.vars[offset:] {
  812. if v.forLoopCounter {
  813. block.ir.LocalVars = append(block.ir.LocalVars, shaderir.Type{})
  814. continue
  815. }
  816. block.ir.LocalVars = append(block.ir.LocalVars, v.typ)
  817. }
  818. }()
  819. if outer.outer == nil && len(outParams) > 0 && outParams[0].name != "" {
  820. for i := range outParams {
  821. block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{
  822. Type: shaderir.Init,
  823. InitIndex: len(inParams) + i,
  824. })
  825. }
  826. }
  827. for _, stmt := range stmts {
  828. ss, ok := cs.parseStmt(block, fname, stmt, inParams, outParams, returnType)
  829. if !ok {
  830. return nil, false
  831. }
  832. block.ir.Stmts = append(block.ir.Stmts, ss...)
  833. }
  834. if checkLocalVariableUsage && len(block.unusedVars) > 0 {
  835. for idx, pos := range block.unusedVars {
  836. cs.addError(pos, fmt.Sprintf("local variable %s is not used", block.vars[idx].name))
  837. }
  838. return nil, false
  839. }
  840. return block, true
  841. }