PixelLightAPI
.
|
00001 /*********************************************************\ 00002 * File: ProgramGenerator.h * 00003 * 00004 * Copyright (C) 2002-2012 The PixelLight Team (http://www.pixellight.org/) 00005 * 00006 * This file is part of PixelLight. 00007 * 00008 * PixelLight is free software: you can redistribute it and/or modify 00009 * it under the terms of the GNU Lesser General Public License as published by 00010 * the Free Software Foundation, either version 3 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * PixelLight is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public License 00019 * along with PixelLight. If not, see <http://www.gnu.org/licenses/>. 00020 \*********************************************************/ 00021 00022 00023 #ifndef __PLRENDERER_PROGRAMGENERATOR_H__ 00024 #define __PLRENDERER_PROGRAMGENERATOR_H__ 00025 #pragma once 00026 00027 00028 //[-------------------------------------------------------] 00029 //[ Includes ] 00030 //[-------------------------------------------------------] 00031 #include <PLCore/String/String.h> 00032 #include <PLCore/Container/Array.h> 00033 #include <PLCore/Container/HashMap.h> 00034 #include <PLCore/Base/Event/EventHandler.h> 00035 #include "PLRenderer/PLRenderer.h" 00036 00037 00038 //[-------------------------------------------------------] 00039 //[ Macro definitions ] 00040 //[-------------------------------------------------------] 00041 /** 00042 * @brief 00043 * Adds a vertex shader flag to the program flags 00044 * 00045 * @param[in] PROGRAMFLAGS 00046 * Program flags were to add the vertex shader flag 00047 * @param[in] FLAG 00048 * Flag to add 00049 */ 00050 #define PL_ADD_VS_FLAG(PROGRAMFLAGS, FLAG) PROGRAMFLAGS.AddVertexShaderFlag(static_cast<PLCore::uint32>(FLAG), #FLAG); 00051 00052 /** 00053 * @brief 00054 * Adds a fragment shader flag to the program flags 00055 * 00056 * @param[in] PROGRAMFLAGS 00057 * Program flags were to add the fragment shader flag 00058 * @param[in] FLAG 00059 * Flag to add 00060 */ 00061 #define PL_ADD_FS_FLAG(PROGRAMFLAGS, FLAG) PROGRAMFLAGS.AddFragmentShaderFlag(static_cast<PLCore::uint32>(FLAG), #FLAG); 00062 00063 00064 //[-------------------------------------------------------] 00065 //[ Namespace ] 00066 //[-------------------------------------------------------] 00067 namespace PLRenderer { 00068 00069 00070 //[-------------------------------------------------------] 00071 //[ Forward declarations ] 00072 //[-------------------------------------------------------] 00073 class Renderer; 00074 class Program; 00075 class VertexShader; 00076 class FragmentShader; 00077 00078 00079 //[-------------------------------------------------------] 00080 //[ Classes ] 00081 //[-------------------------------------------------------] 00082 /** 00083 * @brief 00084 * Program generator for "Über-Shader" 00085 * 00086 * @remarks 00087 * The program generator takes as input vertex shader and fragment shader source codes within a defined shader language and 00088 * returns dynamically composed program instances using given program flags. The generated programs are internally cached so 00089 * during runtime, they need to be dynamically compiled only once. 00090 */ 00091 class ProgramGenerator { 00092 00093 00094 //[-------------------------------------------------------] 00095 //[ Public classes ] 00096 //[-------------------------------------------------------] 00097 public: 00098 /** 00099 * @brief 00100 * Class holding program flags describing the requested program features 00101 * 00102 * @remarks 00103 * In order to tell the program generator the requested program features, an instance of this class is used. 00104 * This is done by using program flags, which internally will be added in front of the shader source code 00105 * as #define preprocessor directives. The goal of the class design was to to make the implementation as 00106 * performant as possible due the heavy usage of this class during rendering. Therefore definition strings are just 00107 * stored as pointer to "char" instead of "PLCore::String" to avoid any overhead produced by strings. As a result, 00108 * this definitions strings must stay valid until "ProgramGenerator::GetProgram()" was called with the program flags. 00109 * To reduce dynamic memory allocations during rendering, it's recommended to just use one program flags instance during 00110 * rendering. When starting the definition of current program flags, call "ProgramFlags::Reset()" to reset the current 00111 * states - this method doesn't produce much overhead. If "m_cProgramFlags" is an instance of "ProgramGenerator", vertex 00112 * shader program flags are usually added by using "PL_ADD_VS_FLAG(m_cProgramFlags, VS_TWOSIDED)" and program flags 00113 * for the fragment shader by using "PL_ADD_FS_FLAG(m_cProgramFlags, FS_ALPHATEST)". The actual flag values "VS_TWOSIDED" 00114 * and "FS_ALPHATEST" are implementation depended and usually defined as enumeration values like "VS_TWOSIDED=1<<0", 00115 * "VS_ANYTHING=1<<1" and so on. Up to 32 flags per shader type are supported. Flags are only added once. 00116 */ 00117 class Flags { 00118 public: 00119 Flags() : 00120 m_nVertexShaderFlags(0), 00121 m_nFragmentShaderFlags(0) 00122 { 00123 m_lstVertexShaderDefinitions.Resize(32, false); 00124 m_lstFragmentShaderDefinitions.Resize(32, false); 00125 } 00126 inline void Reset() 00127 { 00128 m_nVertexShaderFlags = 0; 00129 m_nFragmentShaderFlags = 0; 00130 m_lstVertexShaderDefinitions.Reset(); 00131 m_lstFragmentShaderDefinitions.Reset(); 00132 } 00133 inline void AddVertexShaderFlag(PLCore::uint32 nFlag, const char *pszDefinition) 00134 { 00135 // Is this flag already set? 00136 if (!(m_nVertexShaderFlags & nFlag)) { 00137 // Nope, set it right now 00138 m_nVertexShaderFlags |= nFlag; 00139 m_lstVertexShaderDefinitions.Add(pszDefinition); 00140 } 00141 } 00142 inline void AddFragmentShaderFlag(PLCore::uint32 nFlag, const char *pszDefinition) 00143 { 00144 // Is this flag already set? 00145 if (!(m_nFragmentShaderFlags & nFlag)) { 00146 // Nope, set it right now 00147 m_nFragmentShaderFlags |= nFlag; 00148 m_lstFragmentShaderDefinitions.Add(pszDefinition); 00149 } 00150 } 00151 inline PLCore::uint32 GetVertexShaderFlags() const 00152 { 00153 return m_nVertexShaderFlags; 00154 } 00155 inline const PLCore::Array<const char *> &GetVertexShaderDefinitions() const 00156 { 00157 return m_lstVertexShaderDefinitions; 00158 } 00159 inline PLCore::uint32 GetFragmentShaderFlags() const 00160 { 00161 return m_nFragmentShaderFlags; 00162 } 00163 inline const PLCore::Array<const char *> &GetFragmentShaderDefinitions() const 00164 { 00165 return m_lstFragmentShaderDefinitions; 00166 } 00167 private: 00168 PLCore::uint32 m_nVertexShaderFlags; 00169 PLCore::Array<const char *> m_lstVertexShaderDefinitions; 00170 PLCore::uint32 m_nFragmentShaderFlags; 00171 PLCore::Array<const char *> m_lstFragmentShaderDefinitions; 00172 }; 00173 struct GeneratedProgram { 00174 Program *pProgram; /**< The program, always valid! */ 00175 PLCore::uint32 nVertexShaderFlags; /**< Vertex shader flags used to generate the program */ 00176 PLCore::uint32 nFragmentShaderFlags; /**< Fragment shader flags used to generate the program */ 00177 void *pUserData; /**< User data for the generated program, can be a null pointer, is destroyed automatically of the generated 00178 program is destroyed, may also become a null pointer if for example the program became dirty */ 00179 }; 00180 00181 00182 //[-------------------------------------------------------] 00183 //[ Public functions ] 00184 //[-------------------------------------------------------] 00185 public: 00186 /** 00187 * @brief 00188 * Constructor 00189 * 00190 * @param[in] cRenderer 00191 * Renderer to use 00192 * @param[in] sShaderLanguage 00193 * The name of the shader language the shaders are using (for example "GLSL" or "Cg") 00194 * @param[in] sVertexShader 00195 * Vertex shader ("Über-Shader") source code to use, usually blank ASCII 00196 * @param[in] sVertexShaderProfile 00197 * Vertex shader profile to use (for example "arbvp1" or "glslv" when using Cg, e.g. "130" when using GLSL), if empty string, a default profile will be used which usually 00198 * tries to use the best available profile that runs on most hardware 00199 * @param[in] sFragmentShader 00200 * Fragment shader ("Über-Shader") source code to use, usually blank ASCII 00201 * @param[in] sFragmentShaderProfile 00202 * Fragment shader profile to use (for example "arbfp1" or "glslf" when using Cg, e.g. "130" when using GLSL), if empty string, a default profile will be used which usually 00203 * tries to use the best available profile that runs on most hardware 00204 * 00205 * @note 00206 * - When using GLSL, the profile is the GLSL version to use 00207 */ 00208 PLRENDERER_API ProgramGenerator(Renderer &cRenderer, const PLCore::String &sShaderLanguage, 00209 const PLCore::String &sVertexShader, const PLCore::String &sVertexShaderProfile, 00210 const PLCore::String &sFragmentShader, const PLCore::String &sFragmentShaderProfile); 00211 00212 /** 00213 * @brief 00214 * Destructor 00215 */ 00216 PLRENDERER_API ~ProgramGenerator(); 00217 00218 /** 00219 * @brief 00220 * Returns the used renderer 00221 * 00222 * @return 00223 * The used renderer 00224 */ 00225 inline Renderer &GetRenderer() const; 00226 00227 /** 00228 * @brief 00229 * Returns the name of the used shader language 00230 * 00231 * @return 00232 * The name of the used shader language 00233 */ 00234 inline PLCore::String GetShaderLanguage() const; 00235 00236 /** 00237 * @brief 00238 * Returns the used vertex shader source code 00239 * 00240 * @return 00241 * The used vertex shader source code 00242 */ 00243 inline PLCore::String GetVertexShaderSourceCode() const; 00244 00245 /** 00246 * @brief 00247 * Returns the used fragment shader source code 00248 * 00249 * @return 00250 * The used fragment shader source code 00251 */ 00252 inline PLCore::String GetFragmentShaderSourceCode() const; 00253 00254 /** 00255 * @brief 00256 * Returns a program 00257 * 00258 * @param[in] cFlags 00259 * Program flags describing the requested program features 00260 * 00261 * @return 00262 * Generated program, can be a null pointer 00263 */ 00264 PLRENDERER_API GeneratedProgram *GetProgram(const Flags &cFlags); 00265 00266 /** 00267 * @brief 00268 * Clears the cache of the program generator 00269 * 00270 * @remarks 00271 * All already generated and cached vertex shaders, fragment shaders and linked programs will be destroyed. Don't 00272 * call this method frequently, else the shader programs must be regenerated to often which will have an impact on 00273 * the performance. 00274 */ 00275 PLRENDERER_API void ClearCache(); 00276 00277 00278 //[-------------------------------------------------------] 00279 //[ Private functions ] 00280 //[-------------------------------------------------------] 00281 private: 00282 /** 00283 * @brief 00284 * Copy constructor 00285 * 00286 * @param[in] cSource 00287 * Source to copy from 00288 */ 00289 ProgramGenerator(const ProgramGenerator &cSource); 00290 00291 /** 00292 * @brief 00293 * Copy operator 00294 * 00295 * @param[in] cSource 00296 * Source to copy from 00297 * 00298 * @return 00299 * Reference to this instance 00300 */ 00301 ProgramGenerator &operator =(const ProgramGenerator &cSource); 00302 00303 /** 00304 * @brief 00305 * Called when a program became dirty 00306 * 00307 * @param[in] pProgram 00308 * Program which became dirty 00309 */ 00310 void OnDirty(Program *pProgram); 00311 00312 00313 //[-------------------------------------------------------] 00314 //[ Private event handlers ] 00315 //[-------------------------------------------------------] 00316 private: 00317 PLCore::EventHandler<Program*> EventHandlerDirty; 00318 00319 00320 //[-------------------------------------------------------] 00321 //[ Private data ] 00322 //[-------------------------------------------------------] 00323 private: 00324 // Input 00325 Renderer *m_pRenderer; /**< Renderer to use, always valid! */ 00326 PLCore::String m_sShaderLanguage; /**< The name of the shader language the shaders are using (for example "GLSL" or "Cg") */ 00327 PLCore::String m_sVertexShader; /**< Vertex shader ("Über-Shader") source code to use, usually blank ASCII */ 00328 PLCore::String m_sVertexShaderProfile; /**< Vertex shader profile to use, if empty string, a default profile will be used which usually 00329 tries to use the best available profile that runs on most hardware */ 00330 PLCore::String m_sFragmentShader; /**< Fragment shader ("Über-Shader") source code to use, usually blank ASCII */ 00331 PLCore::String m_sFragmentShaderProfile; /**< Fragment shader profile to use, if empty string, a default profile will be used which usually 00332 tries to use the best available profile that runs on most hardware */ 00333 // Cache 00334 PLCore::Array<VertexShader*> m_lstVertexShaders; /**< List of generated vertex shader instances */ 00335 PLCore::HashMap<PLCore::uint32, VertexShader*> m_mapVertexShaders; /**< Program flags -> vertex shader instance */ 00336 PLCore::Array<FragmentShader*> m_lstFragmentShaders; /**< List of generated fragment shader instances */ 00337 PLCore::HashMap<PLCore::uint32, FragmentShader*> m_mapFragmentShaders; /**< Program flags -> fragment shader instance */ 00338 PLCore::Array<GeneratedProgram*> m_lstPrograms; /**< List of generated program instances */ 00339 PLCore::HashMap<PLCore::uint64, GeneratedProgram*> m_mapPrograms; /**< Program flags -> program instance */ 00340 00341 00342 }; 00343 00344 00345 //[-------------------------------------------------------] 00346 //[ Namespace ] 00347 //[-------------------------------------------------------] 00348 } // PLRenderer 00349 00350 00351 //[-------------------------------------------------------] 00352 //[ Implementation ] 00353 //[-------------------------------------------------------] 00354 #include "PLRenderer/Renderer/ProgramGenerator.inl" 00355 00356 00357 #endif // __PLRENDERER_PROGRAMGENERATOR_H__
|