Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

339 linhas
12 KiB

  1. unit uengShaderFile;
  2. { Package: SpaceEngine
  3. Prefix: eng - ENGine
  4. Beschreibung: stellt Klassen zum laden von Shader-Datein zur Verfügung
  5. beim laden des Codes wird gleichzeitig die Präprozessor-Sprache ausgewertet }
  6. {$mode objfpc}{$H+}
  7. {$I uengShaderFile.inc}
  8. interface
  9. uses
  10. Classes, sysutils,
  11. uengShaderPart, uengShaderPartClass, uengShaderFileParser, uengShaderFileTypes,
  12. uengShaderGenerator, uengShaderGeneratorArgs
  13. {$IFDEF USE_BITSPACE_UTILS}
  14. , uutlSerialization
  15. {$ENDIF}
  16. ;
  17. type
  18. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  19. TengShaderFileLogEvent = procedure(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String) of object;
  20. TengShaderFile = class(TengShaderGenerator)
  21. { Code Loading & Storage }
  22. private
  23. fFilename: String;
  24. fFileReader: IutlFileReader;
  25. fFileWriter: IutlFileWriter;
  26. fClasses: TengShaderPartClassMap;
  27. private
  28. function GetGenerator(const aName: String): TengShaderGenerator;
  29. function GetGeneratorCount: Integer;
  30. function GetGeneratorNames(const aIndex: Integer): String;
  31. procedure UpdateClasses;
  32. protected
  33. function GetFilename: String; override;
  34. function GetFileReader: IengShaderFileReader; override;
  35. function GetFileWriter: IengShaderFileWriter; override;
  36. procedure UpdateProperties; override;
  37. public
  38. procedure LoadFromFile(const aFilename: String; const aFileReader: IengShaderFileReader = nil);
  39. procedure SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter = nil);
  40. { Code Generation }
  41. public
  42. procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override;
  43. { General }
  44. private
  45. fOnLog: TengShaderFileLogEvent;
  46. protected
  47. procedure LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String); override;
  48. public
  49. property Generator [const aName: String]: TengShaderGenerator read GetGenerator;
  50. property GeneratorNames[const aIndex: Integer]: String read GetGeneratorNames;
  51. property GeneratorCount: Integer read GetGeneratorCount;
  52. property OnLog: TengShaderFileLogEvent read fOnLog write fOnLog;
  53. procedure Clear; override;
  54. constructor Create; overload;
  55. constructor Create(const aParent: TengShaderPart); override; overload;
  56. destructor Destroy; override;
  57. end;
  58. implementation
  59. uses
  60. uengShaderPartInclude, uengShaderPartKeyValuePair, uengShaderFileHelper, uengShaderPartProc;
  61. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  62. //TengShaderFile////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  63. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  64. function TengShaderFile.GetGenerator(const aName: String): TengShaderGenerator;
  65. begin
  66. result := fClasses[aName];
  67. if not Assigned(result) then
  68. result := self;
  69. end;
  70. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  71. function TengShaderFile.GetGeneratorCount: Integer;
  72. begin
  73. result := fClasses.Count+1;
  74. end;
  75. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  76. function TengShaderFile.GetGeneratorNames(const aIndex: Integer): String;
  77. begin
  78. if (aIndex < 0) or (aIndex >= Count) then
  79. raise EengOutOfRange.Create(0, Count-1, aIndex, self);
  80. if (aIndex = 0)
  81. then result := ''
  82. else result := fClasses.Keys[aIndex-1];
  83. end;
  84. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  85. procedure TengShaderFile.UpdateClasses;
  86. procedure AddClass(const aClass: TengShaderPartClass);
  87. var
  88. c: TengShaderPartClass;
  89. s: String;
  90. begin
  91. c := fClasses[aClass.Name];
  92. if Assigned(c) then begin
  93. s := Format('use of duplicate identifier: %s (%s %d:%d)', [aClass.Name, aClass.Filename, aClass.Line + 1, aClass.Col]) + sLineBreak +
  94. 'previously declared here:' + sLineBreak +
  95. Format(' %s %d:%d', [c.Filename, c.Line + 1, c.Col]) + sLineBreak;
  96. LogMsg(llWarning, s);
  97. fClasses[aClass.Name] := aClass;
  98. end else
  99. fClasses.Add(aClass.Name, aClass);
  100. end;
  101. var
  102. sr: TengSearchResults;
  103. walker: TengSearchWalker;
  104. p: TengShaderPart;
  105. begin
  106. sr := TengSearchResults.Create;
  107. walker := TengSearchWalker.Create(sr);
  108. try
  109. walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartClass);
  110. walker.SearchFlags := [sfSearchChildren];
  111. fClasses.Clear;
  112. for p in sr do
  113. AddClass(p as TengShaderPartClass);
  114. finally
  115. FreeAndNil(walker);
  116. FreeAndNil(sr);
  117. end;
  118. end;
  119. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  120. function TengShaderFile.GetFilename: String;
  121. begin
  122. result := fFilename;
  123. end;
  124. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  125. function TengShaderFile.GetFileReader: IengShaderFileReader;
  126. begin
  127. result := fFileReader;
  128. if not Assigned(result) and Assigned(Parent) then
  129. result := Parent.FileReader;
  130. end;
  131. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  132. function TengShaderFile.GetFileWriter: IengShaderFileWriter;
  133. begin
  134. result := fFileWriter;
  135. if not Assigned(result) and Assigned(Parent) then
  136. result := Parent.FileWriter;
  137. end;
  138. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  139. procedure TengShaderFile.UpdateProperties;
  140. var
  141. sr: TengSearchResults;
  142. walker: TengSearchWalker;
  143. p: TengShaderPart;
  144. begin
  145. inherited UpdateProperties;
  146. sr := TengSearchResults.Create;
  147. walker := TengSearchWalker.Create(sr);
  148. try
  149. walker.Owner := self;
  150. walker.SearchFlags := [sfSearchChildren, sfIgnoreOwner];
  151. walker.ResultTypes := CengShaderPartArr.Create(TengShaderFile);
  152. walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderGenerator);
  153. walker.Run(self);
  154. for p in sr do
  155. (p as TengShaderFile).CopyProperties(self);
  156. walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartProperty);
  157. sr.Clear;
  158. walker.Run(self);
  159. for p in sr do
  160. AddProperty(p as TengShaderPartProperty);
  161. finally
  162. FreeAndNil(walker);
  163. FreeAndNil(sr);
  164. end;
  165. end;
  166. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  167. procedure TengShaderFile.LoadFromFile(const aFilename: String; const aFileReader: IengShaderFileReader);
  168. var
  169. args: TengParseArgs;
  170. token: String;
  171. ms: TMemoryStream;
  172. begin
  173. fFileReader := aFileReader;
  174. if not Assigned(fFileReader) then
  175. fFileReader := GetFileReader;
  176. if not Assigned(fFileReader) then
  177. fFileReader := TengShaderFileReader.Create;
  178. ms := TMemoryStream.Create;
  179. try
  180. Clear;
  181. if not fFileReader.LoadStream(aFilename, ms) then
  182. raise EengShaderPart.Create('unable to open file: ' + aFilename, Parent);
  183. ms.Position := 0;
  184. fFilename := aFilename;
  185. args := TengParseArgs.Create(ms, Filename);
  186. try
  187. token := ParseText(args);
  188. if (token <> '') then with args do
  189. raise EengShaderPart.Create('unknown token ''' + token + '''', Line, Col, Filename, self);
  190. if (self = Root) then
  191. UpdateClasses;
  192. finally
  193. FreeAndNil(args);
  194. end;
  195. finally
  196. FreeAndNil(ms);
  197. fFileReader := nil;
  198. end;
  199. end;
  200. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  201. procedure TengShaderFile.SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter);
  202. var
  203. i: Integer;
  204. sr: TengSearchResults;
  205. sl: TStringList;
  206. ms: TMemoryStream;
  207. walker: TengSearchWalker;
  208. begin
  209. fFileWriter := aFileWriter;
  210. if not Assigned(fFileWriter) then
  211. fFileWriter := FileWriter;
  212. if not Assigned(fFileWriter) then
  213. fFileWriter := TengShaderFileWriter.Create;
  214. sr := TengSearchResults.Create;
  215. sl := TStringList.Create;
  216. ms := TMemoryStream.Create;
  217. walker := TengSearchWalker.Create(sr);
  218. try
  219. walker.SearchFlags := [sfSearchChildren];
  220. walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartInclude);
  221. for i := 0 to sr.Count-1 do
  222. (sr[i] as TengShaderPartInclude).SaveToFile(aFilename, aFileWriter);
  223. sl.Text := Text;
  224. sl.SaveToStream(ms);
  225. ms.Position := 0;
  226. fFileWriter.SaveStream(aFilename, ms);
  227. finally
  228. FreeAndNil(walker);
  229. FreeAndNil(sr);
  230. FreeAndNil(sl);
  231. FreeAndNil(ms);
  232. fFileWriter := nil;
  233. end;
  234. end;
  235. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  236. procedure TengShaderFile.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs);
  237. var
  238. sr: TengSearchResults;
  239. walker: TengSearchWalker;
  240. main: TengShaderPartMain;
  241. begin
  242. inherited GenerateCodeIntern(aArgs);
  243. if (aArgs.Root = self) then begin
  244. sr := TengSearchResults.Create;
  245. walker := TengSearchWalker.Create(sr);
  246. try
  247. walker.SearchFlags := [sfSearchChildren, sfEvaluateIf];
  248. walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartMain);
  249. walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderGenerator);
  250. walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile);
  251. walker.Run(self);
  252. main := (ExtractSearchResult(self, TengShaderPartMain.GetTokenName, sr, []) as TengShaderPartMain);
  253. if Assigned(main) then begin
  254. aArgs.PushFlags((aArgs.Flags * [gfAddProcedureItem, gfAddParameterItem]) + [gfGenerateProcedureCode]);
  255. try
  256. main.GenerateCodeIntern(aArgs);
  257. finally
  258. aArgs.PopFlags;
  259. end;
  260. end;
  261. finally
  262. FreeAndNil(walker);
  263. FreeAndNil(sr);
  264. end;
  265. end;
  266. end;
  267. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  268. procedure TengShaderFile.LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String);
  269. var
  270. tmp: TengShaderFileLogEvent;
  271. begin
  272. inherited LogMsgIntern(aSender, aLogLevel, aMsg);
  273. tmp := fOnLog;
  274. if Assigned(tmp) then
  275. tmp(aSender, aLogLevel, aMsg);
  276. end;
  277. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  278. procedure TengShaderFile.Clear;
  279. begin
  280. inherited Clear;
  281. fClasses.Clear;
  282. end;
  283. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  284. constructor TengShaderFile.Create;
  285. begin
  286. Create(nil);
  287. end;
  288. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  289. constructor TengShaderFile.Create(const aParent: TengShaderPart);
  290. begin
  291. inherited Create(aParent);
  292. if not Assigned(fRoot) then
  293. fRoot := self;
  294. fClasses := TengShaderPartClassMap.Create(false);
  295. end;
  296. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  297. destructor TengShaderFile.Destroy;
  298. begin
  299. FreeAndNil(fClasses);
  300. inherited Destroy;
  301. fFileReader := nil;
  302. fFileWriter := nil;
  303. end;
  304. end.