Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!

1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!

Andreas Jonsson

Member Since 26 Mar 2000
Offline Last Active Today, 02:59 PM

#5238285 AngelScript 2.30.1 is out

Posted by Andreas Jonsson on 03 July 2015 - 07:24 PM

In this new version I had the fortune to get my hands on a MIPS Creator CI20 board, thanks to Alexandru Voica from Imagination Technologies, so I spent some time on adding support for native calling conventions for MIPS processors on Linux and Android.


Adding support for the native calling conventions on Linux was easy enough, since I had already done similar work with ARM, and AngelScript already had support for MIPS on PSP. The ABI used by Linux (MIPS O32) is different than what is used by PSP (MIPS N32) so I still had to do a fair bit of reverse engineering of the ABI by reading assembler code and figure out how values are passed in and out of functions, but the original implementation by Manu Evans for PSP back in 2006 still helped a lot.


The Android support took more time. Not because of the ABI itself, which turned out to be identical to Linux, but because I had never worked with Android myself before. But, I decided it was time to sit down and learn the tools, so I went ahead and installed Android Studio, and Android NDK. It took some time to figure out how it works, but I managed to get the regression test suite to compile and upload it to the CI20. I didn't manage to figure out how to debug the native code on Android, but luckily I didn't have to as the ABI worked perfectly so it was mostly a matter of figuring out how to setup the configurations in as_config.h.


It's been fun learning about Android. I'm still a newbie in this world, but perhaps sometime in the future I'll start writing apps for Android too.


Of course, support for native calling conventions on MIPS is not the only improvement with this version. I've made some optimizations, especially scripts that do a lot of array access operations should hopefully notice a boost in performance. Loading pre-compiled byte-code should also be a lot faster, especially on mobile devices that don't have so much raw computing power.


dkrusu contributed a small language enhancement: for-loops can now have multiple increment expressions separated by commas.


Other than that, there is the usual load of bug fixes and minor improvements throughout. Refer to the changelist for the details.




#5236241 Script builder addon does not detect duplicate scripts on Windows

Posted by Andreas Jonsson on 22 June 2015 - 06:38 PM

I've fixed this in revision 2182.




#5235541 Very slow loading of bytecode on iOS

Posted by Andreas Jonsson on 18 June 2015 - 01:33 PM

From the screenshot it looks like most of the time with loading the bytecode is spent in the function asCReader::ReadUsedFunctions, more specifically with the calls to IsSignatureEqual.


A trivial optimization would be to switch the order of the comparisons in the conditions. For example:


    for( asUINT i = 0; i < engine->scriptFunctions.GetLength(); i++ )
     asCScriptFunction *f = engine->scriptFunctions[i];
     if( f == 0 ||
      !func.IsSignatureEqual(f) ||                        // <-- make this the last check in the condition, since it is the most expensive
      func.objectType != f->objectType ||
      func.nameSpace != f->nameSpace )
     usedFunctions[n] = f;


Going a bit further but still keeping it simple, I would look into rearranging the logic inside IsSignatureEqual(). For example:


bool asCScriptFunction::IsSignatureEqual(const asCScriptFunction *func) const
 if( !IsSignatureExceptNameEqual(func) || name != func->name ) return false;  // <-- change this so the name is compared first
 return true;


Just these two simple changes has the potential of saving 1-2 seconds on your loading time.


Would you mind making the above changes and verifying if the improvement is worth it? If it is I'll have the changes checked in to the SVN for the next release.







A much more complex optimization can be done by storing the functions in a hash map so the lookup done in ReadUsedFunctions() isn't done linearly. This would require a considerable amount of work, and I'm not entirely sure how much time it would save (though I'd guess it would be in the range of 80% of the time).


If the trivial changes I proposed above are good enough, then it will probably not be worth it to spend this time to implement the hash map.

#5232221 Characters being offset by a pixel in BMFont

Posted by Andreas Jonsson on 01 June 2015 - 01:58 PM

This blurriness with the interpolated samples, plus the fact that it was almost correct with point sampling, tells me that you're likely getting samples that are offset by (0.5,0.5) texels, thus each pixel will be rendered as an average of the 4 nearby texels.


Try adjusting the UV coordinates with (0.5,0.5) texels, or perhaps the screen coordinates with (0.5,0.5) pixels.

#5232203 Characters being offset by a pixel in BMFont

Posted by Andreas Jonsson on 01 June 2015 - 12:33 PM

What is the difference between the two applications?



By the looks of the output, I have a feeling it may have something to do with the sampling of the font texture. Are you perhaps using point-sampling, i.e. no interpolation? Have you set up the transform matrices for pixel-perfect rendering? Specifically check the manual for how to adjust coordinates (if necessary) for pixel perfect sampling. It might be that you need to add (0.5,0.5) texels to the UV coordinates to get the best result.

#5230947 Channel information invalidating texture for BMFont

Posted by Andreas Jonsson on 25 May 2015 - 06:57 PM

The DWORD value 256 seen in hexadecimal looks like this 0x00000100. If you consider that each byte of the DWORD represent one channel you'll get (0,0,1,0). 


Then it is just a matter of knowing which byte represents which channel. 


From your vertex format you're telling DX11 that the DWORD should be interpreted as R8G8B8A8, i.e. (Red, Green, Blue, Alpha).

#5230897 Channel information invalidating texture for BMFont

Posted by Andreas Jonsson on 25 May 2015 - 02:40 PM

At least you know now what to investigate further to find the cause of the problem. :)


Let us know what it was when you find it.

#5230839 Channel information invalidating texture for BMFont

Posted by Andreas Jonsson on 25 May 2015 - 08:16 AM

Everything you've shown so far SEEMS to be correct, the problem is most likely a very specific little detail that we're not seeing.


I've yet to use DX11 so I can't say if the difference that behc mentioned would change anything. In my own code I use DX9 and the BLENDINDICES part of the vertex format uses the type D3DDECLTYPE_UBYTE4. I suppose this would be the same as DXGI_FORMAT_R8G8B8A8_UINT in DC11, but cannot confirm it.


You'll need to do some debugging. Let us know what the value of the channel is when you draw the 'testna' characters.


float4 PS( VS_OUTPUT input) : SV_Target 
   float4 pixel = textureDiffuse0.Sample(textureSampler0, input.Tex); 
   // Are we rendering a colored image, or 
   // a character from only one of the channels 
   if( dot(vector(1,1,1,1), input.channel) )                // input.channel should have the value vector(0,0,1,0) here (assuming ARGB order)
      // Get the pixel value 
      float val = dot(pixel, input.channel);                 // with vector(0,0,1,0) the dot function will return just the value of the green channel
      pixel.rgb = 1; 
      pixel.a = val;                                                     // the value of the green channel will be used for the alpha blending
   return pixel; 


The code I use can be found here (in case you haven't seen it before):


* acgfx_font.cpp (.h)

* acgfx_dynrender.cpp(.h)

#5230747 Channel information invalidating texture for BMFont

Posted by Andreas Jonsson on 24 May 2015 - 06:08 PM

What value are you placing in the vertex' channel argument? It should be a vector with only one of the red, green, blue, or alpha channels set to 1 (or 255). Which channel to set to 1 is given in the .fnt file for the character that you're drawing.


From the first image all characters in the word 'testna' are in the green channel, so you'll want to use the value (0,0,1,0) assuming th order of the channels is (A,R,G,B).

#5229709 Inheriting from application registered class

Posted by Andreas Jonsson on 18 May 2015 - 04:54 PM

Oops. The article in the manual is obviously missing an important piece. I'll have that corrected a.s.a.p.


Anyway, the factory function can for example be implemented like this:


static FooScripted *FooScripted::Factory()
  asIScriptContext *ctx = asGetActiveContext();

  // Get the function that is calling the factory so we can be certain it is the FooScript class
  asIScriptFunction *func = ctx->GetFunction(0);
  if( func->GetObjectType() == 0 || std::string(func->GetObjectType()->GetName()) != "FooScripted" )
    ctx->SetException("Invalid attempt to manually instantiate FooScript_t");
    return 0;

  // Get the this pointer from the calling function
  asIScriptObject *obj = reinterpret_cast<asIScriptObject*>(ctx->GetThisPointer(0));

  return new FooScripted(obj);


The test code available in the svn might help give more clarity too (beware, the code has not really been written as a tutorial so it may be a bit confusing wink.png)

#5221332 QtScript vs AngelScript

Posted by Andreas Jonsson on 04 April 2015 - 09:21 AM

I implemented a special bytecode instruction for calling registered class methods with signature 'type &obj::func(int)' in revision 2147. With this there are almost no runtime decisions that has to be made when making the function call, so the overhead is greatly reduced.


In my tests, a script that accesses array members 20 million times took about 1.2 seconds without this new bytecode instruction, and with it it was reduced to about 0.4 seconds. 


In comparison, the same logic implemented directly in C++, takes about 0.04 seconds. So the script is approximately 10 times slower than C++ now. With the use of a JIT compiler this difference should be reduced even further (though I haven't tried it).




I did experiment with implementing the opIndex call as direct access by inlining the call as bytecode instructions, and the performance was about the same as with the new bytecode instruction. For now I've decided to put this option on hold, as the effort to get it to work is too great compared to the benefits it will have. 

#5215552 Register handle as reference

Posted by Andreas Jonsson on 09 March 2015 - 07:27 PM

I've finally added support for registering class members as references, e.g.


engine->RegisterObjectProperty("type", "complex &cmplx", asOFFSET(type, cmplx));


This is available in revision 2142.




#5214602 Errors produced by classes in namespaces accessing global properties

Posted by Andreas Jonsson on 04 March 2015 - 07:37 PM

I've fixed this in revision 2139.




#5213395 **== and >>>==

Posted by Andreas Jonsson on 27 February 2015 - 03:54 PM

These are compound assignment operators.


A **= B;  means A = A ** B;  (** is power-of or exponent operator)


A >>>= B; means A = A >>> B; (>>> is arithmetic shift right)

#5212836 Virtual property compound assignment on temporary object handle (v2.30.0)

Posted by Andreas Jonsson on 24 February 2015 - 09:06 PM

I've fixed this bug in revision 2137.