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

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