Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

228 рядки
8.8 KiB

  1. unit uengShaderGenerator;
  2. {$mode objfpc}{$H+}
  3. {$I uengShaderFile.inc}
  4. interface
  5. uses
  6. Classes, SysUtils,
  7. uengShaderPart, uengShaderFileTypes, uengShaderFileParser, uengShaderPartScope,
  8. uengShaderPartKeyValuePair, uengShaderGeneratorArgs;
  9. type
  10. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  11. TengShaderGenerator = class(TengShaderPartScope)
  12. { Code Loading & Storage }
  13. private
  14. fPropertyMap: TengShaderPartPropertyMap;
  15. function GetPropertyByIndex(const aIndex: Integer): Variant;
  16. function GetPropertyByName(const aName: String): Variant;
  17. function GetPropertyCount: Integer;
  18. function GetPropertyNames(const aIndex: Integer): String;
  19. procedure SetPropertyByIndex(const aIndex: Integer; aValue: Variant);
  20. procedure SetPropertyByName(const aName: String; aValue: Variant);
  21. protected
  22. procedure AddProperty(const aProp: TengShaderPartProperty; const aShowWarning: Boolean = true);
  23. procedure CopyProperties(const aGen: TengShaderGenerator);
  24. procedure UpdateProperties; virtual;
  25. function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override;
  26. public
  27. property PropertyByName [const aName: String]: Variant read GetPropertyByName write SetPropertyByName;
  28. property PropertyByIndex[const aIndex: Integer]: Variant read GetPropertyByIndex write SetPropertyByIndex;
  29. property PropertyNames [const aIndex: Integer]: String read GetPropertyNames;
  30. property PropertyCount: Integer read GetPropertyCount;
  31. { Generate Shader Code }
  32. public
  33. procedure GenerateCode(const aCode: TengShaderCode);
  34. { General }
  35. public
  36. constructor Create(const aParent: TengShaderPart); override;
  37. destructor Destroy; override;
  38. end;
  39. implementation
  40. uses
  41. uengShaderFile, uengShaderFileHelper, uengShaderPartProc, uengShaderPartParameter;
  42. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  43. //TengShaderGenerator///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  44. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  45. function TengShaderGenerator.GetPropertyByIndex(const aIndex: Integer): Variant;
  46. begin
  47. result := fPropertyMap.ValueAt[aIndex].Value;
  48. end;
  49. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  50. function TengShaderGenerator.GetPropertyByName(const aName: String): Variant;
  51. var
  52. l: TengShaderPartPropertyList;
  53. begin
  54. l := fPropertyMap[aName];
  55. if not Assigned(l) then
  56. EengUnknownIdentifier.Create(aName, self);
  57. result := l.Value;
  58. end;
  59. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  60. function TengShaderGenerator.GetPropertyCount: Integer;
  61. begin
  62. result := fPropertyMap.Count;
  63. end;
  64. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  65. function TengShaderGenerator.GetPropertyNames(const aIndex: Integer): String;
  66. begin
  67. result := fPropertyMap.KeyValuePairs[aIndex].Key;
  68. end;
  69. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  70. procedure TengShaderGenerator.SetPropertyByIndex(const aIndex: Integer; aValue: Variant);
  71. begin
  72. fPropertyMap.ValueAt[aIndex].Value := aValue;
  73. end;
  74. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  75. procedure TengShaderGenerator.SetPropertyByName(const aName: String; aValue: Variant);
  76. var
  77. l: TengShaderPartPropertyList;
  78. begin
  79. l := fPropertyMap[aName];
  80. if not Assigned(l) then
  81. raise EengUnknownIdentifier.Create(aName, self);
  82. l.Value := aValue;
  83. end;
  84. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  85. procedure TengShaderGenerator.AddProperty(const aProp: TengShaderPartProperty; const aShowWarning: Boolean);
  86. var
  87. i: Integer;
  88. l: TengShaderPartPropertyList;
  89. p: TengShaderPartProperty;
  90. s: String;
  91. begin
  92. i := -1;
  93. l := fPropertyMap[aProp.Name];
  94. if Assigned(l) then begin
  95. i := l.IndexOf(aProp);
  96. if aShowWarning and (i >= 0) then begin
  97. p := l.Last;
  98. s := Format('use of duplicate identifier: %s (%s %d:%d)', [aProp.Name, aProp.Filename, aProp.Line + 1, aProp.Col]) + sLineBreak +
  99. 'previously declared here:' + sLineBreak +
  100. Format(' %s %d:%d', [p.Filename, p.Line + 1, p.Col]) + sLineBreak;
  101. LogMsg(llWarning, s);
  102. end;
  103. end else begin
  104. l := TengShaderPartPropertyList.Create;
  105. fPropertyMap.Add(aProp.Name, l);
  106. end;
  107. if (i < 0) then begin
  108. l.Add(aProp);
  109. if (aProp.Value <> Unassigned) then
  110. l.Value := aProp.Value;
  111. end;
  112. end;
  113. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  114. procedure TengShaderGenerator.CopyProperties(const aGen: TengShaderGenerator);
  115. var
  116. l: TengShaderPartPropertyList;
  117. p: TengShaderPartProperty;
  118. begin
  119. for l in fPropertyMap do
  120. for p in l do
  121. aGen.AddProperty(p, false);
  122. end;
  123. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  124. procedure TengShaderGenerator.UpdateProperties;
  125. begin
  126. fPropertyMap.Clear;
  127. end;
  128. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  129. function TengShaderGenerator.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
  130. begin
  131. result := inherited ParseIntern(aArgs, aParams);
  132. UpdateProperties;
  133. end;
  134. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  135. procedure TengShaderGenerator.GenerateCode(const aCode: TengShaderCode);
  136. var
  137. args: TengShaderGeneratorArgs;
  138. sr: TengSearchResults;
  139. walker: TengSearchWalker;
  140. main: TengShaderPartMain;
  141. begin
  142. args := TengShaderGeneratorArgs.Create(self);
  143. try
  144. fPropertyMap.ApplyValues;
  145. GenerateCodeIntern(args);
  146. args.PushCode;
  147. sr := TengSearchResults.Create;
  148. walker := TengSearchWalker.Create(sr);
  149. try
  150. walker.SearchFlags := [sfSearchChildren, sfEvaluateIf];
  151. walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartMain);
  152. walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderGenerator);
  153. walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile);
  154. walker.Run(self);
  155. if (self is TengShaderFile)
  156. then main := (ExtractSearchResult(self, TengShaderPartMain.GetTokenName, sr, []) as TengShaderPartMain)
  157. else main := (ExtractSearchResult(self, TengShaderPartMain.GetTokenName, sr) as TengShaderPartMain);
  158. if Assigned(main) then begin
  159. args.PushFlags((args.Flags * [gfAddProcedureItem, gfAddParameterItem]) + [gfGenerateProcedureCode, gfGenerateProcedureMain]);
  160. try
  161. main.GenerateCodeIntern(args);
  162. finally
  163. args.PopFlags;
  164. end;
  165. end;
  166. args.GenerateProcedureCode;
  167. args.GenerateParameterCode(CengShaderPartArr.Create(TengShaderPartVar));
  168. args.GenerateParameterCode(CengShaderPartArr.Create(TengShaderPartVarying));
  169. args.GenerateParameterCode(CengShaderPartArr.Create(TengShaderPartUniform));
  170. finally
  171. FreeAndNil(walker);
  172. FreeAndNil(sr);
  173. args.PopCode([pcfAppend, pcfAddEmptyLine]);
  174. end;
  175. args.PushCode;
  176. try
  177. args.GenerateMetaCode;
  178. finally
  179. args.PopCode([pcfPrepend, pcfAddEmptyLine]);
  180. end;
  181. args.GenerateCode(aCode);
  182. finally
  183. FreeAndNil(args);
  184. end;
  185. end;
  186. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  187. constructor TengShaderGenerator.Create(const aParent: TengShaderPart);
  188. begin
  189. inherited Create(aParent);
  190. fPropertyMap := TengShaderPartPropertyMap.Create(true);
  191. end;
  192. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  193. destructor TengShaderGenerator.Destroy;
  194. begin
  195. FreeAndNil(fPropertyMap);
  196. inherited Destroy;
  197. end;
  198. end.