Advertisement

Loading binding data

Started by August 25, 2014 08:45 AM
9 comments, last by _Engine_ 10 years, 2 months ago

Hi!

Currently when we load scene in our engine we make lots of bindings. And this become huge bottleneck even on pc with iCore 5. So it is possible to save code bindigs and load this info like precompiled bytecode?

With bindings do you mean 'imported functions'?

How many imported functions do you have? How big is this 'huge bottleneck' in seconds?

Is the long loading times coming from the LoadByteCode method or from the BindAllImportedFunctions method?

It's not possible to save the bindings with the bytecode, but I can certainly look into optimizing the code if needed.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement

After loading scene we are make bindings of c++ classes and do something like this:

Machine()->RegisterObjectType(class_symbol_inst, sizeof(NGUISymbolInstance), asOBJ_REF| asOBJ_NOCOUNT);
for (int i=0;i<prop.size();i++)
{
prop->EmbedingScript();
}
Machine()->RegisterObjectProperty(class_symbol_inst, "ref handle",offsetof(NGUISymbolInstance, script_handle));
Machine()->RegisterObjectMethod(class_symbol_inst, "bool IsVisible()", asMETHOD(NGUISymbolInstance,IsVisible), asCALL_THISCALL);
Machine()->RegisterObjectMethod(class_symbol_inst, "void Show(bool show)", asMETHOD(NGUISymbolInstance,Show), asCALL_THISCALL);
Machine()->RegisterObjectMethod(class_symbol_inst, "bool IsActive()", asMETHOD(NGUISymbolInstance,IsActive), asCALL_THISCALL);
Machine()->RegisterObjectMethod(class_symbol_inst, "void Activate(bool Active)", asMETHOD(NGUISymbolInstance,Activate), asCALL_THISCALL);
Machine()->RegisterObjectMethod(class_symbol_inst, "void SetTransformPos(Vector&in pos)", asMETHOD(NGUISymbolInstance,SetTransformPos), asCALL_THISCALL);
Machine()->RegisterObjectMethod(class_symbol_inst, "void GetTransformPos(Vector&out pos)", asMETHOD(NGUISymbolInstance,GetTransformPos), asCALL_THISCALL);
For our scene we are binding about 50 such types because we need register for each symbol entity his own class. And if we look at data that we are bind - this is static data because we are pairing declaration with offset. So this data looks like may be saved and loaded in manner like we are loading and saving bytecode (somehow related with ConfigGroup, before we are start binding we call BeginConfigGroup and call EndConfigGroup after finishing binding)
On PC binging time are various. On same PCs with core-i5 binding takes less 1 second on same binding times take about 35 seconds. On android devices and on iphones binding times take about 3-4 seconds.

So if it is was possible to not to call each times big amount of bindings and just call one function to load bindings from one file this may lead to huge speed boost.

OK, so the bottleneck you're facing is with the various Register methods. I'll see what I can do to optimize them so the registration is performed faster.

I don't think it is possible to serialize this, as there is no guarantee that the function addresses will be the same for each execution.

However, I don't see why you need to register this for every scene. Can't you just register the interface once at startup and reuse the same for every scene? What is it that differs from one scene to another?

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

We are reproducing scene object binding in adobe flash manner i.e. scene objects may have child's and child have child's etc. and this relation we are binding into script. For example if scene object MainWindow have child Panel and Panel have child Button we can access to Button as follow:

ButtonType@ btn_ref = MainWindow.Panel.Button;

So for each scene object with child's we are bind his own type into script with properties that's allow access to his child's.

May be there are another way to do this but now such manner of binding leads to slow down of scene start up.

Honestly this looks like misuse of the AngelScript interface registration. I'd recommend to register each scene object class once at startup, and provide accessor methods for each kind of child the scene objects can possibly have, like get_Panel, get_Button etc. If the corresponding child element doesn't exist, the accessor can return null.

Advertisement

If i register something like GetChildButton("child_name") and so on for each type of object of course i do not need so many types. But this is ugly. I will stick witch start up problem rather then do such uncomfortable accessor because if i want to get access to child of the child i must remember not only name but also a type for each member and code will look like

ButtonType@ btn_ref = MainWindow.GetChildLabel("Panel").GetChildButton("Button");

This is not suitable.

I understand now what you're doing. It's a bit unusual, but it's not wrong. You'll always have an overhead with registering the interface dynamically like this, but I'll do what I can to optimize the code so the overhead is as small as possible.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

maybe it is possible to add of registering accessor with fixed return type (not for simple types) but with dynamic name?

For example i call something like this

void NGUIWidgetGetProp(asIScriptGeneric* gen)
{
NGUIWidget* widget = (NGUIWidget*)gen->GetObject();
const char* str = &gen->GetFunction()->GetName()[4];
void* ptr = null;
for (int i=0;i<symbol->childs.size();i++)
{
SceneEntity* entity = symbol->childs;
if (String::IsEqual(str, entity->GetName()))
{
ptr = entity;
break;
}
}
gen->SetReturnAddress(ptr);
}
....
core->Script()->Machine()->RegisterObjectMethod("NGUIWidget", "NGUIWidgetButton@ get_xxx", asFUNCTION(NGUIWidgetGetProp), asCALL_GENERIC);
core->Script()->Machine()->RegisterObjectMethod("NGUIWidget", "NGUIWidgetLabel@ get_xxx", asFUNCTION(NGUIWidgetGetProp), asCALL_GENERIC);
core->Script()->Machine()->RegisterObjectMethod("NGUIWidget", "NGUIWidgetScroller@ get_xxx", asFUNCTION(NGUIWidgetGetProp), asCALL_GENERIC);
core->Script()->Machine()->RegisterObjectMethod("NGUIWidget", "NGUIWidgetPager@ get_xxx", asFUNCTION(NGUIWidgetGetProp), asCALL_GENERIC);
...
and AngelScript knows if somewhere in script someone accessesd to property of type NGUIWidgetButton than AngelScript not search accessor width such type and name but search accessor with only by return type.

This mechanism would save me from unnecessary type binding and also introduce mechanism to construct class types in runtime.
Would a syntax like the following be acceptable in your script?


ButtonType@ btn_ref = MainWindow.Get("Panel").Get("Button");
 
// or even like this
ButtonType@ btn_ref = MainWindow.Get("Panel.Button");
?
?
You could quite easily accomplish this by implementing a special object that can represent any of the possible NGUI types you wish to treat, i.e. Button, Label, Scroller, and Pager.

This special object would be created and registered similarly to the CScriptHandle generic handle add-on. It would then additional implement asBEHAVE_IMPLICIT_REF_CAST to each of the types.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement