Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/RenderSystems/Direct3D9/src/OgreD3D9HLSLProgram.cpp @ 3

Last change on this file since 3 was 3, checked in by anonymous, 17 years ago

=update

File size: 16.8 KB
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-2006 Torus Knot Software Ltd
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
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#include "OgreD3D9HLSLProgram.h"
30#include "OgreGpuProgramManager.h"
31#include "OgreStringConverter.h"
32#include "OgreD3D9GpuProgram.h"
33
34namespace Ogre {
35    //-----------------------------------------------------------------------
36    D3D9HLSLProgram::CmdEntryPoint D3D9HLSLProgram::msCmdEntryPoint;
37    D3D9HLSLProgram::CmdTarget D3D9HLSLProgram::msCmdTarget;
38    D3D9HLSLProgram::CmdPreprocessorDefines D3D9HLSLProgram::msCmdPreprocessorDefines;
39    D3D9HLSLProgram::CmdColumnMajorMatrices D3D9HLSLProgram::msCmdColumnMajorMatrices;
40    //-----------------------------------------------------------------------
41    //-----------------------------------------------------------------------
42    void D3D9HLSLProgram::loadFromSource(void)
43    {
44        // Populate preprocessor defines
45        String stringBuffer;
46
47        std::vector<D3DXMACRO> defines;
48        const D3DXMACRO* pDefines = 0;
49        if (!mPreprocessorDefines.empty())
50        {
51            stringBuffer = mPreprocessorDefines;
52
53            // Split preprocessor defines and build up macro array
54            D3DXMACRO macro;
55            String::size_type pos = 0;
56            while (pos != String::npos)
57            {
58                macro.Name = &stringBuffer[pos];
59                macro.Definition = 0;
60
61                                String::size_type start_pos=pos;
62
63                // Find delims
64                pos = stringBuffer.find_first_of(";,=", pos);
65
66                                if(start_pos==pos)
67                                {
68                                        if(pos==stringBuffer.length())
69                                        {
70                                                break;
71                                        }
72                                        pos++;
73                                        continue;
74                                }
75
76                if (pos != String::npos)
77                {
78                    // Check definition part
79                    if (stringBuffer[pos] == '=')
80                    {
81                        // Setup null character for macro name
82                        stringBuffer[pos++] = '\0';
83                        macro.Definition = &stringBuffer[pos];
84                        pos = stringBuffer.find_first_of(";,", pos);
85                    }
86                    else
87                    {
88                        // No definition part, define as "1"
89                        macro.Definition = "1";
90                    }
91
92                    if (pos != String::npos)
93                    {
94                        // Setup null character for macro name or definition
95                        stringBuffer[pos++] = '\0';
96                    }
97                }
98                                else
99                                {
100                                        macro.Definition = "1";
101                                }
102                                if(strlen(macro.Name)>0)
103                                {
104                                        defines.push_back(macro);
105                                }
106                                else
107                                {
108                                        break;
109                                }
110            }
111
112            // Add NULL terminator
113            macro.Name = 0;
114            macro.Definition = 0;
115            defines.push_back(macro);
116
117            pDefines = &defines[0];
118        }
119
120        // Populate compile flags
121        DWORD compileFlags = 0;
122        if (mColumnMajorMatrices)
123            compileFlags |= D3DXSHADER_PACKMATRIX_COLUMNMAJOR;
124        else
125            compileFlags |= D3DXSHADER_PACKMATRIX_ROWMAJOR;
126
127        LPD3DXBUFFER errors = 0;
128
129        // Compile & assemble into microcode
130        HRESULT hr = D3DXCompileShader(
131            mSource.c_str(),
132            static_cast<UINT>(mSource.length()),
133            pDefines,
134            NULL, //no includes
135            mEntryPoint.c_str(),
136            mTarget.c_str(),
137            compileFlags,
138            &mpMicroCode,
139            &errors,
140            &mpConstTable);
141
142        if (FAILED(hr))
143        {
144            String message = "Cannot assemble D3D9 high-level shader " + mName + " Errors:\n" +
145                static_cast<const char*>(errors->GetBufferPointer());
146            errors->Release();
147            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, message,
148                "D3D9HLSLProgram::loadFromSource");
149        }
150
151
152    }
153    //-----------------------------------------------------------------------
154    void D3D9HLSLProgram::createLowLevelImpl(void)
155    {
156        // Create a low-level program, give it the same name as us
157        mAssemblerProgram = 
158            GpuProgramManager::getSingleton().createProgramFromString(
159                mName, 
160                mGroup,
161                "",// dummy source, since we'll be using microcode
162                mType, 
163                mTarget);
164        static_cast<D3D9GpuProgram*>(mAssemblerProgram.get())->setExternalMicrocode(mpMicroCode);
165
166    }
167    //-----------------------------------------------------------------------
168    void D3D9HLSLProgram::unloadHighLevelImpl(void)
169    {
170        SAFE_RELEASE(mpMicroCode);
171        SAFE_RELEASE(mpConstTable);
172
173    }
174    //-----------------------------------------------------------------------
175    void D3D9HLSLProgram::buildConstantDefinitions() const
176    {
177        // Derive parameter names from const table
178        assert(mpConstTable && "Program not loaded!");
179        // Get contents of the constant table
180        D3DXCONSTANTTABLE_DESC desc;
181        HRESULT hr = mpConstTable->GetDesc(&desc);
182
183                mFloatLogicalToPhysical.bufferSize = 0;
184                mIntLogicalToPhysical.bufferSize = 0;
185                mConstantDefs.floatBufferSize = 0;
186                mConstantDefs.intBufferSize = 0;
187
188        if (FAILED(hr))
189        {
190            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 
191                "Cannot retrieve constant descriptions from HLSL program.", 
192                "D3D9HLSLProgram::buildParameterNameMap");
193        }
194        // Iterate over the constants
195        for (unsigned int i = 0; i < desc.Constants; ++i)
196        {
197            // Recursively descend through the structure levels
198            processParamElement(NULL, "", i);
199        }
200
201       
202    }
203    //-----------------------------------------------------------------------
204    void D3D9HLSLProgram::processParamElement(D3DXHANDLE parent, String prefix, 
205        unsigned int index) const
206    {
207        D3DXHANDLE hConstant = mpConstTable->GetConstant(parent, index);
208
209        // Since D3D HLSL doesn't deal with naming of array and struct parameters
210        // automatically, we have to do it by hand
211
212        D3DXCONSTANT_DESC desc;
213        unsigned int numParams = 1;
214        HRESULT hr = mpConstTable->GetConstantDesc(hConstant, &desc, &numParams);
215        if (FAILED(hr))
216        {
217            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 
218                "Cannot retrieve constant description from HLSL program.", 
219                "D3D9HLSLProgram::processParamElement");
220        }
221
222        String paramName = desc.Name;
223        // trim the odd '$' which appears at the start of the names in HLSL
224        if (paramName.at(0) == '$')
225            paramName.erase(paramName.begin());
226
227                // Also trim the '[0]' suffix if it exists, we will add our own indexing later
228                if (StringUtil::endsWith(paramName, "[0]", false))
229                {
230                        paramName.erase(paramName.size() - 3);
231                }
232
233
234        if (desc.Class == D3DXPC_STRUCT)
235        {
236            // work out a new prefix for nested members, if it's an array, we need an index
237            prefix = prefix + paramName + ".";
238            // Cascade into struct
239            for (unsigned int i = 0; i < desc.StructMembers; ++i)
240            {
241                processParamElement(hConstant, prefix, i);
242            }
243        }
244        else
245        {
246            // Process params
247            if (desc.Type == D3DXPT_FLOAT || desc.Type == D3DXPT_INT || desc.Type == D3DXPT_BOOL)
248            {
249                size_t paramIndex = desc.RegisterIndex;
250                String name = prefix + paramName;
251               
252                                GpuConstantDefinition def;
253                                // populate type, array size & element size
254                                populateDef(desc, def);
255                                if (def.isFloat())
256                                {
257                                        def.physicalIndex = mFloatLogicalToPhysical.bufferSize;
258                                        OGRE_LOCK_MUTEX(mFloatLogicalToPhysical.mutex)
259                                        mFloatLogicalToPhysical.map.insert(
260                                                GpuLogicalIndexUseMap::value_type(paramIndex, 
261                                                GpuLogicalIndexUse(def.physicalIndex, def.arraySize * def.elementSize)));
262                                        mFloatLogicalToPhysical.bufferSize += def.arraySize * def.elementSize;
263                                        mConstantDefs.floatBufferSize = mFloatLogicalToPhysical.bufferSize;
264                                }
265                                else
266                                {
267                                        def.physicalIndex = mIntLogicalToPhysical.bufferSize;
268                                        OGRE_LOCK_MUTEX(mIntLogicalToPhysical.mutex)
269                                        mIntLogicalToPhysical.map.insert(
270                                                GpuLogicalIndexUseMap::value_type(paramIndex, 
271                                                GpuLogicalIndexUse(def.physicalIndex, def.arraySize * def.elementSize)));
272                                        mIntLogicalToPhysical.bufferSize += def.arraySize * def.elementSize;
273                                        mConstantDefs.intBufferSize = mIntLogicalToPhysical.bufferSize;
274                                }
275
276                mConstantDefs.map.insert(GpuConstantDefinitionMap::value_type(name, def));
277
278                                // Now deal with arrays
279                                mConstantDefs.generateConstantDefinitionArrayEntries(name, def);
280            }
281        }
282           
283    }
284        //-----------------------------------------------------------------------
285        void D3D9HLSLProgram::populateDef(D3DXCONSTANT_DESC& d3dDesc, GpuConstantDefinition& def) const
286        {
287                def.arraySize = d3dDesc.Elements;
288                switch(d3dDesc.Type)
289                {
290                case D3DXPT_INT:
291                        switch(d3dDesc.Columns)
292                        {
293                        case 1:
294                                def.constType = GCT_INT1;
295                                def.elementSize = 4; // HLSL always packs
296                                break;
297                        case 2:
298                                def.constType = GCT_INT2;
299                                def.elementSize = 4; // HLSL always packs
300                                break;
301                        case 3:
302                                def.constType = GCT_INT3;
303                                def.elementSize = 4; // HLSL always packs
304                                break;
305                        case 4:
306                                def.constType = GCT_INT4;
307                                def.elementSize = 4; 
308                                break;
309                        } // columns
310                        break;
311                case D3DXPT_FLOAT:
312                        switch(d3dDesc.Rows)
313                        {
314                        case 1:
315                                switch(d3dDesc.Columns)
316                                {
317                                case 1:
318                                        def.constType = GCT_FLOAT1;
319                                        def.elementSize = 4; // HLSL always packs
320                                        break;
321                                case 2:
322                                        def.constType = GCT_FLOAT2;
323                                        def.elementSize = 4; // HLSL always packs
324                                        break;
325                                case 3:
326                                        def.constType = GCT_FLOAT3;
327                                        def.elementSize = 4; // HLSL always packs
328                                        break;
329                                case 4:
330                                        def.constType = GCT_FLOAT4;
331                                        def.elementSize = 4; 
332                                        break;
333                                } // columns
334                                break;
335                        case 2:
336                                switch(d3dDesc.Columns)
337                                {
338                                case 2:
339                                        def.constType = GCT_MATRIX_2X2;
340                                        def.elementSize = 8; // HLSL always packs
341                                        break;
342                                case 3:
343                                        def.constType = GCT_MATRIX_2X3;
344                                        def.elementSize = 8; // HLSL always packs
345                                        break;
346                                case 4:
347                                        def.constType = GCT_MATRIX_2X4;
348                                        def.elementSize = 8; 
349                                        break;
350                                } // columns
351                                break;
352                        case 3:
353                                switch(d3dDesc.Columns)
354                                {
355                                case 2:
356                                        def.constType = GCT_MATRIX_3X2;
357                                        def.elementSize = 12; // HLSL always packs
358                                        break;
359                                case 3:
360                                        def.constType = GCT_MATRIX_3X3;
361                                        def.elementSize = 12; // HLSL always packs
362                                        break;
363                                case 4:
364                                        def.constType = GCT_MATRIX_3X4;
365                                        def.elementSize = 12; 
366                                        break;
367                                } // columns
368                                break;
369                        case 4:
370                                switch(d3dDesc.Columns)
371                                {
372                                case 2:
373                                        def.constType = GCT_MATRIX_4X2;
374                                        def.elementSize = 16; // HLSL always packs
375                                        break;
376                                case 3:
377                                        def.constType = GCT_MATRIX_4X3;
378                                        def.elementSize = 16; // HLSL always packs
379                                        break;
380                                case 4:
381                                        def.constType = GCT_MATRIX_4X4;
382                                        def.elementSize = 16; 
383                                        break;
384                                } // columns
385                                break;
386
387                        } // rows
388                        break;
389                       
390                default:
391                        // not mapping samplers, don't need to take the space
392                        break;
393                };
394
395        }
396    //-----------------------------------------------------------------------
397    D3D9HLSLProgram::D3D9HLSLProgram(ResourceManager* creator, const String& name, 
398        ResourceHandle handle, const String& group, bool isManual, 
399        ManualResourceLoader* loader)
400        : HighLevelGpuProgram(creator, name, handle, group, isManual, loader)
401        , mTarget()
402        , mEntryPoint()
403        , mPreprocessorDefines()
404        , mColumnMajorMatrices(true)
405        , mpMicroCode(NULL), mpConstTable(NULL)
406    {
407        if (createParamDictionary("D3D9HLSLProgram"))
408        {
409            setupBaseParamDictionary();
410            ParamDictionary* dict = getParamDictionary();
411
412            dict->addParameter(ParameterDef("entry_point", 
413                "The entry point for the HLSL program.",
414                PT_STRING),&msCmdEntryPoint);
415            dict->addParameter(ParameterDef("target", 
416                "Name of the assembler target to compile down to.",
417                PT_STRING),&msCmdTarget);
418            dict->addParameter(ParameterDef("preprocessor_defines", 
419                "Preprocessor defines use to compile the program.",
420                PT_STRING),&msCmdPreprocessorDefines);
421            dict->addParameter(ParameterDef("column_major_matrices", 
422                "Whether matrix packing in column-major order.",
423                PT_BOOL),&msCmdColumnMajorMatrices);
424        }
425       
426    }
427    //-----------------------------------------------------------------------
428    D3D9HLSLProgram::~D3D9HLSLProgram()
429    {
430        // have to call this here reather than in Resource destructor
431        // since calling virtual methods in base destructors causes crash
432        if (isLoaded())
433        {
434            unload();
435        }
436        else
437        {
438            unloadHighLevel();
439        }
440    }
441    //-----------------------------------------------------------------------
442    bool D3D9HLSLProgram::isSupported(void) const
443    {
444        if (mCompileError || !isRequiredCapabilitiesSupported())
445            return false;
446
447        return GpuProgramManager::getSingleton().isSyntaxSupported(mTarget);
448    }
449    //-----------------------------------------------------------------------
450    GpuProgramParametersSharedPtr D3D9HLSLProgram::createParameters(void)
451    {
452        // Call superclass
453        GpuProgramParametersSharedPtr params = HighLevelGpuProgram::createParameters();
454
455        // Need to transpose matrices if compiled with column-major matrices
456        params->setTransposeMatrices(mColumnMajorMatrices);
457
458        return params;
459    }
460    //-----------------------------------------------------------------------
461    void D3D9HLSLProgram::setTarget(const String& target)
462    {
463        mTarget = target;
464    }
465
466    //-----------------------------------------------------------------------
467    const String& D3D9HLSLProgram::getLanguage(void) const
468    {
469        static const String language = "hlsl";
470
471        return language;
472    }
473
474    //-----------------------------------------------------------------------
475    //-----------------------------------------------------------------------
476    String D3D9HLSLProgram::CmdEntryPoint::doGet(const void *target) const
477    {
478        return static_cast<const D3D9HLSLProgram*>(target)->getEntryPoint();
479    }
480    void D3D9HLSLProgram::CmdEntryPoint::doSet(void *target, const String& val)
481    {
482        static_cast<D3D9HLSLProgram*>(target)->setEntryPoint(val);
483    }
484    //-----------------------------------------------------------------------
485    String D3D9HLSLProgram::CmdTarget::doGet(const void *target) const
486    {
487        return static_cast<const D3D9HLSLProgram*>(target)->getTarget();
488    }
489    void D3D9HLSLProgram::CmdTarget::doSet(void *target, const String& val)
490    {
491        static_cast<D3D9HLSLProgram*>(target)->setTarget(val);
492    }
493    //-----------------------------------------------------------------------
494    String D3D9HLSLProgram::CmdPreprocessorDefines::doGet(const void *target) const
495    {
496        return static_cast<const D3D9HLSLProgram*>(target)->getPreprocessorDefines();
497    }
498    void D3D9HLSLProgram::CmdPreprocessorDefines::doSet(void *target, const String& val)
499    {
500        static_cast<D3D9HLSLProgram*>(target)->setPreprocessorDefines(val);
501    }
502    //-----------------------------------------------------------------------
503    String D3D9HLSLProgram::CmdColumnMajorMatrices::doGet(const void *target) const
504    {
505        return StringConverter::toString(static_cast<const D3D9HLSLProgram*>(target)->getColumnMajorMatrices());
506    }
507    void D3D9HLSLProgram::CmdColumnMajorMatrices::doSet(void *target, const String& val)
508    {
509        static_cast<D3D9HLSLProgram*>(target)->setColumnMajorMatrices(StringConverter::parseBool(val));
510    }
511
512}
Note: See TracBrowser for help on using the repository browser.