#ifndef LIB_SHADER_FILE_HPP #define LIB_SHADER_FILE_HPP #include #include #include #include #if defined(WIN32) || defined(WIN64) # include #elif defined(LINUX) # include #else # error "unknown operation system" #endif /**********************************************************************************************************************************/ /* public interface */ /**********************************************************************************************************************************/ namespace lsf { enum LogLevel { llDebug = 0, llInfo = 1, llWarning = 2, llError = 3, }; enum ErrorCode { errNone = 0x00000000, errNotInit = 0x00000001, errInvalidHandleShaderFile = 0x00000010, errInvalidHandleShaderGenerator = 0x00000011, errInvalidGeneratorName = 0x00000020, errInvalidPropertyIndex = 0x00000021, errInvalidPropertyName = 0x00000022, errGeneratorNotAssignedToFile = 0x00000023, errUnknownIdentfifier = 0x00001000, errDuplicateIdentifier = 0x00001001, errOutOfRange = 0x00001002, errInvalidIdentifier = 0x00001003, errInvalidParamterCount = 0x00001004, errInvalidParamter = 0x00001005, errUnexpectedToken = 0x00001006, errInvalidToken = 0x00001007, errExpressionInternal = 0x00001008, errExpression = 0x00001009, errShaderPartInternal = 0x0000100a, errShaderPart = 0x0000100b, errInvalidLibraryName = 0x00002000, errInvalidLibraryHandle = 0x00002001, errInvalidMethodName = 0x00002002, errUnknown = 0xffffffff, }; /** class to load and manage shared library */ class Library { friend class ShaderFile; friend class Generator; public: #if defined(WIN32) || defined(WIN64) typedef HMODULE Handle; //!< shader file handle #elif defined(LINUX) #error "linux is not supported yet" #else #error "unknown operation system" #endif private: struct Impl; //!< struct that implements the libraries methods Impl* _impl; //!< struct that implements the libraries methods Handle _handle; //!< handle of shared library public: /** get last error code * @return error code of last failed operation */ ErrorCode getLastErrorCode() const; /** get last error message * @return error message of last failed operation */ std::string getLastErrorMsg() const; /** get last error trace * @return error trace of last failed operation */ std::string getLastErrorTrace() const; /** constructor * @param libName name of shared library file */ Library(std::string libName); /** destructor */ virtual ~Library(); private: /** deleted copy constructor */ Library(const Library& that) { }; }; /** class to manage a shader file */ class ShaderFile { public: typedef void* Handle; //!< shader file handle private: const Library::Impl& _impl; //!< struct that implements the libraries methods Handle _handle; //!< handle of this shader file protected: /** method to log messages from shader file and code generation * @param logLevel level of the log message * @param msg message to write log log */ virtual void logMsg(LogLevel logLevel, const std::string& msg); public: /** get shader file handle * @return handle of this shader file */ Handle getHandle() const; /** get library * @return library object this shader file is attached to */ const Library& getLibrary() const; /** load shader file from a given file * @param filename file to load shader code from */ void loadFromFile(std::string filename); /** save shader file to a given file * @param filename file to save shader code to */ void saveToFile(std::string filename) const; /** constructor * @param library library this shader file is attached to */ ShaderFile(const Library& library); /** destructor */ virtual ~ShaderFile(); private: /** deleted copy constructor */ ShaderFile(const ShaderFile& that); public: /** callback method for log messages * @param logLevel log level of the log message * @param msg log message * @param userargs user defined arguments */ static void __stdcall logCallback(const LogLevel loglevel, const char* msg, void* userargs); }; /** class to manage a shader code generator */ class Generator { public: typedef void* Handle; //!< shader generator handle typedef std::vector StringVec; //!< vector of strings private: const Library::Impl& _impl; //!< struct that implements the libraries methods const ShaderFile& _shaderFile; //!< shader file the generator is attached to std::string _name; //!< name of this generator Handle _handle; //!< handle of this generator StringVec _propertyNames; //!< vector with all known properties public: /** get generator name * @return name of this generator */ std::string getName() const; /** get generator handle * @return handle of this generator */ Handle getHandle() const; /** get shader file this generator is attached to * @return shader file this genrator is attached to */ const ShaderFile& getShaderFile() const; /** get a vector of all known properties * @return vecotr with all known properties */ const StringVec& getPropertyNames() const; /** get the value of a single property by its name * @param name name of the property * @return value of the property */ std::string getProperty(const std::string& name) const; /** get the value of a single property by its index * @param index index of the property (see getPropertyNames() to get the index of a property) * @return value of the property */ std::string getProperty(int index) const; /** set the value of a single property by its name * @param name name of the property * @param value value of the property */ void setProperty(const std::string& name, const std::string& value); /** set the value of a single property by its index * @param index index of the property (see getPropertyNames() to get the index of a property) * @param value value of the property */ void setProperty(int index, const std::string& value); /** generate the shader code with the current property setup * @return generated shader code */ std::string generateCode() const; /** constructor * @param shaderFile shader file this generator is attached to * @param name name of a valid generator inside the shaderFile */ Generator(const ShaderFile& shaderFile, std::string name); /** destructor */ virtual ~Generator(); private: /** deleted copy constructor */ Generator(const Generator& that); }; /** object to handle error inside this library */ class Exception : public std::exception { private: std::string _message; //!< error message ErrorCode _errorCode; //!< suitable error code to the error message public: /** get error code * @return error code of this exception */ ErrorCode getErrorCode() const; /** get error message * @return error message of this exception */ std::string getMessage() const; /** @return error message of this exception */ virtual const char* what() const throw(); /** constructor */ Exception(std::string message, ErrorCode errorCode = errUnknown); /** destructor */ ~Exception() throw(); }; } /**********************************************************************************************************************************/ /* private implementation */ /**********************************************************************************************************************************/ #if defined(WIN32) || defined(WIN64) lsf::Library::Handle libOpen(const char* name) { return LoadLibrary(name); }; template T getAddr(lsf::Library::Handle handle, const char* name) { FARPROC tmp = GetProcAddress(handle, name); return reinterpret_cast(tmp); }; int libClose(lsf::Library::Handle handle) { return FreeLibrary(handle); }; #elif defined(LINUX) # include # error "linux is not supported yet" #else # error "unknown operation system" #endif /* Library::Impl ******************************************************************************************************************/ struct lsf::Library::Impl { typedef ShaderFile::Handle (__stdcall *lsf_shader_file_create_t) (); typedef void (__stdcall *lsf_shader_file_log_callback_t) (const LogLevel loglevel, const char* msg, void* userargs); typedef ErrorCode (__stdcall *lsf_shader_file_set_log_callback_t) (const ShaderFile::Handle handle, const lsf_shader_file_log_callback_t callback, void* userargs); typedef ErrorCode (__stdcall *lsf_shader_file_load_from_file_t) (const ShaderFile::Handle handle, const char* filename); typedef ErrorCode (__stdcall *lsf_shader_file_save_to_file_t) (const ShaderFile::Handle handle, const char* filename); typedef const char* (__stdcall *lsf_shader_file_get_generator_names_t) (const ShaderFile::Handle handle); typedef ErrorCode (__stdcall *lsf_shader_file_destroy_t) (const ShaderFile::Handle handle); typedef Generator::Handle (__stdcall *lsf_generator_create_t) (const ShaderFile::Handle handle, const char* name); typedef const char* (__stdcall *lsf_generator_get_property_names_t) (const Generator::Handle handle); typedef const char* (__stdcall *lsf_generator_get_property_t) (const Generator::Handle handle, const int index); typedef const char* (__stdcall *lsf_generator_get_property_by_name_t) (const Generator::Handle handle, const char* name); typedef ErrorCode (__stdcall *lsf_generator_set_property_t) (const Generator::Handle handle, const int index, const char* value); typedef ErrorCode (__stdcall *lsf_generator_set_property_by_name_t) (const Generator::Handle handle, const char* name, const char* value); typedef const char* (__stdcall *lsf_generator_generate_code_t) (const Generator::Handle handle); typedef ErrorCode (__stdcall *lsf_generator_destroy_t) (const Generator::Handle handle); typedef ErrorCode (__stdcall *lsf_init_t) (); typedef ErrorCode (__stdcall *lsf_get_last_error_code_t) (); typedef const char* (__stdcall *lsf_get_last_error_msg_t) (); typedef const char* (__stdcall *lsf_get_last_error_trace_t) (); typedef ErrorCode (__stdcall *lsf_finish_t) (); const Library& library; lsf_shader_file_create_t lsf_shader_file_create; lsf_shader_file_set_log_callback_t lsf_shader_file_set_log_callback; lsf_shader_file_load_from_file_t lsf_shader_file_load_from_file; lsf_shader_file_save_to_file_t lsf_shader_file_save_to_file; lsf_shader_file_get_generator_names_t lsf_shader_file_get_generator_names; lsf_shader_file_destroy_t lsf_shader_file_destroy; lsf_generator_create_t lsf_generator_create; lsf_generator_get_property_names_t lsf_generator_get_property_names; lsf_generator_get_property_t lsf_generator_get_property; lsf_generator_get_property_by_name_t lsf_generator_get_property_by_name; lsf_generator_set_property_t lsf_generator_set_property; lsf_generator_set_property_by_name_t lsf_generator_set_property_by_name; lsf_generator_generate_code_t lsf_generator_generate_code; lsf_generator_destroy_t lsf_generator_destroy; lsf_init_t lsf_init; lsf_get_last_error_code_t lsf_get_last_error_code; lsf_get_last_error_msg_t lsf_get_last_error_msg; lsf_get_last_error_trace_t lsf_get_last_error_trace; lsf_finish_t lsf_finish; Impl(const Library& library) : library (library), lsf_shader_file_create (NULL), lsf_shader_file_set_log_callback (NULL), lsf_shader_file_load_from_file (NULL), lsf_shader_file_save_to_file (NULL), lsf_shader_file_get_generator_names (NULL), lsf_shader_file_destroy (NULL), lsf_generator_create (NULL), lsf_generator_get_property_names (NULL), lsf_generator_get_property (NULL), lsf_generator_get_property_by_name (NULL), lsf_generator_set_property (NULL), lsf_generator_set_property_by_name (NULL), lsf_generator_generate_code (NULL), lsf_generator_destroy (NULL), lsf_init (NULL), lsf_get_last_error_code (NULL), lsf_get_last_error_msg (NULL), lsf_get_last_error_trace (NULL), lsf_finish (NULL) { }; }; /* Library ************************************************************************************************************************/ template inline void loadProc(lsf::Library::Handle handle, T& proc, const char* name) { proc = getAddr(handle, name); if (!proc) throw lsf::Exception(std::string("unable to load method from library: ") + name, lsf::errInvalidMethodName); } lsf::ErrorCode lsf::Library::getLastErrorCode() const { return _impl->lsf_get_last_error_code(); } std::string lsf::Library::getLastErrorMsg() const { return std::string(_impl->lsf_get_last_error_msg()); } std::string lsf::Library::getLastErrorTrace() const { return std::string(_impl->lsf_get_last_error_trace()); } lsf::Library::Library(std::string libName) : _impl(new Impl(*this)) { _handle = libOpen(libName.c_str()); if (!_handle) throw Exception("unable to open shared library: " + libName, lsf::errInvalidLibraryName); loadProc(_handle, _impl->lsf_shader_file_create, "lsf_ShaderFile_create"); loadProc(_handle, _impl->lsf_shader_file_set_log_callback, "lsf_ShaderFile_setLogCallback"); loadProc(_handle, _impl->lsf_shader_file_load_from_file, "lsf_ShaderFile_loadFromFile"); loadProc(_handle, _impl->lsf_shader_file_save_to_file, "lsf_ShaderFile_saveToFile"); loadProc(_handle, _impl->lsf_shader_file_get_generator_names, "lsf_ShaderFile_getGeneratorNames"); loadProc(_handle, _impl->lsf_shader_file_destroy, "lsf_ShaderFile_destroy"); loadProc(_handle, _impl->lsf_generator_create, "lsf_Generator_create"); loadProc(_handle, _impl->lsf_generator_get_property_names, "lsf_Generator_getPropertyNames"); loadProc(_handle, _impl->lsf_generator_get_property, "lsf_Generator_getProperty"); loadProc(_handle, _impl->lsf_generator_get_property_by_name, "lsf_Generator_getPropertyByName"); loadProc(_handle, _impl->lsf_generator_set_property, "lsf_Generator_setProperty"); loadProc(_handle, _impl->lsf_generator_set_property_by_name, "lsf_Generator_setPropertyByName"); loadProc(_handle, _impl->lsf_generator_generate_code, "lsf_Generator_generateCode"); loadProc(_handle, _impl->lsf_generator_destroy, "lsf_Generator_destroy"); loadProc(_handle, _impl->lsf_init, "lsf_init"); loadProc(_handle, _impl->lsf_get_last_error_code, "lsf_getLastErrorCode"); loadProc(_handle, _impl->lsf_get_last_error_msg, "lsf_getLastErrorMsg"); loadProc(_handle, _impl->lsf_get_last_error_trace, "lsf_getLastErrorTrace"); loadProc(_handle, _impl->lsf_finish, "lsf_finish"); ErrorCode err = _impl->lsf_init(); if (err != lsf::errNone) throw Exception("unable to initialize library", err); } lsf::Library::~Library() { if (_impl) { _impl->lsf_finish(); delete _impl; _impl = NULL; } if (_handle) { libClose(_handle); _handle = NULL; } } /* ShaderFile *********************************************************************************************************************/ void lsf::ShaderFile::logMsg(LogLevel logLevel, const std::string& msg) { /* DUMMY */ } inline lsf::ShaderFile::Handle lsf::ShaderFile::getHandle() const { return _handle; } inline const lsf::Library& lsf::ShaderFile::getLibrary() const { return _impl.library; } void lsf::ShaderFile::loadFromFile(std::string filename) { ErrorCode err = _impl.lsf_shader_file_load_from_file(_handle, filename.c_str()); if (err != errNone) throw Exception("unable to load file", err); } void lsf::ShaderFile::saveToFile(std::string filename) const { ErrorCode err = _impl.lsf_shader_file_load_from_file(_handle, filename.c_str()); if (err != errNone) throw Exception("unable to load file", err); } lsf::ShaderFile::ShaderFile(const Library& library) : _impl(*library._impl) { _handle = _impl.lsf_shader_file_create(); if (!_handle) throw Exception(_impl.lsf_get_last_error_msg(), _impl.lsf_get_last_error_code()); ErrorCode err = _impl.lsf_shader_file_set_log_callback(_handle, &ShaderFile::logCallback, this); if (err != errNone) logMsg(llWarning, "unable to register log callback"); } lsf::ShaderFile::~ShaderFile() { _impl.lsf_shader_file_destroy(_handle); _handle = NULL; } void lsf::ShaderFile::logCallback(const lsf::LogLevel loglevel, const char* msg, void* userargs) { static_cast(userargs)->logMsg(loglevel, std::string(msg)); } /* Generator **********************************************************************************************************************/ inline std::string lsf::Generator::getName() const { return _name; }; inline lsf::Generator::Handle lsf::Generator::getHandle() const { return _handle; }; inline const lsf::ShaderFile& lsf::Generator::getShaderFile() const { return _shaderFile; }; inline const lsf::Generator::StringVec& lsf::Generator::getPropertyNames() const { return _propertyNames; }; std::string lsf::Generator::getProperty(const std::string& name) const { const char* ret = _impl.lsf_generator_get_property_by_name(_handle, name.c_str()); if (!ret) throw Exception(_impl.lsf_get_last_error_msg(), _impl.lsf_get_last_error_code()); return std::string(ret); } std::string lsf::Generator::getProperty(int index) const { const char* ret = _impl.lsf_generator_get_property(_handle, index); if (!ret) throw Exception(_impl.lsf_get_last_error_msg(), _impl.lsf_get_last_error_code()); return std::string(ret); } void lsf::Generator::setProperty(const std::string& name, const std::string& value) { ErrorCode err = _impl.lsf_generator_set_property_by_name(_handle, name.c_str(), value.c_str()); if (err != errNone) throw Exception(_impl.lsf_get_last_error_msg(), err); } void lsf::Generator::setProperty(int index, const std::string& value) { ErrorCode err = _impl.lsf_generator_set_property(_handle, index, value.c_str()); if (err != errNone) throw Exception(_impl.lsf_get_last_error_msg(), err); } std::string lsf::Generator::generateCode() const { const char* ret = _impl.lsf_generator_generate_code(_handle); if (!ret) throw Exception(_impl.lsf_get_last_error_msg(), _impl.lsf_get_last_error_code()); return std::string(ret); } lsf::Generator::Generator(const ShaderFile& shaderFile, std::string name) : _shaderFile (shaderFile), _impl (*shaderFile.getLibrary()._impl), _name (name) { _handle = _impl.lsf_generator_create(_shaderFile.getHandle(), _name.c_str()); if (!_handle) throw Exception(_impl.lsf_get_last_error_msg(), _impl.lsf_get_last_error_code()); const char* propertyNames = _impl.lsf_generator_get_property_names(_handle); if (propertyNames) { std::stringstream ss(propertyNames); std::string item; while (std::getline(ss, item, '\x10')) _propertyNames.push_back(item); } } lsf::Generator::~Generator() { _impl.lsf_generator_destroy(_handle); _handle = NULL; } /* Exception **********************************************************************************************************************/ inline lsf::ErrorCode lsf::Exception::getErrorCode() const { return _errorCode; } inline std::string lsf::Exception::getMessage() const { return _message; } const char* lsf::Exception::what() const throw() { return _message.c_str(); }; lsf::Exception::Exception(std::string message, ErrorCode errorCode) : _message (message), _errorCode (errorCode) { } lsf::Exception::~Exception() throw() { } #endif /* LIB_SHADER_FILE_HPP */