Alignment requirements

Started by
29 comments, last by Starfox 10 years, 4 months ago

I'm having trouble registering a float3 class with a float3(float x, float y, float z) constructor as a scoped ref type. Calls specifying asBEHAVE_CONSTRUCT fail when the flags are asOBJ_REF | asOBJ_SCOPED and adding asOBJ_APP_CLASS fails when registering the object type. How would I do that?

If possible, I'd like to cast a vote for the alignment feature request described at http://www.gamedev.net/topic/606270-memory-aligned-objects/?gopid=4835684 - aligned vector types exist in every single game engine that I know of, and that option would significantly improve the ease of binding.

Holy crap I started a blog - http://unobvious.typepad.com/
Advertisement

You should use asBEHAVE_FACTORY for asOBJ_SCOPED objects. Consider coupling this with a memory pool to avoid doing dynamic allocations for each instance.

You'll also need to register the asBEHAVE_RELEASE behaviour to free the memory allocated with the factory, but not the asBEHAVE_ADDREF behaviour as there is no reference counting with asOBJ_SCOPED objects..

Manual: Registering scoped reference types

I agree that the alignment feature might make things a lot easier, but it is a feature that will require quite a bit of work to get right, not the least to update the assembly code for the native calling conventions to support this type too. Needless to say, it will take a while before I'll get to start implementing this feature, though it is always in the back of my mind.

You may however want to consider if it is really wise to expose the aligned vector class to the script. They are great for math heavy calculations, but when mixed with other computation they have quite a bit of overhead as the loading and unloading of the SIMD registers will be performed even for trivial calculations. It will also use up 33% more memory than you usually need for a vector3 structure.

This is why for example DirectXMath has two separate vector classes. One for heavy duty math work (XMVECTOR), and one for normal work and storage (XMFLOAT3).

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

Math-heavy scripts are of course a bad idea, but for simple back and forth passing of parameters implementing a whole new class just for unaligned storage is overkill. If you accept contributions we could have someone do the work necessary if you can provide some outline assistance.

Holy crap I started a blog - http://unobvious.typepad.com/

I haven't made a complete mapping of all the changes that would be needed, but these are the high level changes:

  • The script context must make sure to always allocate the local stack memory buffer on 16byte aligned boundaries (asCContext::ReserveStackSpace)
  • The engine must make sure to always allocate the memory for the script objects on 16byte aligned boundaries (asCScriptEngine::CallAlloc)
  • The application needs to inform a new flag when registering types that require 16byte alignment, e.g. asOBJ_APP_ALIGN16 (asCScriptEngine::RegisterObjectType)
  • The script object type must make sure to align member properties of these types correctly (asCObjectType::AddPropertyToClass)
  • Script global properties must allocate memory on 16byte boundaries if holding these types (asCGlobalProperty::AllocateMemory)
  • The script compiler must make sure to allocate the local variables on 16byte boundaries (asCCompiler::AllocateVariable)
  • The script compiler must add pad bytes on the stack for all function calls to guarantee that the stack position is 16byte aligned on entry in the called function (asCCompiler)
  • The bytecode serializer must be capable of adjusting these pad bytes to guarantee platform independent saved bytecode. Remember that the registered type may not be 16byte aligned on all platforms (asCWriter & asCReader)
  • The bytecode serializer must also be prepared to adjust the position of the local variables according to the need fro 16byte alignment (asCWriter & asCReader)
  • The code for the native calling conventions must be adjusted for all platforms that should support 16byte aligned types (as_callfunc...)
  • When the context needs to grow the local stack memory it must copy the function arguments so that the stack entry position is 16byte aligned (asCContext::CallScriptFunction)
  • When the context is prepared for a new call, it must set the initial stack position so the stack entry position is 16byte aligned (asCContext::Prepare)

There may be some other changes needed as well. If I remember anything else later I'll add to this list.

The bullets in red are the complex changes.The other changes should be quite trivial.

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

Sounds good. I'll dive into the code as soon as I can.

One thing I noticed though: The alignment errors only happen in release builds, and not debug builds - is it possible that this is due to the behavioral changes of malloc()? If so, can those changed be simulated for the release build? Sounds a less-effort fix.

Holy crap I started a blog - http://unobvious.typepad.com/

I don't think it is because of anything malloc does. More likely the debug build uses different instructions to load the SIMD registers so the __m128 types doesn't require alignment. This is however something that would be in your application, and not in AngelScript.

You can set custom memory functions with asSetGlobalMemoryFunctions(). With this the application can use memory routines that is guaranteed to always return 16byte aligned memory to the script library. You probably don't want to use 16byte aligned allocations for everything though, as it will waste a lot of memory when the allocations are smaller than 16bytes.

This gave me an idea. The code in as_memory.h can perhaps be enhanced to have a new macro for allocating 16byte aligned memory, e.g. asNEW16 and asNEWARRAY16. This macro can then call a new userAlloc16 global function. The pieces of code I mentioned above that need to guarantee 16byte aligned memory would then only have to call these macros instead of the existing ones to allocate the memory.

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

FWIW, they currently both call userAlloc, which defaults to malloc() which guarantees 16 byte alignment on OS X - so that's probably not it. Something else about the debug environment is causing variables created on the AS stack to always have 16-byte aligned addresses - if only I can know what it is I would change it so that it's guaranteed to behave in the way that happens by accident under the debug environment...

Holy crap I started a blog - http://unobvious.typepad.com/

There is nothing in the AngelScript code to guarantee 16byte aligned addresses of local variables at the moment. Even if malloc() is guaranteed to return properly aligned memory buffers, the local variables in the script will be packed at 4byte boundaries.

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

I haven't made a complete mapping of all the changes that would be needed, but these are the high level changes:

  • The script context must make sure to always allocate the local stack memory buffer on 16byte aligned boundaries (asCContext::ReserveStackSpace)

I think I implemented that part, check out commits https://bitbucket.org/sherief/angelscript/commits/b9bca19ffa001ce628d106adc95669c666af4efb and https://bitbucket.org/sherief/angelscript/commits/c8070156e0141c28fad7e782f28947431834919a and let me know what you think.

Holy crap I started a blog - http://unobvious.typepad.com/
  • The script object type must make sure to align member properties of these types correctly (asCObjectType::AddPropertyToClass)

asCObjectType::AddPropertyToClass() now supports specifying an alignment parameter - added in https://bitbucket.org/sherief/angelscript/commits/962189ef1a752736e9e9c480d10b2e14d0e4e685

Holy crap I started a blog - http://unobvious.typepad.com/

This topic is closed to new replies.

Advertisement