Yes. Lime provides not bad performance comparing to native C++, since its done in the way you described. Personally i think that most time takes rendering which is done internally by Irrlicht, so will do same speed in C++ and C#. When you get 1000 fps in C++ and get 900 fps in C# equivalent its performance loss, but in general you don't need those 1000 fps, and its not so bad to have 900. Also in real app i believe when C++ will give you 40-50 fps, C# will give the same (maybe -1/-2 fps).zaki wrote: IrrlichtLime definitely has less overhead than Irrlicht.NET, and it doesn't use P/Invoke, so performance must also be better
More about performance. Lime compiled in Debug mode should give even bigger performance loss than in Release (comparing to Debug/Release of native Irrlicht), because I add a lot of asserts into the code, in every place where it is clear to know what value acceptable, and this must help user to detect some errors. In Release mode, all the asserts omitted, so it runs as fast as possible.
For example, when you create a Video.Coloru (which is video::SColor), in Debug mode additionally 4 comparisons done each time:
Code: Select all
Coloru(unsigned int r, unsigned int g, unsigned int b, unsigned int a)
: Lime::NativeValue<video::SColor>(true)
{
LIME_ASSERT(r <= 255);
LIME_ASSERT(g <= 255);
LIME_ASSERT(b <= 255);
LIME_ASSERT(a <= 255);
m_NativeValue = new video::SColor(a, r, g, b);
}
Code: Select all
Colorf(float r, float g, float b, float a)
: Lime::NativeValue<video::SColorf>(true)
{
LIME_ASSERT(r >= 0.0f && r <= 1.0f);
LIME_ASSERT(g >= 0.0f && g <= 1.0f);
LIME_ASSERT(b >= 0.0f && b <= 1.0f);
LIME_ASSERT(a >= 0.0f && a <= 1.0f);
m_NativeValue = new video::SColorf(r, g, b, a);
}
"plus" you don't copy functionality (bodies of methods) from native Irrlicht;
"plus" if native implementation changes (or bug fixed) you don't need to change anything;
"plus" if some Irrlicht' method takes a reference on that value internally and changes it, you don't need to bother "how to sync value with my managed copy?".
"minus" performance loss, for example next one is definitely a bit slower:
Code: Select all
bool GetIntersectionWithSphere(Vector3Df^ sphereOrigin, float sphereRadius, [Out] double% distance)
{
LIME_ASSERT(sphereOrigin != nullptr);
f64 d = 0.0f;
bool b = m_NativeValue->getIntersectionWithSphere(
*sphereOrigin->m_NativeValue,
sphereRadius,
d);
if (b)
distance = d;
return b;
}
Each interface (or almost each) has its own wrapping managed class. And IReferenceCounted is not an exception. Lime doesn't do any "automatic" reference counting that you might think. If native Irrlicht doesn't do it, Lime doesn't do it as well. For example if user does bad reference counting, like doing double Drop(), Lime falls like native Irrlicht does. In C++ you do not use "new" and "delete" for Irrlicht, you use "create" and "drop", so Lime wraps this and doesn't uses IDisposable managed interface for this things, because i don't think its right way to help user in this -- better user must know what he doing.zaki wrote: For curiousity, greenya, how do you work with IReferenceCounted? I'm not very familiar with managed C++, is there any place we need to be cautious about GC or is it something that will just work with C++?
Also, for example Irrlicht.NETCP provides a constructor for IrrlichtDevice, so you create the device by creating an object using "new". I don't think its good way, since than you must enclose executing into try-catch, because if device failed to create, Irrlicht doesn't fall and just return null pointer, which is indication of error. In Lime it's just the same, we have IrrlichtLime.CreateDevice() (a static method), it may return null and it is only way to create the device (just like native Irrlicht do this).
Wrapping in this way, gives us a bonus in further supporting, becasue if native Irrlicht changes internally we just wrap this in that simple way, not building our different engine on Irrlicht, so when base changes some specific part strong enough, we changed only that part and all other part should work just the same if they wasn't changed in native Irrlicht.
Yes, if you use "/clr:safe" than it just managed code and i guess it can run OK. But this is not our case, since "safe" means "no unmanaged pointers at all" which is impossible. If i turn "safe" on, i get million ofzaki wrote: The page I found on the mono site recommends compiling with the /clr:safe switch, but I don't think that is possible, because IrrlichtLime links against native Irrlicht.
If i use "/clr:pure", i don't get messages about native pointers, but i get a million oferror C4956: 'char *' : this type is not verifiable
so i can compile it only as "unsafe".error C3862: 'swprintf': cannot compile an unmanaged function with /clr:pure or /clr:safe