You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

674 lines
26 KiB

  1. library libShaderFile;
  2. {$mode objfpc}{$H+}
  3. uses
  4. SysUtils, variants,
  5. uengShaderFile, uengShaderGenerator, uengShaderPart,
  6. uengShaderFileGenerics, uengShaderFileTypes;
  7. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  8. //external types and contstants/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  9. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  10. const
  11. {%H-}LSF_LOGLEVEL_DEBUG = llDebug;
  12. {%H-}LSF_LOGLEVEL_INFO = llInfo;
  13. {%H-}LSF_LOGLEVEL_WARNING = llWarning;
  14. {%H-}LSF_LOGLEVEL_ERROR = llError;
  15. LSF_ERR_NONE = $00000000;
  16. LSF_ERR_NOT_INIT = $00000001;
  17. LSF_ERR_INVALID_HANDLE_SHADER_FILE = $00000010;
  18. LSF_ERR_INVALID_HANDLE_SHADER_GENERATOR = $00000011;
  19. LSF_ERR_INVALID_GENERATOR_NAME = $00000020;
  20. LSF_ERR_INVALID_PROPERTY_INDEX = $00000021;
  21. LSF_ERR_INVALID_PROPERTY_NAME = $00000022;
  22. LSF_ERR_UNKNOWN_IDENTFIFIER = $00001000;
  23. LSF_ERR_DUPLICATE_IDENTIFIER = $00001001;
  24. LSF_ERR_OUT_OF_RANGE = $00001002;
  25. LSF_ERR_INVALID_IDENTIFIER = $00001003;
  26. LSF_ERR_INVALID_PARAMTER_COUNT = $00001004;
  27. LSF_ERR_INVALID_PARAMTER = $00001005;
  28. LSF_ERR_UNEXPECTED_TOKEN = $00001006;
  29. LSF_ERR_INVALID_TOKEN = $00001007;
  30. LSF_ERR_EXPRESSION_INTERNAL = $00001008;
  31. LSF_ERR_EXPRESSION = $00001009;
  32. LSF_ERR_SHADER_PART_INTERNAL = $0000100A;
  33. LSF_ERR_SHADER_PART = $0000100B;
  34. LSF_ERR_UNKNOWN = $FFFFFFFF;
  35. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  36. type
  37. TlsfErrorCode = Cardinal;
  38. TlsfLogLevel = Cardinal;
  39. TlsfShaderFileHandle = Pointer;
  40. TlsfShaderGeneratorHandle = Pointer;
  41. TlsfShaderFileLogEvent = procedure(const aLogLevel: TlsfLogLevel; const aMsg: PAnsiChar; const aUserArgs: Pointer);
  42. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  43. //internal types and contstants/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  44. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  45. type
  46. TShaderFile = class;
  47. TPropertyMap = specialize TutlMap<string, variant>;
  48. TShaderGenerator = class(TObject)
  49. private
  50. fOwner: TShaderFile;
  51. fGenerator: TengShaderGenerator;
  52. fProperties: TPropertyMap;
  53. fPropertyNames: String;
  54. fPropertyValue: String;
  55. fGeneratedCode: String;
  56. public
  57. property Owner: TShaderFile read fOwner;
  58. property PropertyNames: String read fPropertyNames;
  59. property Properties: TPropertyMap read fProperties;
  60. function GetProperty(const aIndex: Integer): PAnsiChar;
  61. function GetProperty(const aName: String): PAnsiChar;
  62. function SetProperty(const aIndex: Integer; const aValue: PAnsiChar): TlsfErrorCode;
  63. function SetProperty(const aName: String; const aValue: PAnsiChar): TlsfErrorCode;
  64. function GenerateCode: PAnsiChar;
  65. constructor Create(const aOwner: TShaderFile; const aGenerator: TengShaderGenerator);
  66. destructor Destroy; override;
  67. end;
  68. TShaderGeneratorHashSet = specialize TutlHashSet<TlsfShaderGeneratorHandle>;
  69. TShaderFile = class(TengShaderFile)
  70. private
  71. fLogUserArgs: Pointer;
  72. fLogCallback: TlsfShaderFileLogEvent;
  73. fGenerators: TShaderGeneratorHashSet;
  74. fGeneratorNames: String;
  75. protected
  76. procedure LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String); override;
  77. public
  78. property LogCallback: TlsfShaderFileLogEvent read fLogCallback write fLogCallback;
  79. property LogUserArgs: Pointer read fLogUserArgs write fLogUserArgs;
  80. property GeneratorNames: String read fGeneratorNames;
  81. procedure LoadFromFile(const aFilename: String); reintroduce;
  82. function CreateGenerator(const aName: String): TShaderGenerator;
  83. procedure DestroyGenerator(const aGenerator: TShaderGenerator);
  84. constructor Create; overload;
  85. destructor Destroy; override;
  86. end;
  87. TShaderFileHashSet = specialize TutlHashSet<TShaderFile>;
  88. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  89. var
  90. ShaderFiles: TShaderFileHashSet = nil;
  91. ShaderGenerators: TShaderGeneratorHashSet = nil;
  92. LastErrorCode: TlsfErrorCode = LSF_ERR_NONE;
  93. LastErrorMsg: String = '';
  94. LastErrorTrace: String = '';
  95. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  96. //Misc (not exportet)///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  97. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  98. procedure SetLastError(const aErrorCode: TlsfErrorCode; const aMsg: String);
  99. begin
  100. LastErrorCode := aErrorCode;
  101. LastErrorMsg := aMsg;
  102. LastErrorTrace := '';
  103. end;
  104. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  105. procedure SetLastError(const aException: Exception);
  106. begin
  107. if (aException is EengUnknownIdentifier) then
  108. LastErrorCode := LSF_ERR_UNKNOWN_IDENTFIFIER
  109. else if (aException is EengDuplicateIdentifier) then
  110. LastErrorCode := LSF_ERR_DUPLICATE_IDENTIFIER
  111. else if (aException is EengOutOfRange) then
  112. LastErrorCode := LSF_ERR_OUT_OF_RANGE
  113. else if (aException is EengInvalidIdentifier) then
  114. LastErrorCode := LSF_ERR_INVALID_IDENTIFIER
  115. else if (aException is EengInvalidParamterCount) then
  116. LastErrorCode := LSF_ERR_INVALID_PARAMTER_COUNT
  117. else if (aException is EengInvalidParamter) then
  118. LastErrorCode := LSF_ERR_INVALID_PARAMTER
  119. else if (aException is EengUnexpectedToken) then
  120. LastErrorCode := LSF_ERR_UNEXPECTED_TOKEN
  121. else if (aException is EengInvalidToken) then
  122. LastErrorCode := LSF_ERR_INVALID_TOKEN
  123. else if (aException is EengExpressionInternal) then
  124. LastErrorCode := LSF_ERR_EXPRESSION_INTERNAL
  125. else if (aException is EengExpression) then
  126. LastErrorCode := LSF_ERR_EXPRESSION
  127. else if (aException is EengShaderPartInternal) then
  128. LastErrorCode := LSF_ERR_SHADER_PART_INTERNAL
  129. else if (aException is EengShaderPart ) then
  130. LastErrorCode := LSF_ERR_SHADER_PART
  131. else
  132. LastErrorCode := LSF_ERR_UNKNOWN;
  133. if (aException is EengShaderPart)
  134. then LastErrorTrace := (aException as EengShaderPart).PrintTrace
  135. else LastErrorTrace := '';
  136. LastErrorMsg := aException.Message;
  137. end;
  138. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  139. function CheckIfInitialized: Boolean;
  140. begin
  141. try
  142. result := Assigned(ShaderFiles);
  143. if not result then
  144. SetLastError(LSf_ERR_NOT_INIT, 'libShaderFile has not been initialized. call lsf_init before using any other methods.');
  145. except
  146. on e: Exception do begin
  147. SetLastError(e);
  148. result := false;
  149. end;
  150. end;
  151. end;
  152. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  153. function CheckShaderFileHandle(const aHandle: TlsfShaderFileHandle): Boolean;
  154. begin
  155. try
  156. result := CheckIfInitialized;
  157. if result then begin
  158. result := ShaderFiles.Contains(TShaderFile(aHandle));
  159. if not result then
  160. SetLastError(LSF_ERR_INVALID_HANDLE_SHADER_FILE, Format('0x%x is not a valid shader file handle', [{%H-}PtrUInt(aHandle)]));
  161. end;
  162. except
  163. on e: Exception do begin
  164. SetLastError(e);
  165. result := false;
  166. end;
  167. end;
  168. end;
  169. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  170. function CheckShaderGeneratorHandle(const aHandle: TlsfShaderGeneratorHandle): Boolean;
  171. begin
  172. try
  173. result := CheckIfInitialized;
  174. if result then begin
  175. result := ShaderGenerators.Contains(TShaderGenerator(aHandle));
  176. if not result then
  177. SetLastError(LSF_ERR_INVALID_HANDLE_SHADER_GENERATOR, Format('0x%x is not a valid shader generator handle', [{%H-}PtrUInt(aHandle)]));
  178. end;
  179. except
  180. on e: Exception do begin
  181. SetLastError(e);
  182. result := false;
  183. end;
  184. end;
  185. end;
  186. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  187. //ShaderFile////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  188. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  189. function lsf_ShaderFile_create: TlsfShaderFileHandle; stdcall;
  190. var
  191. sf: TShaderFile;
  192. begin
  193. try
  194. result := nil;
  195. if not CheckIfInitialized then
  196. exit;
  197. sf := TShaderFile.Create;
  198. ShaderFiles.Add(sf);
  199. result := sf;
  200. except
  201. on e: Exception do begin
  202. SetLastError(e);
  203. result := nil;
  204. end;
  205. end;
  206. end;
  207. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  208. function lsf_ShaderFile_setLogCallback(const aHandle: TlsfShaderFileHandle; const aCallback: TlsfShaderFileLogEvent; const aUserArgs: Pointer): TlsfErrorCode; stdcall;
  209. begin
  210. try
  211. result := LSF_ERR_NONE;
  212. if CheckShaderFileHandle(aHandle) then with TShaderFile(aHandle) do begin
  213. LogCallback := aCallback;
  214. LogUserArgs := aUserArgs;
  215. end else
  216. result := LastErrorCode;
  217. except
  218. on e: Exception do begin
  219. SetLastError(e);
  220. result := LastErrorCode;
  221. end;
  222. end;
  223. end;
  224. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  225. function lsf_ShaderFile_loadFromFile(const aHandle: TlsfShaderFileHandle; const aFilename: PAnsiChar): TlsfErrorCode; stdcall;
  226. begin
  227. try
  228. result := LSF_ERR_NONE;
  229. if not CheckShaderFileHandle(aHandle)
  230. then result := LastErrorCode
  231. else TShaderFile(aHandle).LoadFromFile(aFilename);
  232. except
  233. on e: Exception do begin
  234. SetLastError(e);
  235. result := LastErrorCode;
  236. end;
  237. end;
  238. end;
  239. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  240. function lsf_ShaderFile_saveToFile(const aHandle: TlsfShaderFileHandle; const aFilename: PAnsiChar): TlsfErrorCode; stdcall;
  241. begin
  242. try
  243. result := LSF_ERR_NONE;
  244. if not CheckShaderFileHandle(aHandle)
  245. then result := LastErrorCode
  246. else TShaderFile(aHandle).SaveToFile(aFilename);
  247. except
  248. on e: Exception do begin
  249. SetLastError(e);
  250. result := LastErrorCode;
  251. end;
  252. end;
  253. end;
  254. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  255. function lsf_ShaderFile_getGeneratorNames(const aHandle: TlsfShaderFileHandle): PAnsiChar; stdcall;
  256. begin
  257. try
  258. if not CheckShaderFileHandle(aHandle)
  259. then result := nil
  260. else result := PAnsiChar(TShaderFile(aHandle).GeneratorNames);
  261. except
  262. on e: Exception do begin
  263. SetLastError(e);
  264. result := nil;
  265. end;
  266. end;
  267. end;
  268. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  269. function lsf_ShaderFile_destroy(const aHandle: TlsfShaderFileHandle): TlsfErrorCode; stdcall;
  270. begin
  271. try
  272. result := LSF_ERR_NONE;
  273. if not CheckShaderFileHandle(aHandle)
  274. then result := LastErrorCode
  275. else ShaderFiles.Remove(TShaderFile(aHandle));
  276. except
  277. on e: Exception do begin
  278. SetLastError(e);
  279. result := LastErrorCode;
  280. end;
  281. end;
  282. end;
  283. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  284. //Generator/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  285. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  286. function lsf_Generator_create(const aHandle: TlsfShaderFileHandle; const aName: PAnsiChar): TlsfShaderGeneratorHandle; stdcall;
  287. begin
  288. try
  289. if not CheckShaderFileHandle(aHandle)
  290. then result := nil
  291. else result := TShaderFile(aHandle).CreateGenerator(string(aName));
  292. except
  293. on e: Exception do begin
  294. SetLastError(e);
  295. result := nil;
  296. end;
  297. end;
  298. end;
  299. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  300. function lsf_Generator_getPropertyNames(const aHandle: TlsfShaderGeneratorHandle): PAnsiChar; stdcall;
  301. begin
  302. try
  303. if not CheckShaderGeneratorHandle(aHandle)
  304. then result := nil
  305. else result := PAnsiChar(TShaderGenerator(aHandle).PropertyNames);
  306. except
  307. on e: Exception do begin
  308. SetLastError(e);
  309. result := nil;
  310. end;
  311. end;
  312. end;
  313. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  314. function lsf_Generator_getProperty(const aHandle: TlsfShaderGeneratorHandle; const aIndex: Integer): PAnsiChar; stdcall;
  315. begin
  316. try
  317. if not CheckShaderGeneratorHandle(aHandle)
  318. then result := nil
  319. else result := TShaderGenerator(aHandle).GetProperty(aIndex);
  320. except
  321. on e: Exception do begin
  322. SetLastError(e);
  323. result := nil;
  324. end;
  325. end;
  326. end;
  327. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  328. function lsf_Generator_getPropertyByName(const aHandle: TlsfShaderGeneratorHandle; const aName: PAnsiChar): PAnsiChar; stdcall;
  329. begin
  330. try
  331. if not CheckShaderGeneratorHandle(aHandle)
  332. then result := nil
  333. else result := TShaderGenerator(aHandle).GetProperty(aName);
  334. except
  335. on e: Exception do begin
  336. SetLastError(e);
  337. result := nil;
  338. end;
  339. end;
  340. end;
  341. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  342. function lsf_Generator_setProperty(const aHandle: TlsfShaderGeneratorHandle; const aIndex: Integer; const aValue: PAnsiChar): TlsfErrorCode; stdcall;
  343. begin
  344. try
  345. if not CheckShaderGeneratorHandle(aHandle)
  346. then result := LastErrorCode
  347. else result := TShaderGenerator(aHandle).SetProperty(aIndex, aValue);
  348. except
  349. on e: Exception do begin
  350. SetLastError(e);
  351. result := LastErrorCode;
  352. end;
  353. end;
  354. end;
  355. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  356. function lsf_Generator_setPropertyByName(const aHandle: TlsfShaderGeneratorHandle; const aName, aValue: PAnsiChar): TlsfErrorCode; stdcall;
  357. begin
  358. try
  359. if not CheckShaderGeneratorHandle(aHandle)
  360. then result := LastErrorCode
  361. else result := TShaderGenerator(aHandle).SetProperty(aName, aValue);
  362. except
  363. on e: Exception do begin
  364. SetLastError(e);
  365. result := LastErrorCode;
  366. end;
  367. end;
  368. end;
  369. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  370. function lsf_Generator_generateCode(const aHandle: TlsfShaderGeneratorHandle): PAnsiChar; stdcall;
  371. begin
  372. try
  373. if not CheckShaderGeneratorHandle(aHandle)
  374. then result := nil
  375. else result := TShaderGenerator(aHandle).GenerateCode;
  376. except
  377. on e: Exception do begin
  378. SetLastError(e);
  379. result := nil;
  380. end;
  381. end;
  382. end;
  383. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  384. function lsf_Generator_destroy(const aHandle: TlsfShaderGeneratorHandle): TlsfErrorCode; stdcall;
  385. var
  386. sg: TShaderGenerator;
  387. sf: TShaderFile;
  388. begin
  389. try
  390. result := LSF_ERR_NONE;
  391. if CheckShaderGeneratorHandle(aHandle) then begin
  392. sg := TShaderGenerator(aHandle);
  393. sf := sg.Owner;
  394. sf.DestroyGenerator(sg);
  395. end else
  396. result := LastErrorCode;
  397. except
  398. on e: Exception do begin
  399. SetLastError(e);
  400. result := LastErrorCode;
  401. end;
  402. end;
  403. end;
  404. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  405. //Global////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  406. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  407. function lsf_init: TlsfErrorCode; stdcall;
  408. begin
  409. try
  410. result := LSF_ERR_NONE;
  411. ShaderFiles := TShaderFileHashSet.Create(true);
  412. ShaderGenerators := TShaderGeneratorHashSet.Create(false);
  413. except
  414. on e: Exception do begin
  415. SetLastError(e);
  416. result := LastErrorCode;
  417. end;
  418. end;
  419. end;
  420. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  421. function lsf_getLastErrorCode: TlsfErrorCode; stdcall;
  422. begin
  423. result := LastErrorCode;
  424. end;
  425. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  426. function lsf_getLastErrorMsg: PAnsiChar; stdcall;
  427. begin
  428. result := PAnsiChar(LastErrorMsg);
  429. end;
  430. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  431. function lsf_getLastErrorTrace: PAnsiChar; stdcall;
  432. begin
  433. result := PAnsiChar(LastErrorTrace);
  434. end;
  435. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  436. function lsf_finish: TlsfErrorCode; stdcall;
  437. begin
  438. try
  439. result := LSF_ERR_NONE;
  440. FreeAndNil(ShaderGenerators);
  441. FreeAndNil(ShaderFiles);
  442. except
  443. on e: Exception do begin
  444. SetLastError(e);
  445. result := LastErrorCode;
  446. end;
  447. end;
  448. end;
  449. exports
  450. lsf_ShaderFile_create,
  451. lsf_ShaderFile_setLogCallback,
  452. lsf_ShaderFile_loadFromFile,
  453. lsf_ShaderFile_saveToFile,
  454. lsf_ShaderFile_getGeneratorNames,
  455. lsf_ShaderFile_destroy,
  456. lsf_Generator_create,
  457. lsf_Generator_getPropertyNames,
  458. lsf_Generator_getProperty,
  459. lsf_Generator_getPropertyByName,
  460. lsf_Generator_setProperty,
  461. lsf_Generator_setPropertyByName,
  462. lsf_Generator_generateCode,
  463. lsf_Generator_destroy,
  464. lsf_init,
  465. lsf_getLastErrorCode,
  466. lsf_getLastErrorMsg,
  467. lsf_getLastErrorTrace,
  468. lsf_finish;
  469. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  470. //TShaderGenerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  471. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  472. function TShaderGenerator.GetProperty(const aIndex: Integer): PAnsiChar;
  473. begin
  474. result := nil;
  475. if (aIndex < 0) or (aIndex >= fProperties.Count) then begin
  476. SetLastError(LSF_ERR_INVALID_PROPERTY_INDEX, Format('index (%d) out of range (%d:%d)', [aIndex, 0, fProperties.Count-1]));
  477. exit;
  478. end;
  479. fPropertyValue := fProperties.ValueAt[aIndex];
  480. result := PAnsiChar(fPropertyValue);
  481. end;
  482. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  483. function TShaderGenerator.GetProperty(const aName: String): PAnsiChar;
  484. var
  485. i: Integer;
  486. begin
  487. result := nil;
  488. i := fProperties.IndexOf(aName);
  489. if (i >= 0)
  490. then result := GetProperty(i)
  491. else SetLastError(LSF_ERR_INVALID_PROPERTY_NAME, Format('%s is not a valid/known property name', [aName]));
  492. end;
  493. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  494. function TShaderGenerator.SetProperty(const aIndex: Integer; const aValue: PAnsiChar): TlsfErrorCode;
  495. begin
  496. result := LSF_ERR_NONE;
  497. if (aIndex < 0) or (aIndex >= fProperties.Count) then begin
  498. SetLastError(LSF_ERR_INVALID_PROPERTY_INDEX, Format('index (%d) out of range (%d:%d)', [aIndex, 0, fProperties.Count-1]));
  499. result := LastErrorCode;
  500. end;
  501. fProperties.ValueAt[aIndex] := string(aValue);
  502. end;
  503. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  504. function TShaderGenerator.SetProperty(const aName: String; const aValue: PAnsiChar): TlsfErrorCode;
  505. var
  506. i: Integer;
  507. begin
  508. i := fProperties.IndexOf(aName);
  509. if (i <= 0) then begin
  510. SetLastError(LSF_ERR_INVALID_PROPERTY_NAME, Format('%s is not a valid/known property name', [aName]));
  511. result := LastErrorCode;
  512. end else
  513. result := SetProperty(i, aValue)
  514. end;
  515. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  516. function TShaderGenerator.GenerateCode: PAnsiChar;
  517. var
  518. kvp: TPropertyMap.TKeyValuePair;
  519. c: TengShaderCode;
  520. begin
  521. for kvp in fProperties.KeyValuePairs do
  522. fGenerator.PropertyByName[kvp.Key] := kvp.Value;
  523. c := TengShaderCode.Create;
  524. try
  525. fGenerator.GenerateCode(c);
  526. fGeneratedCode := c.Text;
  527. result := PAnsiChar(fGeneratedCode);
  528. finally
  529. FreeAndNil(c);
  530. end;
  531. end;
  532. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  533. constructor TShaderGenerator.Create(const aOwner: TShaderFile; const aGenerator: TengShaderGenerator);
  534. var
  535. i: Integer;
  536. begin
  537. inherited Create;
  538. fOwner := aOwner;
  539. fGenerator := aGenerator;
  540. fProperties := TPropertyMap.Create(true);
  541. fPropertyNames := '';
  542. for i := 0 to fGenerator.PropertyCount-1 do begin
  543. fProperties.Add(fGenerator.PropertyNames[i], fGenerator.PropertyByIndex[i]);
  544. fPropertyNames := fPropertyNames + fGenerator.PropertyNames[i] + sLineBreak;
  545. end;
  546. end;
  547. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  548. destructor TShaderGenerator.Destroy;
  549. begin
  550. FreeAndNil(fProperties);
  551. inherited Destroy;
  552. end;
  553. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  554. //TShaderFile///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  555. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  556. procedure TShaderFile.LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String);
  557. var
  558. tmp: TlsfShaderFileLogEvent;
  559. begin
  560. inherited LogMsgIntern(aSender, aLogLevel, aMsg);
  561. tmp := fLogCallback;
  562. if Assigned(tmp) then
  563. tmp(Cardinal(aLogLevel), PAnsiChar(aMsg), fLogUserArgs);
  564. end;
  565. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  566. procedure TShaderFile.LoadFromFile(const aFilename: String);
  567. var
  568. i: Integer;
  569. begin
  570. inherited LoadFromFile(aFilename, nil);
  571. fGeneratorNames := '';
  572. for i := 0 to GeneratorCount-1 do
  573. fGeneratorNames := fGeneratorNames + inherited GeneratorNames[i] + sLineBreak;
  574. end;
  575. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  576. function TShaderFile.CreateGenerator(const aName: String): TShaderGenerator;
  577. function CheckName: Boolean;
  578. var
  579. i: Integer;
  580. begin
  581. result := true;
  582. for i := 0 to GeneratorCount-1 do
  583. if (inherited GeneratorNames[i] = aName) then
  584. exit;
  585. result := false;
  586. end;
  587. begin
  588. result := nil;
  589. if not CheckName then begin
  590. SetLastError(LSF_ERR_INVALID_GENERATOR_NAME, 'a generator with the name ''' + aName + ''' does not exist');
  591. exit;
  592. end;
  593. result := TShaderGenerator.Create(self, Generator[aName]);
  594. fGenerators.Add(result);
  595. ShaderGenerators.Add(result);
  596. end;
  597. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  598. procedure TShaderFile.DestroyGenerator(const aGenerator: TShaderGenerator);
  599. begin
  600. if Assigned(ShaderGenerators) then
  601. ShaderGenerators.Remove(aGenerator);
  602. fGenerators.Remove(aGenerator);
  603. end;
  604. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  605. constructor TShaderFile.Create;
  606. begin
  607. inherited Create;
  608. fGenerators := TShaderGeneratorHashSet.Create(true);
  609. end;
  610. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  611. destructor TShaderFile.Destroy;
  612. begin
  613. FreeAndNil(fGenerators);
  614. inherited Destroy;
  615. end;
  616. end.