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

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