25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

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