@galacean/engine-shader-compiler 2.0.0-alpha.55 → 2.0.0-alpha.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -156,8 +156,69 @@ function _create_class(Constructor, protoProps, staticProps) {
156
156
  return Constructor;
157
157
  }
158
158
 
159
+ /**
160
+ * Words that ShaderLab accepts as identifiers but GLSL ES 1.00 or 3.00 reserves. GLES100 output also runs as
161
+ * GLSL ES 3.00 on WebGL2, so both versions apply to every target.
162
+ */ var reservedWords = new Set(("asm attribute active atomic_uint case cast centroid class coherent common default double dvec2 dvec3 dvec4 " + "enum extern external filter fixed flat fvec2 fvec3 fvec4 goto half hvec2 hvec3 hvec4 iimage1D iimage1DArray " + "iimage2D iimage2DArray iimage3D iimageBuffer iimageCube image1D image1DArray image2D image2DArray image3D " + "imageBuffer imageCube inline input interface isampler1D isampler1DArray isampler2D isampler2DArray " + "isampler2DMS isampler2DMSArray isampler2DRect isampler3D isamplerBuffer isamplerCube layout long mat2x2 " + "mat2x3 mat2x4 mat3x2 mat3x3 mat3x4 mat4x2 mat4x3 mat4x4 namespace noinline noperspective output packed " + "partition patch public readonly resource restrict sample sampler1D sampler1DArray sampler1DArrayShadow " + "sampler1DShadow sampler2DArray sampler2DArrayShadow sampler2DMS sampler2DMSArray sampler2DRect " + "sampler2DRectShadow sampler2DShadow sampler3D sampler3DRect samplerBuffer samplerCubeShadow short sizeof " + "smooth static subroutine superp switch template this typedef uimage1D uimage1DArray uimage2D uimage2DArray " + "uimage3D uimageBuffer uimageCube uint union unsigned usampler1D usampler1DArray usampler2D usampler2DArray " + "usampler2DMS usampler2DMSArray usampler2DRect usampler3D usamplerBuffer usamplerCube using uvec2 uvec3 uvec4 " + "varying volatile writeonly").split(" "));
163
+ /**
164
+ * Tests whether GLSL ES rejects an identifier that ShaderLab accepts.
165
+ * @param name - Source identifier
166
+ * @returns Whether the identifier uses a reserved word or namespace
167
+ * @internal
168
+ */ function isUnsafeGLSLIdentifier(name) {
169
+ return reservedWords.has(name) || name.startsWith("gl_") || name.includes("__");
170
+ }
171
+ /**
172
+ * Allocates generated identifiers that avoid source identifiers and each other.
173
+ * @internal
174
+ */ var NameAllocator = /*#__PURE__*/ function() {
175
+ function NameAllocator() {
176
+ this._used = new Set();
177
+ this._names = new Map();
178
+ }
179
+ var _proto = NameAllocator.prototype;
180
+ /**
181
+ * Reserves a source identifier so that generated names never shadow it.
182
+ * @param name - Source identifier
183
+ */ _proto.reserve = function reserve(name) {
184
+ this._used.add(name);
185
+ };
186
+ /**
187
+ * Keeps a source identifier when GLSL accepts it, otherwise assigns a legal name to its identity.
188
+ * @param key - Source declaration or namespace identity
189
+ * @param name - Source identifier
190
+ * @returns Identifier used by the declaration and its references
191
+ */ _proto.sourceName = function sourceName(key, name) {
192
+ if (!isUnsafeGLSLIdentifier(name)) return name;
193
+ return this.allocate(key, name.startsWith("gl_") ? "user_" + name : "" + name + "_");
194
+ };
195
+ /**
196
+ * Returns the same identifier for every request with the same key.
197
+ * @param key - Identity of the generated declaration, independent of its spelling
198
+ * @param preferred - Readable base name. Repeated underscores collapse to one, because WebGL rejects `__`
199
+ * @returns An identifier that differs from every reserved and previously allocated name
200
+ */ _proto.allocate = function allocate(key, preferred) {
201
+ var name = this._names.get(key);
202
+ if (name === undefined) {
203
+ var base = preferred.replace(/_{2,}/g, "_");
204
+ var separator = base.endsWith("_") ? "" : "_";
205
+ name = base;
206
+ for(var suffix = 1; this._used.has(name); suffix++)name = "" + base + separator + suffix;
207
+ this._used.add(name);
208
+ this._names.set(key, name);
209
+ }
210
+ return name;
211
+ };
212
+ /** Releases all reservations and allocations between compilation requests. */ _proto.reset = function reset() {
213
+ this._used.clear();
214
+ this._names.clear();
215
+ };
216
+ return NameAllocator;
217
+ }();
218
+
159
219
  /** @internal */ var VisitorContext = /*#__PURE__*/ function() {
160
220
  function VisitorContext() {
221
+ this.names = new NameAllocator();
161
222
  this._lookupSymbol = new internal.SymbolInfo("", null);
162
223
  this._structRoles = new Map();
163
224
  this._vertexUnresolvedVariableRoles = new Map();
@@ -174,16 +235,12 @@ function _create_class(Constructor, protoProps, staticProps) {
174
235
  this._referencedGlobalMacroASTs = [];
175
236
  this._structVariableRoles = new Map();
176
237
  this.codeCache = new Map();
177
- this.fragmentReturnModes = new Map();
178
- this.terminalInterfaceReturns = new Set();
179
238
  this.reset();
180
239
  }
181
240
  var _proto = VisitorContext.prototype;
182
241
  _proto.reset = function reset(resetAll) {
183
242
  if (resetAll === void 0) resetAll = true;
184
243
  this.codeCache.clear();
185
- this.fragmentReturnModes.clear();
186
- this.terminalInterfaceReturns.clear();
187
244
  if (resetAll) {
188
245
  this.attributeStructs.length = 0;
189
246
  this.attributeList.length = 0;
@@ -287,30 +344,6 @@ function _create_class(Constructor, protoProps, staticProps) {
287
344
  }
288
345
  return resolvedRole;
289
346
  };
290
- /**
291
- * Marks a value-return belonging to a fragment entry for backend lowering.
292
- * @param statement - Exact return statement identity.
293
- * @param mode - Fragment output contract of the containing entry declaration.
294
- */ _proto.registerFragmentReturn = function registerFragmentReturn(statement, mode) {
295
- this.fragmentReturnModes.set(statement, mode);
296
- };
297
- /**
298
- * Finds the output contract for a fragment-entry return statement.
299
- * @param statement - Return statement identity.
300
- * @returns Output mode, or `undefined` for ordinary helper/vertex returns.
301
- */ _proto.getFragmentReturnMode = function getFragmentReturnMode(statement) {
302
- return this.fragmentReturnModes.get(statement);
303
- };
304
- /** Marks a syntactically final interface return whose control-flow exit can be omitted. */ _proto.registerTerminalInterfaceReturn = function registerTerminalInterfaceReturn(statement) {
305
- this.terminalInterfaceReturns.add(statement);
306
- };
307
- /**
308
- * Tests whether an interface return is the final syntactic statement in its function.
309
- * @param statement - Return statement identity.
310
- * @returns Whether backend lowering may omit a trailing `return;`.
311
- */ _proto.isTerminalInterfaceReturn = function isTerminalInterfaceReturn(statement) {
312
- return this.terminalInterfaceReturns.has(statement);
313
- };
314
347
  _proto.referenceAttribute = function referenceAttribute(ident) {
315
348
  this._referenceProp(ident.lexeme, this.attributeList, this._referencedAttributeList);
316
349
  };
@@ -387,7 +420,7 @@ var TempArray = /*#__PURE__*/ function() {
387
420
  var child = _step.value;
388
421
  if (_instanceof(child, internal.BaseToken)) {
389
422
  // Legacy opaque `#define` lexemes carry the directive verbatim; expression-style defines use the AST path
390
- ret.array.push(child.lexeme);
423
+ ret.array.push(this.tokenLexeme(child));
391
424
  } else {
392
425
  ret.array.push(child.codeGen(this));
393
426
  }
@@ -397,6 +430,16 @@ var TempArray = /*#__PURE__*/ function() {
397
430
  pool.return(ret);
398
431
  return result;
399
432
  };
433
+ /**
434
+ * Spells a source token in the generated code.
435
+ * @param token - Source token
436
+ * @returns Generated text for the token
437
+ */ _proto.tokenLexeme = function tokenLexeme(token) {
438
+ return token.lexeme;
439
+ };
440
+ _proto.interfaceMemberName = function interfaceMemberName(name) {
441
+ return name;
442
+ };
400
443
  _proto.visitPostfixExpression = function visitPostfixExpression(node) {
401
444
  var children = node.children;
402
445
  var derivationLength = children.length;
@@ -417,13 +460,13 @@ var TempArray = /*#__PURE__*/ function() {
417
460
  var unresolvedName = internal.ParserUtils.extractDirectIdentLexeme(postExpr);
418
461
  role = symbols.length ? context.getStructVarRole(symbols) : unresolvedName ? context.getUnresolvedStructVarRole(unresolvedName) : undefined;
419
462
  }
463
+ if (!directRoot) role = context.getStructRole(node.resolvedMemberOwners);
420
464
  if (role) {
421
465
  if (role === internal.ShaderStructRole.Attribute) context.referenceAttribute(prop);
422
466
  else if (role === internal.ShaderStructRole.Varying) context.referenceVarying(prop);
423
467
  else context.referenceMRTProp(prop);
424
- return prop.lexeme;
425
468
  }
426
- return postExpr.codeGen(this) + "." + prop.lexeme;
469
+ return postExpr.codeGen(this) + "." + (role ? this.interfaceMemberName(prop.lexeme) : prop.lexeme);
427
470
  } else {
428
471
  return postExpr.codeGen(this) + "." + prop.codeGen(this);
429
472
  }
@@ -458,35 +501,6 @@ var TempArray = /*#__PURE__*/ function() {
458
501
  var symbol = _step.value;
459
502
  this.referenceFunction(symbol, node.location.start.index, node._branch);
460
503
  }
461
- var paramList = call.children[2];
462
- if (_instanceof(paramList, internal.ASTNode.FunctionCallParameterList)) {
463
- var astNodes = paramList.paramNodes;
464
- var finalSymbol = this.context._referencedGlobals[call.fnSymbol.ident].find(function(candidate) {
465
- return _instanceof(candidate, internal.FnSymbol) && candidate.equal(call.fnSymbol);
466
- });
467
- var paramInfoList = (finalSymbol != null ? finalSymbol : call.fnSymbol).astNode.protoType.parameterList;
468
- var context = this.context;
469
- var params = astNodes.filter(function(_, i) {
470
- var _paramInfoList_i;
471
- var parameter = paramInfoList == null ? void 0 : (_paramInfoList_i = paramInfoList[i]) == null ? void 0 : _paramInfoList_i.astNode;
472
- // Drop struct-IO parameters (attribute/varying/mrt) — they're flattened
473
- // into top-level declarations and no longer exist as function-call args.
474
- return !_instanceof(parameter, internal.ASTNode.ParameterDeclaration) || !parameter.symbol || !context.getStructVarRole([
475
- parameter.symbol
476
- ]);
477
- });
478
- var paramsCode = "";
479
- for(var i = 0, length = params.length; i < length; i++){
480
- var astNode = params[i];
481
- var code = astNode.codeGen(this);
482
- if (_instanceof(astNode, internal.ASTNode.MacroCallArgBlock) || i === 0) {
483
- paramsCode += code;
484
- } else {
485
- paramsCode += ", " + code;
486
- }
487
- }
488
- return call.fnSymbol.ident + "(" + paramsCode + ")";
489
- }
490
504
  }
491
505
  return this.defaultCodeGen(node.children);
492
506
  };
@@ -495,25 +509,7 @@ var TempArray = /*#__PURE__*/ function() {
495
509
  var paramList = children[2];
496
510
  if (_instanceof(paramList, internal.ASTNode.FunctionCallParameterList)) {
497
511
  var astNodes = paramList.paramNodes;
498
- var context = this.context;
499
- // Drop bare IO-struct args only when the macro aliases a user fn (whose
500
- // formal was flattened). All other shapes preserve args verbatim.
501
- var params;
502
- if (node.isFunctionLikeMacro || !node.aliasesNonBuiltinIdent) {
503
- params = astNodes;
504
- } else {
505
- params = astNodes.filter(function(arg) {
506
- if (_instanceof(arg, internal.ASTNode.AssignmentExpression)) {
507
- var variableParam = internal.ParserUtils.unwrapBareIdentifier(arg, {
508
- allowParens: false
509
- });
510
- if (variableParam && context.getStructVarRole(variableParam.resolvedValueSymbols())) {
511
- return false;
512
- }
513
- }
514
- return true;
515
- });
516
- }
512
+ var params = astNodes;
517
513
  var paramsCode = "";
518
514
  for(var i = 0, length = params.length; i < length; i++){
519
515
  var argNode = params[i];
@@ -539,8 +535,7 @@ var TempArray = /*#__PURE__*/ function() {
539
535
  };
540
536
  /**
541
537
  * Code-generate a `#define` macro parsed as expression AST. Produces a `#define`
542
- * directive whose value is the AST-rewritten string — so varying flattening
543
- * happens naturally via `visitPostfixExpression` inside the AST walk.
538
+ * directive whose value retains ordinary expression and member-access semantics.
544
539
  */ _proto.visitMacroDefine = function visitMacroDefine(node) {
545
540
  // For function-like macros, preserve the original `(params)` lexeme verbatim —
546
541
  // the parameter list is user-authored text that shouldn't be canonicalized.
@@ -562,79 +557,27 @@ var TempArray = /*#__PURE__*/ function() {
562
557
  var fullType = children[0];
563
558
  if (_instanceof(fullType, internal.ASTNode.FullySpecifiedType) && fullType.typeSpecifier.isCustom) {
564
559
  var context = this.context;
565
- // Global interface variables are flattened and therefore are not emitted as uniforms.
560
+ // Global interface variables are mutable shader values, not material bindings.
566
561
  if (context.getStructVarRole([
567
562
  node.declarator.symbol
568
563
  ])) {
569
- return "";
564
+ return this.defaultCodeGen(children);
570
565
  }
571
566
  context.referenceGlobal(fullType.type, internal.ESymbolType.STRUCT);
572
567
  }
573
568
  return "uniform " + this.defaultCodeGen(children);
574
569
  };
575
570
  _proto.visitDeclaration = function visitDeclaration(node) {
576
- var context = this.context;
577
- var children = node.children;
578
- var child = children[0];
579
- if (_instanceof(child, internal.ASTNode.InitDeclaratorList)) {
580
- var first = child.children[0];
581
- var _child_declarator;
582
- var declarator = (_child_declarator = child.declarator) != null ? _child_declarator : _instanceof(first, internal.ASTNode.SingleDeclaration) ? first.declarator : undefined;
583
- var role = declarator && context.getStructVarRole([
584
- declarator.symbol
585
- ]);
586
- if (role === internal.ShaderStructRole.Varying || role === internal.ShaderStructRole.Mrt) return "";
587
- }
588
- return this.defaultCodeGen(children);
571
+ return this.defaultCodeGen(node.children);
589
572
  };
590
573
  _proto.visitFunctionParameterList = function visitFunctionParameterList(node) {
591
- var context = this.context;
592
- var params = node.parameterInfoList.filter(function(item) {
593
- var parameter = item.astNode;
594
- return !_instanceof(parameter, internal.ASTNode.ParameterDeclaration) || !parameter.symbol || !context.getStructVarRole([
595
- parameter.symbol
596
- ]);
597
- });
598
- var out = "";
599
- for(var i = 0, length = params.length; i < length; i++){
600
- var item = params[i];
601
- var astNode = item.astNode;
602
- var code = astNode.codeGen(this);
603
- if (_instanceof(astNode, internal.ASTNode.MacroParamBlock) || i === 0) {
604
- out += code;
605
- } else {
606
- out += ", " + code;
607
- }
608
- }
609
- return out;
574
+ return this.defaultCodeGen(node.children);
610
575
  };
611
576
  _proto.visitFunctionHeader = function visitFunctionHeader(node) {
612
- var returnType = node.returnType.typeSpecifier;
613
- if (this.context.getStructRole(returnType.structDeclarations) === internal.ShaderStructRole.Varying) {
614
- return "void " + node.ident.lexeme + "(";
615
- }
616
577
  return this.defaultCodeGen(node.children);
617
578
  };
618
579
  _proto.visitJumpStatement = function visitJumpStatement(node) {
619
- var children = node.children;
620
- var cmd = children[0];
621
- if (cmd.type === internal.Keyword.RETURN) {
622
- var expr = children[1];
623
- if (_instanceof(expr, internal.ASTNode.Expression)) {
624
- var returnVar = internal.ParserUtils.unwrapNodeByType(expr, internal.NoneTerminal.variable_identifier);
625
- if (returnVar && this.context.getStructVarRole(returnVar.resolvedValueSymbols()) === internal.ShaderStructRole.Varying) {
626
- return this.context.isTerminalInterfaceReturn(node) ? "" : "return;";
627
- }
628
- var returnFnCall = internal.ParserUtils.unwrapNodeByType(expr, internal.NoneTerminal.function_call);
629
- var calledFunction = returnFnCall == null ? void 0 : returnFnCall.children[0];
630
- var returnDeclarations = _instanceof(calledFunction == null ? void 0 : calledFunction.fnSymbol, internal.FnSymbol) ? calledFunction.fnSymbol.astNode.protoType.returnType.typeSpecifier.structDeclarations : [];
631
- if (this.context.getStructRole(returnDeclarations) === internal.ShaderStructRole.Varying) {
632
- var call = "" + expr.codeGen(this) + ";";
633
- return this.context.isTerminalInterfaceReturn(node) ? call : "{ " + call + " return; }";
634
- }
635
- }
636
- }
637
- return this.defaultCodeGen(children);
580
+ return this.defaultCodeGen(node.children);
638
581
  };
639
582
  _proto.visitFunctionIdentifier = function visitFunctionIdentifier(node) {
640
583
  return this.defaultCodeGen(node.children);
@@ -643,63 +586,10 @@ var TempArray = /*#__PURE__*/ function() {
643
586
  return this.defaultCodeGen(node.children);
644
587
  };
645
588
  _proto.visitStructSpecifier = function visitStructSpecifier(node) {
646
- var _this = this;
647
- var context = this.context;
648
- var varyingStructs = context.varyingStructs, attributeStructs = context.attributeStructs, mrtStructs = context.mrtStructs;
649
- var isVaryingStruct = varyingStructs.indexOf(node) !== -1;
650
- var isAttributeStruct = attributeStructs.indexOf(node) !== -1;
651
- var isMRTStruct = mrtStructs.indexOf(node) !== -1;
652
- if (isVaryingStruct || isAttributeStruct || isMRTStruct) {
653
- var _result;
654
- var result = [];
655
- (_result = result).push.apply(_result, [].concat(node.macroExpressions.map(function(item) {
656
- return {
657
- text: _instanceof(item, internal.BaseToken) ? item.lexeme : item.codeGen(_this),
658
- index: item.location.start.index
659
- };
660
- })));
661
- for(var _iterator = _create_for_of_iterator_helper_loose(node.propList), _step; !(_step = _iterator()).done;){
662
- var prop = _step.value;
663
- var _context__referencedVaryingList_name, _context__referencedAttributeList_name, _context__referencedMRTList_name;
664
- var name = prop.ident.lexeme;
665
- if (isVaryingStruct && ((_context__referencedVaryingList_name = context._referencedVaryingList[name]) == null ? void 0 : _context__referencedVaryingList_name.indexOf(prop)) >= 0) {
666
- result.push({
667
- text: "" + this.getVaryingProp(prop) + "\n",
668
- index: prop.ident.location.start.index
669
- });
670
- } else if (isAttributeStruct && ((_context__referencedAttributeList_name = context._referencedAttributeList[name]) == null ? void 0 : _context__referencedAttributeList_name.indexOf(prop)) >= 0) {
671
- result.push({
672
- text: "" + this.getAttributeProp(prop) + "\n",
673
- index: prop.ident.location.start.index
674
- });
675
- } else if (isMRTStruct && ((_context__referencedMRTList_name = context._referencedMRTList[name]) == null ? void 0 : _context__referencedMRTList_name.indexOf(prop)) >= 0) {
676
- result.push({
677
- text: "" + this.getMRTProp(prop) + "\n",
678
- index: prop.ident.location.start.index
679
- });
680
- }
681
- }
682
- var text = result.sort(function(a, b) {
683
- return a.index - b.index;
684
- }).map(function(item) {
685
- return item.text;
686
- }).join("");
687
- return text;
688
- } else {
689
- return this.defaultCodeGen(node.children);
690
- }
589
+ return this.defaultCodeGen(node.children);
691
590
  };
692
591
  _proto.visitFunctionDefinition = function visitFunctionDefinition(fnNode) {
693
- var fnName = fnNode.protoType.ident.lexeme;
694
- var context = this.context;
695
- var terminal = internal.ParserUtils.lastStatement(fnNode.statements);
696
- if (_instanceof(terminal, internal.ASTNode.JumpStatement)) context.registerTerminalInterfaceReturn(terminal);
697
- if (fnName == context.stageEntry) {
698
- var statements = fnNode.statements.codeGen(this);
699
- return "void main() " + statements;
700
- } else {
701
- return this.defaultCodeGen(fnNode.children);
702
- }
592
+ return this.defaultCodeGen(fnNode.children);
703
593
  };
704
594
  return CodeGenVisitor;
705
595
  }();
@@ -1068,7 +958,7 @@ ShaderInstructionEncoder._FUNC_MACRO_RE = /^(\w+)\(([^)]*)\)\s*(.*)/;
1068
958
  _inherits(GLESVisitor, CodeGenVisitor);
1069
959
  function GLESVisitor() {
1070
960
  var _this;
1071
- _this = CodeGenVisitor.apply(this, arguments) || this, _this._globalCodeArray = [], _this._forwardFunctionDeclarations = new Map(), _this._forwardStructIndices = new Map(), _this._structCodeSegments = new Map(), _this._forwardVariableIndices = new Map(), _this._variableCodeSegments = new Map(), _this._declarationOwners = new Map(), _this._deferredPrototypes = new Map(), _this._declarationReferences = new Map(), _this._outerMacroDeclarations = [];
961
+ _this = CodeGenVisitor.apply(this, arguments) || this, _this.supportsArrayStructReturn = true, /** Names of pass-scope declarations, which stage-interface globals must not redeclare. */ _this._globalNames = new Set(), /** Interface type and variable tokens whose source names GLSL ES rejects. */ _this._escapedDeclarations = new Map(), _this._fragmentVaryingProps = new Set(), _this._globalInputs = new Map(), _this._inputHelperBodies = new Map(), _this._inputHelperGroups = new Map(), _this._globalCodeArray = [], _this._forwardFunctionDeclarations = new Map(), _this._forwardStructIndices = new Map(), _this._structCodeSegments = new Map(), _this._forwardVariableIndices = new Map(), _this._variableCodeSegments = new Map(), _this._declarationOwners = new Map(), _this._deferredPrototypes = new Map(), _this._declarationReferences = new Map(), _this._outerMacroDeclarations = [];
1072
962
  return _this;
1073
963
  }
1074
964
  var _proto = GLESVisitor.prototype;
@@ -1084,6 +974,8 @@ ShaderInstructionEncoder._FUNC_MACRO_RE = /^(\w+)\(([^)]*)\)\s*(.*)/;
1084
974
  this._variableCodeSegments.clear();
1085
975
  this._deferredPrototypes.clear();
1086
976
  this._declarationReferences.clear();
977
+ this._inputHelperBodies.clear();
978
+ this._inputHelperGroups.clear();
1087
979
  this._currentDeclaration = undefined;
1088
980
  };
1089
981
  /**
@@ -1091,6 +983,10 @@ ShaderInstructionEncoder._FUNC_MACRO_RE = /^(\w+)\(([^)]*)\)\s*(.*)/;
1091
983
  * @internal
1092
984
  */ _proto.dispose = function dispose() {
1093
985
  this.context.reset();
986
+ this.context.names.reset();
987
+ this._globalNames.clear();
988
+ this._escapedDeclarations.clear();
989
+ this._vertexOutputNames = undefined;
1094
990
  this.reset();
1095
991
  };
1096
992
  /**
@@ -1098,8 +994,15 @@ ShaderInstructionEncoder._FUNC_MACRO_RE = /^(\w+)\(([^)]*)\)\s*(.*)/;
1098
994
  * @param data - Parser-owned shader facts.
1099
995
  * @param out - Destination code segments.
1100
996
  */ _proto.getOtherGlobal = function getOtherGlobal(data, out) {
1101
- for(var _iterator = _create_for_of_iterator_helper_loose(data.globalPrecisions), _step; !(_step = _iterator()).done;){
1102
- var precision = _step.value;
997
+ for(var _iterator = _create_for_of_iterator_helper_loose(this._inputHelperGroups.values()), _step; !(_step = _iterator()).done;){
998
+ var _step_value = _step.value, name = _step_value.name, fallback = _step_value.fallback;
999
+ out.push({
1000
+ text: ShaderInstructionEncoder.declaration("void " + name + "() {}", fallback) + ShaderInstructionEncoder.reference(0, fallback.id),
1001
+ index: -1
1002
+ });
1003
+ }
1004
+ for(var _iterator1 = _create_for_of_iterator_helper_loose(data.globalPrecisions), _step1; !(_step1 = _iterator1()).done;){
1005
+ var precision = _step1.value;
1103
1006
  out.push({
1104
1007
  text: precision.codeGen(this),
1105
1008
  index: precision.location.start.index
@@ -1112,14 +1015,39 @@ ShaderInstructionEncoder._FUNC_MACRO_RE = /^(\w+)\(([^)]*)\)\s*(.*)/;
1112
1015
  * @param coreInfo - Entry and stage-interface facts derived from the same IR.
1113
1016
  * @returns Generated vertex and fragment source.
1114
1017
  */ _proto.generate = function generate(ir, coreInfo) {
1115
- var _this = this;
1018
+ var _this, _loop = function(_i, _iter) {
1019
+ var _iter__i = _iter[_i], stage = _iter__i[0], variables = _iter__i[1];
1020
+ var inputRole = stage === internal.EShaderStage.VERTEX ? internal.ShaderStructRole.Attribute : internal.ShaderStructRole.Varying;
1021
+ _this._globalInputs.set(stage, Array.from(variables).filter(function(param) {
1022
+ var variable = param[0], role = param[1];
1023
+ return role === inputRole && _instanceof(variable.astNode, internal.ASTNode.VariableDeclaration);
1024
+ }).map(function(param) {
1025
+ var variable = param[0];
1026
+ return variable;
1027
+ }));
1028
+ };
1029
+ var _this1 = this;
1116
1030
  var _context_attributeStructs, _context_attributeList, _context_varyingStructs, _context_varyingList, _context_mrtStructs, _context_mrtList;
1117
1031
  this.context.reset();
1032
+ this.context.names.reset();
1033
+ this._globalNames.clear();
1034
+ this._escapedDeclarations.clear();
1035
+ this._vertexOutputNames = undefined;
1118
1036
  this.reset();
1119
1037
  var node = ir.program;
1120
1038
  var shaderData = node.shaderData;
1121
1039
  var context = this.context;
1122
1040
  context._passSymbolTable = shaderData.symbolTable;
1041
+ var hasUnsafeIdentifier = false;
1042
+ var _ir_source_match;
1043
+ for(var _iterator = _create_for_of_iterator_helper_loose((_ir_source_match = ir.source.match(/[A-Za-z_][A-Za-z0-9_]*/g)) != null ? _ir_source_match : []), _step; !(_step = _iterator()).done;){
1044
+ var name = _step.value;
1045
+ context.names.reserve(name);
1046
+ hasUnsafeIdentifier || (hasUnsafeIdentifier = isUnsafeGLSLIdentifier(name));
1047
+ }
1048
+ shaderData.symbolTable.forEach(function(symbol) {
1049
+ return _this1._globalNames.add(symbol.ident);
1050
+ });
1123
1051
  var outerGlobalMacroDeclarations = coreInfo.outerGlobalMacroDeclarations;
1124
1052
  var io = coreInfo.io;
1125
1053
  (_context_attributeStructs = context.attributeStructs).push.apply(_context_attributeStructs, [].concat(io.attributeStructs));
@@ -1140,23 +1068,50 @@ ShaderInstructionEncoder._FUNC_MACRO_RE = /^(\w+)\(([^)]*)\)\s*(.*)/;
1140
1068
  io.fragmentStructVariableRoles.forEach(function(role, variable) {
1141
1069
  context.registerStructVar(variable, role, internal.EShaderStage.FRAGMENT);
1142
1070
  });
1071
+ if (hasUnsafeIdentifier) this._collectEscapedDeclarations(node);
1072
+ this._globalInputs.clear();
1073
+ for(var _i = 0, _iter = [
1074
+ [
1075
+ internal.EShaderStage.VERTEX,
1076
+ io.vertexStructVariableRoles
1077
+ ],
1078
+ [
1079
+ internal.EShaderStage.FRAGMENT,
1080
+ io.fragmentStructVariableRoles
1081
+ ]
1082
+ ]; _i < _iter.length; _i++)_this = this, _loop(_i, _iter);
1143
1083
  this._sourceIR = ir;
1144
1084
  this._outerMacroDeclarations = outerGlobalMacroDeclarations;
1145
1085
  try {
1146
1086
  coreInfo.deferredDeclarationOwnership.forEach(function(owner, symbol) {
1147
- return _this._declarationOwners.set(symbol.astNode, owner);
1087
+ return _this1._declarationOwners.set(symbol.astNode, owner);
1148
1088
  });
1089
+ var nextInputOwner = 0;
1090
+ for(var _iterator1 = _create_for_of_iterator_helper_loose(this._declarationOwners.values()), _step1; !(_step1 = _iterator1()).done;){
1091
+ var owner = _step1.value;
1092
+ nextInputOwner = Math.max(nextInputOwner, owner.id, owner.group);
1093
+ }
1094
+ for(var _iterator2 = _create_for_of_iterator_helper_loose(this._globalInputs.values()), _step2; !(_step2 = _iterator2()).done;){
1095
+ var variables = _step2.value;
1096
+ for(var _iterator3 = _create_for_of_iterator_helper_loose(variables), _step3; !(_step3 = _iterator3()).done;){
1097
+ var variable = _step3.value;
1098
+ if (this._declarationOwners.has(variable.astNode)) continue;
1099
+ var id = ++nextInputOwner;
1100
+ this._declarationOwners.set(variable.astNode, {
1101
+ id: id,
1102
+ group: id,
1103
+ sourceScope: variable.sourceScope
1104
+ });
1105
+ }
1106
+ }
1149
1107
  if (this._declarationOwners.size) {
1150
- var nextId = 0;
1151
- var nextGroup = 0;
1152
- this._declarationOwners.forEach(function(owner) {
1153
- nextId = Math.max(nextId, owner.id);
1154
- nextGroup = Math.max(nextGroup, owner.group);
1155
- });
1108
+ // `nextInputOwner` already exceeds every owner id and group.
1109
+ var nextId = nextInputOwner;
1110
+ var nextGroup = nextInputOwner;
1156
1111
  // Reachability follows the selected declaration, including dependencies without an override.
1157
1112
  shaderData.symbolTable.forEach(function(symbol) {
1158
- if (symbol.astNode && !_this._declarationOwners.has(symbol.astNode)) {
1159
- _this._declarationOwners.set(symbol.astNode, {
1113
+ if (symbol.astNode && !_this1._declarationOwners.has(symbol.astNode)) {
1114
+ _this1._declarationOwners.set(symbol.astNode, {
1160
1115
  id: ++nextId,
1161
1116
  group: ++nextGroup,
1162
1117
  sourceScope: symbol.sourceScope
@@ -1166,54 +1121,71 @@ ShaderInstructionEncoder._FUNC_MACRO_RE = /^(\w+)\(([^)]*)\)\s*(.*)/;
1166
1121
  context.onReferenceGlobal = function(symbols) {
1167
1122
  var _this_currentDeclarationOwner;
1168
1123
  var _this_currentDeclarationOwner_id;
1169
- var from = (_this_currentDeclarationOwner_id = (_this_currentDeclarationOwner = _this.currentDeclarationOwner) == null ? void 0 : _this_currentDeclarationOwner.id) != null ? _this_currentDeclarationOwner_id : 0;
1124
+ var from = (_this_currentDeclarationOwner_id = (_this_currentDeclarationOwner = _this1.currentDeclarationOwner) == null ? void 0 : _this_currentDeclarationOwner.id) != null ? _this_currentDeclarationOwner_id : 0;
1170
1125
  for(var _iterator = _create_for_of_iterator_helper_loose(symbols), _step; !(_step = _iterator()).done;){
1171
1126
  var symbol = _step.value;
1172
- _this._referenceDeclaration(from, symbol.astNode);
1127
+ _this1._referenceDeclaration(from, symbol.astNode);
1173
1128
  }
1174
1129
  };
1175
1130
  var propDeclarations = new Map();
1176
- for(var _iterator = _create_for_of_iterator_helper_loose([].concat(io.attributeStructs, io.varyingStructs, io.mrtStructs)), _step; !(_step = _iterator()).done;){
1177
- var struct = _step.value;
1178
- for(var _iterator1 = _create_for_of_iterator_helper_loose(struct.propList), _step1; !(_step1 = _iterator1()).done;){
1179
- var prop = _step1.value;
1131
+ for(var _iterator4 = _create_for_of_iterator_helper_loose([].concat(io.attributeStructs, io.varyingStructs, io.mrtStructs)), _step4; !(_step4 = _iterator4()).done;){
1132
+ var struct = _step4.value;
1133
+ for(var _iterator5 = _create_for_of_iterator_helper_loose(struct.propList), _step5; !(_step5 = _iterator5()).done;){
1134
+ var prop = _step5.value;
1180
1135
  propDeclarations.set(prop, struct);
1181
1136
  }
1182
1137
  }
1183
1138
  context.onReferenceStructProps = function(props) {
1184
1139
  var _this_currentDeclarationOwner;
1185
1140
  var _this_currentDeclarationOwner_id;
1186
- var from = (_this_currentDeclarationOwner_id = (_this_currentDeclarationOwner = _this.currentDeclarationOwner) == null ? void 0 : _this_currentDeclarationOwner.id) != null ? _this_currentDeclarationOwner_id : 0;
1141
+ var from = (_this_currentDeclarationOwner_id = (_this_currentDeclarationOwner = _this1.currentDeclarationOwner) == null ? void 0 : _this_currentDeclarationOwner.id) != null ? _this_currentDeclarationOwner_id : 0;
1187
1142
  for(var _iterator = _create_for_of_iterator_helper_loose(props), _step; !(_step = _iterator()).done;){
1188
1143
  var prop = _step.value;
1189
- _this._referenceDeclaration(from, propDeclarations.get(prop));
1144
+ _this1._referenceDeclaration(from, propDeclarations.get(prop));
1190
1145
  }
1191
1146
  };
1192
1147
  }
1193
1148
  if (coreInfo.unsupportedDeferredDeclarations.length) {
1194
1149
  throw internal.mapExpandedShaderError(new internal.GSError(internal.GSErrorName.CompilationError, "Deferred inheritance requires exact signatures and cannot resolve a known partial-coverage conflict.", coreInfo.unsupportedDeferredDeclarations[0].astNode.location, ir.source, undefined, "UnsupportedDeferredDeclaration"), ir.source, ir.sourceMap);
1195
1150
  }
1151
+ this._fragmentVaryingProps.clear();
1152
+ var fragment = this._fragmentMain(coreInfo.fragmentEntry, shaderData, outerGlobalMacroDeclarations);
1153
+ var vertex = this._vertexMain(coreInfo.vertexEntry, shaderData, outerGlobalMacroDeclarations);
1196
1154
  return {
1197
- vertex: this._vertexMain(coreInfo.vertexEntry, shaderData, outerGlobalMacroDeclarations),
1198
- fragment: this._fragmentMain(coreInfo.fragmentEntry, shaderData, outerGlobalMacroDeclarations)
1155
+ vertex: vertex,
1156
+ fragment: fragment,
1157
+ vertexOutputNames: this._vertexOutputNames
1199
1158
  };
1200
1159
  } finally{
1201
1160
  this._sourceIR = undefined;
1202
1161
  this._outerMacroDeclarations = [];
1162
+ this._globalInputs.clear();
1203
1163
  this._declarationOwners.clear();
1204
1164
  context.onReferenceGlobal = undefined;
1205
1165
  context.onReferenceStructProps = undefined;
1166
+ this._fragmentVaryingProps.clear();
1167
+ this._globalNames.clear();
1168
+ this._escapedDeclarations.clear();
1169
+ this._vertexOutputNames = undefined;
1170
+ context.reset();
1171
+ context.names.reset();
1206
1172
  }
1207
1173
  };
1208
1174
  _proto._vertexMain = function _vertexMain(entryInfo, data, outerGlobalMacroDeclarations) {
1209
1175
  var context = this.context;
1210
1176
  context.stage = internal.EShaderStage.VERTEX;
1211
1177
  context.stageEntry = entryInfo.name;
1178
+ for(var _iterator = _create_for_of_iterator_helper_loose(this._fragmentVaryingProps), _step; !(_step = _iterator()).done;){
1179
+ var prop = _step.value;
1180
+ context.referenceVarying(prop.ident);
1181
+ }
1212
1182
  // Attribute/varying structs were collected in ShaderCoreInfo
1213
1183
  // Pre-walk global `#define` values so referenced struct properties emit `attribute`/`varying` declarations.
1214
1184
  this._preRegisterGlobalMacroRefs(outerGlobalMacroDeclarations);
1215
1185
  var globalCodeArray = this._globalCodeArray;
1216
1186
  context.referenceGlobal(entryInfo.name, internal.ESymbolType.FN);
1187
+ this._referenceInterfaceDependencies([].concat(context.attributeStructs, context.varyingStructs));
1188
+ this._initializeGlobalInputs();
1217
1189
  this._getGlobalSymbol(globalCodeArray);
1218
1190
  this._getCustomStruct(context.attributeStructs, globalCodeArray);
1219
1191
  this._getCustomStruct(context.varyingStructs, globalCodeArray);
@@ -1230,28 +1202,17 @@ ShaderInstructionEncoder._FUNC_MACRO_RE = /^(\w+)\(([^)]*)\)\s*(.*)/;
1230
1202
  return globalCode;
1231
1203
  };
1232
1204
  _proto._fragmentMain = function _fragmentMain(entryInfo, data, outerGlobalMacroStatements) {
1233
- var _this = this;
1234
1205
  var context = this.context;
1235
1206
  context.stage = internal.EShaderStage.FRAGMENT;
1236
1207
  context.stageEntry = entryInfo.name;
1237
1208
  this.prepareFragment(entryInfo, outerGlobalMacroStatements);
1238
- // Every value-return must preserve early-exit control flow after entry return values are
1239
- // lowered into fragment outputs.
1240
- entryInfo.functions.forEach(function(fnSymbol) {
1241
- var returnType = fnSymbol.astNode.protoType.returnType;
1242
- var mode = returnType.type === internal.Keyword.VEC4 ? "color" : returnType.typeSpecifier.structDeclarations.some(function(struct) {
1243
- return context.hasStructRole(struct, internal.ShaderStructRole.Mrt);
1244
- }) ? "mrt" : undefined;
1245
- if (mode) {
1246
- var statements = fnSymbol.astNode.statements;
1247
- _this._registerFragmentReturns(statements, mode, internal.ParserUtils.lastStatement(statements));
1248
- }
1249
- });
1250
1209
  // Struct-variable identities are already populated from ShaderCoreInfo; just pre-walk macro
1251
1210
  // refs so struct codegen sees the references.
1252
1211
  this._preRegisterGlobalMacroRefs(outerGlobalMacroStatements);
1253
1212
  var globalCodeArray = this._globalCodeArray;
1254
1213
  context.referenceGlobal(entryInfo.name, internal.ESymbolType.FN);
1214
+ this._referenceInterfaceDependencies([].concat(context.varyingStructs, context.mrtStructs));
1215
+ this._initializeGlobalInputs();
1255
1216
  this._getGlobalSymbol(globalCodeArray);
1256
1217
  this._getCustomStruct(context.varyingStructs, globalCodeArray);
1257
1218
  this._getCustomStruct(context.mrtStructs, globalCodeArray);
@@ -1263,10 +1224,347 @@ ShaderInstructionEncoder._FUNC_MACRO_RE = /^(\w+)\(([^)]*)\)\s*(.*)/;
1263
1224
  }).map(function(item) {
1264
1225
  return item.text;
1265
1226
  }).join("\n");
1266
- context.reset();
1227
+ for(var _iterator = _create_for_of_iterator_helper_loose(Object.values(context._referencedVaryingList)), _step; !(_step = _iterator()).done;){
1228
+ var props = _step.value;
1229
+ for(var _iterator1 = _create_for_of_iterator_helper_loose(props), _step1; !(_step1 = _iterator1()).done;){
1230
+ var prop = _step1.value;
1231
+ this._fragmentVaryingProps.add(prop);
1232
+ }
1233
+ }
1234
+ context.reset(false);
1267
1235
  this.reset();
1268
1236
  return globalCode;
1269
1237
  };
1238
+ _proto._referenceInterfaceDependencies = function _referenceInterfaceDependencies(structs) {
1239
+ for(var _iterator = _create_for_of_iterator_helper_loose(structs), _step; !(_step = _iterator()).done;){
1240
+ var struct = _step.value;
1241
+ this._currentDeclaration = struct;
1242
+ for(var _iterator1 = _create_for_of_iterator_helper_loose(struct.propList), _step1; !(_step1 = _iterator1()).done;){
1243
+ var prop = _step1.value;
1244
+ var _prop_typeInfo_arraySpecifier;
1245
+ for(var _iterator2 = _create_for_of_iterator_helper_loose(prop.typeInfo.structDeclarations), _step2; !(_step2 = _iterator2()).done;){
1246
+ var dependency = _step2.value;
1247
+ if (dependency.ident) this.context.referenceGlobal(dependency.ident.lexeme, internal.ESymbolType.STRUCT);
1248
+ }
1249
+ (_prop_typeInfo_arraySpecifier = prop.typeInfo.arraySpecifier) == null ? void 0 : _prop_typeInfo_arraySpecifier.codeGen(this);
1250
+ }
1251
+ }
1252
+ this._currentDeclaration = undefined;
1253
+ };
1254
+ /**
1255
+ * Resolves an interface member's global name, shared by both stages for varyings.
1256
+ * @param prop - Interface member
1257
+ * @param role - Stage-interface role of the member's structure
1258
+ * @returns Generated global identifier
1259
+ */ _proto.interfaceName = function interfaceName(prop, role) {
1260
+ var context = this.context;
1261
+ var name = prop.ident.lexeme;
1262
+ var isOutput = role === internal.ShaderStructRole.Mrt;
1263
+ var sameName = function(item) {
1264
+ return item.ident.lexeme === name;
1265
+ };
1266
+ var conflicts = this._globalNames.has(name) || // Vertex attributes and fragment outputs share a stage scope with varyings.
1267
+ !isOutput && (context.attributeList.some(sameName) || context.mrtList.some(sameName));
1268
+ var key = (isOutput ? "output" : "varying") + ":" + name;
1269
+ var generated = isUnsafeGLSLIdentifier(name) ? context.names.sourceName(key, name) : conflicts ? context.names.allocate(key, name) : name;
1270
+ if (!isOutput && context.stage === internal.EShaderStage.VERTEX && generated !== name) {
1271
+ var _this__vertexOutputNames;
1272
+ ((_this__vertexOutputNames = this._vertexOutputNames) != null ? _this__vertexOutputNames : this._vertexOutputNames = Object.create(null))[name] = generated;
1273
+ }
1274
+ return generated;
1275
+ };
1276
+ _proto.interfaceMemberName = function interfaceMemberName(name) {
1277
+ return this.context.names.sourceName("member:" + name, name);
1278
+ };
1279
+ _proto._interfaceTypeName = function _interfaceTypeName(struct) {
1280
+ var name = struct.ident.lexeme;
1281
+ return this.context.names.sourceName("type:" + name, name);
1282
+ };
1283
+ /**
1284
+ * Escapes interface-typed variables whose names GLSL ES reserves.
1285
+ * @param name - Source name
1286
+ * @param structs - Struct declarations of the variable type
1287
+ * @returns The escaped name, or the source name when no escape is necessary
1288
+ */ _proto._interfaceVariableName = function _interfaceVariableName(name, structs) {
1289
+ return (structs == null ? void 0 : structs.length) && this.context.getStructRole(structs) ? this.context.names.sourceName("variable:" + name, name) : name;
1290
+ };
1291
+ _proto._collectEscapedDeclarations = function _collectEscapedDeclarations(node) {
1292
+ if (_instanceof(node, internal.ASTNode.TypeSpecifier) && this.context.getStructRole(node.structDeclarations)) {
1293
+ var _node_structDeclarations__ident;
1294
+ var token = node.children[0].children[0];
1295
+ if (_instanceof(token, internal.BaseToken) && token.lexeme === ((_node_structDeclarations__ident = node.structDeclarations[0].ident) == null ? void 0 : _node_structDeclarations__ident.lexeme)) {
1296
+ var name = this._interfaceTypeName(node.structDeclarations[0]);
1297
+ if (name !== token.lexeme) this._escapedDeclarations.set(token, name);
1298
+ }
1299
+ }
1300
+ var identifier;
1301
+ var structs;
1302
+ if (_instanceof(node, internal.ASTNode.ParameterDeclarator)) {
1303
+ var _node_typeInfo;
1304
+ identifier = node.ident;
1305
+ structs = (_node_typeInfo = node.typeInfo) == null ? void 0 : _node_typeInfo.structDeclarations;
1306
+ } else {
1307
+ var _declarator_typeInfo;
1308
+ // Local, global and multi-variable declarations share the parser's `declarator` record.
1309
+ var declarator = node.declarator;
1310
+ identifier = declarator == null ? void 0 : declarator.identifier;
1311
+ structs = declarator == null ? void 0 : (_declarator_typeInfo = declarator.typeInfo) == null ? void 0 : _declarator_typeInfo.structDeclarations;
1312
+ }
1313
+ if (identifier) {
1314
+ var name1 = this._interfaceVariableName(identifier.lexeme, structs);
1315
+ if (name1 !== identifier.lexeme) this._escapedDeclarations.set(identifier, name1);
1316
+ }
1317
+ for(var _iterator = _create_for_of_iterator_helper_loose(node.children), _step; !(_step = _iterator()).done;){
1318
+ var child = _step.value;
1319
+ if (_instanceof(child, internal.TreeNode)) this._collectEscapedDeclarations(child);
1320
+ }
1321
+ };
1322
+ _proto.tokenLexeme = function tokenLexeme(token) {
1323
+ var _this__escapedDeclarations_get;
1324
+ return (_this__escapedDeclarations_get = this._escapedDeclarations.get(token)) != null ? _this__escapedDeclarations_get : token.lexeme;
1325
+ };
1326
+ _proto._escapedReference = function _escapedReference(node) {
1327
+ var token = node.children[0];
1328
+ if (!this._escapedDeclarations.size || !_instanceof(token, internal.BaseToken) || !isUnsafeGLSLIdentifier(token.lexeme)) {
1329
+ return undefined;
1330
+ }
1331
+ var symbols = node.resolvedValueSymbols();
1332
+ if (!symbols.length) {
1333
+ // Macro values can lack symbols. The stage's unambiguous name-to-role map binds them, as for member access.
1334
+ return this.context.getUnresolvedStructVarRole(token.lexeme) ? this.context.names.sourceName("variable:" + token.lexeme, token.lexeme) : undefined;
1335
+ }
1336
+ var name;
1337
+ for(var _iterator = _create_for_of_iterator_helper_loose(symbols), _step; !(_step = _iterator()).done;){
1338
+ var symbol = _step.value;
1339
+ var _symbol_dataType;
1340
+ var candidate = _instanceof(symbol, internal.VarSymbol) ? this._interfaceVariableName(token.lexeme, (_symbol_dataType = symbol.dataType) == null ? void 0 : _symbol_dataType.structDeclarations) : _instanceof(symbol, internal.StructSymbol) && this.context.getStructRole([
1341
+ symbol.astNode
1342
+ ]) ? this._interfaceTypeName(symbol.astNode) : token.lexeme;
1343
+ // Branch candidates must agree, otherwise the reference keeps its source spelling.
1344
+ if (name !== undefined && name !== candidate) return undefined;
1345
+ name = candidate;
1346
+ }
1347
+ return name;
1348
+ };
1349
+ _proto._transferName = function _transferName(struct, read) {
1350
+ return this.context.names.allocate((read ? "read" : "write") + ":" + struct.ident.lexeme, (read ? "read" : "write") + "_" + struct.ident.lexeme);
1351
+ };
1352
+ _proto.visitStructSpecifier = function visitStructSpecifier(node) {
1353
+ var _this = this;
1354
+ var context = this.context;
1355
+ var role = context.getStructRole([
1356
+ node
1357
+ ]);
1358
+ if (!role) return CodeGenVisitor.prototype.visitStructSpecifier.call(this, node);
1359
+ var typeName = this._interfaceTypeName(node);
1360
+ var memberCode = function(emit) {
1361
+ var segments = node.macroExpressions.map(function(item) {
1362
+ return {
1363
+ text: _instanceof(item, internal.BaseToken) ? item.lexeme : item.codeGen(_this),
1364
+ index: item.location.start.index
1365
+ };
1366
+ });
1367
+ for(var _iterator = _create_for_of_iterator_helper_loose(node.propList), _step; !(_step = _iterator()).done;){
1368
+ var prop = _step.value;
1369
+ if (!retain(prop)) continue;
1370
+ segments.push({
1371
+ text: emit(prop),
1372
+ index: prop.ident.location.start.index
1373
+ });
1374
+ }
1375
+ return segments.sort(function(a, b) {
1376
+ return a.index - b.index;
1377
+ }).map(function(item) {
1378
+ return item.text;
1379
+ }).join("\n");
1380
+ };
1381
+ var references = role === internal.ShaderStructRole.Attribute ? context._referencedAttributeList : role === internal.ShaderStructRole.Varying ? context._referencedVaryingList : context._referencedMRTList;
1382
+ var used = function(prop) {
1383
+ var _references_prop_ident_lexeme;
1384
+ return !!((_references_prop_ident_lexeme = references[prop.ident.lexeme]) == null ? void 0 : _references_prop_ident_lexeme.includes(prop));
1385
+ };
1386
+ // Interface members have no array wire form, and GLSL ES 1.00 functions cannot return structures that contain
1387
+ // arrays. GLES100 therefore omits array members from interface structures.
1388
+ var retain = function(prop) {
1389
+ return _this.supportsArrayStructReturn || !_this._containsArray(prop);
1390
+ };
1391
+ var declaration = function(prop) {
1392
+ var _prop_typeInfo_arraySpecifier;
1393
+ var _prop_typeInfo_arraySpecifier_codeGen;
1394
+ return prop.typeInfo.typeLexeme + " " + _this.interfaceMemberName(prop.ident.lexeme) + ((_prop_typeInfo_arraySpecifier_codeGen = (_prop_typeInfo_arraySpecifier = prop.typeInfo.arraySpecifier) == null ? void 0 : _prop_typeInfo_arraySpecifier.codeGen(_this)) != null ? _prop_typeInfo_arraySpecifier_codeGen : "") + ";";
1395
+ };
1396
+ var structCode;
1397
+ var hasRetainedField = node.propList.some(retain);
1398
+ if (hasRetainedField && !node.macroExpressions.length) {
1399
+ structCode = "struct " + typeName + " {\n" + memberCode(declaration) + "\n};";
1400
+ } else {
1401
+ var hasFields = context.names.allocate(node, "" + typeName + "_has_fields");
1402
+ var padding = context.names.allocate("empty-interface-member", "interface_padding");
1403
+ // A macro configuration can remove every source field; GLSL still requires a nonempty struct.
1404
+ structCode = "#undef " + hasFields + "\nstruct " + typeName + " {\n" + memberCode(function(prop) {
1405
+ return declaration(prop) + "\n#define " + hasFields + "\n";
1406
+ }) + "\n#ifndef " + hasFields + "\nfloat " + padding + ";\n#endif\n};\n#undef " + hasFields + "\n";
1407
+ }
1408
+ var declarations = memberCode(function(prop) {
1409
+ var _this_getMRTProp;
1410
+ return !used(prop) ? "" : role === internal.ShaderStructRole.Attribute ? _this.getAttributeProp(prop) : role === internal.ShaderStructRole.Varying ? _this.getVaryingProp(prop) : (_this_getMRTProp = _this.getMRTProp(prop)) != null ? _this_getMRTProp : "";
1411
+ });
1412
+ var read = role === internal.ShaderStructRole.Attribute || role === internal.ShaderStructRole.Varying && context.stage === internal.EShaderStage.FRAGMENT;
1413
+ var value = context.names.allocate("interface-value", "interface_value");
1414
+ var assignments = memberCode(function(prop) {
1415
+ if (!used(prop)) return "";
1416
+ var wire = role === internal.ShaderStructRole.Attribute ? prop.ident.lexeme : role === internal.ShaderStructRole.Mrt ? _this.mrtOutput(prop) : _this.interfaceName(prop, role);
1417
+ var member = value + "." + _this.interfaceMemberName(prop.ident.lexeme);
1418
+ return read ? member + " = " + wire + ";" : wire + " = " + member + ";";
1419
+ });
1420
+ var transfer = read ? typeName + " " + this._transferName(node, true) + "() { " + typeName + " " + value + ";\n" + assignments + "\nreturn " + value + "; }" : "void " + this._transferName(node, false) + "(" + typeName + " " + value + ") {\n" + assignments + "\n}";
1421
+ return structCode + "\n" + declarations + "\n" + transfer;
1422
+ };
1423
+ _proto._containsArray = function _containsArray(prop, visited) {
1424
+ var _this = this;
1425
+ if (visited === void 0) visited = new Set();
1426
+ if (prop.typeInfo.arraySpecifier) return true;
1427
+ for(var _iterator = _create_for_of_iterator_helper_loose(prop.typeInfo.structDeclarations), _step; !(_step = _iterator()).done;){
1428
+ var struct = _step.value;
1429
+ if (visited.has(struct)) continue;
1430
+ visited.add(struct);
1431
+ if (struct.propList.some(function(member) {
1432
+ return _this._containsArray(member, visited);
1433
+ })) return true;
1434
+ }
1435
+ return false;
1436
+ };
1437
+ _proto.defaultCodeGen = function defaultCodeGen(children) {
1438
+ var _this = this;
1439
+ var parent = _instanceof(children[0], internal.TreeNode) ? children[0].parent : undefined;
1440
+ if (_instanceof(parent, internal.ASTNode.EqualityExpression) && children.length === 3) {
1441
+ var observe = function(node) {
1442
+ if (_instanceof(node, internal.ASTNode.VariableIdentifier)) {
1443
+ for(var _iterator = _create_for_of_iterator_helper_loose(node.resolvedValueSymbols()), _step; !(_step = _iterator()).done;){
1444
+ var symbol = _step.value;
1445
+ var _symbol_dataType;
1446
+ var _symbol_dataType_structDeclarations;
1447
+ if (_instanceof(symbol, internal.VarSymbol)) for(var _iterator1 = _create_for_of_iterator_helper_loose((_symbol_dataType_structDeclarations = (_symbol_dataType = symbol.dataType) == null ? void 0 : _symbol_dataType.structDeclarations) != null ? _symbol_dataType_structDeclarations : []), _step1; !(_step1 = _iterator1()).done;){
1448
+ var struct = _step1.value;
1449
+ _this._observeWholeStruct(struct);
1450
+ }
1451
+ }
1452
+ }
1453
+ if (_instanceof(node, internal.ASTNode.FunctionCallGeneric)) {
1454
+ var _node_fnSymbol;
1455
+ var declaration = (_node_fnSymbol = node.fnSymbol) == null ? void 0 : _node_fnSymbol.astNode;
1456
+ if (_instanceof(declaration, internal.ASTNode.StructSpecifier)) _this._observeWholeStruct(declaration);
1457
+ else if (_instanceof(declaration, internal.ASTNode.FunctionDefinition)) {
1458
+ for(var _iterator2 = _create_for_of_iterator_helper_loose(declaration.protoType.returnType.typeSpecifier.structDeclarations), _step2; !(_step2 = _iterator2()).done;){
1459
+ var struct1 = _step2.value;
1460
+ _this._observeWholeStruct(struct1);
1461
+ }
1462
+ }
1463
+ }
1464
+ for(var _iterator3 = _create_for_of_iterator_helper_loose(node.children), _step3; !(_step3 = _iterator3()).done;){
1465
+ var child = _step3.value;
1466
+ if (_instanceof(child, internal.TreeNode)) observe(child);
1467
+ }
1468
+ };
1469
+ for(var _iterator = _create_for_of_iterator_helper_loose(children), _step; !(_step = _iterator()).done;){
1470
+ var child = _step.value;
1471
+ if (_instanceof(child, internal.TreeNode) && typeof child.type === "string") observe(child);
1472
+ }
1473
+ }
1474
+ return CodeGenVisitor.prototype.defaultCodeGen.call(this, children);
1475
+ };
1476
+ _proto._observeWholeStruct = function _observeWholeStruct(struct) {
1477
+ var role = this.context.getStructRole([
1478
+ struct
1479
+ ]);
1480
+ for(var _iterator = _create_for_of_iterator_helper_loose(struct.propList), _step; !(_step = _iterator()).done;){
1481
+ var prop = _step.value;
1482
+ if (role === internal.ShaderStructRole.Attribute) this.context.referenceAttribute(prop.ident);
1483
+ else if (role === internal.ShaderStructRole.Varying) this.context.referenceVarying(prop.ident);
1484
+ else if (role === internal.ShaderStructRole.Mrt) this.context.referenceMRTProp(prop.ident);
1485
+ }
1486
+ };
1487
+ _proto.visitFunctionHeader = function visitFunctionHeader(node) {
1488
+ if (node.ident.lexeme === "main" && this.context.stageEntry === "main") {
1489
+ return node.returnType.codeGen(this) + " " + this.context.names.allocate("entry-main", "entry_main") + "(";
1490
+ }
1491
+ return CodeGenVisitor.prototype.visitFunctionHeader.call(this, node);
1492
+ };
1493
+ _proto.visitFunctionIdentifier = function visitFunctionIdentifier(node) {
1494
+ var call = node.parent;
1495
+ if (node.lexeme === "main" && this.context.stageEntry === "main" && _instanceof(call, internal.ASTNode.FunctionCallGeneric) && _instanceof(call.fnSymbol, internal.FnSymbol)) {
1496
+ return this.context.names.allocate("entry-main", "entry_main");
1497
+ }
1498
+ return CodeGenVisitor.prototype.visitFunctionIdentifier.call(this, node);
1499
+ };
1500
+ _proto.visitFunctionDefinition = function visitFunctionDefinition(fnNode) {
1501
+ var definition = CodeGenVisitor.prototype.visitFunctionDefinition.call(this, fnNode);
1502
+ if (fnNode.protoType.ident.lexeme !== this.context.stageEntry) return definition;
1503
+ var args = [];
1504
+ var parameters = [];
1505
+ var _fnNode_protoType_parameterList;
1506
+ for(var _iterator = _create_for_of_iterator_helper_loose((_fnNode_protoType_parameterList = fnNode.protoType.parameterList) != null ? _fnNode_protoType_parameterList : []), _step; !(_step = _iterator()).done;){
1507
+ var parameter = _step.value;
1508
+ if (!parameter.ident || !parameter.typeInfo) continue;
1509
+ var struct = parameter.typeInfo.structDeclarations[0];
1510
+ if (struct) {
1511
+ var name = this.context.names.allocate(parameter, "input_" + parameter.ident.lexeme);
1512
+ parameters.push(this._interfaceTypeName(struct) + " " + name + " = " + this._transferName(struct, true) + "();");
1513
+ args.push(name);
1514
+ }
1515
+ }
1516
+ var name1 = fnNode.protoType.ident.lexeme;
1517
+ var entryName = name1 === "main" ? this.context.names.allocate("entry-main", "entry_main") : name1;
1518
+ var call = entryName + "(" + args.join(", ") + ")";
1519
+ var type = fnNode.protoType.returnType;
1520
+ var struct1 = type.typeSpecifier.structDeclarations[0];
1521
+ var statement;
1522
+ if (struct1) {
1523
+ statement = this._transferName(struct1, false) + "(" + call + ");";
1524
+ } else if (this.context.stage === internal.EShaderStage.FRAGMENT && type.type === internal.Keyword.VEC4) {
1525
+ statement = this.fragmentColorOutput() + " = " + call + ";";
1526
+ } else statement = "" + call + ";";
1527
+ var inputs = this._initializeGlobalInputs();
1528
+ return definition + "\nvoid main() {\n" + inputs.join("\n") + "\n" + parameters.join("\n") + "\n" + statement + " }";
1529
+ };
1530
+ _proto._initializeGlobalInputs = function _initializeGlobalInputs() {
1531
+ var calls = new Set();
1532
+ var _this__globalInputs_get;
1533
+ for(var _iterator = _create_for_of_iterator_helper_loose((_this__globalInputs_get = this._globalInputs.get(this.context.stage)) != null ? _this__globalInputs_get : []), _step; !(_step = _iterator()).done;){
1534
+ var variable = _step.value;
1535
+ this.context.referenceGlobal(variable.ident, internal.ESymbolType.VAR);
1536
+ var struct = variable.dataType.structDeclarations[0];
1537
+ var owner = this._declarationOwners.get(variable.astNode);
1538
+ this._referenceDeclaration(owner.id, struct);
1539
+ var group = this._inputHelperGroups.get(owner.group);
1540
+ if (!group) {
1541
+ var nextId = 0;
1542
+ for(var _iterator1 = _create_for_of_iterator_helper_loose(this._declarationOwners.values()), _step1; !(_step1 = _iterator1()).done;){
1543
+ var declaration = _step1.value;
1544
+ nextId = Math.max(nextId, declaration.id);
1545
+ }
1546
+ for(var _iterator2 = _create_for_of_iterator_helper_loose(this._inputHelperGroups.values()), _step2; !(_step2 = _iterator2()).done;){
1547
+ var helper = _step2.value;
1548
+ nextId = Math.max(nextId, helper.fallback.id);
1549
+ }
1550
+ // A missing conditional input selects the no-op; an active declaration selects its own initializer.
1551
+ var fallback = {
1552
+ id: nextId + 1,
1553
+ group: owner.group,
1554
+ sourceScope: -1
1555
+ };
1556
+ var name = this.context.names.allocate("input-initializer:" + owner.group, "initialize_" + variable.ident);
1557
+ this._inputHelperGroups.set(owner.group, group = {
1558
+ name: name,
1559
+ fallback: fallback
1560
+ });
1561
+ }
1562
+ var target = this._interfaceVariableName(variable.ident, variable.dataType.structDeclarations);
1563
+ this._inputHelperBodies.set(variable.astNode, "void " + group.name + "() { " + target + " = " + this._transferName(struct, true) + "(); }");
1564
+ calls.add("" + group.name + "();");
1565
+ }
1566
+ return Array.from(calls);
1567
+ };
1270
1568
  _proto.prepareFragment = function prepareFragment(entryInfo, outerGlobalMacroStatements) {
1271
1569
  };
1272
1570
  /**
@@ -1296,17 +1594,6 @@ ShaderInstructionEncoder._FUNC_MACRO_RE = /^(\w+)\(([^)]*)\)\s*(.*)/;
1296
1594
  }
1297
1595
  }
1298
1596
  };
1299
- _proto._registerFragmentReturns = function _registerFragmentReturns(node, mode, terminal) {
1300
- if (_instanceof(node, internal.ASTNode.JumpStatement) && node.children.length === 3) {
1301
- this.context.registerFragmentReturn(node, mode);
1302
- if (node === terminal) this.context.registerTerminalInterfaceReturn(node);
1303
- return;
1304
- }
1305
- for(var _iterator = _create_for_of_iterator_helper_loose(node.children), _step; !(_step = _iterator()).done;){
1306
- var child = _step.value;
1307
- if (_instanceof(child, internal.TreeNode)) this._registerFragmentReturns(child, mode, terminal);
1308
- }
1309
- };
1310
1597
  _proto._getGlobalSymbol = function _getGlobalSymbol(out) {
1311
1598
  var context = this.context;
1312
1599
  // Set iteration includes dependencies discovered while generating earlier declarations.
@@ -1427,11 +1714,6 @@ ShaderInstructionEncoder._FUNC_MACRO_RE = /^(\w+)\(([^)]*)\)\s*(.*)/;
1427
1714
  for(var _iterator2 = _create_for_of_iterator_helper_loose((_prototype_parameterList = prototype.parameterList) != null ? _prototype_parameterList : []), _step2; !(_step2 = _iterator2()).done;){
1428
1715
  var parameter = _step2.value;
1429
1716
  var _parameter_typeInfo;
1430
- if (_instanceof(parameter.astNode, internal.ASTNode.ParameterDeclaration) && parameter.astNode.symbol && this.context.getStructVarRole([
1431
- parameter.astNode.symbol
1432
- ])) {
1433
- continue;
1434
- }
1435
1717
  var _parameter_typeInfo_structDeclarations;
1436
1718
  this._prepareForwardTypes((_parameter_typeInfo_structDeclarations = (_parameter_typeInfo = parameter.typeInfo) == null ? void 0 : _parameter_typeInfo.structDeclarations) != null ? _parameter_typeInfo_structDeclarations : [], anchor, typeAnchor);
1437
1719
  }
@@ -1439,12 +1721,9 @@ ShaderInstructionEncoder._FUNC_MACRO_RE = /^(\w+)\(([^)]*)\)\s*(.*)/;
1439
1721
  }
1440
1722
  };
1441
1723
  _proto._getForwardSignature = function _getForwardSignature(prototype) {
1442
- var _this, _loop = function() {
1724
+ var _loop = function() {
1443
1725
  var parameter = _step.value;
1444
1726
  var declaration = parameter.astNode;
1445
- if (_instanceof(declaration, internal.ASTNode.ParameterDeclaration) && declaration.symbol && _this.context.getStructVarRole([
1446
- declaration.symbol
1447
- ])) return "continue";
1448
1727
  var tokens = [];
1449
1728
  var visit = function(node) {
1450
1729
  if (_instanceof(node, internal.BaseToken)) {
@@ -1459,7 +1738,7 @@ ShaderInstructionEncoder._FUNC_MACRO_RE = /^(\w+)\(([^)]*)\)\s*(.*)/;
1459
1738
  };
1460
1739
  var parameters = [];
1461
1740
  var _prototype_parameterList;
1462
- for(var _iterator = _create_for_of_iterator_helper_loose((_prototype_parameterList = prototype.parameterList) != null ? _prototype_parameterList : []), _step; !(_step = _iterator()).done;)_this = this, _loop();
1741
+ for(var _iterator = _create_for_of_iterator_helper_loose((_prototype_parameterList = prototype.parameterList) != null ? _prototype_parameterList : []), _step; !(_step = _iterator()).done;)_loop();
1463
1742
  return prototype.returnType.codeGen(this) + "(" + parameters.join(",") + ")";
1464
1743
  };
1465
1744
  _proto._canBranchesOverlap = function _canBranchesOverlap(left, right) {
@@ -1512,7 +1791,8 @@ ShaderInstructionEncoder._FUNC_MACRO_RE = /^(\w+)\(([^)]*)\)\s*(.*)/;
1512
1791
  };
1513
1792
  var code = CodeGenVisitor.prototype.visitVariableIdentifier.call(this, node);
1514
1793
  for(var _iterator = _create_for_of_iterator_helper_loose(node.resolvedSymbols()), _step; !(_step = _iterator()).done;)_this = this, _loop();
1515
- return code;
1794
+ var _this__escapedReference;
1795
+ return (_this__escapedReference = this._escapedReference(node)) != null ? _this__escapedReference : code;
1516
1796
  };
1517
1797
  _proto._getForwardDeclarations = function _getForwardDeclarations(out) {
1518
1798
  var _this, _loop = function() {
@@ -1688,6 +1968,7 @@ ShaderInstructionEncoder._FUNC_MACRO_RE = /^(\w+)\(([^)]*)\)\s*(.*)/;
1688
1968
  _proto._getCustomStruct = function _getCustomStruct(structNodes, out) {
1689
1969
  for(var _iterator = _create_for_of_iterator_helper_loose(structNodes), _step; !(_step = _iterator()).done;){
1690
1970
  var node = _step.value;
1971
+ if (this._structCodeSegments.has(node)) continue;
1691
1972
  var text = node.codeGen(this);
1692
1973
  if (!node.isInMacroBranch) {
1693
1974
  out.push({
@@ -1812,7 +2093,8 @@ ShaderInstructionEncoder._FUNC_MACRO_RE = /^(\w+)\(([^)]*)\)\s*(.*)/;
1812
2093
  };
1813
2094
  _proto._declaration = function _declaration(text, node, activate) {
1814
2095
  if (activate === void 0) activate = true;
1815
- return ShaderInstructionEncoder.declaration(text, this._declarationOwners.get(node), activate);
2096
+ var initializer = text && this._inputHelperBodies.get(node);
2097
+ return ShaderInstructionEncoder.declaration(initializer ? text + "\n" + initializer : text, this._declarationOwners.get(node), activate);
1816
2098
  };
1817
2099
  _create_class(GLESVisitor, [
1818
2100
  {
@@ -1828,57 +2110,29 @@ ShaderInstructionEncoder._FUNC_MACRO_RE = /^(\w+)\(([^)]*)\)\s*(.*)/;
1828
2110
  var GLES100Visitor = /*#__PURE__*/ function(GLESVisitor) {
1829
2111
  _inherits(GLES100Visitor, GLESVisitor);
1830
2112
  function GLES100Visitor() {
1831
- return GLESVisitor.apply(this, arguments) || this;
2113
+ var _this;
2114
+ _this = GLESVisitor.apply(this, arguments) || this, _this.supportsArrayStructReturn = false;
2115
+ return _this;
1832
2116
  }
1833
2117
  var _proto = GLES100Visitor.prototype;
1834
2118
  _proto.getAttributeProp = function getAttributeProp(prop) {
1835
2119
  return "attribute " + prop.typeInfo.typeLexeme + " " + prop.ident.lexeme + ";";
1836
2120
  };
1837
2121
  _proto.getVaryingProp = function getVaryingProp(prop) {
1838
- return "varying " + prop.typeInfo.typeLexeme + " " + prop.ident.lexeme + ";";
2122
+ return "varying " + prop.typeInfo.typeLexeme + " " + this.interfaceName(prop, internal.ShaderStructRole.Varying) + ";";
1839
2123
  };
1840
2124
  _proto.getMRTProp = function getMRTProp() {
1841
2125
  return "";
1842
2126
  };
1843
- _proto.visitPostfixExpression = function visitPostfixExpression(node) {
1844
- var children = node.children;
1845
- var postExpr = children[0];
1846
- var context = this.context;
1847
- var directRoot = _instanceof(postExpr, internal.ASTNode.PostfixExpression) ? internal.ParserUtils.unwrapBareIdentifier(postExpr, {
1848
- allowParens: true
1849
- }) : undefined;
1850
- var _directRoot_resolvedValueSymbols;
1851
- var directSymbols = (_directRoot_resolvedValueSymbols = directRoot == null ? void 0 : directRoot.resolvedValueSymbols()) != null ? _directRoot_resolvedValueSymbols : [];
1852
- var unresolvedName = _instanceof(postExpr, internal.ASTNode.PostfixExpression) ? internal.ParserUtils.extractDirectIdentLexeme(postExpr) : null;
1853
- var directRole = directRoot ? directSymbols.length ? context.getStructVarRole(directSymbols) : unresolvedName ? context.getUnresolvedStructVarRole(unresolvedName) : undefined : undefined;
1854
- if (directRole === internal.ShaderStructRole.Mrt) {
1855
- var propReferenced = children[2];
1856
- var prop = context.mrtList.find(function(item) {
1857
- return item.ident.lexeme === propReferenced.lexeme;
1858
- });
1859
- // The parser already validated struct fields (UndeclaredStructMember); a miss here is an
1860
- // already-errored shader, so emit nothing rather than re-report.
1861
- if (!prop) return "";
1862
- return "gl_FragData[" + prop.mrtIndex + "]";
1863
- }
1864
- return GLESVisitor.prototype.visitPostfixExpression.call(this, node);
2127
+ _proto.fragmentColorOutput = function fragmentColorOutput() {
2128
+ return "gl_FragColor";
1865
2129
  };
1866
- _proto.visitJumpStatement = function visitJumpStatement(node) {
1867
- var mode = this.context.getFragmentReturnMode(node);
1868
- var terminal = this.context.isTerminalInterfaceReturn(node);
1869
- if (mode === "mrt") return terminal ? "" : "return;";
1870
- if (mode === "color") {
1871
- var expression = node.children[1];
1872
- var assignment = "gl_FragColor = " + expression.codeGen(this) + ";";
1873
- return terminal ? assignment : "{ " + assignment + " return; }";
1874
- }
1875
- return GLESVisitor.prototype.visitJumpStatement.call(this, node);
2130
+ _proto.mrtOutput = function mrtOutput(prop) {
2131
+ return "gl_FragData[" + prop.mrtIndex + "]";
1876
2132
  };
1877
2133
  return GLES100Visitor;
1878
2134
  }(GLESVisitor);
1879
2135
 
1880
- var V3_GL_FragColor = "GS_glFragColor";
1881
- var V3_GL_FragData = "GS_glFragData";
1882
2136
  var GLES300Visitor = /*#__PURE__*/ function(GLESVisitor) {
1883
2137
  _inherits(GLES300Visitor, GLESVisitor);
1884
2138
  function GLES300Visitor() {
@@ -1910,15 +2164,15 @@ var GLES300Visitor = /*#__PURE__*/ function(GLESVisitor) {
1910
2164
  };
1911
2165
  _proto.getVaryingProp = function getVaryingProp(prop) {
1912
2166
  var qualifier = this.context.stage === internal.EShaderStage.FRAGMENT ? "in" : "out";
1913
- return qualifier + " " + prop.typeInfo.typeLexeme + " " + prop.ident.lexeme + ";";
2167
+ return qualifier + " " + prop.typeInfo.typeLexeme + " " + this.interfaceName(prop, internal.ShaderStructRole.Varying) + ";";
1914
2168
  };
1915
2169
  _proto.getMRTProp = function getMRTProp(prop) {
1916
- return "layout(location = " + prop.mrtIndex + ") out vec4 " + prop.ident.lexeme + ";";
2170
+ return "layout(location = " + prop.mrtIndex + ") out vec4 " + this.interfaceName(prop, internal.ShaderStructRole.Mrt) + ";";
1917
2171
  };
1918
2172
  _proto.visitFunctionIdentifier = function visitFunctionIdentifier(node) {
1919
2173
  var children = node.children;
1920
2174
  var typeSpecifier = children[0];
1921
- if (typeSpecifier.children.length !== 1 || typeSpecifier.structDependencies.length) {
2175
+ if (!node.isBuiltin || typeSpecifier.children.length !== 1 || typeSpecifier.structDependencies.length) {
1922
2176
  // Struct constructors still need the shared type-dependency visitor.
1923
2177
  return GLESVisitor.prototype.visitFunctionIdentifier.call(this, node);
1924
2178
  }
@@ -1952,14 +2206,14 @@ var GLES300Visitor = /*#__PURE__*/ function(GLESVisitor) {
1952
2206
  var context = this.context;
1953
2207
  if (context.stage === internal.EShaderStage.FRAGMENT && node.builtinSemantic === internal.ShaderBuiltinSemantic.FragmentOutput0) {
1954
2208
  this._registerFragColorVariable();
1955
- return V3_GL_FragColor;
2209
+ return this._fragmentColorName();
1956
2210
  }
1957
2211
  if (context.stage === internal.EShaderStage.FRAGMENT && node.builtinSemantic === internal.ShaderBuiltinSemantic.FragmentDepth) {
1958
2212
  return "gl_FragDepth";
1959
2213
  }
1960
2214
  if (context.stage === internal.EShaderStage.FRAGMENT && node.builtinSemantic === internal.ShaderBuiltinSemantic.FragmentOutputArray) {
1961
2215
  this._registerFragDataArray();
1962
- return V3_GL_FragData;
2216
+ return this._fragmentDataName();
1963
2217
  }
1964
2218
  return GLESVisitor.prototype.visitVariableIdentifier.call(this, node);
1965
2219
  };
@@ -1970,20 +2224,22 @@ var GLES300Visitor = /*#__PURE__*/ function(GLESVisitor) {
1970
2224
  }
1971
2225
  return GLESVisitor.prototype.visitPostfixExpression.call(this, node);
1972
2226
  };
1973
- _proto.visitJumpStatement = function visitJumpStatement(node) {
1974
- var mode = this.context.getFragmentReturnMode(node);
1975
- var terminal = this.context.isTerminalInterfaceReturn(node);
1976
- if (mode === "mrt") return terminal ? "" : "return;";
1977
- if (mode === "color") {
1978
- this._registerFragColorVariable();
1979
- var expression = node.children[1];
1980
- var assignment = V3_GL_FragColor + " = " + expression.codeGen(this) + ";";
1981
- return terminal ? assignment : "{ " + assignment + " return; }";
1982
- }
1983
- return GLESVisitor.prototype.visitJumpStatement.call(this, node);
2227
+ _proto.fragmentColorOutput = function fragmentColorOutput() {
2228
+ this._registerFragColorVariable();
2229
+ return this._fragmentColorName();
2230
+ };
2231
+ _proto.mrtOutput = function mrtOutput(prop) {
2232
+ return this.interfaceName(prop, internal.ShaderStructRole.Mrt);
2233
+ };
2234
+ _proto._fragmentColorName = function _fragmentColorName() {
2235
+ return this.context.names.allocate("fragment-output", "output_color");
2236
+ };
2237
+ _proto._fragmentDataName = function _fragmentDataName() {
2238
+ return this.context.names.allocate("fragment-output-array", "output_colors");
1984
2239
  };
1985
2240
  _proto._registerFragColorVariable = function _registerFragColorVariable() {
1986
- this._registerOutput(V3_GL_FragColor, "out vec4 " + V3_GL_FragColor + ";");
2241
+ var name = this._fragmentColorName();
2242
+ this._registerOutput(name, "out vec4 " + name + ";");
1987
2243
  };
1988
2244
  _proto._registerOutput = function _registerOutput(name, text) {
1989
2245
  var output = this._outputDeclarations.get(name);
@@ -2036,10 +2292,11 @@ var GLES300Visitor = /*#__PURE__*/ function(GLESVisitor) {
2036
2292
  }
2037
2293
  };
2038
2294
  _proto._registerFragDataArray = function _registerFragDataArray() {
2039
- this._registerOutput(V3_GL_FragData, "layout(location = 0) out vec4 " + V3_GL_FragData + "[gl_MaxDrawBuffers];");
2295
+ var name = this._fragmentDataName();
2296
+ this._registerOutput(name, "layout(location = 0) out vec4 " + name + "[gl_MaxDrawBuffers];");
2040
2297
  };
2041
2298
  _proto._registerFragDataVariable = function _registerFragDataVariable(index) {
2042
- var name = "" + V3_GL_FragData + index;
2299
+ var name = this.context.names.allocate("fragment-output:" + index, "output_color_" + index);
2043
2300
  this._registerOutput(name, "layout(location = " + index + ") out vec4 " + name + ";");
2044
2301
  return name;
2045
2302
  };
@@ -2265,6 +2522,7 @@ function generateShaderProgram(ir, coreInfo, backend, preprocessorExpressions) {
2265
2522
  isUsePass: false,
2266
2523
  tags: pass.tags,
2267
2524
  renderStates: serializeRenderStates(pass.renderStates),
2525
+ vertexOutputNames: program.vertexOutputNames,
2268
2526
  vertexShaderInstructions: program.vertexShaderInstructions,
2269
2527
  fragmentShaderInstructions: program.fragmentShaderInstructions
2270
2528
  };