source: OGRE/trunk/ogre_changes/Ogre1.2/RenderSystems/Direct3D9/src/OgreD3D9HLSLProgram.cpp @ 1728

Revision 1728, 13.3 KB checked in by szirmay, 18 years ago (diff)
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#include "OgreD3D9HLSLProgram.h"
26#include "OgreGpuProgramManager.h"
27#include "OgreStringConverter.h"
28#include "OgreD3D9GpuProgram.h"
29#include "OgreGpuProgram.h"
30#include "OgreRoot.h"
31#include "OgreRenderSystem.h"
32#include "OgreRenderSystemCapabilities.h"
33
34namespace Ogre {
35    //-----------------------------------------------------------------------
36    D3D9HLSLProgram::CmdEntryPoint D3D9HLSLProgram::msCmdEntryPoint;
37    D3D9HLSLProgram::CmdTarget D3D9HLSLProgram::msCmdTarget;
38#ifdef GAMETOOLS_ILLUMINATION_MODULE
39        D3D9HLSLProgram::CmdOptimalization D3D9HLSLProgram::msCmdOptimalization;
40        D3D9HLSLProgram::CmdFlowControl D3D9HLSLProgram::msCmdFlowControl;
41#endif
42    //-----------------------------------------------------------------------
43    //-----------------------------------------------------------------------
44    void D3D9HLSLProgram::loadFromSource(void)
45    {
46        LPD3DXBUFFER errors = 0;
47               
48                #ifdef GAMETOOLS_ILLUMINATION_MODULE
49                        mCompilerFlags = NULL;
50                       
51                        if(!mOptimalization)
52                                mCompilerFlags = D3DXSHADER_SKIPOPTIMIZATION;
53                        if(mFlowControl == 1)
54                                mCompilerFlags = mCompilerFlags|D3DXSHADER_PREFER_FLOW_CONTROL;
55                        if(mFlowControl == -1)
56                                mCompilerFlags = mCompilerFlags|D3DXSHADER_AVOID_FLOW_CONTROL;
57
58                        HRESULT hr = D3DXCompileShader(
59                                mSource.c_str(),
60                                static_cast<UINT>(mSource.length()),
61                                NULL, //no preprocessor defines
62                                NULL, //no includes
63                                mEntryPoint.c_str(),
64                                mTarget.c_str(),
65                                mCompilerFlags,
66                                &mpMicroCode,
67                                &errors,
68                                &mpConstTable);
69                #else
70                        // Compile & assemble into microcode
71                        HRESULT hr = D3DXCompileShader(
72                                mSource.c_str(),
73                                static_cast<UINT>(mSource.length()),
74                                NULL, //no preprocessor defines
75                                NULL, //no includes
76                                mEntryPoint.c_str(),
77                                mTarget.c_str(),
78                                NULL, // no compile flags
79                                &mpMicroCode,
80                                &errors,
81                                &mpConstTable);
82                #endif
83
84        if (FAILED(hr))
85        {
86            String message = "Cannot assemble D3D9 high-level shader " + mName + " Errors:\n" +
87                static_cast<const char*>(errors->GetBufferPointer());
88            errors->Release();
89            OGRE_EXCEPT(hr, message,
90                "D3D9HLSLProgram::loadFromSource");
91        }
92
93
94    }
95    //-----------------------------------------------------------------------
96    void D3D9HLSLProgram::createLowLevelImpl(void)
97    {
98        // Create a low-level program, give it the same name as us
99        mAssemblerProgram =
100            GpuProgramManager::getSingleton().createProgramFromString(
101                mName,
102                mGroup,
103                "",// dummy source, since we'll be using microcode
104                mType,
105                mTarget);
106        static_cast<D3D9GpuProgram*>(mAssemblerProgram.get())->setExternalMicrocode(mpMicroCode);
107
108    }
109    //-----------------------------------------------------------------------
110    void D3D9HLSLProgram::unloadHighLevelImpl(void)
111    {
112        SAFE_RELEASE(mpMicroCode);
113        SAFE_RELEASE(mpConstTable);
114
115    }
116    //-----------------------------------------------------------------------
117    void D3D9HLSLProgram::populateParameterNames(GpuProgramParametersSharedPtr params)
118    {
119        // Derive parameter names from const table
120        assert(mpConstTable && "Program not loaded!");
121        // Get contents of the constant table
122        D3DXCONSTANTTABLE_DESC desc;
123        HRESULT hr = mpConstTable->GetDesc(&desc);
124
125        if (FAILED(hr))
126        {
127            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
128                "Cannot retrieve constant descriptions from HLSL program.",
129                "D3D9HLSLProgram::populateParameterNames");
130        }
131        // Iterate over the constants
132        for (unsigned int i = 0; i < desc.Constants; ++i)
133        {
134            // Recursively descend through the structure levels
135            // Since D3D9 has no nice 'leaf' method like Cg (sigh)
136            processParamElement(NULL, "", i, params);
137        }
138
139       
140    }
141    //-----------------------------------------------------------------------
142    void D3D9HLSLProgram::processParamElement(D3DXHANDLE parent, String prefix,
143        unsigned int index, GpuProgramParametersSharedPtr params)
144    {
145        D3DXHANDLE hConstant = mpConstTable->GetConstant(parent, index);
146
147        // Since D3D HLSL doesn't deal with naming of array and struct parameters
148        // automatically, we have to do it by hand
149
150        D3DXCONSTANT_DESC desc;
151        unsigned int numParams = 1;
152        HRESULT hr = mpConstTable->GetConstantDesc(hConstant, &desc, &numParams);
153        if (FAILED(hr))
154        {
155            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
156                "Cannot retrieve constant description from HLSL program.",
157                "D3D9HLSLProgram::processParamElement");
158        }
159
160        String paramName = desc.Name;
161        // trim the odd '$' which appears at the start of the names in HLSL
162        if (paramName.at(0) == '$')
163            paramName.erase(paramName.begin());
164
165        // If it's an array, elements will be > 1
166        for (unsigned int e = 0; e < desc.Elements; ++e)
167        {
168            if (desc.Class == D3DXPC_STRUCT)
169            {
170                // work out a new prefix for nested members, if it's an array, we need an index
171                if (desc.Elements > 1)
172                    prefix = prefix + paramName + "[" + StringConverter::toString(e) + "].";
173                else
174                    prefix = prefix + paramName + ".";
175                // Cascade into struct
176                for (unsigned int i = 0; i < desc.StructMembers; ++i)
177                {
178                    processParamElement(hConstant, prefix, i, params);
179                }
180            }
181            else
182            {
183                // Process params
184                if (desc.Type == D3DXPT_FLOAT || desc.Type == D3DXPT_INT || desc.Type == D3DXPT_BOOL)
185                {
186                    size_t paramIndex = desc.RegisterIndex;
187                    String name = prefix + paramName;
188                    // If this is an array, need to append element index
189                    if (desc.Elements > 1)
190                        name += "[" + StringConverter::toString(e) + "]";
191                   
192                    params->_mapParameterNameToIndex(name, paramIndex);
193                    // setup constant definition
194                    // is it float or int
195                    GpuProgramParameters::ElementType elementType = GpuProgramParameters::ET_INT;
196                    if (desc.Type == D3DXPT_FLOAT)
197                        elementType = GpuProgramParameters::ET_REAL;
198                    params->addConstantDefinition(name, paramIndex, 0, elementType);
199                }
200            }
201        }
202           
203    }
204    //-----------------------------------------------------------------------
205    D3D9HLSLProgram::D3D9HLSLProgram(ResourceManager* creator, const String& name,
206        ResourceHandle handle, const String& group, bool isManual,
207        ManualResourceLoader* loader)
208        : HighLevelGpuProgram(creator, name, handle, group, isManual, loader)
209        , mpMicroCode(NULL), mpConstTable(NULL)
210    {
211                #ifdef GAMETOOLS_ILLUMINATION_MODULE
212                        mOptimalization = true;
213                        mFlowControl = 0;
214                        mCompilerFlags = NULL;
215                #endif
216
217        if (createParamDictionary("D3D9HLSLProgram"))
218        {
219            setupBaseParamDictionary();
220            ParamDictionary* dict = getParamDictionary();
221
222            dict->addParameter(ParameterDef("entry_point",
223                "The entry point for the HLSL program.",
224                PT_STRING),&msCmdEntryPoint);
225            dict->addParameter(ParameterDef("target",
226                "Name of the assembler target to compile down to.",
227                PT_STRING),&msCmdTarget);
228                        #ifdef GAMETOOLS_ILLUMINATION_MODULE
229                                dict->addParameter(ParameterDef("optimalization",
230                                        "Boolean to turn optimalization on/off",
231                                        PT_STRING),&msCmdOptimalization);
232                                dict->addParameter(ParameterDef("flow_control",
233                                        "Flow control: default, prefer, avoid.",
234                                        PT_STRING),&msCmdFlowControl);
235                        #endif
236        }
237       
238    }
239    //-----------------------------------------------------------------------
240    D3D9HLSLProgram::~D3D9HLSLProgram()
241    {
242        // have to call this here reather than in Resource destructor
243        // since calling virtual methods in base destructors causes crash
244        if (mIsLoaded)
245        {
246            unload();
247        }
248        else
249        {
250            unloadHighLevel();
251        }
252    }
253    //-----------------------------------------------------------------------
254    bool D3D9HLSLProgram::isSupported(void) const
255    {
256                // If skeletal animation is being done, we need support for UBYTE4
257                if (isSkeletalAnimationIncluded() &&
258                        !Root::getSingleton().getRenderSystem()->getCapabilities()
259                                ->hasCapability(RSC_VERTEX_FORMAT_UBYTE4))
260                {
261                        return false;
262                }
263
264        return GpuProgramManager::getSingleton().isSyntaxSupported(mTarget);
265    }
266    //-----------------------------------------------------------------------
267    GpuProgramParametersSharedPtr D3D9HLSLProgram::createParameters(void)
268    {
269        // Call superclass
270        GpuProgramParametersSharedPtr params = HighLevelGpuProgram::createParameters();
271
272        // D3D HLSL uses column-major matrices
273        params->setTransposeMatrices(true);
274
275        return params;
276    }
277    //-----------------------------------------------------------------------
278    void D3D9HLSLProgram::setTarget(const String& target)
279    {
280        mTarget = target;
281    }
282
283    //-----------------------------------------------------------------------
284    const String& D3D9HLSLProgram::getLanguage(void) const
285    {
286        static const String language = "hlsl";
287
288        return language;
289    }
290
291        #ifdef GAMETOOLS_ILLUMINATION_MODULE
292                void D3D9HLSLProgram::setOptimalization(const String& optimalization)
293                {
294                        mOptimalization = StringConverter::parseBool(optimalization);                   
295                }
296                const String& D3D9HLSLProgram::getOptimalization() const
297                {
298                        return StringConverter::toString(mOptimalization);
299                }
300                void D3D9HLSLProgram::setFlowControl(const String& control)
301                {
302                        if(control == "default")
303                                mFlowControl = 0;
304                        else if(control == "avoid")
305                                mFlowControl = -1;
306                        else if(control == "prefer")
307                                mFlowControl = 1;       
308                }
309                const String& D3D9HLSLProgram::getFlowControl() const
310                {
311                        static const String def = "default";
312                        static const String pref = "prefer";
313                        static const String av = "avoid";
314                        if(mFlowControl == 0)
315                                return def;
316                        if(mFlowControl == -1)
317                                return av;
318                        if(mFlowControl == 1)
319                                return pref;           
320                }
321        #endif
322
323    //-----------------------------------------------------------------------
324    //-----------------------------------------------------------------------
325    String D3D9HLSLProgram::CmdEntryPoint::doGet(const void *target) const
326    {
327        return static_cast<const D3D9HLSLProgram*>(target)->getEntryPoint();
328    }
329    void D3D9HLSLProgram::CmdEntryPoint::doSet(void *target, const String& val)
330    {
331        static_cast<D3D9HLSLProgram*>(target)->setEntryPoint(val);
332    }
333    //-----------------------------------------------------------------------
334    String D3D9HLSLProgram::CmdTarget::doGet(const void *target) const
335    {
336        return static_cast<const D3D9HLSLProgram*>(target)->getTarget();
337    }
338    void D3D9HLSLProgram::CmdTarget::doSet(void *target, const String& val)
339    {
340        static_cast<D3D9HLSLProgram*>(target)->setTarget(val);
341    }
342
343        #ifdef GAMETOOLS_ILLUMINATION_MODULE
344                String D3D9HLSLProgram::CmdOptimalization::doGet(const void *target) const
345                {
346                        return static_cast<const D3D9HLSLProgram*>(target)->getOptimalization();
347                }
348                void D3D9HLSLProgram::CmdOptimalization::doSet(void *target, const String& val)
349                {
350                        static_cast<D3D9HLSLProgram*>(target)->setOptimalization(val);
351                }
352                String D3D9HLSLProgram::CmdFlowControl::doGet(const void *target) const
353                {
354                        return static_cast<const D3D9HLSLProgram*>(target)->getFlowControl();
355                }
356                void D3D9HLSLProgram::CmdFlowControl::doSet(void *target, const String& val)
357                {
358                        static_cast<D3D9HLSLProgram*>(target)->setFlowControl(val);
359                }
360        #endif
361
362}
Note: See TracBrowser for help on using the repository browser.