Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

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