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

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