PixelLightAPI  .
ProgramGenerator.h
Go to the documentation of this file.
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__


PixelLight PixelLight 0.9.11-R1
Copyright (C) 2002-2012 by The PixelLight Team
Last modified Thu Feb 23 2012 14:08:58
The content of this PixelLight document is published under the
Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported