Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreCgProgram.cpp

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004     (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://www.ogre3d.org/
00006 
00007 Copyright © 2000-2003 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 #include "OgreCgProgram.h"
00026 #include "OgreGpuProgramManager.h"
00027 #include "OgreStringConverter.h"
00028 #include "OgreRoot.h"
00029 #include "OgreRenderSystem.h"
00030 #include "OgreRenderSystemCapabilities.h"
00031 
00032 namespace Ogre {
00033     //-----------------------------------------------------------------------
00034     CgProgram::CmdEntryPoint CgProgram::msCmdEntryPoint;
00035     CgProgram::CmdProfiles CgProgram::msCmdProfiles;
00036     CgProgram::CmdArgs CgProgram::msCmdArgs;
00037     //-----------------------------------------------------------------------
00038     void CgProgram::selectProfile(void)
00039     {
00040         mSelectedProfile = "";
00041         mSelectedCgProfile = CG_PROFILE_UNKNOWN;
00042 
00043         StringVector::iterator i, iend;
00044         iend = mProfiles.end();
00045         GpuProgramManager& gpuMgr = GpuProgramManager::getSingleton();
00046         for (i = mProfiles.begin(); i != iend; ++i)
00047         {
00048             if (gpuMgr.isSyntaxSupported(*i))
00049             {
00050                 mSelectedProfile = *i;
00051                 mSelectedCgProfile = cgGetProfile(mSelectedProfile.c_str());
00052                 // Check for errors
00053                 checkForCgError("CgProgram::selectProfile", 
00054                     "Unable to find CG profile enum for program " + mName + ": ", mCgContext);
00055                 break;
00056             }
00057         }
00058     }
00059     //-----------------------------------------------------------------------
00060     void CgProgram::buildArgs(void)
00061     {
00062         StringVector args;
00063         if (!mCompileArgs.empty())
00064             args = StringUtil::split(mCompileArgs);
00065 
00066         StringVector::const_iterator i;
00067         if (mSelectedCgProfile == CG_PROFILE_VS_1_1)
00068         {
00069             // Need the 'dcls' argument whenever we use this profile
00070             // otherwise compilation of the assembler will fail
00071             bool dclsFound = false;
00072             for (i = args.begin(); i != args.end(); ++i)
00073             {
00074                 if (*i == "dcls")
00075                 {
00076                     dclsFound = true;
00077                     break;
00078                 }
00079             }
00080             if (!dclsFound)
00081             {
00082                 args.push_back("-profileopts dcls");
00083             }
00084         }
00085         // Now split args into that god-awful char** that Cg insists on
00086         freeCgArgs();
00087         mCgArguments = new char*[args.size() + 1];
00088         int index = 0;
00089         for (i = args.begin(); i != args.end(); ++i, ++index)
00090         {
00091             mCgArguments[index] = new char[i->length() + 1];
00092             strcpy(mCgArguments[index], i->c_str());
00093         }
00094         // Null terminate list
00095         mCgArguments[index] = 0;
00096 
00097 
00098     }
00099     //-----------------------------------------------------------------------
00100     void CgProgram::freeCgArgs(void)
00101     {
00102         if (mCgArguments)
00103         {
00104             size_t index = 0;
00105             char* current = mCgArguments[index];
00106             while (current)
00107             {
00108                 delete [] current;
00109                 current = mCgArguments[++index];
00110             }
00111             delete [] mCgArguments;
00112             mCgArguments = 0;
00113         }
00114     }
00115     //-----------------------------------------------------------------------
00116     void CgProgram::loadFromSource(void)
00117     {
00118         // Create Cg Program
00119         selectProfile();
00120         buildArgs();
00121         mCgProgram = cgCreateProgram(mCgContext, CG_SOURCE, mSource.c_str(), 
00122             mSelectedCgProfile, mEntryPoint.c_str(), const_cast<const char**>(mCgArguments));
00123 
00124         // Test
00125         //LogManager::getSingleton().logMessage(cgGetProgramString(mCgProgram, CG_COMPILED_PROGRAM));
00126 
00127         // Check for errors
00128         checkForCgError("CgProgram::loadFromSource", 
00129             "Unable to compile Cg program " + mName + ": ", mCgContext);
00130 
00131     }
00132     //-----------------------------------------------------------------------
00133     void CgProgram::createLowLevelImpl(void)
00134     {
00135         // Create a low-level program, give it the same name as us
00136         mAssemblerProgram = 
00137             GpuProgramManager::getSingleton().createProgramFromString(
00138                 mName, 
00139                 cgGetProgramString(mCgProgram, CG_COMPILED_PROGRAM),
00140                 mType, 
00141                 mSelectedProfile);
00142 
00143     }
00144     //-----------------------------------------------------------------------
00145     void CgProgram::unloadImpl(void)
00146     {
00147         // Unload Cg Program
00148         // Lowlevel program will get unloaded elsewhere
00149         if (mCgProgram)
00150         {
00151             cgDestroyProgram(mCgProgram);
00152             checkForCgError("CgProgram::unloadImpl", 
00153                 "Error while unloading Cg program " + mName + ": ", 
00154                 mCgContext);
00155             mCgProgram = 0;
00156         }
00157     }
00158     //-----------------------------------------------------------------------
00159     void CgProgram::populateParameterNames(GpuProgramParametersSharedPtr params)
00160     {
00161         // Derive parameter names from Cg
00162         assert(mCgProgram && "Cg program not loaded!");
00163         // Note use of 'leaf' format so we only get bottom-level params, not structs
00164         CGparameter parameter = cgGetFirstLeafParameter(mCgProgram, CG_PROGRAM);
00165         while (parameter != 0) 
00166         {
00167             // Look for uniform (non-sampler) parameters only
00168             // Don't bother enumerating unused parameters, especially since they will
00169             // be optimised out and therefore not in the indexed versions
00170             CGtype paramType = cgGetParameterType(parameter);
00171             
00172             // *** test
00173             //String tempName = cgGetParameterName(parameter);
00174             //size_t tempindex = cgGetParameterResourceIndex(parameter);
00175             //LogManager::getSingleton().logMessage(
00176             //    tempName + " -> " + StringConverter::toString(tempindex));
00177 
00178             // *** end test
00179 
00180             if (cgGetParameterVariability(parameter) == CG_UNIFORM &&
00181                 paramType != CG_SAMPLER1D &&
00182                 paramType != CG_SAMPLER2D &&
00183                 paramType != CG_SAMPLER3D &&
00184                 paramType != CG_SAMPLERCUBE &&
00185                 paramType != CG_SAMPLERRECT &&
00186                 cgGetParameterDirection(parameter) != CG_OUT && 
00187                 cgIsParameterReferenced(parameter))
00188             {
00189                 String paramName = cgGetParameterName(parameter);
00190                 size_t index = cgGetParameterResourceIndex(parameter);
00191 
00192                 // Get the parameter resource, so we know what type we're dealing with
00193                 CGresource res = cgGetParameterResource(parameter);
00194                 switch (res)
00195                 {
00196                 case CG_COMBINER_STAGE_CONST0:
00197                     // register combiner, const 0
00198                     // the index relates to the texture stage; store this as (stage * 2) + 0
00199                     index = index * 2;
00200                     break;
00201                 case CG_COMBINER_STAGE_CONST1:
00202                     // register combiner, const 1
00203                     // the index relates to the texture stage; store this as (stage * 2) + 1
00204                     index = (index * 2) + 1;
00205                     break;
00206                 default:
00207                     // do nothing, normal constant
00208                     break;
00209                 };
00210                 params->_mapParameterNameToIndex(paramName, index);
00211             }
00212             // Get next
00213             parameter = cgGetNextLeafParameter(parameter);
00214         }
00215 
00216         
00217     }
00218     //-----------------------------------------------------------------------
00219     CgProgram::CgProgram(const String& name, GpuProgramType gpType, 
00220         const String& language, CGcontext context)
00221         : HighLevelGpuProgram(name, gpType, language), mCgContext(context), 
00222         mCgProgram(0), mSelectedCgProfile(CG_PROFILE_UNKNOWN), mCgArguments(0)
00223     {
00224         if (createParamDictionary("CgProgram"))
00225         {
00226             ParamDictionary* dict = getParamDictionary();
00227 
00228             dict->addParameter(ParameterDef("entry_point", 
00229                 "The entry point for the Cg program.",
00230                 PT_STRING),&msCmdEntryPoint);
00231             dict->addParameter(ParameterDef("profiles", 
00232                 "Space-separated list of Cg profiles supported by this profile.",
00233                 PT_STRING),&msCmdProfiles);
00234             dict->addParameter(ParameterDef("compile_arguments", 
00235                 "A string of compilation arguments to pass to the Cg compiler.",
00236                 PT_STRING),&msCmdArgs);
00237         }
00238         
00239     }
00240     //-----------------------------------------------------------------------
00241     CgProgram::~CgProgram()
00242     {
00243         freeCgArgs();
00244         // unload will be called by superclass
00245     }
00246     //-----------------------------------------------------------------------
00247     bool CgProgram::isSupported(void) const
00248     {
00249         // If skeletal animation is being done, we need support for UBYTE4
00250         if (isSkeletalAnimationIncluded() && 
00251             !Root::getSingleton().getRenderSystem()->getCapabilities()
00252                 ->hasCapability(RSC_VERTEX_FORMAT_UBYTE4))
00253         {
00254             return false;
00255         }
00256 
00257         StringVector::const_iterator i, iend;
00258         iend = mProfiles.end();
00259         // Check to see if any of the profiles are supported
00260         for (i = mProfiles.begin(); i != iend; ++i)
00261         {
00262             if (GpuProgramManager::getSingleton().isSyntaxSupported(*i))
00263             {
00264                 return true;
00265             }
00266         }
00267         return false;
00268 
00269     }
00270     //-----------------------------------------------------------------------
00271     void CgProgram::setProfiles(const StringVector& profiles)
00272     {
00273         mProfiles.clear();
00274         StringVector::const_iterator i, iend;
00275         iend = profiles.end();
00276         for (i = profiles.begin(); i != iend; ++i)
00277         {
00278             mProfiles.push_back(*i);
00279         }
00280     }
00281     //-----------------------------------------------------------------------
00282     //-----------------------------------------------------------------------
00283     String CgProgram::CmdEntryPoint::doGet(const void *target) const
00284     {
00285         return static_cast<const CgProgram*>(target)->getEntryPoint();
00286     }
00287     void CgProgram::CmdEntryPoint::doSet(void *target, const String& val)
00288     {
00289         static_cast<CgProgram*>(target)->setEntryPoint(val);
00290     }
00291     //-----------------------------------------------------------------------
00292     String CgProgram::CmdProfiles::doGet(const void *target) const
00293     {
00294         return StringConverter::toString(
00295             static_cast<const CgProgram*>(target)->getProfiles() );
00296     }
00297     void CgProgram::CmdProfiles::doSet(void *target, const String& val)
00298     {
00299         static_cast<CgProgram*>(target)->setProfiles(StringUtil::split(val));
00300     }
00301     //-----------------------------------------------------------------------
00302     String CgProgram::CmdArgs::doGet(const void *target) const
00303     {
00304         return static_cast<const CgProgram*>(target)->getCompileArguments();
00305     }
00306     void CgProgram::CmdArgs::doSet(void *target, const String& val)
00307     {
00308         static_cast<CgProgram*>(target)->setCompileArguments(val);
00309     }
00310 
00311 }

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:17 2004