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

Revision 2354, 14.5 KB checked in by szirmay, 17 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#ifdef GAMETOOLS_ILLUMINATION_MODULE
96        //-----------------------------------------------------------------------
97        void D3D9HLSLProgram::loadHighLevelImpl(void)
98    {
99        if (mLoadFromFile)
100                loadFromFile();
101        else
102                        loadFromSource();       
103    }
104    void D3D9HLSLProgram::loadFromFile(void)
105        {
106                 LPD3DXBUFFER errors = 0;
107               
108                        mCompilerFlags = NULL;
109                       
110                        if(!mOptimalization)
111                                mCompilerFlags = D3DXSHADER_SKIPOPTIMIZATION;
112                        if(mFlowControl == 1)
113                                mCompilerFlags = mCompilerFlags|D3DXSHADER_PREFER_FLOW_CONTROL;
114                        if(mFlowControl == -1)
115                                mCompilerFlags = mCompilerFlags|D3DXSHADER_AVOID_FLOW_CONTROL;
116
117                        HRESULT hr = D3DXCompileShaderFromFile(
118                                mFilename.c_str(),
119                                NULL, //no preprocessor defines
120                                NULL, //no includes
121                                mEntryPoint.c_str(),
122                                mTarget.c_str(),
123                                mCompilerFlags,
124                                &mpMicroCode,
125                                &errors,
126                                &mpConstTable);         
127
128        if (FAILED(hr))
129        {
130            String message = "Cannot assemble D3D9 high-level shader " + mName + " Errors:\n" +
131                static_cast<const char*>(errors->GetBufferPointer());
132            errors->Release();
133            OGRE_EXCEPT(hr, message,
134                "D3D9HLSLProgram::loadFromSource");
135        }
136        }
137#endif
138    //-----------------------------------------------------------------------
139    void D3D9HLSLProgram::createLowLevelImpl(void)
140    {
141        // Create a low-level program, give it the same name as us
142        mAssemblerProgram =
143            GpuProgramManager::getSingleton().createProgramFromString(
144                mName,
145                mGroup,
146                "",// dummy source, since we'll be using microcode
147                mType,
148                mTarget);
149        static_cast<D3D9GpuProgram*>(mAssemblerProgram.get())->setExternalMicrocode(mpMicroCode);
150
151    }
152    //-----------------------------------------------------------------------
153    void D3D9HLSLProgram::unloadHighLevelImpl(void)
154    {
155        SAFE_RELEASE(mpMicroCode);
156        SAFE_RELEASE(mpConstTable);
157
158    }
159    //-----------------------------------------------------------------------
160    void D3D9HLSLProgram::populateParameterNames(GpuProgramParametersSharedPtr params)
161    {
162        // Derive parameter names from const table
163        assert(mpConstTable && "Program not loaded!");
164        // Get contents of the constant table
165        D3DXCONSTANTTABLE_DESC desc;
166        HRESULT hr = mpConstTable->GetDesc(&desc);
167
168        if (FAILED(hr))
169        {
170            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
171                "Cannot retrieve constant descriptions from HLSL program.",
172                "D3D9HLSLProgram::populateParameterNames");
173        }
174        // Iterate over the constants
175        for (unsigned int i = 0; i < desc.Constants; ++i)
176        {
177            // Recursively descend through the structure levels
178            // Since D3D9 has no nice 'leaf' method like Cg (sigh)
179            processParamElement(NULL, "", i, params);
180        }
181
182       
183    }
184    //-----------------------------------------------------------------------
185    void D3D9HLSLProgram::processParamElement(D3DXHANDLE parent, String prefix,
186        unsigned int index, GpuProgramParametersSharedPtr params)
187    {
188        D3DXHANDLE hConstant = mpConstTable->GetConstant(parent, index);
189
190        // Since D3D HLSL doesn't deal with naming of array and struct parameters
191        // automatically, we have to do it by hand
192
193        D3DXCONSTANT_DESC desc;
194        unsigned int numParams = 1;
195        HRESULT hr = mpConstTable->GetConstantDesc(hConstant, &desc, &numParams);
196        if (FAILED(hr))
197        {
198            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
199                "Cannot retrieve constant description from HLSL program.",
200                "D3D9HLSLProgram::processParamElement");
201        }
202
203        String paramName = desc.Name;
204        // trim the odd '$' which appears at the start of the names in HLSL
205        if (paramName.at(0) == '$')
206            paramName.erase(paramName.begin());
207
208        // If it's an array, elements will be > 1
209        for (unsigned int e = 0; e < desc.Elements; ++e)
210        {
211            if (desc.Class == D3DXPC_STRUCT)
212            {
213                // work out a new prefix for nested members, if it's an array, we need an index
214                if (desc.Elements > 1)
215                    prefix = prefix + paramName + "[" + StringConverter::toString(e) + "].";
216                else
217                    prefix = prefix + paramName + ".";
218                // Cascade into struct
219                for (unsigned int i = 0; i < desc.StructMembers; ++i)
220                {
221                    processParamElement(hConstant, prefix, i, params);
222                }
223            }
224            else
225            {
226                // Process params
227                if (desc.Type == D3DXPT_FLOAT || desc.Type == D3DXPT_INT || desc.Type == D3DXPT_BOOL)
228                {
229                    size_t paramIndex = desc.RegisterIndex;
230                    String name = prefix + paramName;
231                    // If this is an array, need to append element index
232                    if (desc.Elements > 1)
233                        name += "[" + StringConverter::toString(e) + "]";
234                   
235                    params->_mapParameterNameToIndex(name, paramIndex);
236                    // setup constant definition
237                    // is it float or int
238                    GpuProgramParameters::ElementType elementType = GpuProgramParameters::ET_INT;
239                    if (desc.Type == D3DXPT_FLOAT)
240                        elementType = GpuProgramParameters::ET_REAL;
241                    params->addConstantDefinition(name, paramIndex, 0, elementType);
242                }
243            }
244        }
245           
246    }
247    //-----------------------------------------------------------------------
248    D3D9HLSLProgram::D3D9HLSLProgram(ResourceManager* creator, const String& name,
249        ResourceHandle handle, const String& group, bool isManual,
250        ManualResourceLoader* loader)
251        : HighLevelGpuProgram(creator, name, handle, group, isManual, loader)
252        , mpMicroCode(NULL), mpConstTable(NULL)
253    {
254                #ifdef GAMETOOLS_ILLUMINATION_MODULE
255                        mOptimalization = true;
256                        mFlowControl = 0;
257                        mCompilerFlags = NULL;
258                #endif
259
260        if (createParamDictionary("D3D9HLSLProgram"))
261        {
262            setupBaseParamDictionary();
263            ParamDictionary* dict = getParamDictionary();
264
265            dict->addParameter(ParameterDef("entry_point",
266                "The entry point for the HLSL program.",
267                PT_STRING),&msCmdEntryPoint);
268            dict->addParameter(ParameterDef("target",
269                "Name of the assembler target to compile down to.",
270                PT_STRING),&msCmdTarget);
271                        #ifdef GAMETOOLS_ILLUMINATION_MODULE
272                                dict->addParameter(ParameterDef("optimalization",
273                                        "Boolean to turn optimalization on/off",
274                                        PT_STRING),&msCmdOptimalization);
275                                dict->addParameter(ParameterDef("flow_control",
276                                        "Flow control: default, prefer, avoid.",
277                                        PT_STRING),&msCmdFlowControl);
278                        #endif
279        }
280       
281    }
282    //-----------------------------------------------------------------------
283    D3D9HLSLProgram::~D3D9HLSLProgram()
284    {
285        // have to call this here reather than in Resource destructor
286        // since calling virtual methods in base destructors causes crash
287        if (mIsLoaded)
288        {
289            unload();
290        }
291        else
292        {
293            unloadHighLevel();
294        }
295    }
296    //-----------------------------------------------------------------------
297    bool D3D9HLSLProgram::isSupported(void) const
298    {
299                // If skeletal animation is being done, we need support for UBYTE4
300                if (isSkeletalAnimationIncluded() &&
301                        !Root::getSingleton().getRenderSystem()->getCapabilities()
302                                ->hasCapability(RSC_VERTEX_FORMAT_UBYTE4))
303                {
304                        return false;
305                }
306
307        return GpuProgramManager::getSingleton().isSyntaxSupported(mTarget);
308    }
309    //-----------------------------------------------------------------------
310    GpuProgramParametersSharedPtr D3D9HLSLProgram::createParameters(void)
311    {
312        // Call superclass
313        GpuProgramParametersSharedPtr params = HighLevelGpuProgram::createParameters();
314
315        // D3D HLSL uses column-major matrices
316        params->setTransposeMatrices(true);
317
318        return params;
319    }
320    //-----------------------------------------------------------------------
321    void D3D9HLSLProgram::setTarget(const String& target)
322    {
323        mTarget = target;
324    }
325
326    //-----------------------------------------------------------------------
327    const String& D3D9HLSLProgram::getLanguage(void) const
328    {
329        static const String language = "hlsl";
330
331        return language;
332    }
333
334        #ifdef GAMETOOLS_ILLUMINATION_MODULE
335                void D3D9HLSLProgram::setOptimalization(const String& optimalization)
336                {
337                        mOptimalization = StringConverter::parseBool(optimalization);                   
338                }
339                const String& D3D9HLSLProgram::getOptimalization() const
340                {
341                        return StringConverter::toString(mOptimalization);
342                }
343                void D3D9HLSLProgram::setFlowControl(const String& control)
344                {
345                        if(control == "default")
346                                mFlowControl = 0;
347                        else if(control == "avoid")
348                                mFlowControl = -1;
349                        else if(control == "prefer")
350                                mFlowControl = 1;       
351                }
352                const String& D3D9HLSLProgram::getFlowControl() const
353                {
354                        static const String def = "default";
355                        static const String pref = "prefer";
356                        static const String av = "avoid";
357                        if(mFlowControl == 0)
358                                return def;
359                        if(mFlowControl == -1)
360                                return av;
361                        if(mFlowControl == 1)
362                                return pref;           
363                }
364        #endif
365
366    //-----------------------------------------------------------------------
367    //-----------------------------------------------------------------------
368    String D3D9HLSLProgram::CmdEntryPoint::doGet(const void *target) const
369    {
370        return static_cast<const D3D9HLSLProgram*>(target)->getEntryPoint();
371    }
372    void D3D9HLSLProgram::CmdEntryPoint::doSet(void *target, const String& val)
373    {
374        static_cast<D3D9HLSLProgram*>(target)->setEntryPoint(val);
375    }
376    //-----------------------------------------------------------------------
377    String D3D9HLSLProgram::CmdTarget::doGet(const void *target) const
378    {
379        return static_cast<const D3D9HLSLProgram*>(target)->getTarget();
380    }
381    void D3D9HLSLProgram::CmdTarget::doSet(void *target, const String& val)
382    {
383        static_cast<D3D9HLSLProgram*>(target)->setTarget(val);
384    }
385
386        #ifdef GAMETOOLS_ILLUMINATION_MODULE
387                String D3D9HLSLProgram::CmdOptimalization::doGet(const void *target) const
388                {
389                        return static_cast<const D3D9HLSLProgram*>(target)->getOptimalization();
390                }
391                void D3D9HLSLProgram::CmdOptimalization::doSet(void *target, const String& val)
392                {
393                        static_cast<D3D9HLSLProgram*>(target)->setOptimalization(val);
394                }
395                String D3D9HLSLProgram::CmdFlowControl::doGet(const void *target) const
396                {
397                        return static_cast<const D3D9HLSLProgram*>(target)->getFlowControl();
398                }
399                void D3D9HLSLProgram::CmdFlowControl::doSet(void *target, const String& val)
400                {
401                        static_cast<D3D9HLSLProgram*>(target)->setFlowControl(val);
402                }
403        #endif
404
405}
Note: See TracBrowser for help on using the repository browser.