Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreOptimisedUtil.cpp @ 3

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

=update

File size: 13.9 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 "OgreStableHeaders.h"
30
31#include "OgreOptimisedUtil.h"
32
33#include "OgrePlatformInformation.h"
34
35//#define __DO_PROFILE__
36#ifdef __DO_PROFILE__
37#include "OgreRoot.h"
38#endif
39
40namespace Ogre {
41
42    //---------------------------------------------------------------------
43    // External functions
44    extern OptimisedUtil* _getOptimisedUtilGeneral(void);
45#if __OGRE_HAVE_SSE
46    extern OptimisedUtil* _getOptimisedUtilSSE(void);
47#endif
48
49#ifdef __DO_PROFILE__
50    //---------------------------------------------------------------------
51#if OGRE_COMPILER == OGRE_COMPILER_MSVC
52    typedef unsigned __int64 uint64;
53#pragma warning(push)
54#pragma warning(disable: 4035)  // no return value
55    static FORCEINLINE uint64 getCpuTimestamp(void)
56    {
57        __asm rdtsc
58        // Return values in edx:eax, No return statment requirement here for VC.
59    }
60#pragma warning(pop)
61
62#elif OGRE_COMPILER == OGRE_COMPILER_GNUC
63    typedef unsigned long long uint64;
64    static FORCEINLINE uint64 getCpuTimestamp(void)
65    {
66        uint64 result;
67        __asm__ __volatile__ ( "rdtsc" : "=A" (result) );
68        return result;
69    }
70
71#endif  // OGRE_COMPILER
72
73    //---------------------------------------------------------------------
74    class OptimisedUtilProfiler : public OptimisedUtil
75    {
76    protected:
77
78        enum
79        {
80            IMPL_DEFAULT,
81#if __OGRE_HAVE_SSE
82            IMPL_SSE,
83#endif
84            IMPL_COUNT
85        };
86
87        struct ProfileItem
88        {
89            uint mAvgTicks;
90            uint mCount;
91            uint64 mTotalTicks;
92            uint64 mStartTick;
93
94            ProfileItem(void)
95                : mAvgTicks()
96                , mCount()
97                , mTotalTicks()
98            {
99            }
100
101            void begin(void)
102            {
103                mStartTick = getCpuTimestamp();
104            }
105
106            void end(void)
107            {
108                uint64 ticks = getCpuTimestamp() - mStartTick;
109                mTotalTicks += ticks;
110                ++mCount;
111                mAvgTicks = mTotalTicks / mCount;
112            }
113        };
114
115        typedef ProfileItem ProfileItems[IMPL_COUNT];
116
117        typedef std::vector<OptimisedUtil*> OptimisedUtilList;
118        OptimisedUtilList mOptimisedUtils;
119
120    public:
121        OptimisedUtilProfiler(void)
122        {
123            mOptimisedUtils.push_back(_getOptimisedUtilGeneral());
124#if __OGRE_HAVE_SSE
125            if (PlatformInformation::getCpuFeatures() & PlatformInformation::CPU_FEATURE_SSE)
126            {
127                mOptimisedUtils.push_back(_getOptimisedUtilSSE());
128            }
129#endif
130        }
131
132        virtual void softwareVertexSkinning(
133            const float *srcPosPtr, float *destPosPtr,
134            const float *srcNormPtr, float *destNormPtr,
135            const float *blendWeightPtr, const unsigned char* blendIndexPtr,
136            const Matrix4* const* blendMatrices,
137            size_t srcPosStride, size_t destPosStride,
138            size_t srcNormStride, size_t destNormStride,
139            size_t blendWeightStride, size_t blendIndexStride,
140            size_t numWeightsPerVertex,
141            size_t numVertices)
142        {
143            static ProfileItems results;
144            static size_t index;
145            index = Root::getSingleton().getCurrentFrameNumber() % mOptimisedUtils.size();
146            OptimisedUtil* impl = mOptimisedUtils[index];
147            ProfileItem& profile = results[index];
148
149            profile.begin();
150            impl->softwareVertexSkinning(
151                srcPosPtr, destPosPtr,
152                srcNormPtr, destNormPtr,
153                blendWeightPtr, blendIndexPtr,
154                blendMatrices,
155                srcPosStride, destPosStride,
156                srcNormStride, destNormStride,
157                blendWeightStride, blendIndexStride,
158                numWeightsPerVertex,
159                numVertices);
160            profile.end();
161
162            // You can put break point here while running test application, to
163            // watch profile results.
164            ++index;    // So we can put break point here even if in release build
165        }
166
167        virtual void softwareVertexMorph(
168            Real t,
169            const float *srcPos1, const float *srcPos2,
170            float *dstPos,
171            size_t numVertices)
172        {
173            static ProfileItems results;
174            static size_t index;
175            index = Root::getSingleton().getCurrentFrameNumber() % mOptimisedUtils.size();
176            OptimisedUtil* impl = mOptimisedUtils[index];
177            ProfileItem& profile = results[index];
178
179            profile.begin();
180            impl->softwareVertexMorph(
181                t,
182                srcPos1, srcPos2,
183                dstPos,
184                numVertices);
185            profile.end();
186
187            // You can put break point here while running test application, to
188            // watch profile results.
189            ++index;    // So we can put break point here even if in release build
190        }
191
192        virtual void concatenateAffineMatrices(
193            const Matrix4& baseMatrix,
194            const Matrix4* srcMatrices,
195            Matrix4* dstMatrices,
196            size_t numMatrices)
197        {
198            static ProfileItems results;
199            static size_t index;
200            index = Root::getSingleton().getCurrentFrameNumber() % mOptimisedUtils.size();
201            OptimisedUtil* impl = mOptimisedUtils[index];
202            ProfileItem& profile = results[index];
203
204            profile.begin();
205            impl->concatenateAffineMatrices(
206                baseMatrix,
207                srcMatrices,
208                dstMatrices,
209                numMatrices);
210            profile.end();
211
212            // You can put break point here while running test application, to
213            // watch profile results.
214            ++index;    // So we can put break point here even if in release build
215        }
216
217        /// @copydoc OptimisedUtil::calculateFaceNormals
218        virtual void calculateFaceNormals(
219            const float *positions,
220            const EdgeData::Triangle *triangles,
221            Vector4 *faceNormals,
222            size_t numTriangles)
223        {
224            static ProfileItems results;
225            static size_t index;
226            index = Root::getSingleton().getCurrentFrameNumber() % mOptimisedUtils.size();
227            OptimisedUtil* impl = mOptimisedUtils[index];
228            ProfileItem& profile = results[index];
229
230            profile.begin();
231            impl->calculateFaceNormals(
232                positions,
233                triangles,
234                faceNormals,
235                numTriangles);
236            profile.end();
237
238            //
239            //   Dagon SkeletonAnimation sample test results (CPU timestamp per-function call):
240            //
241            //                  Pentium 4 3.0G HT       Athlon XP 2500+
242            //
243            //      General     657080                  486494
244            //      SSE         223559                  399495
245            //
246
247            // You can put break point here while running test application, to
248            // watch profile results.
249            ++index;    // So we can put break point here even if in release build
250        }
251
252        /// @copydoc OptimisedUtil::calculateLightFacing
253        virtual void calculateLightFacing(
254            const Vector4& lightPos,
255            const Vector4* faceNormals,
256            char* lightFacings,
257            size_t numFaces)
258        {
259            static ProfileItems results;
260            static size_t index;
261            index = Root::getSingleton().getCurrentFrameNumber() % mOptimisedUtils.size();
262            OptimisedUtil* impl = mOptimisedUtils[index];
263            ProfileItem& profile = results[index];
264
265            profile.begin();
266            impl->calculateLightFacing(
267                lightPos,
268                faceNormals,
269                lightFacings,
270                numFaces);
271            profile.end();
272
273            //
274            //   Dagon SkeletonAnimation sample test results (CPU timestamp per-function call):
275            //
276            //                  Pentium 4 3.0G HT       Athlon XP 2500+
277            //
278            //      General     171875                  86998
279            //      SSE          47934                  63995
280            //
281
282            // You can put break point here while running test application, to
283            // watch profile results.
284            ++index;    // So we can put break point here even if in release build
285        }
286
287        virtual void extrudeVertices(
288            const Vector4& lightPos,
289            Real extrudeDist,
290            const float* srcPositions,
291            float* destPositions,
292            size_t numVertices)
293        {
294            static ProfileItems results;
295            static size_t index;
296            index = Root::getSingleton().getCurrentFrameNumber() % mOptimisedUtils.size();
297            OptimisedUtil* impl = mOptimisedUtils[index];
298            ProfileItem& profile = results[index];
299
300            profile.begin();
301            impl->extrudeVertices(
302                lightPos,
303                extrudeDist,
304                srcPositions,
305                destPositions,
306                numVertices);
307            profile.end();
308
309            //
310            //   Dagon SkeletonAnimation sample test results (CPU timestamp per-function call):
311            //
312            //                                  Pentium 4 3.0G HT   Athlon XP 2500+
313            //
314            //      Directional Light, General   38106               92306
315            //      Directional Light, SSE       27292               67055
316            //
317            //      Point Light, General        224209              155483
318            //      Point Light, SSE             56817              106663
319            //
320
321            // You can put break point here while running test application, to
322            // watch profile results.
323            ++index;    // So we can put break point here even if in release build
324        }
325
326    };
327#endif // __DO_PROFILE__
328
329    //---------------------------------------------------------------------
330    OptimisedUtil* OptimisedUtil::msImplementation = OptimisedUtil::_detectImplementation();
331
332    //---------------------------------------------------------------------
333    OptimisedUtil* OptimisedUtil::_detectImplementation(void)
334    {
335        //
336        // Some speed test results (averaged number of CPU timestamp (RDTSC) per-function call):
337        //
338        //   Dagon SkeletonAnimation sample - softwareVertexSkinning:
339        //
340        //                                      Pentium 4 3.0G HT       Athlon XP 2500+     Athlon 64 X2 Dual Core 3800+
341        //
342        //      Shared Buffers, General C       763677                  462903              473038
343        //      Shared Buffers, Unrolled SSE    210030 *best*           369762              228328 *best*
344        //      Shared Buffers, General SSE     286202                  352412 *best*       302796
345        //
346        //      Separated Buffers, General C    762640                  464840              478740
347        //      Separated Buffers, Unrolled SSE 219222 *best*           287992 *best*       238770 *best*
348        //      Separated Buffers, General SSE  290129                  341614              307262
349        //
350        //      PosOnly, General C              388663                  257350              262831
351        //      PosOnly, Unrolled SSE           139814 *best*           200323 *best*       168995 *best*
352        //      PosOnly, General SSE            172693                  213704              175447
353        //
354        //   Another my own test scene - softwareVertexSkinning:
355        //
356        //                                      Pentium P4 3.0G HT      Athlon XP 2500+
357        //
358        //      Shared Buffers, General C       74527                   -
359        //      Shared Buffers, Unrolled SSE    22743 *best*            -
360        //      Shared Buffers, General SSE     28527                   -
361        //
362        //
363        // Note that speed test appears unaligned load/store instruction version
364        // loss performance 5%-10% than aligned load/store version, even if both
365        // of them access to aligned data. Thus, we should use aligned load/store
366        // as soon as possible.
367        //
368        //
369        // We are pick up the implementation based on test results above.
370        //
371#ifdef __DO_PROFILE__
372        {
373            static OptimisedUtilProfiler msOptimisedUtilProfiler;
374            return &msOptimisedUtilProfiler;
375        }
376
377#else   // !__DO_PROFILE__
378
379#if __OGRE_HAVE_SSE
380        if (PlatformInformation::getCpuFeatures() & PlatformInformation::CPU_FEATURE_SSE)
381        {
382            return _getOptimisedUtilSSE();
383        }
384        else
385#endif  // __OGRE_HAVE_SSE
386        {
387            return _getOptimisedUtilGeneral();
388        }
389
390#endif  // __DO_PROFILE__
391    }
392
393}
Note: See TracBrowser for help on using the repository browser.