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.

451 lines
20 KiB

  1. unit ulibShaderFile;
  2. {$IFDEF fpc}
  3. {$mode objfpc}{$H+}
  4. {$ENDIF}
  5. interface
  6. uses
  7. Classes, SysUtils, Variants;
  8. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  9. type
  10. {$Z4}
  11. TlsfLogLevel = (
  12. llDebug = 0,
  13. llInfo = 1,
  14. llWarning = 2,
  15. llError = 3
  16. );
  17. {$Z4}
  18. TlsfErrorCode = (
  19. errUnknown = -1,
  20. errNone = $00000000,
  21. errNotInit = $00000001,
  22. errInvalidHandleShaderFile = $00000010,
  23. errInvalidHandleShaderGenerator = $00000011,
  24. errInvalidGeneratorName = $00000020,
  25. errInvalidPropertyIndex = $00000021,
  26. errInvalidPropertyName = $00000022,
  27. errGeneratorNotAssignedToFile = $00000023,
  28. errUnknownIdentfifier = $00001000,
  29. errDuplicateIdentifier = $00001001,
  30. errOutOfRange = $00001002,
  31. errInvalidIdentifier = $00001003,
  32. errInvalidParamterCount = $00001004,
  33. errInvalidParamter = $00001005,
  34. errUnexpectedToken = $00001006,
  35. errInvalidToken = $00001007,
  36. errExpressionInternal = $00001008,
  37. errExpression = $00001009,
  38. errShaderPartInternal = $0000100a,
  39. errShaderPart = $0000100b,
  40. errInvalidLibraryName = $00002000,
  41. errInvalidLibraryHandle = $00002001,
  42. errInvalidMethodName = $00002002
  43. );
  44. TlsfShaderFileHandle = Pointer;
  45. TlsfGeneratorHandle = Pointer;
  46. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  47. TlsfShaderFileLogEvent = procedure(const aLogLevel: TlsfLogLevel; const aMsg: PAnsiChar; const aUserArgs: Pointer); stdcall;
  48. Tlsf_ShaderFile_create = function: TlsfShaderFileHandle; stdcall;
  49. Tlsf_ShaderFile_setLogCallback = function(const aHandle: TlsfShaderFileHandle; const aCallback: TlsfShaderFileLogEvent; const aUserArgs: Pointer): TlsfErrorCode; stdcall;
  50. Tlsf_ShaderFile_loadFromFile = function(const aHandle: TlsfShaderFileHandle; const aFilename: PAnsiChar): TlsfErrorCode; stdcall;
  51. Tlsf_ShaderFile_saveToFile = function(const aHandle: TlsfShaderFileHandle; const aFilename: PAnsiChar): TlsfErrorCode; stdcall;
  52. Tlsf_ShaderFile_getGeneratorNames = function(const aHandle: TlsfShaderFileHandle): PAnsiChar; stdcall;
  53. Tlsf_ShaderFile_destroy = function(const aHandle: TlsfShaderFileHandle): TlsfErrorCode; stdcall;
  54. Tlsf_Generator_create = function(const aHandle: TlsfShaderFileHandle; const aName: PAnsiChar): TlsfGeneratorHandle; stdcall;
  55. Tlsf_Generator_getPropertyNames = function(const aHandle: TlsfGeneratorHandle): PAnsiChar; stdcall;
  56. Tlsf_Generator_getProperty = function(const aHandle: TlsfGeneratorHandle; const aIndex: Integer): PAnsiChar; stdcall;
  57. Tlsf_Generator_getPropertyByName = function(const aHandle: TlsfGeneratorHandle; const aName: PAnsiChar): PAnsiChar; stdcall;
  58. Tlsf_Generator_setProperty = function(const aHandle: TlsfGeneratorHandle; const aIndex: Integer; const aValue: PAnsiChar): TlsfErrorCode; stdcall;
  59. Tlsf_Generator_setPropertyByName = function(const aHandle: TlsfGeneratorHandle; const aName: PAnsiChar; const aValue: PAnsiChar): TlsfErrorCode; stdcall;
  60. Tlsf_Generator_generateCode = function(const aHandle: TlsfGeneratorHandle): PAnsiChar; stdcall;
  61. Tlsf_Generator_destroy = function(const aHandle: TlsfGeneratorHandle): TlsfErrorCode; stdcall;
  62. Tlsf_init = function: TlsfErrorCode; stdcall;
  63. Tlsf_getLastErrorCode = function: TlsfErrorCode; stdcall;
  64. Tlsf_getLastErrorMsg = function: PAnsiChar; stdcall;
  65. Tlsf_getLastErrorTrace = function: PAnsiChar; stdcall;
  66. Tlsf_finish = function: TlsfErrorCode; stdcall;
  67. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  68. TlsfShaderFile = class(TObject)
  69. private
  70. fHandle: TlsfShaderFileHandle;
  71. protected
  72. procedure LogMsg(const aLogLevel: TlsfLogLevel; const aMsg: String); virtual;
  73. public
  74. property Handle: TlsfShaderFileHandle read fHandle;
  75. procedure LoadFromFile(const aFilename: String);
  76. procedure SaveToFile(const aFilename: String);
  77. constructor Create;
  78. destructor Destroy; override;
  79. end;
  80. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  81. TlsfGenerator = class(TObject)
  82. private
  83. fName: String;
  84. fHandle: TlsfGeneratorHandle;
  85. fShaderFile: TlsfShaderFile;
  86. fProperties: TStringList;
  87. function GetProperties: TStrings;
  88. public
  89. property Name: String read fName;
  90. property ShaderFile: TlsfShaderFile read fShaderFile;
  91. property Properties: TStrings read GetProperties;
  92. function GetProperty(const aName: String): Variant; overload;
  93. function GetProperty(const aIndex: Integer): Variant; overload;
  94. procedure SetProperty(const aName: String; const aValue: Variant); overload;
  95. procedure SetProperty(const aIndex: Integer; const aValue: Variant); overload;
  96. function GenerateCode: String;
  97. constructor Create(const aShaderFile: TlsfShaderFile; const aName: String);
  98. destructor Destroy; override;
  99. end;
  100. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  101. TlsfException = class(Exception)
  102. private
  103. fErrorCode: TlsfErrorCode;
  104. public
  105. property ErrorCode: TlsfErrorCode read fErrorCode;
  106. constructor Create(const aMsg: string; const aError: TlsfErrorCode = errNone);
  107. end;
  108. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  109. var
  110. lsf_ShaderFile_create: Tlsf_ShaderFile_create;
  111. lsf_ShaderFile_setLogCallback: Tlsf_ShaderFile_setLogCallback;
  112. lsf_ShaderFile_loadFromFile: Tlsf_ShaderFile_loadFromFile;
  113. lsf_ShaderFile_saveToFile: Tlsf_ShaderFile_saveToFile;
  114. lsf_ShaderFile_getGeneratorNames: Tlsf_ShaderFile_getGeneratorNames;
  115. lsf_ShaderFile_destroy: Tlsf_ShaderFile_destroy;
  116. lsf_Generator_create: Tlsf_Generator_create;
  117. lsf_Generator_getPropertyNames: Tlsf_Generator_getPropertyNames;
  118. lsf_Generator_getProperty: Tlsf_Generator_getProperty;
  119. lsf_Generator_getPropertyByName: Tlsf_Generator_getPropertyByName;
  120. lsf_Generator_setProperty: Tlsf_Generator_setProperty;
  121. lsf_Generator_setPropertyByName: Tlsf_Generator_setPropertyByName;
  122. lsf_Generator_generateCode: Tlsf_Generator_generateCode;
  123. lsf_Generator_destroy: Tlsf_Generator_destroy;
  124. lsf_getLastErrorCode: Tlsf_getLastErrorCode;
  125. lsf_getLastErrorMsg: Tlsf_getLastErrorMsg;
  126. lsf_getLastErrorTrace: Tlsf_getLastErrorTrace;
  127. procedure lsf_init(const aLibName: String);
  128. procedure lsf_finish;
  129. implementation
  130. {$IF DEFINED(WIN32) OR DEFINED(WIN64)}
  131. uses
  132. windows;
  133. type
  134. TLibHandle = HMODULE;
  135. const
  136. InvalidLibHandle: TLibHandle = 0;
  137. function LibOpen(const aLibName: String; out aError: String): TLibHandle;
  138. begin
  139. result := LoadLibraryA(PAnsiChar(AnsiString(aLibName)));
  140. if (result = 0)
  141. then aError := SysErrorMessage(GetLastError())
  142. else aError := '';
  143. end;
  144. function GetAddr(const aLibHandle: TLibHandle; const aName: String): Pointer;
  145. begin
  146. result := GetProcAddress(aLibHandle, PAnsiChar(AnsiString(aName)));
  147. end;
  148. procedure LibClose(const aLibHandle: TLibHandle);
  149. begin
  150. FreeLibrary(aLibHandle);
  151. end;
  152. {$ELSEIF DEFINED(LINUX)}
  153. uses
  154. dl;
  155. type
  156. TLibHandle = Pointer;
  157. const
  158. InvalidLibHandle: TLibHandle = nil;
  159. function LibOpen(const aLibName: String; out aError: String): TLibHandle;
  160. begin
  161. dlerror();
  162. result := dlopen(PChar(aLibName), RTLD_LAZY);
  163. if (result = InvalidLibHandle)
  164. then aError := dlerror()
  165. else aError := '';
  166. end;
  167. function GetAddr(const aLibHandle: TLibHandle; const aName: String): Pointer;
  168. begin
  169. result := dlsym(aLibHandle, PChar(aName));
  170. end;
  171. procedure LibClose(const aLibHandle: TLibHandle);
  172. begin
  173. dlclose(aLibHandle);
  174. end;
  175. {$ELSE}
  176. {$ERROR 'unknown operation system'}
  177. {$IFEND}
  178. var
  179. libHandle: TLibHandle;
  180. lsf_init_intern: Tlsf_init;
  181. lsf_finish_intern: Tlsf_finish;
  182. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  183. procedure lsf_init(const aLibName: String);
  184. function LoadProc(const aName: String): Pointer;
  185. begin
  186. result := GetAddr(libHandle, aName);
  187. if not Assigned(result) then
  188. raise Exception.CreateFmt('unable to load ''%s'' from ''%s''', [aName, aLibName]);
  189. end;
  190. var
  191. eMsg: String;
  192. err: TlsfErrorCode;
  193. begin
  194. libHandle := LibOpen(aLibName, eMsg);
  195. if (libHandle = InvalidLibHandle) then
  196. raise Exception.Create('unable to load library: ' + eMsg);
  197. lsf_ShaderFile_create := Tlsf_ShaderFile_create( LoadProc('lsf_ShaderFile_create'));
  198. lsf_ShaderFile_setLogCallback := Tlsf_ShaderFile_setLogCallback( LoadProc('lsf_ShaderFile_setLogCallback'));
  199. lsf_ShaderFile_loadFromFile := Tlsf_ShaderFile_loadFromFile( LoadProc('lsf_ShaderFile_loadFromFile'));
  200. lsf_ShaderFile_saveToFile := Tlsf_ShaderFile_saveToFile( LoadProc('lsf_ShaderFile_saveToFile'));
  201. lsf_ShaderFile_getGeneratorNames := Tlsf_ShaderFile_getGeneratorNames( LoadProc('lsf_ShaderFile_getGeneratorNames'));
  202. lsf_ShaderFile_destroy := Tlsf_ShaderFile_destroy( LoadProc('lsf_ShaderFile_destroy'));
  203. lsf_Generator_create := Tlsf_Generator_create( LoadProc('lsf_Generator_create'));
  204. lsf_Generator_getPropertyNames := Tlsf_Generator_getPropertyNames( LoadProc('lsf_Generator_getPropertyNames'));
  205. lsf_Generator_getProperty := Tlsf_Generator_getProperty( LoadProc('lsf_Generator_getProperty'));
  206. lsf_Generator_getPropertyByName := Tlsf_Generator_getPropertyByName( LoadProc('lsf_Generator_getPropertyByName'));
  207. lsf_Generator_setProperty := Tlsf_Generator_setProperty( LoadProc('lsf_Generator_setProperty'));
  208. lsf_Generator_setPropertyByName := Tlsf_Generator_setPropertyByName( LoadProc('lsf_Generator_setPropertyByName'));
  209. lsf_Generator_generateCode := Tlsf_Generator_generateCode( LoadProc('lsf_Generator_generateCode'));
  210. lsf_Generator_destroy := Tlsf_Generator_destroy( LoadProc('lsf_Generator_destroy'));
  211. lsf_init_intern := Tlsf_init( LoadProc('lsf_init'));
  212. lsf_getLastErrorCode := Tlsf_getLastErrorCode( LoadProc('lsf_getLastErrorCode'));
  213. lsf_getLastErrorMsg := Tlsf_getLastErrorMsg( LoadProc('lsf_getLastErrorMsg'));
  214. lsf_getLastErrorTrace := Tlsf_getLastErrorTrace( LoadProc('lsf_getLastErrorTrace'));
  215. lsf_finish_intern := Tlsf_finish( LoadProc('lsf_finish'));
  216. err := lsf_init_intern();
  217. if (err <> errNone) then
  218. raise TlsfException.Create('error while initializing library: ' + lsf_getLastErrorMsg(), err);
  219. end;
  220. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  221. procedure lsf_finish;
  222. begin
  223. lsf_finish_intern();
  224. lsf_ShaderFile_create := nil;
  225. lsf_ShaderFile_setLogCallback := nil;
  226. lsf_ShaderFile_loadFromFile := nil;
  227. lsf_ShaderFile_saveToFile := nil;
  228. lsf_ShaderFile_getGeneratorNames := nil;
  229. lsf_ShaderFile_destroy := nil;
  230. lsf_getLastErrorCode := nil;
  231. lsf_getLastErrorMsg := nil;
  232. lsf_getLastErrorTrace := nil;
  233. if (libHandle <> InvalidLibHandle) then begin
  234. LibClose(libHandle);
  235. libHandle := InvalidLibHandle;
  236. end;
  237. end;
  238. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  239. procedure LogCallback(const aLogLevel: TlsfLogLevel; const aMsg: PAnsiChar; const aUserArgs: Pointer); stdcall;
  240. begin
  241. TlsfShaderFile(aUserArgs).LogMsg(aLogLevel, String(aMsg));
  242. end;
  243. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  244. //TlsfShaderFile////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  245. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  246. procedure TlsfShaderFile.LogMsg(const aLogLevel: TlsfLogLevel; const aMsg: String);
  247. begin
  248. // DUMMY
  249. end;
  250. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  251. procedure TlsfShaderFile.LoadFromFile(const aFilename: String);
  252. var
  253. err: TlsfErrorCode;
  254. begin
  255. err := lsf_ShaderFile_loadFromFile(fHandle, PAnsiChar(AnsiString(aFilename)));
  256. if (err <> errNone) then
  257. raise TlsfException.Create('error while loading from file: ' + lsf_getLastErrorMsg(), lsf_getLastErrorCode());
  258. end;
  259. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  260. procedure TlsfShaderFile.SaveToFile(const aFilename: String);
  261. var
  262. err: TlsfErrorCode;
  263. begin
  264. err := lsf_ShaderFile_saveToFile(fHandle, PAnsiChar(AnsiString(aFilename)));
  265. if (err <> errNone) then
  266. raise TlsfException.Create('error while saving to file: ' + lsf_getLastErrorMsg(), lsf_getLastErrorCode());
  267. end;
  268. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  269. constructor TlsfShaderFile.Create;
  270. var
  271. err: TlsfErrorCode;
  272. begin
  273. inherited Create;
  274. fHandle := lsf_ShaderFile_create();
  275. if not Assigned(fHandle) then
  276. raise TlsfException.Create('error while creating shader file: ' + lsf_getLastErrorMsg(), lsf_getLastErrorCode());
  277. err := lsf_ShaderFile_setLogCallback(fHandle, @LogCallback, self);
  278. if (err <> errNone) then
  279. raise TlsfException.Create('error while settings log callback: ' + lsf_getLastErrorMsg(), lsf_getLastErrorCode());
  280. end;
  281. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  282. destructor TlsfShaderFile.Destroy;
  283. begin
  284. if Assigned(fHandle) then begin
  285. lsf_ShaderFile_destroy(fHandle);
  286. fHandle := nil;
  287. end;
  288. inherited Destroy;
  289. end;
  290. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  291. //TlsfGenerator/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  292. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  293. function TlsfGenerator.GetProperties: TStrings;
  294. begin
  295. result := fProperties;
  296. end;
  297. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  298. function TlsfGenerator.GetProperty(const aName: String): Variant;
  299. var
  300. s: PAnsiChar;
  301. begin
  302. s := lsf_Generator_getPropertyByName(fHandle, PAnsiChar(AnsiString(aName)));
  303. if not Assigned(s) then
  304. raise TlsfException.Create('error while getting property by name: ' + lsf_getLastErrorMsg(), lsf_getLastErrorCode());
  305. result := String(s);
  306. end;
  307. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  308. function TlsfGenerator.GetProperty(const aIndex: Integer): Variant;
  309. var
  310. s: PAnsiChar;
  311. begin
  312. s := lsf_Generator_getProperty(fHandle, aIndex);
  313. if not Assigned(s) then
  314. raise TlsfException.Create('error while getting property by index: ' + lsf_getLastErrorMsg(), lsf_getLastErrorCode());
  315. result := String(s);
  316. end;
  317. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  318. procedure TlsfGenerator.SetProperty(const aName: String; const aValue: Variant);
  319. var
  320. err: TlsfErrorCode;
  321. s: AnsiString;
  322. begin
  323. s := AnsiString(aValue);
  324. err := lsf_Generator_setPropertyByName(fHandle, PAnsiChar(AnsiString(aName)), PAnsiChar(s));
  325. if (err <> errNone) then
  326. raise TlsfException.Create('error while settings property by name: ' + lsf_getLastErrorMsg(), err);
  327. end;
  328. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  329. procedure TlsfGenerator.SetProperty(const aIndex: Integer; const aValue: Variant);
  330. var
  331. err: TlsfErrorCode;
  332. s: AnsiString;
  333. begin
  334. s := AnsiString(aValue);
  335. err := lsf_Generator_setProperty(fHandle, aIndex, PAnsiChar(s));
  336. if (err <> errNone) then
  337. raise TlsfException.Create('error while settings property by name: ' + lsf_getLastErrorMsg(), err);
  338. end;
  339. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  340. function TlsfGenerator.GenerateCode: String;
  341. var
  342. s: PAnsiChar;
  343. begin
  344. s := lsf_Generator_generateCode(fHandle);
  345. if not Assigned(s) then
  346. raise TlsfException.Create('error while generating code: ' + lsf_getLastErrorMsg(), lsf_getLastErrorCode());
  347. result := String(s);
  348. end;
  349. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  350. constructor TlsfGenerator.Create(const aShaderFile: TlsfShaderFile; const aName: String);
  351. var
  352. s: PAnsiChar;
  353. begin
  354. inherited Create;
  355. fProperties := TStringList.Create;
  356. fShaderFile := aShaderFile;
  357. fName := aName;
  358. fHandle := lsf_Generator_create(fShaderFile.Handle, PAnsiChar(AnsiString(aName)));
  359. if not Assigned(fHandle) then
  360. raise TlsfException.Create('error while opening generator: ' + lsf_getLastErrorMsg(), lsf_getLastErrorCode());
  361. s := lsf_Generator_getPropertyNames(fHandle);
  362. if not Assigned(s) then
  363. raise TlsfException.Create('error while generating code: ' + lsf_getLastErrorMsg(), lsf_getLastErrorCode());
  364. fProperties.Text := string(s);
  365. end;
  366. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  367. destructor TlsfGenerator.Destroy;
  368. begin
  369. if Assigned(fHandle) then begin
  370. lsf_Generator_destroy(fHandle);
  371. fHandle := nil;
  372. end;
  373. FreeAndNil(fProperties);
  374. inherited Destroy;
  375. end;
  376. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  377. //TlsfException/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  378. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  379. constructor TlsfException.Create(const aMsg: string; const aError: TlsfErrorCode);
  380. begin
  381. inherited Create(aMsg);
  382. fErrorCode := aError;
  383. end;
  384. end.