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

OgreD3D9HLSLProgram.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 "OgreD3D9HLSLProgram.h"
00026 #include "OgreGpuProgramManager.h"
00027 #include "OgreStringConverter.h"
00028 #include "OgreD3D9GpuProgram.h"
00029 #include "OgreGpuProgram.h"
00030 #include "OgreRoot.h"
00031 #include "OgreRenderSystem.h"
00032 #include "OgreRenderSystemCapabilities.h"
00033 
00034 namespace Ogre {
00035     //-----------------------------------------------------------------------
00036     D3D9HLSLProgram::CmdEntryPoint D3D9HLSLProgram::msCmdEntryPoint;
00037     D3D9HLSLProgram::CmdTarget D3D9HLSLProgram::msCmdTarget;
00038     //-----------------------------------------------------------------------
00039     //-----------------------------------------------------------------------
00040     void D3D9HLSLProgram::loadFromSource(void)
00041     {
00042         LPD3DXBUFFER errors = 0;
00043 
00044         // Compile & assemble into microcode
00045         HRESULT hr = D3DXCompileShader(
00046             mSource.c_str(),
00047             static_cast<UINT>(mSource.length()),
00048             NULL, //no preprocessor defines
00049             NULL, //no includes
00050             mEntryPoint.c_str(),
00051             mTarget.c_str(),
00052             NULL, // no compile flags
00053             &mpMicroCode,
00054             &errors,
00055             &mpConstTable);
00056 
00057         if (FAILED(hr))
00058         {
00059             Except(hr, "Cannot assemble D3D9 high-level shader " + mName + 
00060                 static_cast<const char*>(errors->GetBufferPointer()),
00061                 "D3D9HLSLProgram::loadFromSource");
00062         }
00063 
00064 
00065     }
00066     //-----------------------------------------------------------------------
00067     void D3D9HLSLProgram::createLowLevelImpl(void)
00068     {
00069         // Create a low-level program, give it the same name as us
00070         mAssemblerProgram = 
00071             GpuProgramManager::getSingleton().createProgramFromString(
00072                 mName, 
00073                 "",// dummy source, since we'll be using microcode
00074                 mType, 
00075                 mTarget);
00076         static_cast<D3D9GpuProgram*>(mAssemblerProgram)->setExternalMicrocode(mpMicroCode);
00077 
00078     }
00079     //-----------------------------------------------------------------------
00080     void D3D9HLSLProgram::unloadImpl(void)
00081     {
00082         SAFE_RELEASE(mpMicroCode);
00083         // mpConstTable is embedded inside the shader, so will get released with it
00084         mpConstTable = NULL;
00085 
00086     }
00087     //-----------------------------------------------------------------------
00088     void D3D9HLSLProgram::populateParameterNames(GpuProgramParametersSharedPtr params)
00089     {
00090         // Derive parameter names from const table
00091         assert(mpConstTable && "Program not loaded!");
00092         // Get contents of the constant table
00093         D3DXCONSTANTTABLE_DESC desc;
00094         HRESULT hr = mpConstTable->GetDesc(&desc);
00095 
00096         if (FAILED(hr))
00097         {
00098             Except(Exception::ERR_INTERNAL_ERROR, 
00099                 "Cannot retrieve constant descriptions from HLSL program.", 
00100                 "D3D9HLSLProgram::populateParameterNames");
00101         }
00102         // Iterate over the constants
00103         for (unsigned int i = 0; i < desc.Constants; ++i)
00104         {
00105             // Recursively descend through the structure levels
00106             // Since D3D9 has no nice 'leaf' method like Cg (sigh)
00107             processParamElement(NULL, "", i, params);
00108         }
00109 
00110         
00111     }
00112     //-----------------------------------------------------------------------
00113     void D3D9HLSLProgram::processParamElement(D3DXHANDLE parent, String prefix, 
00114         unsigned int index, GpuProgramParametersSharedPtr params)
00115     {
00116         D3DXHANDLE hConstant = mpConstTable->GetConstant(parent, index);
00117 
00118         // Since D3D HLSL doesn't deal with naming of array and struct parameters
00119         // automatically, we have to do it by hand
00120 
00121         D3DXCONSTANT_DESC desc;
00122         unsigned int numParams = 1;
00123         HRESULT hr = mpConstTable->GetConstantDesc(hConstant, &desc, &numParams);
00124         if (FAILED(hr))
00125         {
00126             Except(Exception::ERR_INTERNAL_ERROR, 
00127                 "Cannot retrieve constant description from HLSL program.", 
00128                 "D3D9HLSLProgram::processParamElement");
00129         }
00130 
00131         String paramName = desc.Name;
00132         // trim the odd '$' which appears at the start of the names in HLSL
00133         if (paramName.at(0) == '$')
00134             paramName.erase(paramName.begin());
00135 
00136         // If it's an array, elements will be > 1
00137         for (unsigned int e = 0; e < desc.Elements; ++e)
00138         {
00139             if (desc.Class == D3DXPC_STRUCT)
00140             {
00141                 // work out a new prefix for nested members, if it's an array, we need an index
00142                 if (desc.Elements > 1)
00143                     prefix = prefix + paramName + "[" + StringConverter::toString(e) + "].";
00144                 else
00145                     prefix = prefix + paramName + ".";
00146                 // Cascade into struct
00147                 for (unsigned int i = 0; i < desc.StructMembers; ++i)
00148                 {
00149                     processParamElement(hConstant, prefix, i, params);
00150                 }
00151             }
00152             else
00153             {
00154                 // Process params
00155                 if (desc.Type == D3DXPT_FLOAT || desc.Type == D3DXPT_INT || desc.Type == D3DXPT_BOOL)
00156                 {
00157                     size_t paramIndex = desc.RegisterIndex;
00158                     String name = prefix + paramName;
00159                     // If this is an array, need to append element index
00160                     if (desc.Elements > 1)
00161                         name += "[" + StringConverter::toString(e) + "]";
00162 
00163                     params->_mapParameterNameToIndex(name, paramIndex);
00164                 }
00165             }
00166         }
00167             
00168     }
00169     //-----------------------------------------------------------------------
00170     D3D9HLSLProgram::D3D9HLSLProgram(const String& name, GpuProgramType gpType, 
00171         const String& language)
00172         : HighLevelGpuProgram(name, gpType, language), mpMicroCode(NULL), 
00173         mpConstTable(NULL)
00174     {
00175         if (createParamDictionary("D3D9HLSLProgram"))
00176         {
00177             ParamDictionary* dict = getParamDictionary();
00178 
00179             dict->addParameter(ParameterDef("entry_point", 
00180                 "The entry point for the HLSL program.",
00181                 PT_STRING),&msCmdEntryPoint);
00182             dict->addParameter(ParameterDef("target", 
00183                 "Name of the assembler target to compile down to.",
00184                 PT_STRING),&msCmdTarget);
00185         }
00186         
00187     }
00188     //-----------------------------------------------------------------------
00189     D3D9HLSLProgram::~D3D9HLSLProgram()
00190     {
00191         // unload will be called by superclass
00192     }
00193     //-----------------------------------------------------------------------
00194     bool D3D9HLSLProgram::isSupported(void) const
00195     {
00196         // If skeletal animation is being done, we need support for UBYTE4
00197         if (isSkeletalAnimationIncluded() && 
00198             !Root::getSingleton().getRenderSystem()->getCapabilities()
00199                 ->hasCapability(RSC_VERTEX_FORMAT_UBYTE4))
00200         {
00201             return false;
00202         }
00203 
00204         return GpuProgramManager::getSingleton().isSyntaxSupported(mTarget);
00205     }
00206     //-----------------------------------------------------------------------
00207     GpuProgramParametersSharedPtr D3D9HLSLProgram::createParameters(void)
00208     {
00209         // Call superclass
00210         GpuProgramParametersSharedPtr params = HighLevelGpuProgram::createParameters();
00211 
00212         // D3D HLSL uses column-major matrices
00213         params->setTransposeMatrices(true);
00214 
00215         return params;
00216     }
00217     //-----------------------------------------------------------------------
00218     void D3D9HLSLProgram::setTarget(const String& target)
00219     {
00220         mTarget = target;
00221     }
00222     //-----------------------------------------------------------------------
00223     //-----------------------------------------------------------------------
00224     String D3D9HLSLProgram::CmdEntryPoint::doGet(const void *target) const
00225     {
00226         return static_cast<const D3D9HLSLProgram*>(target)->getEntryPoint();
00227     }
00228     void D3D9HLSLProgram::CmdEntryPoint::doSet(void *target, const String& val)
00229     {
00230         static_cast<D3D9HLSLProgram*>(target)->setEntryPoint(val);
00231     }
00232     //-----------------------------------------------------------------------
00233     String D3D9HLSLProgram::CmdTarget::doGet(const void *target) const
00234     {
00235         return static_cast<const D3D9HLSLProgram*>(target)->getTarget();
00236     }
00237     void D3D9HLSLProgram::CmdTarget::doSet(void *target, const String& val)
00238     {
00239         static_cast<D3D9HLSLProgram*>(target)->setTarget(val);
00240     }
00241 
00242 }

Copyright © 2002-2003 by The OGRE Team
Last modified Fri May 14 23:22:02 2004