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-2014 Torus Knot Software Ltd
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
14 
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
17 
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 THE SOFTWARE.
25 -----------------------------------------------------------------------------
26 */
27 
28 #include "OgreShaderPrecompiledHeaders.h"
29 
30 namespace Ogre {
31 namespace RTShader {
32 
33 //-----------------------------------------------------------------------------
Program(GpuProgramType type)34 Program::Program(GpuProgramType type)
35 {
36     mType               = type;
37     mEntryPointFunction = NULL;
38     mSkeletalAnimation  = false;
39     mColumnMajorMatrices = true;
40 }
41 
42 //-----------------------------------------------------------------------------
~Program()43 Program::~Program()
44 {
45     destroyParameters();
46 
47     destroyFunctions();
48 }
49 
50 //-----------------------------------------------------------------------------
destroyParameters()51 void Program::destroyParameters()
52 {
53     mParameters.clear();
54 }
55 
56 //-----------------------------------------------------------------------------
destroyFunctions()57 void Program::destroyFunctions()
58 {
59     ShaderFunctionIterator it;
60 
61     for (it = mFunctions.begin(); it != mFunctions.end(); ++it)
62     {
63         OGRE_DELETE *it;
64     }
65     mFunctions.clear();
66 }
67 
68 //-----------------------------------------------------------------------------
getType() const69 GpuProgramType Program::getType() const
70 {
71     return mType;
72 }
73 
74 //-----------------------------------------------------------------------------
addParameter(UniformParameterPtr parameter)75 void Program::addParameter(UniformParameterPtr parameter)
76 {
77     if (getParameterByName(parameter->getName()).get() != NULL)
78     {
79         OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
80             "Parameter <" + parameter->getName() + "> already declared in program.",
81             "Program::addParameter" );
82     }
83 
84     mParameters.push_back(parameter);
85 }
86 
87 //-----------------------------------------------------------------------------
removeParameter(UniformParameterPtr parameter)88 void Program::removeParameter(UniformParameterPtr parameter)
89 {
90     UniformParameterIterator it;
91 
92     for (it = mParameters.begin(); it != mParameters.end(); ++it)
93     {
94         if ((*it) == parameter)
95         {
96             (*it).reset();
97             mParameters.erase(it);
98             break;
99         }
100     }
101 }
102 
103 //-----------------------------------------------------------------------------
104 
isArray(GpuProgramParameters::AutoConstantType autoType)105 static bool isArray(GpuProgramParameters::AutoConstantType autoType)
106 {
107     switch (autoType)
108     {
109     case GpuProgramParameters::ACT_WORLD_MATRIX_ARRAY_3x4:
110     case GpuProgramParameters::ACT_WORLD_MATRIX_ARRAY:
111     case GpuProgramParameters::ACT_WORLD_DUALQUATERNION_ARRAY_2x4:
112     case GpuProgramParameters::ACT_WORLD_SCALE_SHEAR_MATRIX_ARRAY_3x4:
113     case GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR_ARRAY:
114     case GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR_ARRAY:
115     case GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR_POWER_SCALED_ARRAY:
116     case GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR_POWER_SCALED_ARRAY:
117     case GpuProgramParameters::ACT_LIGHT_ATTENUATION_ARRAY:
118     case GpuProgramParameters::ACT_LIGHT_POSITION_ARRAY:
119     case GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE_ARRAY:
120     case GpuProgramParameters::ACT_LIGHT_POSITION_VIEW_SPACE_ARRAY:
121     case GpuProgramParameters::ACT_LIGHT_DIRECTION_ARRAY:
122     case GpuProgramParameters::ACT_LIGHT_DIRECTION_OBJECT_SPACE_ARRAY:
123     case GpuProgramParameters::ACT_LIGHT_DIRECTION_VIEW_SPACE_ARRAY:
124     case GpuProgramParameters::ACT_LIGHT_DISTANCE_OBJECT_SPACE_ARRAY:
125     case GpuProgramParameters::ACT_LIGHT_POWER_SCALE_ARRAY:
126     case GpuProgramParameters::ACT_SPOTLIGHT_PARAMS_ARRAY:
127     case GpuProgramParameters::ACT_DERIVED_LIGHT_DIFFUSE_COLOUR_ARRAY:
128     case GpuProgramParameters::ACT_DERIVED_LIGHT_SPECULAR_COLOUR_ARRAY:
129     case GpuProgramParameters::ACT_LIGHT_CASTS_SHADOWS_ARRAY:
130     case GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX_ARRAY:
131     case GpuProgramParameters::ACT_TEXTURE_WORLDVIEWPROJ_MATRIX_ARRAY:
132     case GpuProgramParameters::ACT_SPOTLIGHT_VIEWPROJ_MATRIX_ARRAY:
133     case GpuProgramParameters::ACT_SPOTLIGHT_WORLDVIEWPROJ_MATRIX_ARRAY:
134     case GpuProgramParameters::ACT_SHADOW_SCENE_DEPTH_RANGE_ARRAY:
135         return true;
136     default:
137         return false;
138     }
139 }
140 
resolveParameter(GpuProgramParameters::AutoConstantType autoType,size_t data)141 UniformParameterPtr Program::resolveParameter(GpuProgramParameters::AutoConstantType autoType, size_t data)
142 {
143     UniformParameterPtr param;
144 
145     // Check if parameter already exists.
146     param = getParameterByAutoType(autoType);
147 
148     size_t size = 0;
149     if(isArray(autoType)) std::swap(size, data); // for array autotypes the extra parameter is the size
150 
151     if (param && param->getAutoConstantIntData() == data)
152     {
153         return param;
154     }
155 
156     // Create new parameter
157     param = UniformParameterPtr(OGRE_NEW UniformParameter(autoType, data, size));
158     addParameter(param);
159 
160     return param;
161 }
162 
resolveAutoParameterReal(GpuProgramParameters::AutoConstantType autoType,Real data,size_t size)163 UniformParameterPtr Program::resolveAutoParameterReal(GpuProgramParameters::AutoConstantType autoType,
164                                                 Real data, size_t size)
165 {
166     UniformParameterPtr param;
167 
168     // Check if parameter already exists.
169     param = getParameterByAutoType(autoType);
170     if (param.get() != NULL)
171     {
172         if (param->isAutoConstantRealParameter() &&
173             param->getAutoConstantRealData() == data)
174         {
175             param->setSize(std::max(size, param->getSize()));
176             return param;
177         }
178     }
179 
180     // Create new parameter.
181     param = UniformParameterPtr(OGRE_NEW UniformParameter(autoType, data, size));
182     addParameter(param);
183 
184     return param;
185 }
186 
187 //-----------------------------------------------------------------------------
resolveAutoParameterReal(GpuProgramParameters::AutoConstantType autoType,GpuConstantType type,Real data,size_t size)188 UniformParameterPtr Program::resolveAutoParameterReal(GpuProgramParameters::AutoConstantType autoType, GpuConstantType type,
189                                                 Real data, size_t size)
190 {
191     UniformParameterPtr param;
192 
193     // Check if parameter already exists.
194     param = getParameterByAutoType(autoType);
195     if (param.get() != NULL)
196     {
197         if (param->isAutoConstantRealParameter() &&
198             param->getAutoConstantRealData() == data)
199         {
200             param->setSize(std::max(size, param->getSize()));
201             return param;
202         }
203     }
204 
205     // Create new parameter.
206     param = UniformParameterPtr(OGRE_NEW UniformParameter(autoType, data, size, type));
207     addParameter(param);
208 
209     return param;
210 }
211 
212 //-----------------------------------------------------------------------------
resolveAutoParameterInt(GpuProgramParameters::AutoConstantType autoType,size_t data,size_t size)213 UniformParameterPtr Program::resolveAutoParameterInt(GpuProgramParameters::AutoConstantType autoType,
214                                            size_t data, size_t size)
215 {
216     UniformParameterPtr param;
217 
218     // Check if parameter already exists.
219     param = getParameterByAutoType(autoType);
220     if (param.get() != NULL)
221     {
222         if (param->isAutoConstantIntParameter() &&
223             param->getAutoConstantIntData() == data)
224         {
225             param->setSize(std::max(size, param->getSize()));
226             return param;
227         }
228     }
229 
230     // Create new parameter.
231     param = UniformParameterPtr(OGRE_NEW UniformParameter(autoType, data, size));
232     addParameter(param);
233 
234     return param;
235 }
236 
237 //-----------------------------------------------------------------------------
resolveAutoParameterInt(GpuProgramParameters::AutoConstantType autoType,GpuConstantType type,size_t data,size_t size)238 UniformParameterPtr Program::resolveAutoParameterInt(GpuProgramParameters::AutoConstantType autoType, GpuConstantType type,
239                                            size_t data, size_t size)
240 {
241     UniformParameterPtr param;
242 
243     // Check if parameter already exists.
244     param = getParameterByAutoType(autoType);
245     if (param.get() != NULL)
246     {
247         if (param->isAutoConstantIntParameter() &&
248             param->getAutoConstantIntData() == data)
249         {
250             param->setSize(std::max(size, param->getSize()));
251             return param;
252         }
253     }
254 
255     // Create new parameter.
256     param = UniformParameterPtr(OGRE_NEW UniformParameter(autoType, data, size, type));
257     addParameter(param);
258 
259     return param;
260 }
261 
262 //-----------------------------------------------------------------------------
resolveParameter(GpuConstantType type,int index,uint16 variability,const String & suggestedName,size_t size)263 UniformParameterPtr Program::resolveParameter(GpuConstantType type,
264                                     int index, uint16 variability,
265                                     const String& suggestedName,
266                                     size_t size)
267 {
268     UniformParameterPtr param;
269 
270     if (index == -1)
271     {
272         index = 0;
273 
274         // Find the next available index of the target type.
275         UniformParameterIterator it;
276 
277         for (it = mParameters.begin(); it != mParameters.end(); ++it)
278         {
279             if ((*it)->getType() == type &&
280                 (*it)->isAutoConstantParameter() == false)
281             {
282                 index++;
283             }
284         }
285     }
286     else
287     {
288         // Check if parameter already exists.
289         param = getParameterByType(type, index);
290         if (param.get() != NULL)
291         {
292             return param;
293         }
294     }
295 
296     // Create new parameter.
297     param = ParameterFactory::createUniform(type, index, variability, suggestedName, size);
298     addParameter(param);
299 
300     return param;
301 }
302 
303 
304 
305 //-----------------------------------------------------------------------------
getParameterByName(const String & name)306 UniformParameterPtr Program::getParameterByName(const String& name)
307 {
308     UniformParameterIterator it;
309 
310     for (it = mParameters.begin(); it != mParameters.end(); ++it)
311     {
312         if ((*it)->getName() == name)
313         {
314             return *it;
315         }
316     }
317 
318     return UniformParameterPtr();
319 }
320 
321 //-----------------------------------------------------------------------------
getParameterByType(GpuConstantType type,int index)322 UniformParameterPtr Program::getParameterByType(GpuConstantType type, int index)
323 {
324     UniformParameterIterator it;
325 
326     for (it = mParameters.begin(); it != mParameters.end(); ++it)
327     {
328         if ((*it)->getType() == type &&
329             (*it)->getIndex() == index)
330         {
331             return *it;
332         }
333     }
334 
335     return UniformParameterPtr();
336 }
337 
338 //-----------------------------------------------------------------------------
getParameterByAutoType(GpuProgramParameters::AutoConstantType autoType)339 UniformParameterPtr Program::getParameterByAutoType(GpuProgramParameters::AutoConstantType autoType)
340 {
341     UniformParameterIterator it;
342 
343     for (it = mParameters.begin(); it != mParameters.end(); ++it)
344     {
345         if ((*it)->isAutoConstantParameter() && (*it)->getAutoConstantType() == autoType)
346         {
347             return *it;
348         }
349     }
350 
351     return UniformParameterPtr();
352 }
353 
354 //-----------------------------------------------------------------------------
createFunction(const String & name,const String & desc,const Function::FunctionType functionType)355 Function* Program::createFunction(const String& name, const String& desc, const Function::FunctionType functionType)
356 {
357     Function* shaderFunction;
358 
359     shaderFunction = getFunctionByName(name);
360     if (shaderFunction != NULL)
361     {
362         OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
363             "Function " + name + " already declared in program.",
364             "Program::createFunction" );
365     }
366 
367     shaderFunction = OGRE_NEW Function(name, desc, functionType);
368     mFunctions.push_back(shaderFunction);
369 
370     return shaderFunction;
371 }
372 
373 //-----------------------------------------------------------------------------
getFunctionByName(const String & name)374 Function* Program::getFunctionByName(const String& name)
375 {
376     ShaderFunctionIterator it;
377 
378     for (it = mFunctions.begin(); it != mFunctions.end(); ++it)
379     {
380         if ((*it)->getName() == name)
381         {
382             return *it;
383         }
384     }
385 
386     return NULL;
387 }
388 
389 //-----------------------------------------------------------------------------
addDependency(const String & libFileName)390 void Program::addDependency(const String& libFileName)
391 {
392     for (unsigned int i=0; i < mDependencies.size(); ++i)
393     {
394         if (mDependencies[i] == libFileName)
395         {
396             return;
397         }
398     }
399     mDependencies.push_back(libFileName);
400 }
401 
addPreprocessorDefines(const String & defines)402 void Program::addPreprocessorDefines(const String& defines)
403 {
404     mPreprocessorDefines +=
405         mPreprocessorDefines.empty() ? defines : ("," + defines);
406 }
407 
408 //-----------------------------------------------------------------------------
getDependencyCount() const409 size_t Program::getDependencyCount() const
410 {
411     return mDependencies.size();
412 }
413 
414 //-----------------------------------------------------------------------------
getDependency(unsigned int index) const415 const String& Program::getDependency(unsigned int index) const
416 {
417     return mDependencies[index];
418 }
419 
420 }
421 }
422