1 /*
2 -----------------------------------------------------------------------------
3 This source file is part of OGRE
4     (Object-oriented Graphics Rendering Engine)
5 For the latest info, see http://www.ogre3d.org/
6 
7 Copyright (c) 2000-2013 Torus Knot Software Ltd
8 
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
15 
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18 
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 THE SOFTWARE.
26 -----------------------------------------------------------------------------
27 */
28 
29 #include "OgreGLSLGpuProgram.h"
30 #include "OgreGLSLProgram.h"
31 #include "OgreGLSLLinkProgramManager.h"
32 #include "OgreGLSLProgramPipelineManager.h"
33 #include "OgreRoot.h"
34 
35 namespace Ogre {
36 
37 	GLuint GLSLGpuProgram::mVertexShaderCount = 0;
38 	GLuint GLSLGpuProgram::mFragmentShaderCount = 0;
39 	GLuint GLSLGpuProgram::mGeometryShaderCount = 0;
40 	GLuint GLSLGpuProgram::mHullShaderCount = 0;
41 	GLuint GLSLGpuProgram::mDomainShaderCount = 0;
42 	GLuint GLSLGpuProgram::mComputeShaderCount = 0;
43     //-----------------------------------------------------------------------------
GLSLGpuProgram(GLSLProgram * parent)44 	GLSLGpuProgram::GLSLGpuProgram(GLSLProgram* parent) :
45         GL3PlusGpuProgram(parent->getCreator(), parent->getName(), parent->getHandle(),
46             parent->getGroup(), false, 0), mGLSLProgram(parent)
47     {
48         mType = parent->getType();
49         mSyntaxCode = "glsl" + StringConverter::toString(Root::getSingleton().getRenderSystem()->getNativeShadingLanguageVersion());
50 
51         mLinked = 0;
52 
53 		if (parent->getType() == GPT_VERTEX_PROGRAM)
54 		{
55 			mProgramID = ++mVertexShaderCount;
56 		}
57 		else if (parent->getType() == GPT_FRAGMENT_PROGRAM)
58 		{
59 			mProgramID = ++mFragmentShaderCount;
60 		}
61 		else if (parent->getType() == GPT_GEOMETRY_PROGRAM)
62 		{
63 			mProgramID = ++mGeometryShaderCount;
64 		}
65 		else if (parent->getType() == GPT_HULL_PROGRAM)
66 		{
67 			mProgramID = ++mHullShaderCount;
68 		}
69         else if (parent->getType() == GPT_COMPUTE_PROGRAM)
70 		{
71 			mProgramID = ++mComputeShaderCount;
72 		}
73 		else
74 		{
75 			mProgramID = ++mDomainShaderCount;
76 		}
77 
78         // Transfer skeletal animation status from parent
79         mSkeletalAnimation = mGLSLProgram->isSkeletalAnimationIncluded();
80 		// There is nothing to load
81 		mLoadFromFile = false;
82     }
83     //-----------------------------------------------------------------------
~GLSLGpuProgram()84     GLSLGpuProgram::~GLSLGpuProgram()
85     {
86         // Have to call this here rather than in Resource destructor
87         // since calling virtual methods in base destructors causes crash
88         unload();
89     }
90 	//-----------------------------------------------------------------------------
loadImpl(void)91     void GLSLGpuProgram::loadImpl(void)
92     {
93 		// nothing to load
94     }
95 
96 	//-----------------------------------------------------------------------------
unloadImpl(void)97 	void GLSLGpuProgram::unloadImpl(void)
98 	{
99 		// nothing to unload
100 	}
101 
102 	//-----------------------------------------------------------------------------
loadFromSource(void)103     void GLSLGpuProgram::loadFromSource(void)
104     {
105 		// nothing to load
106 	}
107 
108 	//-----------------------------------------------------------------------------
bindProgram(void)109 	void GLSLGpuProgram::bindProgram(void)
110 	{
111         if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS))
112         {
113             // Tell the Program Pipeline Manager what pipeline is to become active
114             switch (mType)
115             {
116                 case GPT_VERTEX_PROGRAM:
117                     GLSLProgramPipelineManager::getSingleton().setActiveVertexLinkProgram( this );
118                     break;
119                 case GPT_FRAGMENT_PROGRAM:
120                     GLSLProgramPipelineManager::getSingleton().setActiveFragmentLinkProgram( this );
121                     break;
122                 case GPT_GEOMETRY_PROGRAM:
123                     GLSLProgramPipelineManager::getSingleton().setActiveGeometryLinkProgram( this );
124                     break;
125                 case GPT_HULL_PROGRAM:
126                     GLSLProgramPipelineManager::getSingleton().setActiveTessHullLinkProgram( this );
127                     break;
128                 case GPT_DOMAIN_PROGRAM:
129                     GLSLProgramPipelineManager::getSingleton().setActiveTessDomainLinkProgram( this );
130                     break;
131                 case GPT_COMPUTE_PROGRAM:
132                     GLSLProgramPipelineManager::getSingleton().setActiveComputeLinkProgram( this );
133                 default:
134                     break;
135             }
136         }
137         else
138         {
139             // Tell the Link Program Manager what shader is to become active
140             switch (mType)
141             {
142                 case GPT_VERTEX_PROGRAM:
143                     GLSLLinkProgramManager::getSingleton().setActiveVertexShader( this );
144                     break;
145                 case GPT_FRAGMENT_PROGRAM:
146                     GLSLLinkProgramManager::getSingleton().setActiveFragmentShader( this );
147                     break;
148                 case GPT_GEOMETRY_PROGRAM:
149                     GLSLLinkProgramManager::getSingleton().setActiveGeometryShader( this );
150                     break;
151                 case GPT_HULL_PROGRAM:
152                     GLSLLinkProgramManager::getSingleton().setActiveHullShader( this );
153                     break;
154                 case GPT_DOMAIN_PROGRAM:
155                     GLSLLinkProgramManager::getSingleton().setActiveDomainShader( this );
156                     break;
157                 case GPT_COMPUTE_PROGRAM:
158                     GLSLLinkProgramManager::getSingleton().setActiveComputeShader( this );
159                 default:
160                     break;
161             }
162         }
163 	}
164 
165 	//-----------------------------------------------------------------------------
unbindProgram(void)166 	void GLSLGpuProgram::unbindProgram(void)
167 	{
168         if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS))
169         {
170             // Tell the Program Pipeline Manager what pipeline is to become inactive
171             if (mType == GPT_VERTEX_PROGRAM)
172             {
173                 GLSLProgramPipelineManager::getSingleton().setActiveVertexLinkProgram( NULL );
174             }
175             else if (mType == GPT_GEOMETRY_PROGRAM)
176             {
177                 GLSLProgramPipelineManager::getSingleton().setActiveGeometryLinkProgram( NULL );
178             }
179             else if (mType == GPT_HULL_PROGRAM)
180             {
181                 GLSLProgramPipelineManager::getSingleton().setActiveTessHullLinkProgram( NULL );
182             }
183             else if (mType == GPT_DOMAIN_PROGRAM)
184             {
185                 GLSLProgramPipelineManager::getSingleton().setActiveTessDomainLinkProgram( NULL );
186             }
187             else if (mType == GPT_COMPUTE_PROGRAM)
188             {
189                 GLSLProgramPipelineManager::getSingleton().setActiveComputeLinkProgram( NULL );
190             }
191             else // Its a fragment shader
192             {
193                 GLSLProgramPipelineManager::getSingleton().setActiveFragmentLinkProgram( NULL );
194             }
195         }
196         else
197         {
198             // Tell the Link Program Manager what shader is to become inactive
199             if (mType == GPT_VERTEX_PROGRAM)
200             {
201                 GLSLLinkProgramManager::getSingleton().setActiveVertexShader( NULL );
202             }
203             else if (mType == GPT_GEOMETRY_PROGRAM)
204             {
205                 GLSLLinkProgramManager::getSingleton().setActiveGeometryShader( NULL );
206             }
207             else if (mType == GPT_HULL_PROGRAM)
208             {
209                 GLSLLinkProgramManager::getSingleton().setActiveHullShader( NULL );
210             }
211             else if (mType == GPT_DOMAIN_PROGRAM)
212             {
213                 GLSLLinkProgramManager::getSingleton().setActiveDomainShader( NULL );
214             }
215             else if (mType == GPT_COMPUTE_PROGRAM)
216             {
217                 GLSLLinkProgramManager::getSingleton().setActiveComputeShader( NULL );
218             }
219             else // Its a fragment shader
220             {
221                 GLSLLinkProgramManager::getSingleton().setActiveFragmentShader( NULL );
222             }
223         }
224 	}
225 
226     //-----------------------------------------------------------------------------
bindProgramSharedParameters(GpuProgramParametersSharedPtr params,uint16 mask)227 	void GLSLGpuProgram::bindProgramSharedParameters(GpuProgramParametersSharedPtr params, uint16 mask)
228 	{
229 		// Link can throw exceptions, ignore them at this point
230 		try
231 		{
232             if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS))
233             {
234                 // Activate the program pipeline object
235                 GLSLProgramPipeline* programPipeline = GLSLProgramPipelineManager::getSingleton().getActiveProgramPipeline();
236                 // Pass on parameters from params to program object uniforms
237                 programPipeline->updateUniformBlocks(params, mask, mType);
238             }
239             else
240             {
241                 // Activate the link program object
242                 GLSLLinkProgram* linkProgram = GLSLLinkProgramManager::getSingleton().getActiveLinkProgram();
243                 // Pass on parameters from params to program object uniforms
244                 linkProgram->updateUniformBlocks(params, mask, mType);
245             }
246 		}
247 		catch (Exception& e) {}
248 	}
249 
250 	//-----------------------------------------------------------------------------
bindProgramParameters(GpuProgramParametersSharedPtr params,uint16 mask)251 	void GLSLGpuProgram::bindProgramParameters(GpuProgramParametersSharedPtr params, uint16 mask)
252 	{
253 		// Link can throw exceptions, ignore them at this point
254 		try
255 		{
256             if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS))
257             {
258                 // Activate the program pipeline object
259                 GLSLProgramPipeline* programPipeline = GLSLProgramPipelineManager::getSingleton().getActiveProgramPipeline();
260                 // Pass on parameters from params to program object uniforms
261                 programPipeline->updateUniforms(params, mask, mType);
262             }
263             else
264             {
265                 // Activate the link program object
266                 GLSLLinkProgram* linkProgram = GLSLLinkProgramManager::getSingleton().getActiveLinkProgram();
267                 // Pass on parameters from params to program object uniforms
268                 linkProgram->updateUniforms(params, mask, mType);
269             }
270 		}
271 		catch (Exception& e) {}
272 	}
273 
274 	//-----------------------------------------------------------------------------
bindProgramPassIterationParameters(GpuProgramParametersSharedPtr params)275 	void GLSLGpuProgram::bindProgramPassIterationParameters(GpuProgramParametersSharedPtr params)
276 	{
277         if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS))
278         {
279             // Activate the program pipeline object
280             GLSLProgramPipeline* programPipeline = GLSLProgramPipelineManager::getSingleton().getActiveProgramPipeline();
281             // Pass on parameters from params to program object uniforms
282             programPipeline->updatePassIterationUniforms( params );
283         }
284         else
285         {
286             // Activate the link program object
287             GLSLLinkProgram* linkProgram = GLSLLinkProgramManager::getSingleton().getActiveLinkProgram();
288             // Pass on parameters from params to program object uniforms
289             linkProgram->updatePassIterationUniforms( params );
290 		}
291 	}
292 }
293 
294