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.
 
 
 
 
 
 

855 lines
35 KiB

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