Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/RenderSystems/GL/src/GLSL/src/OgreGLSLProgram.cpp @ 3

Last change on this file since 3 was 3, checked in by anonymous, 17 years ago

=update

File size: 12.5 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#include "OgreGpuProgram.h"
30#include "OgreRoot.h"
31#include "OgreRenderSystem.h"
32#include "OgreRenderSystemCapabilities.h"
33#include "OgreStringConverter.h"
34#include "OgreGpuProgramManager.h"
35#include "OgreHighLevelGpuProgramManager.h"
36#include "OgreLogManager.h"
37
38#include "OgreGLSLProgram.h"
39#include "OgreGLSLGpuProgram.h"
40#include "OgreGLSLExtSupport.h"
41#include "OgreGLSLLinkProgramManager.h"
42
43namespace Ogre {
44
45    //-----------------------------------------------------------------------
46        GLSLProgram::CmdPreprocessorDefines GLSLProgram::msCmdPreprocessorDefines;
47    GLSLProgram::CmdAttach GLSLProgram::msCmdAttach;
48    //-----------------------------------------------------------------------
49    //---------------------------------------------------------------------------
50    GLSLProgram::~GLSLProgram()
51    {
52        // have to call this here reather than in Resource destructor
53        // since calling virtual methods in base destructors causes crash
54        if (isLoaded())
55        {
56            unload();
57        }
58        else
59        {
60            unloadHighLevel();
61        }
62    }
63    //-----------------------------------------------------------------------
64    void GLSLProgram::loadFromSource(void)
65    {
66        // only create a shader object if glsl is supported
67        if (isSupported())
68        {
69            checkForGLSLError( "GLSLProgram::GLSLProgram", "GL Errors before creating shader object", 0 );
70            // create shader object
71            mGLHandle = glCreateShaderObjectARB(
72                (mType == GPT_VERTEX_PROGRAM) ? GL_VERTEX_SHADER_ARB : GL_FRAGMENT_SHADER_ARB );
73
74            checkForGLSLError( "GLSLProgram::GLSLProgram", "Error creating GLSL shader Object", 0 );
75        }
76
77                // build preprocessor defines
78                // GLSL has no explicit interface for defining preprocessor flags outside
79                // of the source code, so we'll prepend some extra source code
80                String preprocessorSource;
81                if (!mPreprocessorDefines.empty())
82                {
83                        StringUtil::StrStreamType tempStr;
84                        // Split preprocessor defines and build up macro array
85                        String::size_type pos = 0;
86                        while (pos != String::npos)
87                        {
88                                // Find delims
89                                String::size_type endPos = mPreprocessorDefines.find_first_of(";,=", pos);
90                                if (endPos != String::npos)
91                                {
92                                        // ok, we have a definition
93                                        tempStr << "#define ";
94                                        // name
95                                        tempStr << mPreprocessorDefines.substr(pos, endPos - pos) << " ";
96                                        pos = endPos;
97                                       
98                                        // Check definition part
99                                        if (mPreprocessorDefines[pos] == '=')
100                                        {
101                                                // set up a definition, skip delim
102                                                ++pos;
103                                                endPos = mPreprocessorDefines.find_first_of(";,", pos);
104                                                if (endPos == String::npos)
105                                                {
106                                                        tempStr << mPreprocessorDefines.substr(pos, String::npos);
107                                                        pos = endPos;
108                                                }
109                                                else
110                                                {
111                                                        tempStr << mPreprocessorDefines.substr(pos, endPos - pos);
112                                                        pos = endPos+1;
113                                                }
114                                        }
115                                        else
116                                        {
117                                                // No definition part, define as "1"
118                                                ++pos;
119                                                tempStr << "1";
120                                        }
121
122                                        tempStr << std::endl;
123                                }
124                                else
125                                {
126                                        pos = endPos;
127                                }
128                        }
129
130                        preprocessorSource = tempStr.str();
131                }
132
133                // Add preprocessor extras and main source
134                const char* sources[2];
135                sources[0] = preprocessorSource.c_str();
136                sources[1] = mSource.c_str();
137                glShaderSourceARB(mGLHandle, 2, sources, NULL);
138                // check for load errors
139                checkForGLSLError( "GLSLProgram::loadFromSource", "Cannot load GLSL high-level shader source : " + mName, 0 );
140
141                compile();
142    }
143   
144    //---------------------------------------------------------------------------
145        bool GLSLProgram::compile(const bool checkErrors)
146        {
147        if (checkErrors)
148        {
149            logObjectInfo("GLSL compiling: " + mName, mGLHandle);
150        }
151
152                glCompileShaderARB(mGLHandle);
153                // check for compile errors
154                glGetObjectParameterivARB(mGLHandle, GL_OBJECT_COMPILE_STATUS_ARB, &mCompiled);
155                // force exception if not compiled
156                if (checkErrors)
157                {
158                        checkForGLSLError( "GLSLProgram::loadFromSource", "Cannot compile GLSL high-level shader : " + mName + " ", mGLHandle, !mCompiled, !mCompiled );
159                       
160                        if (mCompiled)
161                        {
162                                logObjectInfo("GLSL compiled : " + mName, mGLHandle);
163                        }
164                }
165                return (mCompiled == 1);
166
167        }
168
169        //-----------------------------------------------------------------------
170        void GLSLProgram::createLowLevelImpl(void)
171        {
172                mAssemblerProgram = GpuProgramPtr(new GLSLGpuProgram( this ));
173        }
174        //---------------------------------------------------------------------------
175        void GLSLProgram::unloadImpl()
176        {   
177                // We didn't create mAssemblerProgram through a manager, so override this
178                // implementation so that we don't try to remove it from one. Since getCreator()
179                // is used, it might target a different matching handle!
180                mAssemblerProgram.setNull();
181
182                unloadHighLevel();
183        }
184        //-----------------------------------------------------------------------
185    void GLSLProgram::unloadHighLevelImpl(void)
186    {
187                if (isSupported())
188                {
189                        glDeleteObjectARB(mGLHandle);
190                }
191
192
193    }
194
195        //-----------------------------------------------------------------------
196    void GLSLProgram::populateParameterNames(GpuProgramParametersSharedPtr params)
197    {
198                params->_setNamedConstants(&getConstantDefinitions());
199                // Don't set logical / physical maps here, as we can't access parameters by logical index in GLHL.
200    }
201        //-----------------------------------------------------------------------
202    void GLSLProgram::buildConstantDefinitions() const
203    {
204                // We need an accurate list of all the uniforms in the shader, but we
205                // can't get at them until we link all the shaders into a program object.
206
207
208                // Therefore instead, parse the source code manually and extract the uniforms
209                mConstantDefs.floatBufferSize = 0;
210                mConstantDefs.intBufferSize = 0;
211                GLSLLinkProgramManager::getSingleton().extractConstantDefs(mSource, mConstantDefs, mName);
212
213                // Also parse any attached sources
214                for (GLSLProgramContainer::const_iterator i = mAttachedGLSLPrograms.begin();
215                        i != mAttachedGLSLPrograms.end(); ++i)
216                {
217                        GLSLProgram* childShader = *i;
218
219                        GLSLLinkProgramManager::getSingleton().extractConstantDefs(
220                                childShader->getSource(), mConstantDefs, childShader->getName());
221
222                }
223
224
225
226    }
227
228        //-----------------------------------------------------------------------
229    GLSLProgram::GLSLProgram(ResourceManager* creator, 
230        const String& name, ResourceHandle handle,
231        const String& group, bool isManual, ManualResourceLoader* loader)
232        : HighLevelGpuProgram(creator, name, handle, group, isManual, loader)
233    {
234                // add parameter command "attach" to the material serializer dictionary
235        if (createParamDictionary("GLSLProgram"))
236        {
237            setupBaseParamDictionary();
238            ParamDictionary* dict = getParamDictionary();
239
240                        dict->addParameter(ParameterDef("preprocessor_defines", 
241                                "Preprocessor defines use to compile the program.",
242                                PT_STRING),&msCmdPreprocessorDefines);
243            dict->addParameter(ParameterDef("attach", 
244                "name of another GLSL program needed by this program",
245                PT_STRING),&msCmdAttach);
246        }
247        // Manually assign language now since we use it immediately
248        mSyntaxCode = "glsl";
249
250                // want scenemanager to pass on surface and light states to the rendersystem
251                mPassSurfaceAndLightStates = true;
252
253       
254    }
255
256        //-----------------------------------------------------------------------
257    String GLSLProgram::CmdAttach::doGet(const void *target) const
258    {
259        return (static_cast<const GLSLProgram*>(target))->getAttachedShaderNames();
260    }
261        //-----------------------------------------------------------------------
262    void GLSLProgram::CmdAttach::doSet(void *target, const String& shaderNames)
263    {
264                //get all the shader program names: there could be more than one
265                StringVector vecShaderNames = StringUtil::split(shaderNames, " \t", 0);
266
267                size_t programNameCount = vecShaderNames.size();
268                for ( size_t i = 0; i < programNameCount; ++i )
269                {
270                static_cast<GLSLProgram*>(target)->attachChildShader(vecShaderNames[i]);
271                }
272    }
273        //-----------------------------------------------------------------------
274        String GLSLProgram::CmdPreprocessorDefines::doGet(const void *target) const
275        {
276                return static_cast<const GLSLProgram*>(target)->getPreprocessorDefines();
277        }
278        void GLSLProgram::CmdPreprocessorDefines::doSet(void *target, const String& val)
279        {
280                static_cast<GLSLProgram*>(target)->setPreprocessorDefines(val);
281        }
282
283        //-----------------------------------------------------------------------
284    void GLSLProgram::attachChildShader(const String& name)
285        {
286                // is the name valid and already loaded?
287                // check with the high level program manager to see if it was loaded
288                HighLevelGpuProgramPtr hlProgram = HighLevelGpuProgramManager::getSingleton().getByName(name);
289                if (!hlProgram.isNull())
290                {
291                        if (hlProgram->getSyntaxCode() == "glsl")
292                        {
293                                // make sure attached program source gets loaded and compiled
294                                // don't need a low level implementation for attached shader objects
295                                // loadHighLevelImpl will only load the source and compile once
296                                // so don't worry about calling it several times
297                                GLSLProgram* childShader = static_cast<GLSLProgram*>(hlProgram.getPointer());
298                                // load the source and attach the child shader only if supported
299                                if (isSupported())
300                                {
301                                        childShader->loadHighLevelImpl();
302                                        // add to the container
303                                        mAttachedGLSLPrograms.push_back( childShader );
304                                        mAttachedShaderNames += name + " ";
305                                }
306                        }
307                }
308        }
309
310        //-----------------------------------------------------------------------
311        void GLSLProgram::attachToProgramObject( const GLhandleARB programObject )
312        {
313                glAttachObjectARB( programObject, mGLHandle );
314                checkForGLSLError( "GLSLLinkProgram::GLSLLinkProgram",
315                        "Error attaching " + mName + " shader object to GLSL Program Object", programObject );
316                // attach child objects
317                GLSLProgramContainerIterator childprogramcurrent = mAttachedGLSLPrograms.begin();
318                GLSLProgramContainerIterator childprogramend = mAttachedGLSLPrograms.end();
319
320                while (childprogramcurrent != childprogramend)
321                {
322
323                        GLSLProgram* childShader = *childprogramcurrent;
324                        // bug in ATI GLSL linker : modules without main function must be recompiled each time
325                        // they are linked to a different program object
326                        // don't check for compile errors since there won't be any
327                        // *** minor inconvenience until ATI fixes there driver
328                        childShader->compile(false);
329
330                        childShader->attachToProgramObject( programObject );
331
332                        ++childprogramcurrent;
333                }
334
335        }
336        //-----------------------------------------------------------------------
337        void GLSLProgram::detachFromProgramObject( const GLhandleARB programObject )
338        {
339                glDetachObjectARB(programObject, mGLHandle);
340                checkForGLSLError( "GLSLLinkProgram::GLSLLinkProgram",
341                        "Error detaching " + mName + " shader object from GLSL Program Object", programObject );
342                // attach child objects
343                GLSLProgramContainerIterator childprogramcurrent = mAttachedGLSLPrograms.begin();
344                GLSLProgramContainerIterator childprogramend = mAttachedGLSLPrograms.end();
345
346                while (childprogramcurrent != childprogramend)
347                {
348                        GLSLProgram* childShader = *childprogramcurrent;
349                        childShader->detachFromProgramObject( programObject );
350                        ++childprogramcurrent;
351                }
352
353        }
354
355    //-----------------------------------------------------------------------
356    const String& GLSLProgram::getLanguage(void) const
357    {
358        static const String language = "glsl";
359
360        return language;
361    }
362
363 
364}
Note: See TracBrowser for help on using the repository browser.