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 00029 namespace Ogre { 00030 //----------------------------------------------------------------------- 00031 CgProgram::CmdEntryPoint CgProgram::msCmdEntryPoint; 00032 CgProgram::CmdProfiles CgProgram::msCmdProfiles; 00033 CgProgram::CmdArgs CgProgram::msCmdArgs; 00034 //----------------------------------------------------------------------- 00035 void CgProgram::selectProfile(void) 00036 { 00037 mSelectedProfile = ""; 00038 mSelectedCgProfile = CG_PROFILE_UNKNOWN; 00039 00040 StringVector::iterator i, iend; 00041 iend = mProfiles.end(); 00042 GpuProgramManager& gpuMgr = GpuProgramManager::getSingleton(); 00043 for (i = mProfiles.begin(); i != iend; ++i) 00044 { 00045 if (gpuMgr.isSyntaxSupported(*i)) 00046 { 00047 mSelectedProfile = *i; 00048 mSelectedCgProfile = cgGetProfile(mSelectedProfile); 00049 // Check for errors 00050 checkForCgError("CgProgram::selectProfile", 00051 "Unable to find CG profile enum for program " + mName + ": ", mCgContext); 00052 break; 00053 } 00054 } 00055 } 00056 //----------------------------------------------------------------------- 00057 void CgProgram::buildArgs(void) 00058 { 00059 StringVector args; 00060 if (!mCompileArgs.empty()) 00061 args = mCompileArgs.split(); 00062 00063 StringVector::const_iterator i; 00064 if (mSelectedCgProfile == CG_PROFILE_VS_1_1) 00065 { 00066 // Need the 'dcls' argument whenever we use this profile 00067 // otherwise compilation of the assembler will fail 00068 bool dclsFound = false; 00069 for (i = args.begin(); i != args.end(); ++i) 00070 { 00071 if (*i == "dcls") 00072 { 00073 dclsFound = true; 00074 break; 00075 } 00076 } 00077 if (!dclsFound) 00078 { 00079 args.push_back("-profileopts dcls"); 00080 } 00081 } 00082 // Now split args into that god-awful char** that Cg insists on 00083 freeCgArgs(); 00084 mCgArguments = new char*[args.size() + 1]; 00085 int index = 0; 00086 for (i = args.begin(); i != args.end(); ++i, ++index) 00087 { 00088 mCgArguments[index] = new char[i->length() + 1]; 00089 strcpy(mCgArguments[index], i->c_str()); 00090 } 00091 // Null terminate list 00092 mCgArguments[index] = 0; 00093 00094 00095 } 00096 //----------------------------------------------------------------------- 00097 void CgProgram::freeCgArgs(void) 00098 { 00099 if (mCgArguments) 00100 { 00101 size_t index = 0; 00102 char* current = mCgArguments[index]; 00103 while (current) 00104 { 00105 delete [] current; 00106 current = mCgArguments[++index]; 00107 } 00108 delete [] mCgArguments; 00109 mCgArguments = 0; 00110 } 00111 } 00112 //----------------------------------------------------------------------- 00113 void CgProgram::loadFromSource(void) 00114 { 00115 // Create Cg Program 00116 selectProfile(); 00117 buildArgs(); 00118 mCgProgram = cgCreateProgram(mCgContext, CG_SOURCE, mSource.c_str(), 00119 mSelectedCgProfile, mEntryPoint.c_str(), const_cast<const char**>(mCgArguments)); 00120 00121 // Test 00122 //LogManager::getSingleton().logMessage(cgGetProgramString(mCgProgram, CG_COMPILED_PROGRAM)); 00123 00124 // Check for errors 00125 checkForCgError("CgProgram::loadFromSource", 00126 "Unable to compile Cg program " + mName + ": ", mCgContext); 00127 00128 } 00129 //----------------------------------------------------------------------- 00130 void CgProgram::createLowLevelImpl(void) 00131 { 00132 // Create a low-level program, give it the same name as us 00133 mAssemblerProgram = 00134 GpuProgramManager::getSingleton().createProgramFromString( 00135 mName, 00136 cgGetProgramString(mCgProgram, CG_COMPILED_PROGRAM), 00137 mType, 00138 mSelectedProfile); 00139 00140 } 00141 //----------------------------------------------------------------------- 00142 void CgProgram::unloadImpl(void) 00143 { 00144 // Unload Cg Program 00145 // Lowlevel program will get unloaded elsewhere 00146 if (mCgProgram) 00147 { 00148 cgDestroyProgram(mCgProgram); 00149 checkForCgError("CgProgram::unloadImpl", 00150 "Error while unloading Cg program " + mName + ": ", 00151 mCgContext); 00152 mCgProgram = 0; 00153 } 00154 } 00155 //----------------------------------------------------------------------- 00156 void CgProgram::populateParameterNames(GpuProgramParametersSharedPtr params) 00157 { 00158 // Derive parameter names from Cg 00159 assert(mCgProgram && "Cg program not loaded!"); 00160 // Note use of 'leaf' format so we only get bottom-level params, not structs 00161 CGparameter parameter = cgGetFirstLeafParameter(mCgProgram, CG_PROGRAM); 00162 while (parameter != 0) 00163 { 00164 // Look for uniform (non-sampler) parameters only 00165 // Don't bother enumerating unused parameters, especially since they will 00166 // be optimised out and therefore not in the indexed versions 00167 CGtype paramType = cgGetParameterType(parameter); 00168 00169 // *** test 00170 //String tempName = cgGetParameterName(parameter); 00171 //size_t tempindex = cgGetParameterResourceIndex(parameter); 00172 //LogManager::getSingleton().logMessage( 00173 // tempName + " -> " + StringConverter::toString(tempindex)); 00174 00175 // *** end test 00176 00177 if (cgGetParameterVariability(parameter) == CG_UNIFORM && 00178 paramType != CG_SAMPLER1D && 00179 paramType != CG_SAMPLER2D && 00180 paramType != CG_SAMPLER3D && 00181 paramType != CG_SAMPLERCUBE && 00182 paramType != CG_SAMPLERRECT && 00183 cgGetParameterDirection(parameter) != CG_OUT && 00184 cgIsParameterReferenced(parameter)) 00185 { 00186 String paramName = cgGetParameterName(parameter); 00187 size_t index = cgGetParameterResourceIndex(parameter); 00188 00189 // Get the parameter resource, so we know what type we're dealing with 00190 CGresource res = cgGetParameterResource(parameter); 00191 switch (res) 00192 { 00193 case CG_COMBINER_STAGE_CONST0: 00194 // register combiner, const 0 00195 // the index relates to the texture stage; store this as (stage * 2) + 0 00196 index = index * 2; 00197 break; 00198 case CG_COMBINER_STAGE_CONST1: 00199 // register combiner, const 1 00200 // the index relates to the texture stage; store this as (stage * 2) + 1 00201 index = (index * 2) + 1; 00202 break; 00203 default: 00204 // do nothing, normal constant 00205 break; 00206 }; 00207 params->_mapParameterNameToIndex(paramName, index); 00208 } 00209 // Get next 00210 parameter = cgGetNextLeafParameter(parameter); 00211 } 00212 00213 00214 } 00215 //----------------------------------------------------------------------- 00216 CgProgram::CgProgram(const String& name, GpuProgramType gpType, 00217 const String& language, CGcontext context) 00218 : HighLevelGpuProgram(name, gpType, language), mCgContext(context), 00219 mCgProgram(0), mSelectedCgProfile(CG_PROFILE_UNKNOWN), mCgArguments(0) 00220 { 00221 if (createParamDictionary("CgProgram")) 00222 { 00223 ParamDictionary* dict = getParamDictionary(); 00224 00225 dict->addParameter(ParameterDef("entry_point", 00226 "The entry point for the Cg program.", 00227 PT_STRING),&msCmdEntryPoint); 00228 dict->addParameter(ParameterDef("profiles", 00229 "Space-separated list of Cg profiles supported by this profile.", 00230 PT_STRING),&msCmdProfiles); 00231 dict->addParameter(ParameterDef("compile_arguments", 00232 "A string of compilation arguments to pass to the Cg compiler.", 00233 PT_STRING),&msCmdArgs); 00234 } 00235 00236 } 00237 //----------------------------------------------------------------------- 00238 CgProgram::~CgProgram() 00239 { 00240 freeCgArgs(); 00241 // unload will be called by superclass 00242 } 00243 //----------------------------------------------------------------------- 00244 bool CgProgram::isSupported(void) const 00245 { 00246 StringVector::const_iterator i, iend; 00247 iend = mProfiles.end(); 00248 // Check to see if any of the profiles are supported 00249 for (i = mProfiles.begin(); i != iend; ++i) 00250 { 00251 if (GpuProgramManager::getSingleton().isSyntaxSupported(*i)) 00252 { 00253 return true; 00254 } 00255 } 00256 return false; 00257 00258 } 00259 //----------------------------------------------------------------------- 00260 void CgProgram::setProfiles(const StringVector& profiles) 00261 { 00262 mProfiles.clear(); 00263 StringVector::const_iterator i, iend; 00264 iend = profiles.end(); 00265 for (i = profiles.begin(); i != iend; ++i) 00266 { 00267 mProfiles.push_back(*i); 00268 } 00269 } 00270 //----------------------------------------------------------------------- 00271 //----------------------------------------------------------------------- 00272 String CgProgram::CmdEntryPoint::doGet(const void *target) const 00273 { 00274 return static_cast<const CgProgram*>(target)->getEntryPoint(); 00275 } 00276 void CgProgram::CmdEntryPoint::doSet(void *target, const String& val) 00277 { 00278 static_cast<CgProgram*>(target)->setEntryPoint(val); 00279 } 00280 //----------------------------------------------------------------------- 00281 String CgProgram::CmdProfiles::doGet(const void *target) const 00282 { 00283 return StringConverter::toString( 00284 static_cast<const CgProgram*>(target)->getProfiles() ); 00285 } 00286 void CgProgram::CmdProfiles::doSet(void *target, const String& val) 00287 { 00288 static_cast<CgProgram*>(target)->setProfiles(val.split()); 00289 } 00290 //----------------------------------------------------------------------- 00291 String CgProgram::CmdArgs::doGet(const void *target) const 00292 { 00293 return static_cast<const CgProgram*>(target)->getCompileArguments(); 00294 } 00295 void CgProgram::CmdArgs::doSet(void *target, const String& val) 00296 { 00297 static_cast<CgProgram*>(target)->setCompileArguments(val); 00298 } 00299 00300 }
Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:04 2004