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