No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 
 
 

871 líneas
36 KiB

  1. library libShaderFile;
  2. {$mode objfpc}{$H+}
  3. uses
  4. SysUtils, variants, Classes,
  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_HANDLE_STREAM = $00000012;
  20. LSF_ERR_INVALID_GENERATOR_NAME = $00000020;
  21. LSF_ERR_INVALID_PROPERTY_INDEX = $00000021;
  22. LSF_ERR_INVALID_PROPERTY_NAME = $00000022;
  23. LSF_ERR_GENERATOR_NOT_ASSIGNED_TO_FILE = $00000023;
  24. LSF_ERR_UNKNOWN_IDENTFIFIER = $00001000;
  25. LSF_ERR_DUPLICATE_IDENTIFIER = $00001001;
  26. LSF_ERR_OUT_OF_RANGE = $00001002;
  27. LSF_ERR_INVALID_IDENTIFIER = $00001003;
  28. LSF_ERR_INVALID_PARAMTER_COUNT = $00001004;
  29. LSF_ERR_INVALID_PARAMTER = $00001005;
  30. LSF_ERR_UNEXPECTED_TOKEN = $00001006;
  31. LSF_ERR_INVALID_TOKEN = $00001007;
  32. LSF_ERR_EXPRESSION_INTERNAL = $00001008;
  33. LSF_ERR_EXPRESSION = $00001009;
  34. LSF_ERR_SHADER_PART_INTERNAL = $0000100A;
  35. LSF_ERR_SHADER_PART = $0000100B;
  36. LSF_ERR_UNKNOWN = $FFFFFFFF;
  37. {%H-}LSF_SEEK_BEG = soBeginning;
  38. {%H-}LSF_SEEK_CUR = soCurrent;
  39. {%H-}LSF_SEEK_END = soEnd;
  40. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  41. type
  42. TlsfErrorCode = Cardinal;
  43. TlsfLogLevel = Cardinal;
  44. TlsfSeekOrigin = Cardinal;
  45. TlsfShaderFileHandle = Pointer;
  46. TlsfShaderGeneratorHandle = Pointer;
  47. TlsfStreamHandle = Pointer;
  48. TlsfShaderFileLogEvent = procedure(const aLogLevel: TlsfLogLevel; const aMsg: PAnsiChar; const aUserArgs: Pointer); stdcall;
  49. TlsfSaveDataCallback = procedure(const aFilename: PAnsiChar; const aHandle: TlsfStreamHandle; const aUserArgs: Pointer); stdcall;
  50. TlsfLoadDataCallback = function(const aFilename: PAnsiChar; const aHandle: TlsfStreamHandle; const aUserArgs: Pointer): Boolean; stdcall;
  51. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  52. //internal types and contstants/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  53. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  54. type
  55. TShaderFile = class;
  56. TShaderGenerator = class;
  57. TPropertyMap = specialize TutlMap<string, variant>;
  58. TShaderGeneratorHandleHashSet = specialize TutlHashSet<TlsfShaderGeneratorHandle>;
  59. TShaderGeneratorHashSet = specialize TutlHashSet<TShaderGenerator>;
  60. TStreamHashSet = specialize TutlHashSet<TStream>;
  61. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  62. TShaderGenerator = class(TObject)
  63. private
  64. fOwner: TShaderFile;
  65. fGenerator: TengShaderGenerator;
  66. fProperties: TPropertyMap;
  67. fPropertyNames: String;
  68. fPropertyValue: String;
  69. fGeneratedCode: String;
  70. public
  71. property Owner: TShaderFile read fOwner;
  72. property PropertyNames: String read fPropertyNames;
  73. property Properties: TPropertyMap read fProperties;
  74. function GetProperty(const aIndex: Integer): PAnsiChar;
  75. function GetProperty(const aName: String): PAnsiChar;
  76. function SetProperty(const aIndex: Integer; const aValue: PAnsiChar): TlsfErrorCode;
  77. function SetProperty(const aName: String; const aValue: PAnsiChar): TlsfErrorCode;
  78. function GenerateCode: PAnsiChar;
  79. constructor Create(const aOwner: TShaderFile; const aGenerator: TengShaderGenerator);
  80. destructor Destroy; override;
  81. end;
  82. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  83. TShaderFile = class(TengShaderFile)
  84. private
  85. fLogUserArgs: Pointer;
  86. fLogCallback: TlsfShaderFileLogEvent;
  87. fGenerators: TShaderGeneratorHashSet;
  88. fGeneratorNames: String;
  89. protected
  90. procedure LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String); override;
  91. public
  92. property LogCallback: TlsfShaderFileLogEvent read fLogCallback write fLogCallback;
  93. property LogUserArgs: Pointer read fLogUserArgs write fLogUserArgs;
  94. property GeneratorNames: String read fGeneratorNames;
  95. procedure LoadFromFile(const aFilename: String; const aFileReader: IengShaderFileReader = nil); reintroduce;
  96. function CreateGenerator(const aName: String): TShaderGenerator;
  97. function DestroyGenerator(const aGenerator: TShaderGenerator): TlsfErrorCode;
  98. constructor Create; overload;
  99. destructor Destroy; override;
  100. end;
  101. TShaderFileHashSet = specialize TutlHashSet<TShaderFile>;
  102. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  103. TFileWriterProxy = class(TInterfacedObject, IengShaderFileWriter)
  104. private
  105. fUserArgs: Pointer;
  106. fCallback: TlsfSaveDataCallback;
  107. public
  108. procedure SaveStream(const aFilename: String; const aStream: TStream);
  109. constructor Create(const aCallback: TlsfSaveDataCallback; const aUserArgs: Pointer);
  110. end;
  111. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  112. TFileReaderProxy = class(TInterfacedObject, IengShaderFileReader)
  113. private
  114. fUserArgs: Pointer;
  115. fCallback: TlsfLoadDataCallback;
  116. public
  117. function LoadStream(const aFilename: String; const aStream: TStream): Boolean;
  118. constructor Create(const aCallback: TlsfLoadDataCallback; const aUserArgs: Pointer);
  119. end;
  120. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  121. var
  122. ShaderFiles: TShaderFileHashSet = nil;
  123. ShaderGenerators: TShaderGeneratorHandleHashSet = nil;
  124. Streams: TStreamHashSet = nil;
  125. LastErrorCode: TlsfErrorCode = LSF_ERR_NONE;
  126. LastErrorMsg: String = '';
  127. LastErrorTrace: String = '';
  128. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  129. //Misc (not exportet)///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  130. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  131. procedure SetLastError(const aErrorCode: TlsfErrorCode; const aMsg: String);
  132. begin
  133. LastErrorCode := aErrorCode;
  134. LastErrorMsg := aMsg;
  135. LastErrorTrace := '';
  136. end;
  137. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  138. procedure SetLastError(const aException: Exception);
  139. begin
  140. if (aException is EengUnknownIdentifier) then
  141. LastErrorCode := LSF_ERR_UNKNOWN_IDENTFIFIER
  142. else if (aException is EengDuplicateIdentifier) then
  143. LastErrorCode := LSF_ERR_DUPLICATE_IDENTIFIER
  144. else if (aException is EengOutOfRange) then
  145. LastErrorCode := LSF_ERR_OUT_OF_RANGE
  146. else if (aException is EengInvalidIdentifier) then
  147. LastErrorCode := LSF_ERR_INVALID_IDENTIFIER
  148. else if (aException is EengInvalidParamterCount) then
  149. LastErrorCode := LSF_ERR_INVALID_PARAMTER_COUNT
  150. else if (aException is EengInvalidParamter) then
  151. LastErrorCode := LSF_ERR_INVALID_PARAMTER
  152. else if (aException is EengUnexpectedToken) then
  153. LastErrorCode := LSF_ERR_UNEXPECTED_TOKEN
  154. else if (aException is EengInvalidToken) then
  155. LastErrorCode := LSF_ERR_INVALID_TOKEN
  156. else if (aException is EengExpressionInternal) then
  157. LastErrorCode := LSF_ERR_EXPRESSION_INTERNAL
  158. else if (aException is EengExpression) then
  159. LastErrorCode := LSF_ERR_EXPRESSION
  160. else if (aException is EengShaderPartInternal) then
  161. LastErrorCode := LSF_ERR_SHADER_PART_INTERNAL
  162. else if (aException is EengShaderPart ) then
  163. LastErrorCode := LSF_ERR_SHADER_PART
  164. else
  165. LastErrorCode := LSF_ERR_UNKNOWN;
  166. if (aException is EengShaderPart)
  167. then LastErrorTrace := (aException as EengShaderPart).PrintTrace
  168. else LastErrorTrace := '';
  169. LastErrorMsg := aException.Message;
  170. end;
  171. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  172. function CheckIfInitialized: Boolean;
  173. begin
  174. result := Assigned(ShaderFiles);
  175. if not result then
  176. SetLastError(LSf_ERR_NOT_INIT, 'libShaderFile has not been initialized. call lsf_init before using any other methods.');
  177. end;
  178. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  179. function CheckShaderFileHandle(const aHandle: TlsfShaderFileHandle): Boolean;
  180. begin
  181. result := CheckIfInitialized;
  182. if result then begin
  183. result := ShaderFiles.Contains(TShaderFile(aHandle));
  184. if not result then
  185. SetLastError(LSF_ERR_INVALID_HANDLE_SHADER_FILE, Format('0x%x is not a valid shader file handle', [{%H-}PtrUInt(aHandle)]));
  186. end;
  187. end;
  188. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  189. function CheckShaderGeneratorHandle(const aHandle: TlsfShaderGeneratorHandle): Boolean;
  190. begin
  191. result := CheckIfInitialized;
  192. if result then begin
  193. result := ShaderGenerators.Contains(TShaderGenerator(aHandle));
  194. if not result then
  195. SetLastError(LSF_ERR_INVALID_HANDLE_SHADER_GENERATOR, Format('0x%x is not a valid shader generator handle', [{%H-}PtrUInt(aHandle)]));
  196. end;
  197. end;
  198. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  199. function CheckStreamHandle(const aHandle: TlsfStreamHandle): Boolean;
  200. begin
  201. result := CheckIfInitialized;
  202. if result then begin
  203. result := Streams.Contains(TStream(aHandle));
  204. if not result then
  205. SetLastError(LSF_ERR_INVALID_HANDLE_STREAM, Format('0x%x is not a valid stream handle', [{%H-}PtrUInt(aHandle)]));
  206. end;
  207. end;
  208. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  209. //ShaderFile////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  210. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  211. function lsf_ShaderFile_create: TlsfShaderFileHandle; stdcall;
  212. var
  213. sf: TShaderFile;
  214. begin
  215. try
  216. result := nil;
  217. if not CheckIfInitialized then
  218. exit;
  219. sf := TShaderFile.Create;
  220. ShaderFiles.Add(sf);
  221. result := sf;
  222. except
  223. on e: Exception do begin
  224. SetLastError(e);
  225. result := nil;
  226. end;
  227. end;
  228. end;
  229. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  230. function lsf_ShaderFile_setLogCallback(const aHandle: TlsfShaderFileHandle; const aCallback: TlsfShaderFileLogEvent; const aUserArgs: Pointer): TlsfErrorCode; stdcall;
  231. begin
  232. try
  233. result := LSF_ERR_NONE;
  234. if CheckShaderFileHandle(aHandle) then with TShaderFile(aHandle) do begin
  235. LogCallback := aCallback;
  236. LogUserArgs := aUserArgs;
  237. end else
  238. result := LastErrorCode;
  239. except
  240. on e: Exception do begin
  241. SetLastError(e);
  242. result := LastErrorCode;
  243. end;
  244. end;
  245. end;
  246. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  247. function lsf_ShaderFile_loadFromFile(const aHandle: TlsfShaderFileHandle; const aFilename: PAnsiChar): TlsfErrorCode; stdcall;
  248. begin
  249. try
  250. result := LSF_ERR_NONE;
  251. if not CheckShaderFileHandle(aHandle)
  252. then result := LastErrorCode
  253. else TShaderFile(aHandle).LoadFromFile(aFilename);
  254. except
  255. on e: Exception do begin
  256. SetLastError(e);
  257. result := LastErrorCode;
  258. end;
  259. end;
  260. end;
  261. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  262. function lsf_ShaderFile_loadFromFunc(const aHandle: TlsfShaderFileHandle; const aFilename: PAnsiChar;
  263. const aCallback: TlsfLoadDataCallback; const aUserArgs: Pointer): TlsfErrorCode; stdcall;
  264. begin
  265. try
  266. result := LSF_ERR_NONE;
  267. if not CheckShaderFileHandle(aHandle)
  268. then result := LastErrorCode
  269. else TShaderFile(aHandle).LoadFromFile(aFilename, TFileReaderProxy.Create(aCallback, aUserArgs));
  270. except
  271. on e: Exception do begin
  272. SetLastError(e);
  273. result := LastErrorCode;
  274. end;
  275. end;
  276. end;
  277. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  278. function lsf_ShaderFile_saveToFile(const aHandle: TlsfShaderFileHandle; const aFilename: PAnsiChar): TlsfErrorCode; stdcall;
  279. begin
  280. try
  281. result := LSF_ERR_NONE;
  282. if not CheckShaderFileHandle(aHandle)
  283. then result := LastErrorCode
  284. else TShaderFile(aHandle).SaveToFile(aFilename);
  285. except
  286. on e: Exception do begin
  287. SetLastError(e);
  288. result := LastErrorCode;
  289. end;
  290. end;
  291. end;
  292. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  293. function lsf_ShaderFile_saveToFunc(const aHandle: TlsfShaderFileHandle; const aFilename: PAnsiChar;
  294. const aCallback: TlsfSaveDataCallback; const aUserArgs: Pointer): TlsfErrorCode; stdcall;
  295. begin
  296. try
  297. result := LSF_ERR_NONE;
  298. if not CheckShaderFileHandle(aHandle)
  299. then result := LastErrorCode
  300. else TShaderFile(aHandle).SaveToFile(aFilename, TFileWriterProxy.Create(aCallback, aUserArgs));
  301. except
  302. on e: Exception do begin
  303. SetLastError(e);
  304. result := LastErrorCode;
  305. end;
  306. end;
  307. end;
  308. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  309. function lsf_ShaderFile_getGeneratorNames(const aHandle: TlsfShaderFileHandle): PAnsiChar; stdcall;
  310. begin
  311. try
  312. if not CheckShaderFileHandle(aHandle)
  313. then result := nil
  314. else result := PAnsiChar(TShaderFile(aHandle).GeneratorNames);
  315. except
  316. on e: Exception do begin
  317. SetLastError(e);
  318. result := nil;
  319. end;
  320. end;
  321. end;
  322. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  323. function lsf_ShaderFile_destroy(const aHandle: TlsfShaderFileHandle): TlsfErrorCode; stdcall;
  324. begin
  325. try
  326. result := LSF_ERR_NONE;
  327. if not CheckShaderFileHandle(aHandle)
  328. then result := LastErrorCode
  329. else ShaderFiles.Remove(TShaderFile(aHandle));
  330. except
  331. on e: Exception do begin
  332. SetLastError(e);
  333. result := LastErrorCode;
  334. end;
  335. end;
  336. end;
  337. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  338. //Generator/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  339. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  340. function lsf_Generator_create(const aHandle: TlsfShaderFileHandle; const aName: PAnsiChar): TlsfShaderGeneratorHandle; stdcall;
  341. begin
  342. try
  343. if not CheckShaderFileHandle(aHandle)
  344. then result := nil
  345. else result := TShaderFile(aHandle).CreateGenerator(string(aName));
  346. except
  347. on e: Exception do begin
  348. SetLastError(e);
  349. result := nil;
  350. end;
  351. end;
  352. end;
  353. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  354. function lsf_Generator_getPropertyNames(const aHandle: TlsfShaderGeneratorHandle): PAnsiChar; stdcall;
  355. begin
  356. try
  357. if not CheckShaderGeneratorHandle(aHandle)
  358. then result := nil
  359. else result := PAnsiChar(TShaderGenerator(aHandle).PropertyNames);
  360. except
  361. on e: Exception do begin
  362. SetLastError(e);
  363. result := nil;
  364. end;
  365. end;
  366. end;
  367. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  368. function lsf_Generator_getProperty(const aHandle: TlsfShaderGeneratorHandle; const aIndex: Integer): PAnsiChar; stdcall;
  369. begin
  370. try
  371. if not CheckShaderGeneratorHandle(aHandle)
  372. then result := nil
  373. else result := TShaderGenerator(aHandle).GetProperty(aIndex);
  374. except
  375. on e: Exception do begin
  376. SetLastError(e);
  377. result := nil;
  378. end;
  379. end;
  380. end;
  381. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  382. function lsf_Generator_getPropertyByName(const aHandle: TlsfShaderGeneratorHandle; const aName: PAnsiChar): PAnsiChar; stdcall;
  383. begin
  384. try
  385. if not CheckShaderGeneratorHandle(aHandle)
  386. then result := nil
  387. else result := TShaderGenerator(aHandle).GetProperty(aName);
  388. except
  389. on e: Exception do begin
  390. SetLastError(e);
  391. result := nil;
  392. end;
  393. end;
  394. end;
  395. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  396. function lsf_Generator_setProperty(const aHandle: TlsfShaderGeneratorHandle; const aIndex: Integer; const aValue: PAnsiChar): TlsfErrorCode; stdcall;
  397. begin
  398. try
  399. if not CheckShaderGeneratorHandle(aHandle)
  400. then result := LastErrorCode
  401. else result := TShaderGenerator(aHandle).SetProperty(aIndex, aValue);
  402. except
  403. on e: Exception do begin
  404. SetLastError(e);
  405. result := LastErrorCode;
  406. end;
  407. end;
  408. end;
  409. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  410. function lsf_Generator_setPropertyByName(const aHandle: TlsfShaderGeneratorHandle; const aName, aValue: PAnsiChar): TlsfErrorCode; stdcall;
  411. begin
  412. try
  413. if not CheckShaderGeneratorHandle(aHandle)
  414. then result := LastErrorCode
  415. else result := TShaderGenerator(aHandle).SetProperty(aName, aValue);
  416. except
  417. on e: Exception do begin
  418. SetLastError(e);
  419. result := LastErrorCode;
  420. end;
  421. end;
  422. end;
  423. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  424. function lsf_Generator_generateCode(const aHandle: TlsfShaderGeneratorHandle): PAnsiChar; stdcall;
  425. begin
  426. try
  427. if not CheckShaderGeneratorHandle(aHandle)
  428. then result := nil
  429. else result := TShaderGenerator(aHandle).GenerateCode;
  430. except
  431. on e: Exception do begin
  432. SetLastError(e);
  433. result := nil;
  434. end;
  435. end;
  436. end;
  437. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  438. function lsf_Generator_destroy(const aHandle: TlsfShaderGeneratorHandle): TlsfErrorCode; stdcall;
  439. var
  440. sg: TShaderGenerator;
  441. sf: TShaderFile;
  442. begin
  443. try
  444. result := LSF_ERR_NONE;
  445. if CheckShaderGeneratorHandle(aHandle) then begin
  446. sg := TShaderGenerator(aHandle);
  447. sf := sg.Owner;
  448. sf.DestroyGenerator(sg);
  449. end else
  450. result := LastErrorCode;
  451. except
  452. on e: Exception do begin
  453. SetLastError(e);
  454. result := LastErrorCode;
  455. end;
  456. end;
  457. end;
  458. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  459. //Stream////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  460. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  461. function lsf_Stream_getSize(const aHandle: TlsfStreamHandle): Integer; stdcall;
  462. begin
  463. try
  464. if CheckStreamHandle(aHandle)
  465. then result := TStream(aHandle).Size
  466. else result := -1;
  467. except
  468. on e: Exception do begin
  469. SetLastError(e);
  470. result := LastErrorCode;
  471. end;
  472. end;
  473. end;
  474. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  475. function lsf_Stream_setSize(const aHandle: TlsfStreamHandle; const aSize: Integer): TlsfErrorCode; stdcall;
  476. begin
  477. try
  478. if CheckStreamHandle(aHandle)
  479. then TStream(aHandle).Size := aSize
  480. else result := LastErrorCode;
  481. except
  482. on e: Exception do begin
  483. SetLastError(e);
  484. result := LastErrorCode;
  485. end;
  486. end;
  487. end;
  488. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  489. function lsf_Stream_seek(const aHandle: TlsfStreamHandle; const aOffset: Integer; const aOrigin: TlsfSeekOrigin): Integer; stdcall;
  490. begin
  491. try
  492. if CheckStreamHandle(aHandle)
  493. then result := TStream(aHandle).Seek(aOrigin, aOrigin)
  494. else result := -1;
  495. except
  496. on e: Exception do begin
  497. SetLastError(e);
  498. result := LastErrorCode;
  499. end;
  500. end;
  501. end;
  502. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  503. function lsf_Stream_read(const aHandle: TlsfStreamHandle; const aBuffer: Pointer; const aSize: Integer): Integer; stdcall;
  504. begin
  505. try
  506. if CheckStreamHandle(aHandle)
  507. then result := TStream(aHandle).Read(aBuffer^, aSize)
  508. else result := -1;
  509. except
  510. on e: Exception do begin
  511. SetLastError(e);
  512. result := LastErrorCode;
  513. end;
  514. end;
  515. end;
  516. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  517. function lsf_Stream_write(const aHandle: TlsfStreamHandle; const aBuffer: Pointer; const aSize: Integer): Integer; stdcall;
  518. begin
  519. try
  520. if CheckStreamHandle(aHandle)
  521. then result := TStream(aHandle).Write(aBuffer^, aSize)
  522. else result := -1;
  523. except
  524. on e: Exception do begin
  525. SetLastError(e);
  526. result := LastErrorCode;
  527. end;
  528. end;
  529. end;
  530. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  531. //Global////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  532. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  533. function lsf_init: TlsfErrorCode; stdcall;
  534. begin
  535. try
  536. result := LSF_ERR_NONE;
  537. ShaderFiles := TShaderFileHashSet.Create(true);
  538. ShaderGenerators := TShaderGeneratorHandleHashSet.Create(true);
  539. Streams := TStreamHashSet.Create(false);
  540. except
  541. on e: Exception do begin
  542. SetLastError(e);
  543. result := LastErrorCode;
  544. end;
  545. end;
  546. end;
  547. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  548. function lsf_getLastErrorCode: TlsfErrorCode; stdcall;
  549. begin
  550. result := LastErrorCode;
  551. end;
  552. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  553. function lsf_getLastErrorMsg: PAnsiChar; stdcall;
  554. begin
  555. result := PAnsiChar(LastErrorMsg);
  556. end;
  557. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  558. function lsf_getLastErrorTrace: PAnsiChar; stdcall;
  559. begin
  560. result := PAnsiChar(LastErrorTrace);
  561. end;
  562. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  563. function lsf_finish: TlsfErrorCode; stdcall;
  564. begin
  565. try
  566. result := LSF_ERR_NONE;
  567. FreeAndNil(Streams);
  568. FreeAndNil(ShaderGenerators);
  569. FreeAndNil(ShaderFiles);
  570. except
  571. on e: Exception do begin
  572. SetLastError(e);
  573. result := LastErrorCode;
  574. end;
  575. end;
  576. end;
  577. exports
  578. lsf_ShaderFile_create,
  579. lsf_ShaderFile_setLogCallback,
  580. lsf_ShaderFile_loadFromFile,
  581. lsf_ShaderFile_loadFromFunc,
  582. lsf_ShaderFile_saveToFile,
  583. lsf_ShaderFile_saveToFunc,
  584. lsf_ShaderFile_getGeneratorNames,
  585. lsf_ShaderFile_destroy,
  586. lsf_Generator_create,
  587. lsf_Generator_getPropertyNames,
  588. lsf_Generator_getProperty,
  589. lsf_Generator_getPropertyByName,
  590. lsf_Generator_setProperty,
  591. lsf_Generator_setPropertyByName,
  592. lsf_Generator_generateCode,
  593. lsf_Generator_destroy,
  594. lsf_Stream_getSize,
  595. lsf_Stream_setSize,
  596. lsf_Stream_seek,
  597. lsf_Stream_read,
  598. lsf_Stream_write,
  599. lsf_init,
  600. lsf_getLastErrorCode,
  601. lsf_getLastErrorMsg,
  602. lsf_getLastErrorTrace,
  603. lsf_finish;
  604. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  605. //TShaderGenerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  606. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  607. function TShaderGenerator.GetProperty(const aIndex: Integer): PAnsiChar;
  608. begin
  609. result := nil;
  610. if (aIndex < 0) or (aIndex >= fProperties.Count) then begin
  611. SetLastError(LSF_ERR_INVALID_PROPERTY_INDEX, Format('index (%d) out of range (%d:%d)', [aIndex, 0, fProperties.Count-1]));
  612. exit;
  613. end;
  614. fPropertyValue := fProperties.ValueAt[aIndex];
  615. result := PAnsiChar(fPropertyValue);
  616. end;
  617. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  618. function TShaderGenerator.GetProperty(const aName: String): PAnsiChar;
  619. var
  620. i: Integer;
  621. begin
  622. result := nil;
  623. i := fProperties.IndexOf(aName);
  624. if (i >= 0)
  625. then result := GetProperty(i)
  626. else SetLastError(LSF_ERR_INVALID_PROPERTY_NAME, Format('%s is not a valid/known property name', [aName]));
  627. end;
  628. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  629. function TShaderGenerator.SetProperty(const aIndex: Integer; const aValue: PAnsiChar): TlsfErrorCode;
  630. begin
  631. result := LSF_ERR_NONE;
  632. if (aIndex < 0) or (aIndex >= fProperties.Count) then begin
  633. SetLastError(LSF_ERR_INVALID_PROPERTY_INDEX, Format('index (%d) out of range (%d:%d)', [aIndex, 0, fProperties.Count-1]));
  634. result := LastErrorCode;
  635. end;
  636. fProperties.ValueAt[aIndex] := string(aValue);
  637. end;
  638. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  639. function TShaderGenerator.SetProperty(const aName: String; const aValue: PAnsiChar): TlsfErrorCode;
  640. var
  641. i: Integer;
  642. begin
  643. i := fProperties.IndexOf(aName);
  644. if (i < 0) then begin
  645. SetLastError(LSF_ERR_INVALID_PROPERTY_NAME, Format('%s is not a valid/known property name', [aName]));
  646. result := LastErrorCode;
  647. end else
  648. result := SetProperty(i, aValue)
  649. end;
  650. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  651. function TShaderGenerator.GenerateCode: PAnsiChar;
  652. var
  653. kvp: TPropertyMap.TKeyValuePair;
  654. c: TengShaderCode;
  655. begin
  656. for kvp in fProperties.KeyValuePairs do
  657. fGenerator.PropertyByName[kvp.Key] := kvp.Value;
  658. c := TengShaderCode.Create;
  659. try
  660. fGenerator.GenerateCode(c);
  661. fGeneratedCode := c.Text;
  662. result := PAnsiChar(fGeneratedCode);
  663. finally
  664. FreeAndNil(c);
  665. end;
  666. end;
  667. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  668. constructor TShaderGenerator.Create(const aOwner: TShaderFile; const aGenerator: TengShaderGenerator);
  669. var
  670. i: Integer;
  671. begin
  672. inherited Create;
  673. fOwner := aOwner;
  674. fGenerator := aGenerator;
  675. fProperties := TPropertyMap.Create(true);
  676. fPropertyNames := '';
  677. for i := 0 to fGenerator.PropertyCount-1 do begin
  678. fProperties.Add(fGenerator.PropertyNames[i], fGenerator.PropertyByIndex[i]);
  679. fPropertyNames := fPropertyNames + fGenerator.PropertyNames[i] + sLineBreak;
  680. end;
  681. end;
  682. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  683. destructor TShaderGenerator.Destroy;
  684. begin
  685. FreeAndNil(fProperties);
  686. inherited Destroy;
  687. end;
  688. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  689. //TShaderFile///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  690. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  691. procedure TShaderFile.LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String);
  692. var
  693. tmp: TlsfShaderFileLogEvent;
  694. begin
  695. inherited LogMsgIntern(aSender, aLogLevel, aMsg);
  696. tmp := fLogCallback;
  697. if Assigned(tmp) then
  698. tmp(Cardinal(aLogLevel), PAnsiChar(aMsg), fLogUserArgs);
  699. end;
  700. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  701. procedure TShaderFile.LoadFromFile(const aFilename: String; const aFileReader: IengShaderFileReader);
  702. var
  703. i: Integer;
  704. begin
  705. inherited LoadFromFile(aFilename, aFileReader);
  706. fGeneratorNames := '';
  707. for i := 0 to GeneratorCount-1 do
  708. fGeneratorNames := fGeneratorNames + inherited GeneratorNames[i] + sLineBreak;
  709. end;
  710. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  711. function TShaderFile.CreateGenerator(const aName: String): TShaderGenerator;
  712. function CheckName: Boolean;
  713. var
  714. i: Integer;
  715. begin
  716. result := true;
  717. for i := 0 to GeneratorCount-1 do
  718. if (inherited GeneratorNames[i] = aName) then
  719. exit;
  720. result := false;
  721. end;
  722. begin
  723. result := nil;
  724. if not CheckName then begin
  725. SetLastError(LSF_ERR_INVALID_GENERATOR_NAME, 'a generator with the name ''' + aName + ''' does not exist');
  726. exit;
  727. end;
  728. result := TShaderGenerator.Create(self, Generator[aName]);
  729. fGenerators.Add(result);
  730. ShaderGenerators.Add(result);
  731. end;
  732. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  733. function TShaderFile.DestroyGenerator(const aGenerator: TShaderGenerator): TlsfErrorCode;
  734. begin
  735. if Assigned(ShaderGenerators) then
  736. ShaderGenerators.Remove(aGenerator);
  737. if not fGenerators.Remove(aGenerator) then begin
  738. SetLastError(LSF_ERR_GENERATOR_NOT_ASSIGNED_TO_FILE, 'the passed generator handle is not owned by any file');
  739. result := LastErrorCode;
  740. end else
  741. result := LSF_ERR_NONE;
  742. end;
  743. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  744. constructor TShaderFile.Create;
  745. begin
  746. inherited Create;
  747. fGenerators := TShaderGeneratorHashSet.Create(true);
  748. end;
  749. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  750. destructor TShaderFile.Destroy;
  751. begin
  752. FreeAndNil(fGenerators);
  753. inherited Destroy;
  754. end;
  755. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  756. //TFileWriterProxy//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  757. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  758. procedure TFileWriterProxy.SaveStream(const aFilename: String; const aStream: TStream);
  759. begin
  760. Streams.Add(aStream);
  761. try
  762. fCallback(PAnsiChar(aFilename), TlsfStreamHandle(aStream), fUserArgs);
  763. finally
  764. Streams.Remove(aStream);
  765. end;
  766. end;
  767. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  768. constructor TFileWriterProxy.Create(const aCallback: TlsfSaveDataCallback; const aUserArgs: Pointer);
  769. begin
  770. inherited Create;
  771. fCallback := aCallback;
  772. fUserArgs := aUserArgs;
  773. end;
  774. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  775. //TFileReaderProxy//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  776. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  777. function TFileReaderProxy.LoadStream(const aFilename: String; const aStream: TStream): Boolean;
  778. begin
  779. Streams.Add(aStream);
  780. try
  781. result := fCallback(PAnsiChar(aFilename), TlsfStreamHandle(aStream), fUserArgs);
  782. finally
  783. Streams.Remove(aStream);
  784. end;
  785. end;
  786. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  787. constructor TFileReaderProxy.Create(const aCallback: TlsfLoadDataCallback; const aUserArgs: Pointer);
  788. begin
  789. inherited Create;
  790. fCallback := aCallback;
  791. fUserArgs := aUserArgs;
  792. end;
  793. end.