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.

575 lines
23 KiB

  1. #ifndef LIB_SHADER_FILE_HPP
  2. #define LIB_SHADER_FILE_HPP
  3. #include <string>
  4. #include <sstream>
  5. #include <vector>
  6. #include <stdint.h>
  7. #if WIN32 || WIN64 || _WIN32 || _WIN64
  8. # include <windows.h>
  9. #elif LINUX || __linux__
  10. # include <dlfcn.h>
  11. #else
  12. # error "unknown operation system"
  13. #endif
  14. #if __MINGW32__
  15. # define WINAPI __stdcall
  16. #else
  17. # define WINAPI
  18. #endif
  19. /**********************************************************************************************************************************/
  20. /* public interface */
  21. /**********************************************************************************************************************************/
  22. namespace lsf
  23. {
  24. enum LogLevel
  25. {
  26. llDebug = 0,
  27. llInfo = 1,
  28. llWarning = 2,
  29. llError = 3,
  30. };
  31. enum ErrorCode
  32. {
  33. errNone = 0x00000000,
  34. errNotInit = 0x00000001,
  35. errInvalidHandleShaderFile = 0x00000010,
  36. errInvalidHandleShaderGenerator = 0x00000011,
  37. errInvalidGeneratorName = 0x00000020,
  38. errInvalidPropertyIndex = 0x00000021,
  39. errInvalidPropertyName = 0x00000022,
  40. errGeneratorNotAssignedToFile = 0x00000023,
  41. errUnknownIdentfifier = 0x00001000,
  42. errDuplicateIdentifier = 0x00001001,
  43. errOutOfRange = 0x00001002,
  44. errInvalidIdentifier = 0x00001003,
  45. errInvalidParamterCount = 0x00001004,
  46. errInvalidParamter = 0x00001005,
  47. errUnexpectedToken = 0x00001006,
  48. errInvalidToken = 0x00001007,
  49. errExpressionInternal = 0x00001008,
  50. errExpression = 0x00001009,
  51. errShaderPartInternal = 0x0000100a,
  52. errShaderPart = 0x0000100b,
  53. errInvalidLibraryName = 0x00002000,
  54. errInvalidLibraryHandle = 0x00002001,
  55. errInvalidMethodName = 0x00002002,
  56. errUnknown = 0xffffffff,
  57. };
  58. /** class to load and manage shared library */
  59. class Library
  60. {
  61. friend class ShaderFile;
  62. friend class Generator;
  63. public:
  64. #if WIN32 || WIN64 || _WIN32 || _WIN64
  65. typedef HMODULE Handle; //!< shader file handle
  66. #elif LINUX || __linux__
  67. typedef void* Handle; //!< shader file handle
  68. #else
  69. #error "unknown operation system"
  70. #endif
  71. private:
  72. struct Impl; //!< struct that implements the libraries methods
  73. Impl* _impl; //!< struct that implements the libraries methods
  74. Handle _handle; //!< handle of shared library
  75. public:
  76. /** get last error code
  77. * @return error code of last failed operation */
  78. ErrorCode getLastErrorCode() const;
  79. /** get last error message
  80. * @return error message of last failed operation */
  81. std::string getLastErrorMsg() const;
  82. /** get last error trace
  83. * @return error trace of last failed operation */
  84. std::string getLastErrorTrace() const;
  85. /** constructor
  86. * @param libName name of shared library file */
  87. Library(std::string libName);
  88. /** destructor */
  89. virtual ~Library();
  90. private:
  91. /** deleted copy constructor */
  92. Library(const Library& that) { };
  93. };
  94. /** class to manage a shader file */
  95. class ShaderFile
  96. {
  97. public:
  98. typedef void* Handle; //!< shader file handle
  99. private:
  100. const Library::Impl& _impl; //!< struct that implements the libraries methods
  101. Handle _handle; //!< handle of this shader file
  102. protected:
  103. /** method to log messages from shader file and code generation
  104. * @param logLevel level of the log message
  105. * @param msg message to write log log */
  106. virtual void logMsg(LogLevel logLevel, const std::string& msg);
  107. public:
  108. /** get shader file handle
  109. * @return handle of this shader file */
  110. Handle getHandle() const;
  111. /** get library
  112. * @return library object this shader file is attached to */
  113. const Library& getLibrary() const;
  114. /** load shader file from a given file
  115. * @param filename file to load shader code from */
  116. void loadFromFile(std::string filename);
  117. /** save shader file to a given file
  118. * @param filename file to save shader code to */
  119. void saveToFile(std::string filename) const;
  120. /** constructor
  121. * @param library library this shader file is attached to */
  122. ShaderFile(const Library& library);
  123. /** destructor */
  124. virtual ~ShaderFile();
  125. private:
  126. /** deleted copy constructor */
  127. ShaderFile(const ShaderFile& that);
  128. public:
  129. /** callback method for log messages
  130. * @param logLevel log level of the log message
  131. * @param msg log message
  132. * @param userargs user defined arguments */
  133. static void WINAPI logCallback(const LogLevel loglevel, const char* msg, void* userargs);
  134. };
  135. /** class to manage a shader code generator */
  136. class Generator
  137. {
  138. public:
  139. typedef void* Handle; //!< shader generator handle
  140. typedef std::vector<std::string> StringVec; //!< vector of strings
  141. private:
  142. const Library::Impl& _impl; //!< struct that implements the libraries methods
  143. const ShaderFile& _shaderFile; //!< shader file the generator is attached to
  144. std::string _name; //!< name of this generator
  145. Handle _handle; //!< handle of this generator
  146. StringVec _propertyNames; //!< vector with all known properties
  147. public:
  148. /** get generator name
  149. * @return name of this generator */
  150. std::string getName() const;
  151. /** get generator handle
  152. * @return handle of this generator */
  153. Handle getHandle() const;
  154. /** get shader file this generator is attached to
  155. * @return shader file this genrator is attached to */
  156. const ShaderFile& getShaderFile() const;
  157. /** get a vector of all known properties
  158. * @return vecotr with all known properties */
  159. const StringVec& getPropertyNames() const;
  160. /** get the value of a single property by its name
  161. * @param name name of the property
  162. * @return value of the property */
  163. std::string getProperty(const std::string& name) const;
  164. /** get the value of a single property by its index
  165. * @param index index of the property (see getPropertyNames() to get the index of a property)
  166. * @return value of the property */
  167. std::string getProperty(int index) const;
  168. /** set the value of a single property by its name
  169. * @param name name of the property
  170. * @param value value of the property */
  171. void setProperty(const std::string& name, const std::string& value);
  172. /** set the value of a single property by its index
  173. * @param index index of the property (see getPropertyNames() to get the index of a property)
  174. * @param value value of the property */
  175. void setProperty(int index, const std::string& value);
  176. /** generate the shader code with the current property setup
  177. * @return generated shader code */
  178. std::string generateCode() const;
  179. /** constructor
  180. * @param shaderFile shader file this generator is attached to
  181. * @param name name of a valid generator inside the shaderFile */
  182. Generator(const ShaderFile& shaderFile, std::string name);
  183. /** destructor */
  184. virtual ~Generator();
  185. private:
  186. /** deleted copy constructor */
  187. Generator(const Generator& that);
  188. };
  189. /** object to handle error inside this library */
  190. class Exception : public std::exception
  191. {
  192. private:
  193. std::string _message; //!< error message
  194. ErrorCode _errorCode; //!< suitable error code to the error message
  195. public:
  196. /** get error code
  197. * @return error code of this exception */
  198. ErrorCode getErrorCode() const;
  199. /** get error message
  200. * @return error message of this exception */
  201. std::string getMessage() const;
  202. /** @return error message of this exception */
  203. virtual const char* what() const throw();
  204. /** constructor */
  205. Exception(std::string message, ErrorCode errorCode = errUnknown);
  206. /** destructor */
  207. ~Exception() throw();
  208. };
  209. }
  210. /**********************************************************************************************************************************/
  211. /* private implementation */
  212. /**********************************************************************************************************************************/
  213. #if WIN32 || WIN64 || _WIN32 || _WIN64
  214. lsf::Library::Handle libOpen(const char* name)
  215. { return LoadLibrary(name); };
  216. template <typename T>
  217. T getAddr(lsf::Library::Handle handle, const char* name)
  218. { return reinterpret_cast<T>(GetProcAddress(handle, name)); };
  219. int libClose(lsf::Library::Handle handle)
  220. { return FreeLibrary(handle); };
  221. #elif LINUX || __linux__
  222. lsf::Library::Handle libOpen(const char* name)
  223. { return dlopen(name, RTLD_LAZY); };
  224. template <typename T>
  225. T getAddr(lsf::Library::Handle handle, const char* name)
  226. { return reinterpret_cast<T>(dlsym(handle, name)); };
  227. int libClose(lsf::Library::Handle handle)
  228. { return !dlclose(handle); };
  229. #else
  230. # error "unknown operation system"
  231. #endif
  232. /* Library::Impl ******************************************************************************************************************/
  233. struct lsf::Library::Impl
  234. {
  235. typedef ShaderFile::Handle (WINAPI *lsf_shader_file_create_t) ();
  236. typedef void (WINAPI *lsf_shader_file_log_callback_t) (const LogLevel loglevel, const char* msg, void* userargs);
  237. typedef ErrorCode (WINAPI *lsf_shader_file_set_log_callback_t) (const ShaderFile::Handle handle, const lsf_shader_file_log_callback_t callback, void* userargs);
  238. typedef ErrorCode (WINAPI *lsf_shader_file_load_from_file_t) (const ShaderFile::Handle handle, const char* filename);
  239. typedef ErrorCode (WINAPI *lsf_shader_file_save_to_file_t) (const ShaderFile::Handle handle, const char* filename);
  240. typedef const char* (WINAPI *lsf_shader_file_get_generator_names_t) (const ShaderFile::Handle handle);
  241. typedef ErrorCode (WINAPI *lsf_shader_file_destroy_t) (const ShaderFile::Handle handle);
  242. typedef Generator::Handle (WINAPI *lsf_generator_create_t) (const ShaderFile::Handle handle, const char* name);
  243. typedef const char* (WINAPI *lsf_generator_get_property_names_t) (const Generator::Handle handle);
  244. typedef const char* (WINAPI *lsf_generator_get_property_t) (const Generator::Handle handle, const int index);
  245. typedef const char* (WINAPI *lsf_generator_get_property_by_name_t) (const Generator::Handle handle, const char* name);
  246. typedef ErrorCode (WINAPI *lsf_generator_set_property_t) (const Generator::Handle handle, const int index, const char* value);
  247. typedef ErrorCode (WINAPI *lsf_generator_set_property_by_name_t) (const Generator::Handle handle, const char* name, const char* value);
  248. typedef const char* (WINAPI *lsf_generator_generate_code_t) (const Generator::Handle handle);
  249. typedef ErrorCode (WINAPI *lsf_generator_destroy_t) (const Generator::Handle handle);
  250. typedef ErrorCode (WINAPI *lsf_init_t) ();
  251. typedef ErrorCode (WINAPI *lsf_get_last_error_code_t) ();
  252. typedef const char* (WINAPI *lsf_get_last_error_msg_t) ();
  253. typedef const char* (WINAPI *lsf_get_last_error_trace_t) ();
  254. typedef ErrorCode (WINAPI *lsf_finish_t) ();
  255. const Library& library;
  256. lsf_shader_file_create_t lsf_shader_file_create;
  257. lsf_shader_file_set_log_callback_t lsf_shader_file_set_log_callback;
  258. lsf_shader_file_load_from_file_t lsf_shader_file_load_from_file;
  259. lsf_shader_file_save_to_file_t lsf_shader_file_save_to_file;
  260. lsf_shader_file_get_generator_names_t lsf_shader_file_get_generator_names;
  261. lsf_shader_file_destroy_t lsf_shader_file_destroy;
  262. lsf_generator_create_t lsf_generator_create;
  263. lsf_generator_get_property_names_t lsf_generator_get_property_names;
  264. lsf_generator_get_property_t lsf_generator_get_property;
  265. lsf_generator_get_property_by_name_t lsf_generator_get_property_by_name;
  266. lsf_generator_set_property_t lsf_generator_set_property;
  267. lsf_generator_set_property_by_name_t lsf_generator_set_property_by_name;
  268. lsf_generator_generate_code_t lsf_generator_generate_code;
  269. lsf_generator_destroy_t lsf_generator_destroy;
  270. lsf_init_t lsf_init;
  271. lsf_get_last_error_code_t lsf_get_last_error_code;
  272. lsf_get_last_error_msg_t lsf_get_last_error_msg;
  273. lsf_get_last_error_trace_t lsf_get_last_error_trace;
  274. lsf_finish_t lsf_finish;
  275. Impl(const Library& library) :
  276. library (library),
  277. lsf_shader_file_create (NULL),
  278. lsf_shader_file_set_log_callback (NULL),
  279. lsf_shader_file_load_from_file (NULL),
  280. lsf_shader_file_save_to_file (NULL),
  281. lsf_shader_file_get_generator_names (NULL),
  282. lsf_shader_file_destroy (NULL),
  283. lsf_generator_create (NULL),
  284. lsf_generator_get_property_names (NULL),
  285. lsf_generator_get_property (NULL),
  286. lsf_generator_get_property_by_name (NULL),
  287. lsf_generator_set_property (NULL),
  288. lsf_generator_set_property_by_name (NULL),
  289. lsf_generator_generate_code (NULL),
  290. lsf_generator_destroy (NULL),
  291. lsf_init (NULL),
  292. lsf_get_last_error_code (NULL),
  293. lsf_get_last_error_msg (NULL),
  294. lsf_get_last_error_trace (NULL),
  295. lsf_finish (NULL)
  296. { };
  297. };
  298. /* Library ************************************************************************************************************************/
  299. template <typename T>
  300. inline void loadProc(lsf::Library::Handle handle, T& proc, const char* name)
  301. {
  302. proc = getAddr<T>(handle, name);
  303. if (!proc)
  304. throw lsf::Exception(std::string("unable to load method from library: ") + name, lsf::errInvalidMethodName);
  305. }
  306. lsf::ErrorCode lsf::Library::getLastErrorCode() const
  307. { return _impl->lsf_get_last_error_code(); }
  308. std::string lsf::Library::getLastErrorMsg() const
  309. { return std::string(_impl->lsf_get_last_error_msg()); }
  310. std::string lsf::Library::getLastErrorTrace() const
  311. { return std::string(_impl->lsf_get_last_error_trace()); }
  312. lsf::Library::Library(std::string libName) :
  313. _impl(new Impl(*this))
  314. {
  315. _handle = libOpen(libName.c_str());
  316. if (!_handle)
  317. throw Exception("unable to open shared library: " + libName, lsf::errInvalidLibraryName);
  318. loadProc(_handle, _impl->lsf_shader_file_create, "lsf_ShaderFile_create");
  319. loadProc(_handle, _impl->lsf_shader_file_set_log_callback, "lsf_ShaderFile_setLogCallback");
  320. loadProc(_handle, _impl->lsf_shader_file_load_from_file, "lsf_ShaderFile_loadFromFile");
  321. loadProc(_handle, _impl->lsf_shader_file_save_to_file, "lsf_ShaderFile_saveToFile");
  322. loadProc(_handle, _impl->lsf_shader_file_get_generator_names, "lsf_ShaderFile_getGeneratorNames");
  323. loadProc(_handle, _impl->lsf_shader_file_destroy, "lsf_ShaderFile_destroy");
  324. loadProc(_handle, _impl->lsf_generator_create, "lsf_Generator_create");
  325. loadProc(_handle, _impl->lsf_generator_get_property_names, "lsf_Generator_getPropertyNames");
  326. loadProc(_handle, _impl->lsf_generator_get_property, "lsf_Generator_getProperty");
  327. loadProc(_handle, _impl->lsf_generator_get_property_by_name, "lsf_Generator_getPropertyByName");
  328. loadProc(_handle, _impl->lsf_generator_set_property, "lsf_Generator_setProperty");
  329. loadProc(_handle, _impl->lsf_generator_set_property_by_name, "lsf_Generator_setPropertyByName");
  330. loadProc(_handle, _impl->lsf_generator_generate_code, "lsf_Generator_generateCode");
  331. loadProc(_handle, _impl->lsf_generator_destroy, "lsf_Generator_destroy");
  332. loadProc(_handle, _impl->lsf_init, "lsf_init");
  333. loadProc(_handle, _impl->lsf_get_last_error_code, "lsf_getLastErrorCode");
  334. loadProc(_handle, _impl->lsf_get_last_error_msg, "lsf_getLastErrorMsg");
  335. loadProc(_handle, _impl->lsf_get_last_error_trace, "lsf_getLastErrorTrace");
  336. loadProc(_handle, _impl->lsf_finish, "lsf_finish");
  337. ErrorCode err = _impl->lsf_init();
  338. if (err != lsf::errNone)
  339. throw Exception("unable to initialize library", err);
  340. }
  341. lsf::Library::~Library()
  342. {
  343. if (_impl)
  344. {
  345. _impl->lsf_finish();
  346. delete _impl;
  347. _impl = NULL;
  348. }
  349. if (_handle)
  350. {
  351. libClose(_handle);
  352. _handle = NULL;
  353. }
  354. }
  355. /* ShaderFile *********************************************************************************************************************/
  356. void lsf::ShaderFile::logMsg(LogLevel logLevel, const std::string& msg)
  357. { /* DUMMY */ }
  358. inline lsf::ShaderFile::Handle lsf::ShaderFile::getHandle() const
  359. { return _handle; }
  360. inline const lsf::Library& lsf::ShaderFile::getLibrary() const
  361. { return _impl.library; }
  362. void lsf::ShaderFile::loadFromFile(std::string filename)
  363. {
  364. ErrorCode err = _impl.lsf_shader_file_load_from_file(_handle, filename.c_str());
  365. if (err != errNone)
  366. throw Exception("unable to load file", err);
  367. }
  368. void lsf::ShaderFile::saveToFile(std::string filename) const
  369. {
  370. ErrorCode err = _impl.lsf_shader_file_load_from_file(_handle, filename.c_str());
  371. if (err != errNone)
  372. throw Exception("unable to load file", err);
  373. }
  374. lsf::ShaderFile::ShaderFile(const Library& library) :
  375. _impl(*library._impl)
  376. {
  377. _handle = _impl.lsf_shader_file_create();
  378. if (!_handle)
  379. throw Exception(_impl.lsf_get_last_error_msg(), _impl.lsf_get_last_error_code());
  380. ErrorCode err = _impl.lsf_shader_file_set_log_callback(_handle, &ShaderFile::logCallback, this);
  381. if (err != errNone)
  382. logMsg(llWarning, "unable to register log callback");
  383. }
  384. lsf::ShaderFile::~ShaderFile()
  385. {
  386. _impl.lsf_shader_file_destroy(_handle);
  387. _handle = NULL;
  388. }
  389. void lsf::ShaderFile::logCallback(const lsf::LogLevel loglevel, const char* msg, void* userargs)
  390. {
  391. static_cast<ShaderFile*>(userargs)->logMsg(loglevel, std::string(msg));
  392. }
  393. /* Generator **********************************************************************************************************************/
  394. inline std::string lsf::Generator::getName() const
  395. { return _name; };
  396. inline lsf::Generator::Handle lsf::Generator::getHandle() const
  397. { return _handle; };
  398. inline const lsf::ShaderFile& lsf::Generator::getShaderFile() const
  399. { return _shaderFile; };
  400. inline const lsf::Generator::StringVec& lsf::Generator::getPropertyNames() const
  401. { return _propertyNames; };
  402. std::string lsf::Generator::getProperty(const std::string& name) const
  403. {
  404. const char* ret = _impl.lsf_generator_get_property_by_name(_handle, name.c_str());
  405. if (!ret)
  406. throw Exception(_impl.lsf_get_last_error_msg(), _impl.lsf_get_last_error_code());
  407. return std::string(ret);
  408. }
  409. std::string lsf::Generator::getProperty(int index) const
  410. {
  411. const char* ret = _impl.lsf_generator_get_property(_handle, index);
  412. if (!ret)
  413. throw Exception(_impl.lsf_get_last_error_msg(), _impl.lsf_get_last_error_code());
  414. return std::string(ret);
  415. }
  416. void lsf::Generator::setProperty(const std::string& name, const std::string& value)
  417. {
  418. ErrorCode err = _impl.lsf_generator_set_property_by_name(_handle, name.c_str(), value.c_str());
  419. if (err != errNone)
  420. throw Exception(_impl.lsf_get_last_error_msg(), err);
  421. }
  422. void lsf::Generator::setProperty(int index, const std::string& value)
  423. {
  424. ErrorCode err = _impl.lsf_generator_set_property(_handle, index, value.c_str());
  425. if (err != errNone)
  426. throw Exception(_impl.lsf_get_last_error_msg(), err);
  427. }
  428. std::string lsf::Generator::generateCode() const
  429. {
  430. const char* ret = _impl.lsf_generator_generate_code(_handle);
  431. if (!ret)
  432. throw Exception(_impl.lsf_get_last_error_msg(), _impl.lsf_get_last_error_code());
  433. return std::string(ret);
  434. }
  435. lsf::Generator::Generator(const ShaderFile& shaderFile, std::string name) :
  436. _shaderFile (shaderFile),
  437. _impl (*shaderFile.getLibrary()._impl),
  438. _name (name)
  439. {
  440. _handle = _impl.lsf_generator_create(_shaderFile.getHandle(), _name.c_str());
  441. if (!_handle)
  442. throw Exception(_impl.lsf_get_last_error_msg(), _impl.lsf_get_last_error_code());
  443. const char* propertyNames = _impl.lsf_generator_get_property_names(_handle);
  444. if (propertyNames)
  445. {
  446. std::stringstream ss(propertyNames);
  447. std::string item;
  448. while (std::getline(ss, item, '\x10'))
  449. _propertyNames.push_back(item);
  450. }
  451. }
  452. lsf::Generator::~Generator()
  453. {
  454. _impl.lsf_generator_destroy(_handle);
  455. _handle = NULL;
  456. }
  457. /* Exception **********************************************************************************************************************/
  458. inline lsf::ErrorCode lsf::Exception::getErrorCode() const
  459. { return _errorCode; }
  460. inline std::string lsf::Exception::getMessage() const
  461. { return _message; }
  462. const char* lsf::Exception::what() const throw()
  463. { return _message.c_str(); };
  464. lsf::Exception::Exception(std::string message, ErrorCode errorCode) :
  465. _message (message),
  466. _errorCode (errorCode)
  467. { }
  468. lsf::Exception::~Exception() throw()
  469. { }
  470. #endif /* LIB_SHADER_FILE_HPP */